Last active
September 14, 2020 23:04
-
-
Save taf2/e1cbaebdfd93ecacb4ebed903da7aac4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*************************************************** | |
This is a library for the Adafruit TTL JPEG Camera (VC0706 chipset) | |
Pick one up today in the adafruit shop! | |
------> http://www.adafruit.com/products/397 | |
These displays use Serial to communicate, 2 pins are required to interface | |
Adafruit invests time and resources providing this open source code, | |
please support Adafruit and open-source hardware by purchasing | |
products from Adafruit! | |
Written by Limor Fried/Ladyada for Adafruit Industries. | |
BSD license, all text above must be included in any redistribution | |
****************************************************/ | |
#include "Adafruit_VC0706.h" | |
// Initialization code used by all constructor types | |
void Adafruit_VC0706::common_init(void) { | |
#if defined(__AVR__) || defined(ESP8266) | |
swSerial = NULL; | |
#endif | |
hwSerial = NULL; | |
frameptr = 0; | |
bufferLen = 0; | |
serialNum = 0; | |
} | |
#if defined(__AVR__) || defined(ESP8266) | |
/**************************************************************************/ | |
/*! | |
@brief Constructor when using SoftwareSerial | |
@param ser Software serial connection | |
*/ | |
/**************************************************************************/ | |
Adafruit_VC0706::Adafruit_VC0706(SoftwareSerial *ser) { | |
common_init(); // Set everything to common state, then... | |
swSerial = ser; // ...override swSerial with value passed. | |
} | |
#endif | |
/**************************************************************************/ | |
/*! | |
@brief Constructor when using HardwareSerial | |
@param ser Hardware serial connection | |
*/ | |
/**************************************************************************/ | |
Adafruit_VC0706::Adafruit_VC0706(HardwareSerial *ser) { | |
common_init(); // Set everything to common state, then... | |
hwSerial = ser; // ...override hwSerial with value passed. | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Connect to and reset the camera | |
@param baud Camera interface baud rate | |
@return True on reset success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::begin(uint32_t baud) { | |
#if defined(__AVR__) || defined(ESP8266) | |
if (swSerial) | |
swSerial->begin(baud); | |
else | |
#endif | |
hwSerial->begin(baud); | |
return reset(); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Soft reset the camera | |
@return True on success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::reset() { | |
uint8_t args[] = {0x0}; | |
return runCommand(VC0706_RESET, args, 1, 5); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Check if motion is detected | |
@return True on motion detected | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::motionDetected() { | |
if (readResponse(4, 200) != 4) { | |
return false; | |
} | |
if (!verifyResponse(VC0706_COMM_MOTION_DETECTED)) | |
return false; | |
return true; | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Set motion detection | |
@param x See datasheet for VC0706_MOTION_CTRL command details | |
@param d1 See datasheet for VC0706_MOTION_CTRL command details | |
@param d2 See datasheet for VC0706_MOTION_CTRL command details | |
@return True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::setMotionStatus(uint8_t x, uint8_t d1, uint8_t d2) { | |
uint8_t args[] = {0x03, x, d1, d2}; | |
return runCommand(VC0706_MOTION_CTRL, args, sizeof(args), 5); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Get motion status | |
@param x See datasheet for VC0706_MOTION_STATUS command details | |
@return True on command success | |
*/ | |
/**************************************************************************/ | |
uint8_t Adafruit_VC0706::getMotionStatus(uint8_t x) { | |
uint8_t args[] = {0x01, x}; | |
return runCommand(VC0706_MOTION_STATUS, args, sizeof(args), 5); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Set motion detection | |
@param flag Whether to activate motion detection | |
@return True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::setMotionDetect(boolean flag) { | |
if (!setMotionStatus(VC0706_MOTIONCONTROL, VC0706_UARTMOTION, | |
VC0706_ACTIVATEMOTION)) | |
return false; | |
uint8_t args[] = {0x01, flag}; | |
runCommand(VC0706_COMM_MOTION_CTRL, args, sizeof(args), 5); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Get motion detection status | |
@return True if motion detection is on! | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::getMotionDetect(void) { | |
uint8_t args[] = {0x0}; | |
if (!runCommand(VC0706_COMM_MOTION_STATUS, args, 1, 6)) | |
return false; | |
return camerabuff[5]; | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Get image size with VC0706_READ_DATA | |
@return VC0706_640x480, VC0706_320x240 or VC0706_160x120 | |
*/ | |
/**************************************************************************/ | |
uint8_t Adafruit_VC0706::getImageSize() { | |
uint8_t args[] = {0x4, 0x4, 0x1, 0x00, 0x19}; | |
if (!runCommand(VC0706_READ_DATA, args, sizeof(args), 6)) | |
return -1; | |
return camerabuff[5]; | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Set image size with VC0706_WRITE_DATA | |
@param x VC0706_640x480, VC0706_320x240 or VC0706_160x120 | |
@return True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::setImageSize(uint8_t x) { | |
uint8_t args[] = {0x05, 0x04, 0x01, 0x00, 0x19, x}; | |
return runCommand(VC0706_WRITE_DATA, args, sizeof(args), 5); | |
} | |
/****************** downsize image control */ | |
/**************************************************************************/ | |
/*! | |
@brief Get downsize Status | |
@return Camera reply byte | |
*/ | |
/**************************************************************************/ | |
uint8_t Adafruit_VC0706::getDownsize(void) { | |
uint8_t args[] = {0x0}; | |
if (!runCommand(VC0706_DOWNSIZE_STATUS, args, 1, 6)) | |
return -1; | |
return camerabuff[5]; | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Set downsize size | |
@param newsize See datasheet for VC0706_DOWNSIZE_CTRL parameters | |
@return True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::setDownsize(uint8_t newsize) { | |
uint8_t args[] = {0x01, newsize}; | |
return runCommand(VC0706_DOWNSIZE_CTRL, args, 2, 5); | |
} | |
/***************** other high level commands */ | |
/**************************************************************************/ | |
/*! | |
@brief Get firmware version | |
@returns Pointer to buffer containing camera response | |
*/ | |
/**************************************************************************/ | |
char *Adafruit_VC0706::getVersion(void) { | |
uint8_t args[] = {0x01}; | |
sendCommand(VC0706_GEN_VERSION, args, 1); | |
// get reply | |
if (!readResponse(CAMERABUFFSIZ, 200)) | |
return 0; | |
camerabuff[bufferLen] = 0; // end it! | |
return (char *)camerabuff; // return it! | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Set the baud rate to 9600 | |
@return The response as a character buffer | |
*/ | |
/**************************************************************************/ | |
char *Adafruit_VC0706::setBaud9600() { | |
uint8_t args[] = {0x03, 0x01, 0xAE, 0xC8}; | |
sendCommand(VC0706_SET_PORT, args, sizeof(args)); | |
// get reply | |
if (!readResponse(CAMERABUFFSIZ, 200)) | |
return 0; | |
camerabuff[bufferLen] = 0; // end it! | |
return (char *)camerabuff; // return it! | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Set the baud rate to 19200 | |
@return The response as a character buffer | |
*/ | |
/**************************************************************************/ | |
char *Adafruit_VC0706::setBaud19200() { | |
uint8_t args[] = {0x03, 0x01, 0x56, 0xE4}; | |
sendCommand(VC0706_SET_PORT, args, sizeof(args)); | |
// get reply | |
if (!readResponse(CAMERABUFFSIZ, 200)) | |
return 0; | |
camerabuff[bufferLen] = 0; // end it! | |
return (char *)camerabuff; // return it! | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Set the baud rate to 38400 | |
@return The response as a character buffer | |
*/ | |
/**************************************************************************/ | |
char *Adafruit_VC0706::setBaud38400() { | |
uint8_t args[] = {0x03, 0x01, 0x2A, 0xF2}; | |
sendCommand(VC0706_SET_PORT, args, sizeof(args)); | |
// get reply | |
if (!readResponse(CAMERABUFFSIZ, 200)) | |
return 0; | |
camerabuff[bufferLen] = 0; // end it! | |
return (char *)camerabuff; // return it! | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Set the baud rate to 57600 | |
@return The response as a character buffer | |
*/ | |
/**************************************************************************/ | |
char *Adafruit_VC0706::setBaud57600() { | |
uint8_t args[] = {0x03, 0x01, 0x1C, 0x1C}; | |
sendCommand(VC0706_SET_PORT, args, sizeof(args)); | |
// get reply | |
if (!readResponse(CAMERABUFFSIZ, 200)) | |
return 0; | |
camerabuff[bufferLen] = 0; // end it! | |
return (char *)camerabuff; // return it! | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Set the baud rate to 115200 | |
@return The response as a character buffer | |
*/ | |
/**************************************************************************/ | |
char *Adafruit_VC0706::setBaud115200() { | |
uint8_t args[] = {0x03, 0x01, 0x0D, 0xA6}; | |
sendCommand(VC0706_SET_PORT, args, sizeof(args)); | |
// get reply | |
if (!readResponse(CAMERABUFFSIZ, 200)) | |
return 0; | |
camerabuff[bufferLen] = 0; // end it! | |
return (char *)camerabuff; // return it! | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Add a character to on screen display | |
@param x X offset | |
@param y Y offset | |
@param str The string to display | |
*/ | |
/**************************************************************************/ | |
void Adafruit_VC0706::OSD(uint8_t x, uint8_t y, char *str) { | |
if (strlen(str) > 14) { | |
str[13] = 0; | |
} | |
uint8_t args[17] = {strlen(str), strlen(str) - 1, | |
(y & 0xF) | ((x & 0x3) << 4)}; | |
for (uint8_t i = 0; i < strlen(str); i++) { | |
char c = str[i]; | |
if ((c >= '0') && (c <= '9')) { | |
str[i] -= '0'; | |
} else if ((c >= 'A') && (c <= 'Z')) { | |
str[i] -= 'A'; | |
str[i] += 10; | |
} else if ((c >= 'a') && (c <= 'z')) { | |
str[i] -= 'a'; | |
str[i] += 36; | |
} | |
args[3 + i] = str[i]; | |
} | |
runCommand(VC0706_OSD_ADD_CHAR, args, strlen(str) + 3, 5); | |
printBuff(); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Set compression rate | |
@param c See datasheet for compression settings | |
@returns True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::setCompression(uint8_t c) { | |
uint8_t args[] = {0x5, 0x1, 0x1, 0x12, 0x04, c}; | |
return runCommand(VC0706_WRITE_DATA, args, sizeof(args), 5); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Get compression rate | |
@returns The character reply | |
*/ | |
/**************************************************************************/ | |
uint8_t Adafruit_VC0706::getCompression(void) { | |
uint8_t args[] = {0x4, 0x1, 0x1, 0x12, 0x04}; | |
runCommand(VC0706_READ_DATA, args, sizeof(args), 6); | |
printBuff(); | |
return camerabuff[5]; | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Set PTZ (orientation), see datasheet for SET_ZOOM command | |
@param wz Rotation | |
@param hz Horizontal | |
@param pan Pan | |
@param tilt Tilt | |
@returns True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::setPTZ(uint16_t wz, uint16_t hz, uint16_t pan, | |
uint16_t tilt) { | |
uint8_t args[] = {0x08, wz >> 8, wz, hz >> 8, wz, | |
pan >> 8, pan, tilt >> 8, tilt}; | |
return (!runCommand(VC0706_SET_ZOOM, args, sizeof(args), 5)); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Get PTZ (orientation), see datasheet for GET_ZOOM command | |
@param w Pointer to variable to store width | |
@param h Pointer to variable to store height | |
@param wz Pointer to variable to store rotation | |
@param hz Pointer to variable to store horizontal | |
@param pan Pointer to variable to store pan | |
@param tilt Pointer to variable to store tilt | |
@returns True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::getPTZ(uint16_t &w, uint16_t &h, uint16_t &wz, | |
uint16_t &hz, uint16_t &pan, uint16_t &tilt) { | |
uint8_t args[] = {0x0}; | |
if (!runCommand(VC0706_GET_ZOOM, args, sizeof(args), 16)) | |
return false; | |
printBuff(); | |
w = camerabuff[5]; | |
w <<= 8; | |
w |= camerabuff[6]; | |
h = camerabuff[7]; | |
h <<= 8; | |
h |= camerabuff[8]; | |
wz = camerabuff[9]; | |
wz <<= 8; | |
wz |= camerabuff[10]; | |
hz = camerabuff[11]; | |
hz <<= 8; | |
hz |= camerabuff[12]; | |
pan = camerabuff[13]; | |
pan <<= 8; | |
pan |= camerabuff[14]; | |
tilt = camerabuff[15]; | |
tilt <<= 8; | |
tilt |= camerabuff[16]; | |
return true; | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Send STOPCURRENTFRAME command | |
@returns True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::takePicture() { | |
frameptr = 0; | |
return cameraFrameBuffCtrl(VC0706_STOPCURRENTFRAME); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Send RESUMEFRAME command | |
@returns True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::resumeVideo() { | |
return cameraFrameBuffCtrl(VC0706_RESUMEFRAME); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief TV output ON | |
@returns True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::TVon() { | |
uint8_t args[] = {0x1, 0x1}; | |
return runCommand(VC0706_TVOUT_CTRL, args, sizeof(args), 5); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief TV output OFF | |
@returns True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::TVoff() { | |
uint8_t args[] = {0x1, 0x0}; | |
return runCommand(VC0706_TVOUT_CTRL, args, sizeof(args), 5); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Send FBUF_CTRL with command | |
@param command The FBUF control command (see datasheet) | |
@returns True on command success | |
*/ | |
/**************************************************************************/ | |
boolean Adafruit_VC0706::cameraFrameBuffCtrl(uint8_t command) { | |
uint8_t args[] = {0x1, command}; | |
return runCommand(VC0706_FBUF_CTRL, args, sizeof(args), 5); | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Get frame buffer length | |
@returns Length reply | |
*/ | |
/**************************************************************************/ | |
uint32_t Adafruit_VC0706::frameLength(void) { | |
uint8_t args[] = {0x01, 0x00}; | |
if (!runCommand(VC0706_GET_FBUF_LEN, args, sizeof(args), 9)) | |
return 0; | |
uint32_t len; | |
len = camerabuff[5]; | |
len <<= 8; | |
len |= camerabuff[6]; | |
len <<= 8; | |
len |= camerabuff[7]; | |
len <<= 8; | |
len |= camerabuff[8]; | |
return len; | |
} | |
/**************************************************************************/ | |
/*! | |
@brief Get available bytes to read | |
@returns Internal buffer length | |
*/ | |
/**************************************************************************/ | |
uint8_t Adafruit_VC0706::available(void) { return bufferLen; } | |
/**************************************************************************/ | |
/*! | |
@brief Read in picture data | |
@param n Number of bytes | |
@returns Pointer to buffer containing n bytes of picture data | |
*/ | |
/**************************************************************************/ | |
uint8_t *Adafruit_VC0706::readPicture(uint8_t n) { | |
uint8_t args[] = {0x0C, | |
0x0, | |
0x0A, | |
0, | |
0, | |
frameptr >> 8, | |
frameptr & 0xFF, | |
0, | |
0, | |
0, | |
n, | |
CAMERADELAY >> 8, | |
CAMERADELAY & 0xFF}; | |
if (!runCommand(VC0706_READ_FBUF, args, sizeof(args), 5, false)) | |
return 0; | |
// read into the buffer PACKETLEN! | |
if (readResponse(n + 5, CAMERADELAY) == 0) | |
return 0; | |
frameptr += n; | |
return camerabuff; | |
} | |
/**************** low level commands */ | |
boolean Adafruit_VC0706::runCommand(uint8_t cmd, uint8_t *args, uint8_t argn, | |
uint8_t resplen, boolean flushflag) { | |
// flush out anything in the buffer? | |
if (flushflag) { | |
readResponse(100, 10); | |
} | |
sendCommand(cmd, args, argn); | |
if (readResponse(resplen, 200) != resplen) | |
return false; | |
if (!verifyResponse(cmd)) | |
return false; | |
return true; | |
} | |
void Adafruit_VC0706::sendCommand(uint8_t cmd, uint8_t args[] = 0, | |
uint8_t argn = 0) { | |
#if defined(__AVR__) || defined(ESP8266) | |
if (swSerial) { | |
swSerial->write((byte)0x56); | |
swSerial->write((byte)serialNum); | |
swSerial->write((byte)cmd); | |
for (uint8_t i = 0; i < argn; i++) { | |
swSerial->write((byte)args[i]); | |
// Serial.print(" 0x"); | |
// Serial.print(args[i], HEX); | |
} | |
} else | |
#endif | |
{ | |
hwSerial->write((byte)0x56); | |
hwSerial->write((byte)serialNum); | |
hwSerial->write((byte)cmd); | |
for (uint8_t i = 0; i < argn; i++) { | |
hwSerial->write((byte)args[i]); | |
// Serial.print(" 0x"); | |
// Serial.print(args[i], HEX); | |
} | |
} | |
// Serial.println(); | |
} | |
uint8_t Adafruit_VC0706::readResponse(uint8_t numbytes, uint8_t timeout) { | |
uint8_t counter = 0; | |
bufferLen = 0; | |
int avail; | |
memset(camerabuff, 0, CAMERABUFFSIZ+1); | |
while ((timeout != counter) && (bufferLen != numbytes)) { | |
#if defined(__AVR__) || defined(ESP8266) | |
avail = swSerial ? swSerial->available() : hwSerial->available(); | |
#else | |
avail = hwSerial->available(); | |
//Serial.println(avail); | |
#endif | |
if (avail <= 0) { | |
delay(1); | |
counter++; | |
continue; | |
} | |
counter = 0; | |
// there's a byte! | |
#if defined(__AVR__) || defined(ESP8266) | |
camerabuff[bufferLen++] = swSerial ? swSerial->read() : hwSerial->read(); | |
#else | |
camerabuff[bufferLen++] = hwSerial->read(); | |
#endif | |
} | |
if (bufferLen != numbytes) { | |
Serial.println("timed out buffer not full!"); | |
Serial.println(bufferLen); | |
Serial.println(numbytes); | |
} | |
/* printBuff(); | |
// camerabuff[bufferLen] = 0; | |
Serial.println("buffer:"); | |
Serial.println((char*)camerabuff); | |
Serial.println("########"); | |
Serial.println(bufferLen); | |
*/ | |
return bufferLen; | |
} | |
boolean Adafruit_VC0706::verifyResponse(uint8_t command) { | |
if ((camerabuff[0] != 0x76) || (camerabuff[1] != serialNum) || | |
(camerabuff[2] != command) || (camerabuff[3] != 0x0)) | |
return false; | |
return true; | |
} | |
void Adafruit_VC0706::printBuff() { | |
for (uint8_t i = 0; i < bufferLen; i++) { | |
Serial.print(" 0x"); | |
Serial.print(camerabuff[i], HEX); | |
} | |
Serial.println(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*************************************************** | |
This is a library for the Adafruit TTL JPEG Camera (VC0706 chipset) | |
Pick one up today in the adafruit shop! | |
------> http://www.adafruit.com/products/397 | |
These displays use Serial to communicate, 2 pins are required to interface | |
Adafruit invests time and resources providing this open source code, | |
please support Adafruit and open-source hardware by purchasing | |
products from Adafruit! | |
Written by Limor Fried/Ladyada for Adafruit Industries. | |
BSD license, all text above must be included in any redistribution | |
****************************************************/ | |
#include <Arduino.h> | |
#if defined(__AVR__) || defined(ESP8266) | |
#include <SoftwareSerial.h> | |
#endif | |
#define VC0706_RESET 0x26 | |
#define VC0706_GEN_VERSION 0x11 | |
#define VC0706_SET_PORT 0x24 | |
#define VC0706_READ_FBUF 0x32 | |
#define VC0706_GET_FBUF_LEN 0x34 | |
#define VC0706_FBUF_CTRL 0x36 | |
#define VC0706_DOWNSIZE_CTRL 0x54 | |
#define VC0706_DOWNSIZE_STATUS 0x55 | |
#define VC0706_READ_DATA 0x30 | |
#define VC0706_WRITE_DATA 0x31 | |
#define VC0706_COMM_MOTION_CTRL 0x37 | |
#define VC0706_COMM_MOTION_STATUS 0x38 | |
#define VC0706_COMM_MOTION_DETECTED 0x39 | |
#define VC0706_MOTION_CTRL 0x42 | |
#define VC0706_MOTION_STATUS 0x43 | |
#define VC0706_TVOUT_CTRL 0x44 | |
#define VC0706_OSD_ADD_CHAR 0x45 | |
#define VC0706_STOPCURRENTFRAME 0x0 | |
#define VC0706_STOPNEXTFRAME 0x1 | |
#define VC0706_RESUMEFRAME 0x3 | |
#define VC0706_STEPFRAME 0x2 | |
#define VC0706_640x480 0x00 | |
#define VC0706_320x240 0x11 | |
#define VC0706_160x120 0x22 | |
#define VC0706_MOTIONCONTROL 0x0 | |
#define VC0706_UARTMOTION 0x01 | |
#define VC0706_ACTIVATEMOTION 0x01 | |
#define VC0706_SET_ZOOM 0x52 | |
#define VC0706_GET_ZOOM 0x53 | |
#define CAMERABUFFSIZ 100 | |
#define CAMERADELAY 32 | |
/**************************************************************************/ | |
/*! | |
@brief Class for communicating with VC0706 cameras | |
*/ | |
/**************************************************************************/ | |
class Adafruit_VC0706 { | |
public: | |
#if defined(__AVR__) || defined(ESP8266) | |
Adafruit_VC0706(SoftwareSerial *ser); // Constructor when using SoftwareSerial | |
#endif | |
Adafruit_VC0706(HardwareSerial *ser); // Constructor when using HardwareSerial | |
boolean begin(uint32_t baud = 38400); | |
boolean reset(void); | |
boolean TVon(void); | |
boolean TVoff(void); | |
boolean takePicture(void); | |
uint8_t *readPicture(uint8_t n); | |
boolean resumeVideo(void); | |
uint32_t frameLength(void); | |
char *getVersion(void); | |
uint8_t available(); | |
uint8_t getDownsize(void); | |
boolean setDownsize(uint8_t); | |
uint8_t getImageSize(); | |
boolean setImageSize(uint8_t); | |
boolean getMotionDetect(); | |
uint8_t getMotionStatus(uint8_t); | |
boolean motionDetected(); | |
boolean setMotionDetect(boolean f); | |
boolean setMotionStatus(uint8_t x, uint8_t d1, uint8_t d2); | |
boolean cameraFrameBuffCtrl(uint8_t command); | |
uint8_t getCompression(); | |
boolean setCompression(uint8_t c); | |
boolean getPTZ(uint16_t &w, uint16_t &h, uint16_t &wz, uint16_t &hz, | |
uint16_t &pan, uint16_t &tilt); | |
boolean setPTZ(uint16_t wz, uint16_t hz, uint16_t pan, uint16_t tilt); | |
void OSD(uint8_t x, uint8_t y, char *s); // isnt supported by the chip :( | |
char *setBaud9600(); | |
char *setBaud19200(); | |
char *setBaud38400(); | |
char *setBaud57600(); | |
char *setBaud115200(); | |
private: | |
uint8_t serialNum; | |
uint8_t camerabuff[CAMERABUFFSIZ + 1]; | |
uint8_t bufferLen; | |
uint16_t frameptr; | |
#if defined(__AVR__) || defined(ESP8266) | |
SoftwareSerial *swSerial; | |
#endif | |
HardwareSerial *hwSerial; | |
void common_init(void); | |
boolean runCommand(uint8_t cmd, uint8_t args[], uint8_t argn, uint8_t resp, | |
boolean flushflag = true); | |
void sendCommand(uint8_t cmd, uint8_t args[], uint8_t argn); | |
uint8_t readResponse(uint8_t numbytes, uint8_t timeout); | |
boolean verifyResponse(uint8_t command); | |
void printBuff(void); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <WiFi.h> | |
#include <Wire.h> | |
#include <Arduino.h> | |
#include <Adafruit_VC0706.h> | |
#include <SPI.h> | |
#define LED_PIN A0 | |
#define CameraConnection Serial1 | |
static void connectToWiFi(const char * ssid, const char * pwd); | |
static void cameraInit(); | |
static int uploadPicture(); | |
static char outbuffer[1024]; | |
const char *ssid = "<%= @config[:ssid] %>"; | |
const char *pass = "<%= @config[:pass] %>"; | |
Adafruit_VC0706 cam = Adafruit_VC0706(&CameraConnection); | |
void setup() { | |
Serial.begin(115200); | |
Serial.println(F("Booting")); | |
pinMode(LED_PIN, OUTPUT); | |
connectToWiFi(ssid, pass); | |
cameraInit(); | |
Serial.println("Snap in 3 secs..."); | |
delay(3000); | |
uploadPicture(); | |
cam.setMotionDetect(true); // turn it on | |
// You can also verify whether motion detection is active! | |
Serial.print("Motion detection is "); | |
if (cam.getMotionDetect()) | |
Serial.println("ON"); | |
else | |
Serial.println("OFF"); | |
} | |
void loop() { | |
if (cam.motionDetected()) { | |
digitalWrite(LED_PIN, HIGH); | |
Serial.println("Motion!"); | |
cam.setMotionDetect(false); | |
delay(8000); | |
// uploadPicture(); | |
cam.resumeVideo(); | |
cam.setMotionDetect(true); | |
digitalWrite(LED_PIN, LOW); | |
} else { | |
digitalWrite(LED_PIN, HIGH); | |
delay(500); | |
digitalWrite(LED_PIN, LOW); | |
delay(500); | |
} | |
} | |
void connectToWiFi(const char * ssid, const char * pwd) { | |
int ledState = 0; | |
Serial.println("Connecting to WiFi network: " + String(ssid)); | |
WiFi.begin(ssid, pwd); | |
while (WiFi.status() != WL_CONNECTED) { | |
// LED_PIN LED while we're connecting: | |
digitalWrite(LED_PIN, ledState); | |
ledState = (ledState + 1) % 2; // Flip ledState | |
delay(500); | |
Serial.print("."); | |
} | |
Serial.println(); | |
Serial.println("WiFi connected!"); | |
Serial.print("IP address: "); | |
Serial.println(WiFi.localIP()); | |
} | |
static void cameraInit() { | |
Serial.println("VC0706 Camera Init"); | |
// Try to locate the camera | |
if (cam.begin()) { // 2400)) {//115200)) { | |
Serial.println("Camera Found:"); | |
} else { | |
digitalWrite(LED_PIN, HIGH); | |
while(!cam.begin()) { | |
Serial.println("No camera found?"); | |
delay(1000); | |
} | |
return; | |
} | |
// Print out the camera version information (optional) | |
char *reply = cam.getVersion(); | |
if (reply == 0) { | |
Serial.print("Failed to get version"); | |
} else { | |
Serial.println("-----------------"); | |
Serial.print(reply); | |
Serial.println("-----------------"); | |
} | |
// Set the picture size - you can choose one of 640x480, 320x240 or 160x120 | |
// Remember that bigger pictures take longer to transmit! | |
// cam.setImageSize(VC0706_640x480); // biggest | |
// cam.setImageSize(VC0706_320x240); // medium | |
cam.setImageSize(VC0706_160x120); // small | |
// You can read the size back from the camera (optional, but maybe useful?) | |
uint8_t imgsize = cam.getImageSize(); | |
Serial.print("Image size: "); | |
if (imgsize == VC0706_640x480) Serial.println("640x480"); | |
if (imgsize == VC0706_320x240) Serial.println("320x240"); | |
if (imgsize == VC0706_160x120) Serial.println("160x120"); | |
} | |
int uploadPicture() { | |
WiFiClient client; | |
int32_t time = millis(); | |
if (!client.connect("<%= @config[:events][:host] %>", <%= @config[:events][:port] %>)) { | |
Serial.println(F("Connection error to <%= @config[:events][:host] %>:<%= @config[:events][:port] %>")); | |
return -2; | |
} | |
Serial.println("connected starting read and upload"); | |
if (!cam.takePicture()) { | |
Serial.println("Failed to snap!"); | |
client.stop(); | |
return -1; // error | |
} else { | |
Serial.println("Picture taken!"); | |
} | |
uint16_t jpglen = cam.frameLength(); | |
if (jpglen == 0 ) { //0 kb | |
Serial.println(F("Size is 0.")); | |
client.stop(); | |
return -3; | |
} | |
Serial.println("doing the POST headers"); | |
/* | |
POST /capture HTTP/1.1 | |
Host: 192.168.2.120 | |
Connection: close | |
Content-Type: image/jpeg | |
Content-Length: 48764 | |
tcp_write: arg == NULL (programmer violates API) | |
[E][WiFiClient.cpp:392] write(): fail on fd 54, errno: 5, "I/O error" | |
done! | |
94 ms elapsed | |
*/ | |
client.setNoDelay(true); | |
client.setTimeout(64); | |
snprintf(outbuffer, 1024, "POST /capture HTTP/1.1\r\nHost: <%= @config[:events][:host] %>\r\nConnection: close\r\nContent-Type: image/jpeg\r\nContent-Length: %d\r\n\r\n", jpglen); | |
client.write(outbuffer); | |
Serial.write(outbuffer); | |
byte count = 0; // For counting # of writes | |
while (jpglen > 0 && client.connected()) { | |
// read 32 bytes at a time; | |
const uint8_t bytesToRead = min((uint16_t)32, jpglen); // change 32 to 64 for a speedup but may not work with all setups! | |
const uint8_t *imgbuf = cam.readPicture(bytesToRead); | |
const uint8_t bytesAvailable = cam.available(); | |
// snprintf(outbuffer, 1024, "Uploading Bytes: %d of %d\n", bytesToRead, bytesAvailable); | |
// Serial.println(outbuffer); | |
if (bytesAvailable == 0) { | |
break; | |
} | |
Serial.println(bytesToRead - bytesAvailable); | |
const uint8_t bytesInBuffer = min(bytesAvailable, bytesToRead); | |
// we crash here when trying to access imgbuf | |
// Serial.printf("CamBytes: read %d bytes: %02x %02x %02x %02x %02x %02x %02x %02x\n",bytesToRead, | |
// imgbuf[0],imgbuf[1],imgbuf[2],imgbuf[3],imgbuf[4],imgbuf[5],imgbuf[6],imgbuf[7]); | |
// size_t write(const uint8_t *buf, size_t size); | |
const size_t sentBytes = client.write(imgbuf, bytesInBuffer); | |
if (sentBytes != bytesInBuffer) { | |
/* tcp_write: arg == NULL (programmer violates API) | |
[E][WiFiClient.cpp:392] write(): fail on fd 54, errno: 5, "I/O error" | |
*/ | |
snprintf(outbuffer, 1024, "Error bytes sent: %d != %d\n", sentBytes, bytesToRead); | |
Serial.println(outbuffer); | |
} | |
//imgFile.write(buffer, bytesToRead); | |
if (++count >= 64) { // Every 2K, give a little feedback so it doesn't appear locked up | |
Serial.print('.'); | |
count = 0; | |
} | |
// Serial.print("Read "); Serial.print(bytesToRead, DEC); Serial.println(" bytes"); | |
jpglen -= bytesInBuffer; | |
// delay(1); // pass control to network stack | |
} | |
//imgFile.close(); | |
time = millis() - time; | |
Serial.println("done!"); | |
Serial.print(time); Serial.println(" ms elapsed"); | |
Serial.println(); | |
Serial.println("closing connection"); | |
client.stop(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment