Skip to content

Commit

Permalink
Merge pull request #1 from tinyMLx/addingLibraryFeatures
Browse files Browse the repository at this point in the history
Adding library features and OV767X Library
  • Loading branch information
plancherb1 committed Jan 23, 2021
2 parents e205139 + 99b9f47 commit b2d9465
Show file tree
Hide file tree
Showing 17 changed files with 3,767 additions and 83 deletions.
339 changes: 339 additions & 0 deletions LICENSE.txt

Large diffs are not rendered by default.

16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
# arduino-library
# Harvard_TinyMLx Arduino Library

Source code and examples for using and testing your Tiny Machine Learning Kit and Shield.

This library also includes a modified verison of the 0.0.2 version of the OV767X Library for Arduino (Copyright (c) 2020 Arduino SA) which is based on https://www.kernel.org[Linux Kernel's] V4L2 driver for OmniVision OV7670 cameras - which was created by Jonathan Corbet.

== License ==

Copyright (c) 2021 TinyMLx. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
54 changes: 10 additions & 44 deletions examples/test_camera/test_camera.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,14 @@
Harvard University
tinyMLx - OV7675 Camera Test
Requires the the Arduino_OV767X library
*/

#include <Arduino_OV767X.h>

#define BUTTON_PIN 13
#include <TinyMLShield.h>

bool commandRecv = false; // flag used for indicating receipt of commands from serial port
bool liveFlag = false; // flag as true to live stream raw camera bytes, set as false to take single images on command
bool captureFlag = false;

// Variables for button debouncing
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
bool lastButtonState = HIGH;
bool buttonState;

