- makeITcircular 2024 content launched – Part of Maker Faire Rome 2024Posted 2 months ago
- Application For Maker Faire Rome 2024: Deadline June 20thPosted 4 months ago
- Building a 3D Digital Clock with ArduinoPosted 9 months ago
- Creating a controller for Minecraft with realistic body movements using ArduinoPosted 9 months ago
- Snowflake with ArduinoPosted 9 months ago
- Holographic Christmas TreePosted 10 months ago
- Segstick: Build Your Own Self-Balancing Vehicle in Just 2 Days with ArduinoPosted 10 months ago
- ZSWatch: An Open-Source Smartwatch Project Based on the Zephyr Operating SystemPosted 11 months ago
- What is IoT and which devices to usePosted 11 months ago
- Maker Faire Rome Unveils Thrilling “Padel Smash Future” Pavilion for Sports EnthusiastsPosted 12 months ago
An ARDUINO based JPEG Camera with IR and PIR
Let’s equip Arduino with a serial-interface JPEG Camera with IR and try two applications: the first one saves shots (on a SD-card) at regular intervals while the second uses a PIR sensor to detect intrusions and photograph what happens.
Recently, miniaturized cameras with serial communication interface have been launched on the market. Compared to traditional cameras, they offer easier integration with Arduino or other microcontroller-based boards.
It is quite easy to understand that using a composite or USB interface camera requires a considerable effort, on both hardware and software sides. If you decide to bet on a serial interface camera, everything gets easier, because all the prototyping boards (Arduino in particular) and all microcontrollers (Microchip, Atmel etc.) have at least one serial port as a standard feature.
The basic concept of these cameras is that you can send all the setup commands, take screenshots and viewing images through appropriate bytes sequences via their serial port.
In our case, we will use a LinkSprite camera connected to Arduino Uno. Special feature of this camera is the ability to capture images even at night; in fact, it has a brightness sensor and infrared LEDs activated automatically when the detected light falls below a certain threshold (refer to the pictures in these pages to get an idea of how infrared LEDs work).
The camera is capable of capturing high-resolution images, sending them as JPEG through the serial port. It has a four-pin connector where two pins are for the power supply (+ 5V and GND) and two for the serial port (RX and TX).
This article will show how to use this camera in two different Arduino projects: the first creates a timing system to take pictures on specific intervals, storing them on the SD-card, while the second is an automatic surveillance system activated only if the special PIR sensor (Passive Infrared Radar) detects a warm object moving in the camera view field. In practice, this second application is a time-lapse video surveillance device that records what happens in a room, activated by the detection of moving people or vehicles. Of course, the PIR detection area must match the same camera angle so that the captured images effectively show the triggering “foe”.
Images will be saved on a Sd-card in JPEG format file and therefore we need a dedicated Sd-card shield (available on Futura Elettronica).
Finally, we will use software libraries (JPEGCamera) developed by us specifically for these camera usage examples.
SYSTEM HARDWARE
About the first application, the hardware consists of an Arduino Uno Rev 3 and a SD-card shield used to save images, all connected to the serial camera. The SD shield has four jumpers allowing us to choose which Arduino pin works as “chip select” (you can choose between D4, D8, D9 and D10); for “chip select” we mean the command line that enables the shield.
In our examples, we use D4 therefore we have to insert the corresponding jumper.
The camera has a four-pin connector used for both power and serial interface, and is supplied with a four wires cable (colors: red, brown, purple and gray) ending with female jumpers. Please note that for the serial communication between Arduino and the camera we decided not to use the hardware serial port, but we use the software one (mapped on Arduino D2 and D3 pins); in this way, the software library keeps the hardware port free for debugging.
To connect Arduino to the camera you need to connect the red wire (RXD) to Arduino D3 pin; the brown (TXD) to D2; the gray to the + 5V signal and finally the violet to ground (GND).
For the second application, we must add the PIR sensor to the hardware just described. What we used for our prototype is a device with a certain “intelligence” on-board, which implements two different trigger modes, providing a programmable delay time (between the motion detection and the signal trigger ) ranging from 0.3 to 180 seconds, has a 120 ° detection angle and 7 meters maximum range. The sensor has three pins (TTL 0V – 3.3V output and positive-negative power supply). To connect Arduino you must create a three-wire cable where the power supply positive and negative pins must be connected to Arduino +5V and GND while the TTL output to Arduino D5 pin. Through the output, the device sends the trigger signal caused by PIR sensor movement detection.
ARDUINO LIBRARY
JPEGCamera
To allow Arduino managing the JPEG camera we have developed a library (JPEGCamera) that offers all the LinkSprite camera functions: initialization, screenshots capturing and saving images.
The library provides an object called JPEGCamera you can call for complete hardware management.
A Begin function initializes the entire camera management system, a Reset physically resets the camera, a setImageSize sets the captured image size (you can choose between 160 x 120, 320 x 280 and 640 x 480 pixels). Then there is the takePicture function , who commands the camera to capture the image currently framed (basically is the take screenshot function) and readJpegFileSize, which reads the size (in bytes) of the image file stored. Other functions include the readJpegFileContent, which deals with reading (a packet at a time) the image data and finally stopTakingPictures, which stops the screenshots capture.
The readJpegFileContent function deserves a special mention: the data reading process works with a packet (64 bytes, in our case) at a time. To do this it is necessary, each time you call the procedure, to indicate the starting address (the first time is equal to 0, the second 64, the third 128 and so on) and the packet size to be read (in our case, always 64; please note that it is not possible to exceed that value). The function requires as input a byte array where data will be saved; also returns the iSend output parameter, which indicates if the reading operation has been completed.
SKETCH EXAMPLE 1
Starting from the beginning, we analyze the first JPEG camera example code, the continuous saving images application (Listing 1).
We include the necessary libraries (JPEGCamera.h, SoftwareSerial.h – since we will use a software serial interface – and SD.h, to save images on the SD-card) and define the size (in bytes) of a single data packet stored (chunk_size; 64 bytes).
Subsequently we define the Arduino pin (D4) we will use as SD-card chip select and some variables that we will use in the program (in particular jpegCamera, used for camera management). Inside the setup function we initialize the board and we call the camera begin command; later we initialize the SD library indicating that we want to use D4 pin as chip select.
In the loop function, we manage the real images capture and saving; first we set to capture 320 x 280 pixels pictures and through jpegCamera.takePicture we start capturing the single screenshot.
Afterwards we can define the “save as” filename (e.g. imageXX.jpg where XX ranges from 00 to 99) and through SD.open we can create and open the file in writing mode on the SD-card. Then, through a while loop we handle the image reading and saving process. With jpegCamera.readJpegFileContent we read one jpeg data packet at a time and we can save it by using the File object write function.
When the while loop ends, all the picture bytes have been read and saved; then we execute the File object close function to close the file handler and jpegCamera.stopTakingPictures to tell the camera to stop capturing images.
Before ending the loop, let’s wait one second and increase the variable that counts the number of pictures taken.
/********************************************************************* * Inclusione librerie * *********************************************************************/ #include <JPEGCamera.h> #include “SoftwareSerial.h” #include <SD.h> // Chunk size per salvataggio immagine #define CHUNK_SIZE 64 /********************************************************************* * Definizione pin I/O Arduino * *********************************************************************/ // Led scheda Arduino const int pinBoardLed = 13; // Pin Arduino Chip Select SD const int pinSDChipSelect = 4; /********************************************************************* * Variabili programma * *********************************************************************/ // Oggetto JPEG Camera JPEGCamera jpegCamera; // JPEG file File jpegFile; // Contatore immagine byte i = 0; /********************************************************************* * Codice programma * *********************************************************************/ // Inizializzazione Scheda void setup() { // Inizializzo I/O pinMode(pinBoardLed, OUTPUT); pinMode(pinSDChipSelect, OUTPUT); // Accendo led Arduino digitalWrite(pinBoardLed, HIGH); // Inizializzo JPEG Camera jpegCamera.begin(); // Init SD pinMode(10, OUTPUT); if (!SD.begin(pinSDChipSelect)) { // Lampeggio led Arduino for (;;) { digitalWrite(pinBoardLed, HIGH); delay(500); digitalWrite(pinBoardLed, LOW); delay(500); } } // Spengo led Arduino digitalWrite(pinBoardLed, LOW); } // Chiusura funzione setup // Programma Principale void loop() { boolean isEnd = false; uint16_t address = 0x0000; uint16_t chunkSize = CHUNK_SIZE; byte body[CHUNK_SIZE]; // Imposto dimensione immagine jpegCamera.setImageSize(jpegCamera.ImageSize320x280); // Reset JPEG Camera jpegCamera.reset(); // Scatto immagine jpegCamera.takePicture(); // Identifico nome file char fileName[12] = “image00.jpg”; fileName[5] = ((i / 10) + 0x30); fileName[6] = ((i % 10) + 0x30); // Apro file jpegFile = SD.open(fileName, FILE_WRITE); // Leggo/salvo i dati immagine isEnd = false; while(isEnd == false) { jpegCamera.readJpegFileContent(address, chunkSize, body, &isEnd); address += chunkSize; // Salvo i dati sul file jpegFile.write(body, chunkSize); } // Chiudo file jpegFile.close(); // Fermo immagine jpegCamera.stopTakingPictures(); // Attesa delay(1000); // Prossimo file i = ((i + 1) % 100); } // Chiusura funzione loop
SKETCH EXAMPLE 2
The second example, besides implementing the functions explained in the previous example, manages a PIR sensor too and therefore can be used as an anti-intrusion detection system prototype.
The algorithm works as follows: cyclically Arduino saves images (max. 5 – image01.jpg, …, image05.jpg – overwriting the oldest cyclically) in a SD-card folder (DIR000, …., DIR999); when it detects an alarm condition the cyclical saving process continues but changing the filename to image06.jpg, …., image10.jpg and increasing the folder name number. Then, everything goes on as before.
The first lines of this software are the same as the previous sketch (libraries inclusion, saving process, Arduino pins definition and variables declaration).
The setup function is similar to that in Listing 1, modified to identify the first free directory (the folder number is indicated by the dirCount variable). Even the loop cycle is quite similar to the previous example; different parts are needed to handle the different folder and file naming during intrusion detection.
In addition, the last function commands added, check if there is an alarm signal coming from the PIR sensor: if yes, the file saving mechanism explained above is executed.
The sketch of the application is in Listing 2.
/****************************************************************************** * Inclusione librerie * ******************************************************************************/ #include <JPEGCamera.h> #include “SoftwareSerial.h” #include <SD.h> // Chunk size per salvataggio immagine #define CHUNK_SIZE 64 /****************************************************************************** * Definizione pin I/O Arduino * ******************************************************************************/ // Led scheda Arduino const int pinBoardLed = 13; // Pin Arduino Chip Select SD const int pinSDChipSelect = 4; // Sensore PIR scheda Arduino const int pinPIRSensor = 5; /****************************************************************************** * Variabili programma * ******************************************************************************/ // Oggetto JPEG Camera JPEGCamera jpegCamera; // JPEG file File jpegFile; // Contatore directory int dirCount = 0; // Contatore immagine byte fileCount = 1; boolean flagSensorePIR = false; /****************************************************************************** * Codice programma * ******************************************************************************/ // Inizializzazione Scheda void setup() { // Inizializzo I/O pinMode(pinBoardLed, OUTPUT); pinMode(pinSDChipSelect, OUTPUT); pinMode(pinPIRSensor, INPUT); // Accendo led Arduino digitalWrite(pinBoardLed, HIGH); // Inizializzo JPEG Camera jpegCamera.begin(); // Init SD pinMode(10, OUTPUT); if (!SD.begin(pinSDChipSelect)) { // Lampeggio led Arduino for (;;) { digitalWrite(pinBoardLed, HIGH); delay(500); digitalWrite(pinBoardLed, LOW); delay(500); } } // Identifico prima directory libera for (;;) { char dirName[7] = “DIR000”; dirName[3] = ((dirCount / 100) + 0x30); dirName[4] = (((dirCount % 100) / 10) + 0x30); dirName[5] = ((dirCount % 10) + 0x30); // Se directory non esiste if (SD.exists(dirName) == false) break; // Prossima directory dirCount++; } // Spengo led Arduino digitalWrite(pinBoardLed, LOW); } // Chiusura funzione setup // Programma Principale void loop() { boolean isEnd = false; uint16_t address = 0x0000; uint16_t chunkSize = CHUNK_SIZE; byte body[CHUNK_SIZE]; // Imposto dimensione immagine jpegCamera.setImageSize(jpegCamera.ImageSize320x280); // Reset JPEG Camera jpegCamera.reset(); // Scatto immagine jpegCamera.takePicture(); // Identifico prima directory libera char dirName[7] = “DIR000”; dirName[3] = ((dirCount / 100) + 0x30); dirName[4] = (((dirCount % 100) / 10) + 0x30); dirName[5] = ((dirCount % 10) + 0x30); // Se directory non esiste if (SD.exists(dirName) == false) // Creo directory SD.mkdir(dirName); // Identifico nome file char pathComplete[22] = “DIR000/image00.jpg”; pathComplete[3] = ((dirCount / 100) + 0x30); pathComplete[4] = (((dirCount % 100) / 10) + 0x30); pathComplete[5] = ((dirCount % 10) + 0x30); pathComplete[12] = ((fileCount / 10) + 0x30); pathComplete[13] = ((fileCount % 10) + 0x30); // Apro file jpegFile = SD.open(pathComplete, FILE_WRITE); // Leggo/salvo i dati immagine isEnd = false; while(isEnd == false) { jpegCamera.readJpegFileContent(address, chunkSize, body, &isEnd); address += chunkSize; // Salvo i dati sul file jpegFile.write(body, chunkSize); // Se sensore PIR non rilevato if (flagSensorePIR == false) { // Se sensore PIR attivo if (digitalRead(pinPIRSensor) == HIGH) { // Prossimo file è il 6 (verrà incrementato in seguito) fileCount = 5; flagSensorePIR = true; } } } // Chiudo file jpegFile.close(); // Fermo immagine jpegCamera.stopTakingPictures(); // Attesa delay(100); // Se sensore PIR non rilevato if (flagSensorePIR == false) { // Se sensore PIR attivo if (digitalRead(pinPIRSensor) == HIGH) { // Prossimo file è il 6 fileCount = 6; flagSensorePIR = true; } // Se sensore PIR non attivo else { // Prossimo file number if (fileCount == 5) fileCount = 1; else fileCount++; } } // Se sensore PIR rilevato else { // Se salvati 5 file if (fileCount == 10) { // Resetto file fileCount = 1; // Prossima directory dirCount++; // Indico reset PIR flagSensorePIR = false; } else fileCount++; } } // Chiusura funzione loop
From store
JPEG Color Camera Serial Interface
Pingback: 2cartridges