Having satisfied myself that my serial JPEG camera was working I have now implemented a fully working system that will detect cats (or any other warm blooded object), take a snapshot using the serial JPEG camera and save the image to a microSD card for later analysis.
The circuit diagram is show below and consist of a Nano connected to a microSD card adapter using the SPI bus, a PIR detector connected to D6 of the Nano and the serial JPEG camera connected via a software serial link using D2 and D3. There is also a 12V lead acid battery for all night operation with a 12V to 5V convertor (not shown) on the circuit diagram.
A video of the completed working system is given below. Unfortunately I was unable to install the Cat Detector Mk IV into the garden overnight before the deadline for this challenge as I skip I ordered for clearing the unwanted soil and rubble from my garden was delivered and I had to attend to that task.
So the only pictures I have are test ones of me waving my hand in front of the PIR detector and the subsequent snapshot saved to microSD. The picture is just of my laptop screen which was just what the camera happened to be pointing at. There is blurring because as I explained in my previous Blog when I was first testing the camera, I seem to somehow have embedded a previous image as some sort of 'watermark' into all subsequent images. One day I'll spend some time trying to get rid of this. Still it shows that it all works. I think the pictures will be quite good once the camera is setup properly, altohugh I'm not sure how well it will work at night.
Getting the serial JPEG camera to talk to the Nano proved to be troublesome for me. The documentation advises the use of a hardware serial communication port if one is available. As the Nano does have hardware serial (for connecting to the IDE and programming) I just somehow assumed it could also connect to the camera as well. But it cannot which I only realised in bed one day as I as despairing of ever getting it to all work together. As soon as I implemented a software serial port it worked fine.
One 'special' thing I did learn from this project, is that if you connect a 12V battery the wrong way round to the input of a 12V to 5V convertor, the convertor blows up! but not immediately. First it provides some crazy voltages on the output (I think this was -38V), then there is a loud bang and bits fly everywhere. Luckily I had a replacement but I think I will try to avoid doing that again.
Dubbie
The programme listing is given below. This is a modified version of a test programme for the serial JPEG camera provided by Adafruit. I have deleted some of the unnecessary statements and inserted some statements to use the PIR detector to trigger a snapshot and save to the microSD card.
/*
* Cat Detector Mk III
* Dubbie Dubbie 12th July'21
* Just for Fun
*
* Uses a Nano, Adafruit mini serial JPEG camera and a micro-SD
* breakout board.
* Adafruit MotionDetect software used as a starting point, heavily
* amended.
*
*/
#include <Adafruit_VC0706.h>
#include <SPI.h>
#include <SD.h>
// camera TX connected to pin 2, camera RX to pin 3:
#include <SoftwareSerial.h>
SoftwareSerial cameraconnection(2, 3);
// Pass serial info to camera software
Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);
// SD card chip select line
#define chipSelect 10
#define PIR 6
void setup()
{
Serial.begin(9600);
Serial.println("Cat Detector Mk III");
Serial.println("Dubbie Dubbie ");
Serial.println("12th July'21");
Serial.println("Just For Fun");
Serial.println();
pinMode(LED_BUILTIN, OUTPUT);
pinMode(PIR, INPUT);
// Setup the micro SD card adapter
if (!SD.begin(chipSelect))
{
Serial.println("Micro SD Not Working ");
while (1) { /* Wait here forever */}
}
else
{
Serial.println("Micro SD Working ");
} /* if */
// Start the camera
if (cam.begin())
{
Serial.println("Camera Started ");
}
else
{
Serial.println("Camera Not Started ");
while (1) { /* Wait here forever */}
} /* if */
delay(1000); /* Needs a delay here to ensure camera is working */
}
// Select image size (VC0706_640x480, VC0706_320x240 or VC0706_160x120)
cam.setImageSize(VC0706_640x480); // medium
// Check the image size is selected correctly
uint8_t imgsize = cam.getImageSize();
Serial.print("Image size: ");
switch(imgsize)
{
case VC0706_640x480 : Serial.println("640x480"); break;
case VC0706_320x240 : Serial.println("320x240"); break;
case VC0706_160x120 : Serial.println("160x120"); break;
default : Serial.println("Unknown Image Size ");
} /* switch */
// Motion detection system can alert you when the camera 'sees' motion!
cam.setMotionDetect(true); // turn it on
//cam.setMotionDetect(false); // turn it off (default)
// Check motion detection
Serial.print("Motion detection is ");
if (cam.getMotionDetect())
Serial.println("ON");
else
Serial.println("OFF");
} /* setup */
void loop()
{
int PIRvalue;
PIRvalue = 0;
PIRvalue = digitalRead(PIR);
while (PIRvalue == 0 )
{
Serial.println("PIR Low ");
delay(1000);
PIRvalue = digitalRead(PIR);
} /* while */
if (PIRvalue == 0)
Serial.println("Pir Low ");
else
Serial.println("PIR High ");
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000);
// if (cam.motionDetected())
{
Serial.println("PIR Motion Detected ");
// cam.setMotionDetect(false);
// Be aware that taking a picture stops the video until 'resumed'.
if (! cam.takePicture())
Serial.println("Failed to take picture!");
else
Serial.println("Picture taken!");
// Use 8.3 filenames, case insensitive
char filename[13];
strcpy(filename, "IMAGE00.JPG");
for (int i = 0; i < 100; i++)
{
filename[5] = '0' + i/10;
filename[6] = '0' + i%10;
// create if does not exist, do not open existing, write, sync after write
if (! SD.exists(filename))
{
break;
} /* if */
} /* for */
File imgFile = SD.open(filename, FILE_WRITE);
uint16_t jpglen = cam.frameLength();
Serial.print(jpglen, DEC);
Serial.println(" byte image");
Serial.print("Writing image to ");
Serial.println(filename);
Serial.println();
while (jpglen > 0)
{
// read 32 bytes at a time;
uint8_t *buffer;
uint8_t bytesToRead = min((uint16_t)32, jpglen);
buffer = cam.readPicture(bytesToRead);
imgFile.write(buffer, bytesToRead);
jpglen -= bytesToRead;
} /* while */
imgFile.close();
Serial.println("Picture Saved");
cam.resumeVideo();
// cam.setMotionDetect(true);
} /* if */
} /* loop */