There are plenty of commercially-available time-lapse photography devices. These require either an AC power source, a solar panel or a beefy battery, expensive photography equipment, and are large and easy to spot. Between the size and the expense, this strongly limits the duration of time lapse I would be able to take even if such a device wasn't prone to being stolen by the first philistine that came across it. My goal is to make the smallest, most energy efficient and least expensive camera possible so that I am free to set them everywhere and see what the passage of time shows me.
To do this, I decided to give ArduCam a try.
Actually, I found ArduCam pretty disappointing and difficult to use for a few reasons:
- The open source libraries don't use any modern version control system like GitHub. They're just a few files. What's more, they fail to compile under Linux without changing the
#include
statements to correct for case-sensitivity. - While the ArduCam website shows full-resolution images pulled from "supported" camera modules, the ArduCam Rev. B shield is unable to take bitmap images greater than 320 by 240 pixels because it has only a 3 megabit buffer. For cameras with on-board JPEG compression it is able to take higher-resolution images, but they come out looking fuzzier than a Georgia peach because they must be made to fit in the buffer. If these images were indeed taken with an ArduCam shield, they weren't done with any code made available on their website.
- The first "supported" camera I bought, the MT9D111, failed to take any worthwhile picture at any resolution. I was only able to get it working with the OV2640 module.
Sample image taken with the "supported" MT9D111 camera using an example from the open-source ArduCam code. |
So, the ArduCam was a bit of a let-down. It is actually pretty impressive that someone figured out how to hack together a camera that interfaces with an Arduino, but it's not particularly useful. The image size is pathetically small and the power draw is substantial (I'm able to take about 370 images on 4 AA batteries). It may be useful for some applications, but quality time-lapse photography is not going to be one of them.
Let's take a look at my camera, my code, and the results.
My ArduCam
My camera uses the following components:
- Arduino Uno Rev. 3
- ArduCam Rev. B Shield
- OV2640 Camera Module
- 2GB MicroSD Card
- 4 AA batteries
Assembly is positively trivial. Everything just fits together. Build time is under a minute.
Note that while the ArduCam board can be made to work with the Arduino Mega, it requires some rewiring because the pinouts are not exactly the same. The power efficiency could have been improved somewhat with a DC step-down buck converter, but I decided against doing this because even if the power efficiency was greater the image resolution was unacceptable.
Note that while the ArduCam board can be made to work with the Arduino Mega, it requires some rewiring because the pinouts are not exactly the same. The power efficiency could have been improved somewhat with a DC step-down buck converter, but I decided against doing this because even if the power efficiency was greater the image resolution was unacceptable.
The first iteration of my code simply took a picture, then waited a minute using
Overall, this was an enlightening exercise but it's clear that if I want a very long-term and reasonably high-quality time lapse photo solution, the platform for that is not going to be ArduCam.
delay
before taking another, repeating until the camera ran out of battery. This managed to take 364 bitmap images until it ran out of juice. The second iteration of my code made use of the Sleep_n0m1 library to place the Arduino in sleep mode and wake it up each minute. I had hoped that this would improve battery life substantially, but instead it managed only to take 370 images before running out of battery.
I assembled the time-lapse photos into a video using the following command with
avconv
on Linux:avconv -f image2 -i %08d.BMP output.avi
Overall, this was an enlightening exercise but it's clear that if I want a very long-term and reasonably high-quality time lapse photo solution, the platform for that is not going to be ArduCam.
Hi Ben I have a question , can the arducam be used for object detection .
ReplyDeleteFor example , detecting a black ball on a white plane in less than 0.5 seconds.
Or do I have to wait 10 seconds for each image i obtain?
Thank You
Yes, it could.
DeleteIf you look at my timelapse_2.ino code, the time it takes to grab the picture is on the order of 10ms. Reading from the FIFO is quite fast. The majority of the time spent taking a picture in my code is the time it takes to save it it to the SD card. If you were only scanning through the FIFO and somehow keeping track of the dark pixels versus the light pixels in memory instead of saving the picture, you would certainly be able to detect your ball faster than 0.5s.
Hi Ben,
ReplyDeletegreat job! I bought my stuff and tried to upload your sketch (timelapse_2.ino). However, I get the following when trying to upload it.
timelapse_2.ino: In function 'void loop()':
timelapse_2:117: error: 'class ArduCAM' has no member named 'enable_fifo'
timelapse_2:134: error: 'class ArduCAM' has no member named 'disable_fifo'
Can you help me out?Thanks.
-Fil
Hi again,
ReplyDeleteI got it... I've downloaded newest v3.0.0 (arducam http://www.arducam.com/download/) instead of v2.0. Also works with v2.1 but not with v1.3 (=>ArduCam Rev. B Shield).
- Fil
hy
ReplyDeletei also bought a arducam with an lcd and now i am a bit angry about me that i didnt inform me more... the open source is not so open as i thought and i am used to arduino.
as i can see rev.c. "only" needs "7" ports and spi+vcc+ground+reset
so did you test acces the remaining I/O pins ?
so far i read that pins: 9,19,A4,A5,6 from the spi port and the standart 5v and gnd io
thx for answers
I did not do any testing regarding which pins are actually used by the shield--but I'm looking and seeing that he's done two new releases of his code since I wrote this. I'll have to try again and see if it can actually capture high quality images now!
DeleteThis comment has been removed by the author.
Deleteok - cause that would be very interresting - it would make acces more easier than always adress a register and check with a mask ... etc. etc... ^^
Deleteyep i´ve here revision "C" ...so in other words version 3.0.
higher quality cams are available and the point you mentioned - low power - also included in the examples
but for further question the producer of this product is not very communicative... sadly
in particular i dont get the shield capture automatically i simply tried it like you just with delay and only comment out the query which checks the trigger register
but if i do so for whatever reason it doesnt store the image... the trigger register with the capture done mask - so the capture done flag seems not to go on HIGH
would be great if you see some other solutions for that - normally - simple taks ... :)
ok i just got it to save pictures but ... the result.... i just ad a manuall delay for 12s between start capture and store it, .. but as there is no further information about it it seems the fifo reading and saving is full of errors with that clumsy solution
Deletei got wrinkels and shifted images
normally i thought a delay is not necessary but as the modul with a manual trigger also waits a few seconds i implemented that ... seems the right direction but also wrong in some kind ... :( :(
i miss a datasheet like it normla for electronic parts (except cheap clones from china)
so i realy look forward if you find the "master trick" :)
ugh i miss an "edit" function here:
Deleteadditional question:
do you know how to manage the thumbnail for bmp ?
this is also not correct it stores somewhere a very old thumbnail made with the shield and puts that on newer stored photos ...
arducam is realy not an easy solution ^^
Hello
DeleteI am attempting to capture photos at 5 minute intervals without using the shutter button. It is using jpeg output and it seems like anything above 1 minute intervals are not working. I wondered if you or anyone has a solution to my issue?
Here is my code
#include
#include
#include
#include
#include
#if defined(__arm__)
#include
#endif
#define SD_CS 9
// set pin 10 as the slave select for SPI:
const int slaveSelectPin = 10;
ArduCAM myCAM(OV5642,10);
UTFT myGLCD(slaveSelectPin);
void setup()
{
#if defined (__AVR__)
Wire.begin();
#endif
#if defined(__arm__)
Wire1.begin();
#endif
Serial.begin(115200);
Serial.println("hello");
// set the slaveSelectPin as an output:
pinMode(slaveSelectPin, OUTPUT);
// initialize SPI:
SPI.begin();
myCAM.write_reg(ARDUCHIP_MODE, 0x00);
myGLCD.InitLCD();
myCAM.set_format(JPEG);
myCAM.InitCAM();
myCAM.write_reg(ARDUCHIP_TIM, VSYNC_LEVEL_MASK); //VSYNC is active HIGH
//Initialize SD Card
if (!SD.begin(SD_CS))
{
//while (1); //If failed, stop here
}
}
void loop()
{
char str[8];
File outFile;
static int k = 0;
static int n = 0;
uint8_t temp,temp_last;
//Flush the FIFO
myCAM.flush_fifo();
//Clear the capture done flag
myCAM.clear_fifo_flag();
//Start capture
myCAM.start_capture();
// Wait for the capture to finish.
while (!(myCAM.read_reg(ARDUCHIP_TRIG) & CAP_DONE_MASK)) {
delay(10);
}
//Construct a file name
k = k + 1;
itoa(k, str, 10);
strcat(str,".jpg");
//Open the new file
outFile = SD.open(str,FILE_WRITE);
if (! outFile)
{
return;
}
//Read JPEG data from FIFO
while( (temp != 0xD9) | (temp_last != 0xFF) )
{
temp_last = temp;
temp = myCAM.read_fifo();
//Write image data to file
outFile.write(temp);
}
//Close the file
outFile.close();
//Clear the capture done flag
myCAM.clear_fifo_flag();
delay(60000);
}
Hi Jim--
DeleteI'd expect it to work fine at longer intervals, because generally the limiting factor seems to be the transfer time between the ArduCAM and the SD card. You could try using my code from this post and see if that works for you.
Just one suggestion. I don't think this is actually the problem, but try changing your delay there at the end to delay(65535) and see if it works. Then, change it to delay(65536) and see if it works. Even though delay supposedly takes an unsigned long, I wonder if there's a bug somewhere whereby argument's getting truncated to an unsigned int, which would limit you to a maximum of delay(65535) as the longest possible delay. If it works at 65535 and not 65536, it's certainly a bug in the Arduino libraries (or their documentation).
~Ben
Your code helped me get 1 minute intervals. I have tried 65535 and 65536 and it works for both. But It appears that the photos captured already do not overwrite and it is working for 5 minute intervals now. Thanks for your assistance.
Deletehi ben
ReplyDeletei wanna ask if your code can be used for arduino mega? im using arducam rev c. with arduino mega 2560R3 for the same project as you done.. if the code can be used can you tell me which part that i need to change the code
I seem to recall that there should be no code change, but the Arducam is not pin compatible with the Mega2560R3--you need to get a couple of wires and switch two pins for it to work. I think there are instructions on the Arducam website.
DeleteHi Ben, can you help me to read JPEG Data from arducam to show on serial monitor?
ReplyDeleteCan you show me how to print jpeg data?
Thx Before
This comment has been removed by the author.
ReplyDeleteSolved!
ReplyDeleteI just print temp.
Thx
Anyway, I want to ask other now, can you tell me, how to get the pixel to 200x200?
What should I do to change on the library?
I using OV2640, & arducam Rev. C.
Thx before
Or can you tell me how to take the original data from arducam? Not a JPEG and still have 3 byte from RGB.
ReplyDeleteThanks
I realise that this is an old thread, ubt I am looking for a solution to wirlessly connect multiple cameras to an Odroid. Is this even viable using Adruinos with WiFi ?
ReplyDeleteThanks in advance
Hi Ben,
ReplyDeleteThis error message came up after compiling the timelapse.ino program
timelapse_1:25: error: no matching function for call to 'ArduCAM::ArduCAM(int, const uint8_t&, const uint8_t&, const uint8_t&, const uint8_t&, int)'
timelapse_1.ino:25:36: note: candidates are:
In file included from timelapse_1.ino:9:0:
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:267:3: note: ArduCAM::ArduCAM(byte, int)
ArduCAM(byte model,int CS);
^
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:267:3: note: candidate expects 2 arguments, 6 provided
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:266:3: note: ArduCAM::ArduCAM()
ArduCAM();
^
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:266:3: note: candidate expects 0 arguments, 6 provided
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:263:7: note: ArduCAM::ArduCAM(const ArduCAM&)
class ArduCAM
^
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:263:7: note: candidate expects 1 argument, 6 provided
timelapse_1.ino: In function 'void loop()':
timelapse_1:114: error: 'class ArduCAM' has no member named 'enable_fifo'
timelapse_1:131: error: 'class ArduCAM' has no member named 'disable_fifo'
no matching function for call to 'ArduCAM::ArduCAM(int, const uint8_t&, const uint8_t&, const uint8_t&, const uint8_t&, int)'
We are using this shield https://learn.sparkfun.com/tutorials/microsd-shield-and-sd-breakout-hookup-guide
Where can we download avr/pgmspace.h?
Thank you,
Arduino Team EVC
I'm not entirely sure what you're doing or why you think avr/pgmspace.h will help you. It looks to me like you're trying to call ArduCAM's constructor with the wrong number of arguments. Jim Hawkins has an example above where the correct number of arguments is used.
DeleteHello, my name is Joseph Guzman and i am a team member in Arduino Team EVC. I would like to add on Alma's request. We are running the exact program you provided online which we are grateful for. We are not modifying any part of the program, simply compiling it and running into the same errors. The number of arguments are as follows:
Delete" ArduCAM myCAM(OV2640,A2,A1,A0,A3,10) " <- this is straight out of you code.
Here is the list of our errors we are encountering:
" no matching function for call to 'ArduCAM::ArduCAM(int,const uint8_t&, const uint8_t&, const8_t&, const8_t&
timelapse_1:25: error: no matching function for call to 'ArduCAM::ArduCAM(int, const uint8_t&, const uint8_t&, const uint8_t&, const uint8_t&, int)'
timelapse_1.ino:25:36: note: candidates are:
In file included from timelapse_1.ino:9:0:
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:267:3: note: ArduCAM::ArduCAM(byte, int)
ArduCAM(byte model,int CS);
^
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:267:3: note: candidate expects 2 arguments, 6 provided
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:266:3: note: ArduCAM::ArduCAM()
ArduCAM();
^
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:266:3: note: candidate expects 0 arguments, 6 provided
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:263:7: note: ArduCAM::ArduCAM(const ArduCAM&)
class ArduCAM
^
C:\Users\engineering\Documents\Arduino\libraries\ArduCAM/ArduCAM.h:263:7: note: candidate expects 1 argument, 6 provided
timelapse_1.ino: In function 'void loop()':
timelapse_1:114: error: 'class ArduCAM' has no member named 'enable_fifo'
timelapse_1:131: error: 'class ArduCAM' has no member named 'disable_fifo'
no matching function for call to 'ArduCAM::ArduCAM(int, const uint8_t&, const uint8_t&, const uint8_t&, const uint8_t&, int)'
"
Please, any help you can provide will get us to complete our project by the end of this month and we've been stuck for the past 2 weeks. We deeply appreciate your help and look foward toyour reply.
Evergreen Valley College Arduino team,
- Joseph Guzman
As I said before, the problem is that you are calling the ArduCAM constructor with incorrect arguments.
DeleteApparently, since I wrote my code the ArduCAM libraries have changed so that the constructor takes 2 arguments, not 6 (as in my code). This means that if you are using my code as an example, you will have to find a more recent one as my code will no longer work.
There is an example that someone else has posted in these comments above where they use the newer constructor. Please see Jim Hawkins' comment. He uses, for instance, ArduCAM myCAM(OV5642,10) to construct his ArduCAM object. This is with 100% certainty a source of your woes and is what you need to do also, except using arguments appropriate to your camera and slaveSelectPin.
Hi, Can I replace the arducam shield with "Arducam-LF Rev.C+ Camera module + 3.2 inch LCD for arduino UNO MEGA2560 DUE" to capture and display images and video.
ReplyDeleteThank you.
Very good, my name is Diego and I have a problem with my arducam ov 5642. The sketch compiles me well, in the monitor window I see the information of the attached photo, save the photos to the SD card, but I am not able to see No photo, I also attach a photo of what appears in the SD when I open it with my laptop. I've been with the camera for a month and I have not yet been able to see a photo, could you tell me what the problem is? I would be grateful.I also send a photo of my connection
ReplyDeletea greeting
Hi Diego--
DeleteI had a very similar issue with the ArduCam. I originally purchased a MT9D111 camera module, but as you can see above I was never actually able to take a good picture with it. I believe the issue is related to the ArduCam shield itself: the shield has only a 3 megabit buffer, which means that it is unable to store more than a 320 by 240 pixel image. When the camera module tries to put an image in to the ArduCam's memory, then, the buffer is overwritten and corrupted. It is not clear to me how the ArduCam makers are, or were ever able to take the high-resolution pictures they show on their website due to this issue.