// Image buffer;
byte image[176 * 144 * 2]; // QCIF: 176x144 x 2 bytes per pixel (RGB565)
int bytesPerFrame;
Expand All @@ -28,12 +19,10 @@ void setup() {
Serial.begin(9600);
while (!Serial);

pinMode(BUTTON_PIN, OUTPUT);
digitalWrite(BUTTON_PIN, HIGH);
nrf_gpio_cfg_out_with_input(digitalPinToPinName(BUTTON_PIN));
initializeShield();

// Initialize camera
if (!Camera.begin(QCIF, RGB565, 1)) {
// Initialize the OV7675 camera
if (!Camera.begin(QCIF, RGB565, 1, OV7675)) {
Serial.println("Failed to initialize camera");
while (1);
}
Expand All @@ -50,28 +39,15 @@ void loop() {
int i = 0;
String command;

bool buttonRead = nrf_gpio_pin_read(digitalPinToPinName(BUTTON_PIN));

if (buttonRead != lastButtonState) {
lastDebounceTime = millis();
}

if (millis() - lastDebounceTime >= debounceDelay) {
if (buttonRead != buttonState) {
buttonState = buttonRead;

if (!buttonState) {
if (!liveFlag) {
if (!captureFlag) {
captureFlag = true;
}
}
bool clicked = readShieldButton();
if (clicked) {
if (!liveFlag) {
if (!captureFlag) {
captureFlag = true;
}
}
}

lastButtonState = buttonRead;

// Read incoming commands from serial monitor
while (Serial.available()) {
char c = Serial.read();
Expand Down Expand Up @@ -132,14 +108,4 @@ void loop() {
Serial.println();
}
}
}

void nrf_gpio_cfg_out_with_input(uint32_t pin_number) {
nrf_gpio_cfg(
pin_number,
NRF_GPIO_PIN_DIR_OUTPUT,
NRF_GPIO_PIN_INPUT_CONNECT,
NRF_GPIO_PIN_PULLUP,
NRF_GPIO_PIN_S0S1,
NRF_GPIO_PIN_NOSENSE);
}
}
65 changes: 27 additions & 38 deletions examples/test_microphone/test_microphone.ino
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,21 @@
*/

#include <PDM.h>

#define BUTTON_PIN 13
#include <TinyMLShield.h>

// PDM buffer
short sampleBuffer[256];
volatile int samplesRead;

// Variables for button debouncing
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
bool lastButtonState = HIGH;
bool buttonState;

bool record = false;
bool commandRecv = false;

void setup() {
Serial.begin(9600);
while (!Serial);

pinMode(BUTTON_PIN, OUTPUT);
digitalWrite(BUTTON_PIN, HIGH);
nrf_gpio_cfg_out_with_input(digitalPinToPinName(BUTTON_PIN));
// Initialize the TinyML Shield
initializeShield();

PDM.onReceive(onPDMdata);
// Initialize PDM microphone in mono mode with 16 kHz sample rate
Expand All @@ -36,38 +29,44 @@ void setup() {
}

Serial.println("Welcome to the microphone test for the built-in microphone on the Nano 33 BLE Sense\n");
Serial.println("Use the on-shield button to start and stop an audio recording");
Serial.println("Use the on-shield button or send the command 'click' to start and stop an audio recording");
Serial.println("Open the Serial Plotter to view the corresponding waveform");
}

void loop() {
bool buttonRead = nrf_gpio_pin_read(digitalPinToPinName(BUTTON_PIN));

if (buttonRead != lastButtonState) {
lastDebounceTime = millis();
// see if the button is pressed and turn off or on recording accordingly
bool clicked = readShieldButton();
if (clicked){
record = !record;
}

if (millis() - lastDebounceTime >= debounceDelay) {
if (buttonRead != buttonState) {
buttonState = buttonRead;

if (!buttonState) {
record = !record;
}

// see if a command was sent over the serial monitor and record it if so
String command;
while (Serial.available()) {
char c = Serial.read();
if ((c != '\n') && (c != '\r')) {
command.concat(c);
}
else if (c == '\r') {
commandRecv = true;
command.toLowerCase();
}
}

lastButtonState = buttonRead;

if (samplesRead) {
// parse the command if applicable
if (commandRecv && command == "click") {
commandRecv = false;
record = !record;
}

// display the audio if applicable
if (samplesRead) {
// print samples to serial plotter
if (record) {
for (int i = 0; i < samplesRead; i++) {
Serial.println(sampleBuffer[i]);
}
}

// clear read count
samplesRead = 0;
}
Expand All @@ -82,13 +81,3 @@ void onPDMdata() {

samplesRead = bytesAvailable / 2;
}

void nrf_gpio_cfg_out_with_input(uint32_t pin_number) {
nrf_gpio_cfg(
pin_number,
NRF_GPIO_PIN_DIR_OUTPUT,
NRF_GPIO_PIN_INPUT_CONNECT,
NRF_GPIO_PIN_PULLUP,
NRF_GPIO_PIN_S0S1,
NRF_GPIO_PIN_NOSENSE);
}
92 changes: 92 additions & 0 deletions extras/CameraCapture/CameraCapture.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
OV767X - Camera Test Pattern
This sketch waits for the letter 'c' on the Serial Monitor,
it then reads a frame from the OmniVision OV7670 camera and
prints the data to the Serial Monitor as a hex string.
The website https://rawpixels.net - can be used the visualize the data:
width: 176
height: 144
RGB565
Little Endian
Circuit:
- Arduino Nano 33 BLE board
- OV7670 camera module:
- 3.3 connected to 3.3
- GND connected GND
- SIOC connected to A5
- SIOD connected to A4
- VSYNC connected to 8
- HREF connected to A1
- PCLK connected to A0
- XCLK connected to 9
- D7 connected to 4
- D6 connected to 6
- D5 connected to 5
- D4 connected to 3
- D3 connected to 2
- D2 connected to 0 / RX
- D1 connected to 1 / TX
- D0 connected to 10
This example code is in the public domain.
*/

#include <Arduino_OV767X.h>

unsigned short pixels[176 * 144]; // QCIF: 176x144 X 2 bytes per pixel (RGB565)

void setup() {
Serial.begin(9600);
while (!Serial);

Serial.println("OV767X Camera Capture");
Serial.println();

if (!Camera.begin(QCIF, RGB565, 1, OV7675)) {
Serial.println("Failed to initialize camera!");
while (1);
}

Serial.println("Camera settings:");
Serial.print("\twidth = ");
Serial.println(Camera.width());
Serial.print("\theight = ");
Serial.println(Camera.height());
Serial.print("\tbits per pixel = ");
Serial.println(Camera.bitsPerPixel());
Serial.println();

Serial.println("Send the 'c' character to read a frame ...");
Serial.println();
}

void loop() {
if (Serial.read() == 'c') {
Serial.println("Reading frame");
Serial.println();
Camera.readFrame(pixels);

int numPixels = Camera.width() * Camera.height();

for (int i = 0; i < numPixels; i++) {
unsigned short p = pixels[i];

if (p < 0x1000) {
Serial.print('0');
}

if (p < 0x0100) {
Serial.print('0');
}

if (p < 0x0010) {
Serial.print('0');
}

Serial.print(p, HEX);
}
}
}
36 changes: 36 additions & 0 deletions extras/CameraCaptureRawBytes/CameraCaptureRawBytes.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
OV767X - Camera Capture Raw Bytes
This sketch reads a frame from the OmniVision OV7675 camera
and writes the bytes to the Serial port. Use the Procesing
sketch in the extras folder to visualize the camera output.
This example code is in the public domain.
*/

#include <Arduino_OV767X.h>

int bytesPerFrame;

byte data[176 * 144 * 2]; // QVGA: 320x240 X 2 bytes per pixel (RGB565)

void setup() {
Serial.begin(9600);
while (!Serial);

if (!Camera.begin(QVGA, RGB565, 1, OV7675)) {
Serial.println("Failed to initialize camera!");
while (1);
}

bytesPerFrame = Camera.width() * Camera.height() * Camera.bytesPerPixel();

// Optionally, enable the test pattern for testing
// Camera.testPattern();
}

void loop() {
Camera.readFrame(data);

Serial.write(data, bytesPerFrame);
}
Loading

0 comments on commit b2d9465

Please sign in to comment.