I am working on a project which requires me to interface the Arduino Duemilanove with a C328 camera. All I need for it to do is take snap shots once a second. The camera is connected to pin 12 and 13 because all the serial ports are taken. So I believe I have to use software serial. After this, I have no clue how to code. I am new to this. Pls help with pointers!
All I need for it to do is take snap shots once a second.
Even with a limited camera like the C328, what you're asking is going to be too much for an arduino, particularly using software serial. Once a minute I wouldn't see a problem assuming you have something to store the images (2k of ram doesn't go anywhere with images), But once a second isn't going to happen unless the arduino has some serious help.
well this is a small part of the larger picture. the idea is to put this in a blimp that will also carry the camera and wirelessly transmit the pictures to a base station that will display it in a website. does that help?
Its going to need something more powerful than an Arduino, the pictures from such a limited camera aren't going to be much to look at if you could get them out. Its pretty limited resolution. I'd be looking at a something with more oomph, something like this perhaps ?
unfortunately the hardware is has already been bought, we can change the specs to a pic per minute if need be. but for now, i need help with gettin the arduino to talk to the camera and vice-versa.
While the camera image quality is low, it is still decent enough for some projects.
You may want to consider just storing the images on an SD card and sift through them after touchdown. Have a look at my Time Lapse Video project with a C328R camera and a uMMC:
The images will be stored on an SD card, then you can do what you want with them. I think I could tweak the sketch to probably get something like 1 picture every 10 seconds or so.
Transmitting the pictures after storing them might be the way to go. I have no idea what distances you're talking about but I think there are plenty of projects around here that talk about wirelessly transmitting data.
b
thank you for the responses. Unfortunately, the specs for the project are extremely rigid. I am expected to transmit it wirelessly to a base station which will then interpret it and display on a website.
I am terrible at coding but here is what I have so far. I dont know how to receive the image package itself. Should I be storing it to EEPROM and then transmitting or just transmitting directly? once the data is received at the base xbee shield, I am not sure how to store it and view it as an image either. I am really lost. HELP!
#include <ctype.h>
#define bit9600Delay 84
#define halfBit9600Delay 42
#define bit4800Delay 188
#define halfBit4800Delay 94
int rx = 12;
int tx = 13;
byte SWval;
int imgsize =0;
void SWprint(int data)
{
byte mask;
//startbit
digitalWrite(tx,LOW);
delayMicroseconds(bit9600Delay);
for (mask = 0x01; mask>0; mask <<= 1) {
if (data & mask){ // choose bit
digitalWrite(tx,HIGH); // send 1
}
else{
digitalWrite(tx,LOW); // send 0
}
delayMicroseconds(bit9600Delay);
}
//stop bit
digitalWrite(tx, HIGH);
delayMicroseconds(bit9600Delay);
}
int SWread()
{
byte val = 0;
while (digitalRead(rx));
//wait for start bit
if (digitalRead(rx) == LOW) {
delayMicroseconds(halfBit9600Delay);
for (int offset = 0; offset < 8; offset++) {
delayMicroseconds(bit9600Delay);
val |= digitalRead(rx) << offset;
}
//wait for stop bit + extra
delayMicroseconds(bit9600Delay);
delayMicroseconds(bit9600Delay);
return val;
}
}
boolean checkACK(byte ackbyte)
{
if(SWread()== 0xAA){
if(SWread() == 0x0E){
if(SWread() == ackbyte){
return true;
}
}
}
Serial.println("Recieved ACK");
}
boolean checkSYNC()
{
if(SWread()== 0xAA){
if(SWread() == 0x0E){
return true;
}
}
Serial.println("Recieved SYNC");
}
void printACK(byte ack2, byte ack3, byte ack5, byte ack6)
{
SWprint(0xAA);
SWprint(ack2);
SWprint(ack3);
SWprint(0x00);
SWprint(ack5);
SWprint(ack6);
Serial.println("ACK");
}
void printSYNC()
{
SWprint(0xAA);
SWprint(0x0D);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
Serial.println("SYNC");
}
void printINITIAL()
{
SWprint(0xAA);
SWprint(0x01);
SWprint(0x00);
SWprint(0x07);
SWprint(0x01);
SWprint(0x07);
Serial.println("INITIAL");
}
void setPkgSize(byte size_l, byte size_u)
{
SWprint(0xAA);
SWprint(0x06);
SWprint(0x08);
if (size_l == 0x00 && size_u == 0x00)
{
SWprint(size_l);
SWprint(size_u);
}
else
{
SWprint(0x00);
SWprint(0x40);
}
SWprint(0x00);
Serial.println("Package size set");
}
void takeSnapShot()
{
SWprint(0xAA);
SWprint(0x05);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
Serial.println("Take Snapshot");
}
void getPicture()
{
byte imgsize1, imgsize2, imgsize3 =0x00;
SWprint(0xAA);
SWprint(0x04);
SWprint(0x01);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
Serial.println("Get picture");
if(checkACK(0x04))
{
if(SWread()== 0xAA){
if(SWread() == 0x0A){
if(SWread() == 0x01){
imgsize1=SWread();
imgsize2=SWread();
imgsize3=SWread();
imgsize |= imgsize1 << 8;
imgsize |= imgsize2 << 8;
imgsize |= imgsize3;
}
}
}
Serial.println("Received image size");
}
}
void getDataPkg()
{
int tmpimgsize;
byte pkgcount = 0x00;
while (tmpimgsize<imgsize)
{
printACK(0x0E, 0x00, pkgcount, 0x00);
delay(100);
//receive imgpackage
}
}
void loop()
{
}
void setup()
{
Serial.begin(9600);
pinMode(rx, INPUT);
pinMode(tx, OUTPUT);
Serial.println("setup");
printSYNC();
while(digitalRead(rx) == 1)
{
printSYNC();
}
if(checkACK(0x0D))
{
if(checkSYNC())
{
printACK(0x0E, 0x0D, 0x00, 0x00);
}
}
printINITIAL();
if(checkACK(0x01))
{
setPkgSize(0x02,0x00); //package size set to 256 bytes
if(checkACK(0x06))
{
takeSnapShot();
delay(1000);
if(checkACK(0x05))
{
getPicture();
getDataPkg();
}
}
}
}
Please use the code button (#) to post code so we don't have to scroll through long posts.
Its more than getting the camera to talk to the arduino or vice versa, since the Arduino doesn't have enough ram to be able to store an image even temporarily. You've going to need either to get the serial data from the camera and immediately transmit it or immediately forward it to something (like an SD card) for storage. If you were to transmit it, you'd struggle to do anything with error detection and correction, due to the extremely limited resources available, so whether you'd get anything worthwhile at the receiving end is open to question. SD card and later processing is probably your best option. Its probably just a matter of pulling the serial data from the camera and writing what it sends to the card, but I've never done anything with SD card storage so I'm far from qualified to advise on this. Everything I've seen about it has just been logging text.
I still maintain you'd be better looking for something with better resources than an Arduino. Arduinos are superb for doing many things, but anything to do with Images isn't on the list.
Sorry, I wasnt aware of the code button. Now its done.
I cannot add an sd card mostly because all of this is going on a mini zepplin whose lift capacity we have already exceeded. We r tryin to get rid of some things to reduce the weight actually. If I even bring up the idea of adding an sd card, the whole team would flip out. I am gonna hav to make do with the error checking at the base station. Either way, is there a sample code i can look at that does the transfer? (to a computer wirelessly or to an sd card?)
thank you for responding!
It depends on how your radio gear is interfaced to the arduino.
At its simplest it would be maybe a couple of libraries and a simple main loop with a read byte and a write byte with maybe a checksum generator for rudimentary error checking. Its a bit specialised for off the shelf code. Take a look at bhagman's time lapse project, its as close as you're going to get for pre-written code, right camera and writing to SD card.
This will probably be right up your street : http://gizmologi.st/2009/04/taking-pictures-with-arduino/
linked from bhagmans post. Its as close as you're going to get to what you want for nothing. Doesn't do radio links though, the code works as is with an external eeprom which is both cheap and light but it won't store many pictures. At its best resolution the pictures are around 20k in size which comes to 160 kbit and the suggested eeprom is 256kbit.....
thank you for the sample code. this is probably a super-dumb question, but here r the exact things i cant figure out
- once the img packets start coming in, in what format do they come in? - how do i no the number of packets?
- how can i recognize the last packet sent out?
Also, when i receive it, do i jus save it in a file n its done?
This is the code I am using to get the camera and arduino to talk. It seems to work. But when I include it in another code that deals with autonomous flight (its supposed to be put up on a mini zepplin), the camera wont sync anymore.
Due to char limit, I am posting the code in 2 seperate posts. the code below works by itself.
#include <ctype.h>
#define bit9600Delay 84
#define halfBit9600Delay 42
#define bit4800Delay 188
#define halfBit4800Delay 94
int rx = 12;
int tx = 13;
byte SWval;
void SWprint(int data)
{
byte mask;
//startbit
digitalWrite(tx,LOW);
delayMicroseconds(bit9600Delay);
for (mask = 0x01; mask>0; mask <<= 1) {
if (data & mask){ // choose bit
digitalWrite(tx,HIGH); // send 1
}
else{
digitalWrite(tx,LOW); // send 0
}
delayMicroseconds(bit9600Delay);
}
//stop bit
digitalWrite(tx, HIGH);
delayMicroseconds(bit9600Delay);
}
int SWread()
{
byte val = 0;
while (digitalRead(rx));
//wait for start bit
if (digitalRead(rx) == LOW) {
delayMicroseconds(halfBit9600Delay);
for (int offset = 0; offset < 8; offset++) {
delayMicroseconds(bit9600Delay);
val |= digitalRead(rx) << offset;
}
//wait for stop bit + extra
delayMicroseconds(bit9600Delay);
delayMicroseconds(bit9600Delay);
return val;
}
}
boolean checkACK(byte ackbyte)
{
if(SWread()== 0xAA){
if(SWread() == 0x0E){
if(SWread() == ackbyte){
return true;
}
}
}
Serial.println("Recieved ACK");
}
boolean checkSYNC()
{
if(SWread()== 0xAA){
if(SWread() == 0x0E){
return true;
}
}
Serial.println("Recieved SYNC");
}
void printACK(byte ack2, byte ack3, byte ack5, byte ack6)
{
SWprint(0xAA);
SWprint(ack2);
SWprint(ack3);
SWprint(0x00);
SWprint(ack5);
SWprint(ack6);
Serial.println("ACK");
}
void printSYNC()
{
SWprint(0xAA);
SWprint(0x0D);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
Serial.println("SYNC");
}
void printINITIAL()
{
SWprint(0xAA);
SWprint(0x01);
SWprint(0x00);
SWprint(0x07);
SWprint(0x01);
SWprint(0x07);
Serial.println("INITIAL");
}
void setPkgSize(byte size_l, byte size_u)
{
SWprint(0xAA);
SWprint(0x06);
SWprint(0x08);
if (size_l == 0x00 && size_u == 0x00)
{
SWprint(size_l);
SWprint(size_u);
}
else
{
SWprint(0x00);
SWprint(0x40);
}
SWprint(0x00);
Serial.println("Package size set");
}
void takeSnapShot()
{
SWprint(0xAA);
SWprint(0x05);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
Serial.println("Take Snapshot");
}
int getPicture()
{
int size;
byte sizebyte =0x00;
SWprint(0xAA);
SWprint(0x04);
SWprint(0x01);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
Serial.println("Get picture");
if(checkACK(0x04))
{
if(SWread()== 0xAA){
if(SWread() == 0x0A){
if(SWread() == 0x01){
sizebyte=SWread();
size |= sizebyte << 8;
sizebyte=SWread();
size |= sizebyte << 8;
sizebyte=SWread();
size |= sizebyte;
}
}
}
Serial.println("Received image size");
}
return size;
}
void getDataPkg(int imgsize)
{
int datasize, imgID, tmpdatasize, tmpimgsize, verifycode;
byte pkgcount = 0x00;
while (tmpimgsize<imgsize)
{
printACK(0x0E, 0x00, pkgcount, 0x00);
delay(100);
imgID |= SWread() << 8;
imgID |= SWread();
datasize |= SWread() << 8;
datasize |= SWread();
tmpdatasize = 0;
while (tmpdatasize < datasize)
{
Serial.write(SWread()); //check with ben
}
verifycode |= SWread() << 8;
verifycode |= SWread();
pkgcount++;
tmpimgsize = tmpimgsize+datasize;
}
}
void loop()
{
}
void setup()
{
Serial.begin(9600);
pinMode(rx, INPUT);
pinMode(tx, OUTPUT);
Serial.println("setup");
printSYNC();
while(digitalRead(rx) == 1)
{
printSYNC();
}
if(checkACK(0x0D))
{
if(checkSYNC())
{
printACK(0x0E, 0x0D, 0x00, 0x00);
}
}
printINITIAL();
if(checkACK(0x01))
{
setPkgSize(0x02,0x00); //package size set to 256 bytes
if(checkACK(0x06))
{
takeSnapShot();
delay(1000);
if(checkACK(0x05))
{
getDataPkg(getPicture());
}
}
}
}
this is the code where the camera wont send back an ack for the sync. What is going on here?
#include "Wire.h"
#include <AFMotor.h>
#include <Servo.h>
#include <ctype.h>
#define bit9600Delay 84
#define halfBit9600Delay 42
#define bit4800Delay 188
#define halfBit4800Delay 94
AF_DCMotor motor(1, MOTOR12_1KHZ); //LEFT
AF_DCMotor motor2(2,MOTOR12_1KHZ); //RIGHT
Servo angle;
int rightSonar = 0xF0;
int leftSonar = 0xF2;
int topSonar = 0xF8;
int frontSonar = 0xF4;
int bottomSonar = 0xF6;
int range;
int currentAngle = 0;
boolean updown = false;
int command;
int rx = 12;
int tx = 13;
byte SWval;
int imgsize =0;
void SWprint(int data)
{
byte mask;
//startbit
digitalWrite(tx,LOW);
delayMicroseconds(bit9600Delay);
for (mask = 0x01; mask>0; mask <<= 1) {
if (data & mask){ // choose bit
digitalWrite(tx,HIGH); // send 1
}
else{
digitalWrite(tx,LOW); // send 0
}
delayMicroseconds(bit9600Delay);
}
//stop bit
digitalWrite(tx, HIGH);
delayMicroseconds(bit9600Delay);
}
int SWread()
{
byte val = 0;
while (digitalRead(rx));
//wait for start bit
if (digitalRead(rx) == LOW) {
delayMicroseconds(halfBit9600Delay);
for (int offset = 0; offset < 8; offset++) {
delayMicroseconds(bit9600Delay);
val |= digitalRead(rx) << offset;
}
//wait for stop bit + extra
delayMicroseconds(bit9600Delay);
delayMicroseconds(bit9600Delay);
return val;
}
}
boolean checkACK(byte ackbyte)
{
if(SWread()== 0xAA){
if(SWread() == 0x0E){
if(SWread() == ackbyte){
return true;
}
}
}
//Serial.println("Recieved ACK");
}
boolean checkSYNC()
{
if(SWread()== 0xAA){
if(SWread() == 0x0E){
return true;
}
}
//Serial.println("Recieved SYNC");
}
void printACK(byte ack2, byte ack3, byte ack5, byte ack6)
{
SWprint(0xAA);
SWprint(ack2);
SWprint(ack3);
SWprint(0x00);
SWprint(ack5);
SWprint(ack6);
//Serial.println("ACK");
}
void printSYNC()
{
SWprint(0xAA);
SWprint(0x0D);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
//Serial.println("SYNC");
}
void printINITIAL()
{
SWprint(0xAA);
SWprint(0x01);
SWprint(0x00);
SWprint(0x07);
SWprint(0x01);
SWprint(0x07);
//Serial.println("INITIAL");
}
void setPkgSize(byte size_l, byte size_u)
{
SWprint(0xAA);
SWprint(0x06);
SWprint(0x08);
if (size_l == 0x00 && size_u == 0x00)
{
SWprint(size_l);
SWprint(size_u);
}
else
{
SWprint(0x00);
SWprint(0x40);
}
SWprint(0x00);
//Serial.println("Package size set");
}
void snapShot()
{
SWprint(0xAA);
SWprint(0x05);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
//Serial.println("Snapshot compressed picture");
}
void getPicture()
{
byte imgsize1, imgsize2, imgsize3 =0x00;
SWprint(0xAA);
SWprint(0x04);
SWprint(0x01);
SWprint(0x00);
SWprint(0x00);
SWprint(0x00);
//Serial.println("Get picture");
if(checkACK(0x04))
{
if(SWread()== 0xAA){
if(SWread() == 0x0A){
if(SWread() == 0x01){
imgsize1=SWread();
imgsize2=SWread();
imgsize3=SWread();
imgsize |= imgsize1 << 8;
imgsize |= imgsize2 << 8;
imgsize |= imgsize3;
}
}
}
//Serial.println("Received image size");
}
}
void getDataPkg()
{
int tmpimgsize;
byte pkgcount = 0x00;
while (tmpimgsize<imgsize)
{
printACK(0x0E, 0x00, pkgcount, 0x00);
delay(100);
}
}
void setup()
{
//Wire.begin();
Serial.begin(9600);
/*angle.attach(10);
motor.setSpeed(200);
motor2.setSpeed(200);
*/
//angle.write(0);
//Serial.println("setup");
pinMode(rx, INPUT);
pinMode(tx, OUTPUT);
//Serial.println("setup");
printSYNC();
while(digitalRead(rx) == 1)
{
printSYNC();
Serial.println("SYNC");
}
Serial.println("done sync");
if(checkACK(0x0D))
{
if(checkSYNC())
{
printACK(0x0E, 0x0D, 0x00, 0x00);
}
}
printINITIAL();
Serial.println("done setup");
}
void loop()
{
/*
1. Check each sonar
2. If range below minimum, run appropriate counter-measures
3. TODO Check if a command has been received, if so, perform that action
4. TODO If no command, go forward
*/
//check front
/*int front = rangeOfSonar(frontSonar);
int left = rangeOfSonar(leftSonar);
int right = rangeOfSonar(rightSonar);
int top = rangeOfSonar(topSonar);
int bottom = rangeOfSonar(bottomSonar);
//Serial.print("bottom range: ");
//Serial.println(bottom,DEC);
if (bottom < 220) //Less than 220cm bellow
{
if (!updown)
{
angle.write(55);
updown = true;
}
//Serial.println("55");
maneuver(BACKWARD,BACKWARD);
} else if (top < 150) //less than 150cm above
{
if (!updown)
{
angle.write(55);
updown = true;
}
maneuver(FORWARD,FORWARD);
}
else if (front < 200) //reverse and turn
{
if (updown)
{
angle.write(0);
updown = false;
}
maneuver(BACKWARD,BACKWARD);
maneuver(FORWARD,BACKWARD);
}
else if (left <200) //turn
{
if (updown)
{
angle.write(0);
updown = false;
}
maneuver(FORWARD,BACKWARD);
}
else if (right < 200) //turn
{
if (updown)
{
angle.write(0);
updown = false;
}
maneuver(BACKWARD,FORWARD);
}
// check if command received, if so perform that action
if (Serial.available() > 0)
{
command = Serial.read();
//Serial.println(command);
if (command == 102 ) //'f', forward
{
angle.write(0);
updown = false;
maneuver(FORWARD,FORWARD);
}
else if (command == 98) //'b', backward
{
angle.write(0);
updown = false;
maneuver(BACKWARD,BACKWARD);
}
else if (command == 117) //'u', up
{
angle.write(55);
updown = true;
maneuver(BACKWARD,BACKWARD);
}
else if (command == 100) //'d', down
{
angle.write(55);
updown = true;
maneuver(FORWARD,FORWARD);
}
else if (command == 108) //'l', left
{
angle.write(0);
updown = false;
maneuver(BACKWARD,FORWARD);
}
else if (command == 114) //'r', right
{
angle.write(0);
updown = false;
maneuver(FORWARD,BACKWARD);
}
else if (command == 99) //'c', camera
{
//take a picture and send it back
if(checkACK(0x01))
{
setPkgSize(0x02,0x00); //package size set to 256 bytes
if(checkACK(0x06))
{
snapShot();
if(checkACK(0x05))
{
getPicture();
getDataPkg();
}
}
}
}
}
/*else // no command, go forward
{
angle.write(0);
updown = false;
maneuver(FORWARD,FORWARD);
}*/
}
void maneuver(int m1, int m2)
{
motor.run(m1);
motor2.run(m2);
delay(2000);
motor.run(RELEASE);
motor2.run(RELEASE);
}
int rangeOfSonar(int address)
{
int timeout = 0;
Wire.beginTransmission(address);
Wire.send(0x00);
Wire.send(0x51);
Wire.endTransmission();
delay(70);
Wire.beginTransmission(address);
Wire.send(0x02);
Wire.endTransmission();
Wire.requestFrom(address,2);
// Serial.println(address,HEX);
while (Wire.available() < 2 && timeout < 10) {
delay(10);
//if (timeout == 9)
//Serial.println(address,HEX);
timeout = timeout + 1;
}
int range = Wire.receive();
range = range << 8;
range |= Wire.receive();
return range;
}
Simple answer, you've got too much going on for one Ar5duino to cope with. This is the first I've heard about you wanting it to fly the blimp as well. I tried to convince you you were asking too much of an arduino when you were talking pictures, now I find out you want to do another complex task at the same time. Just how much do you think you can get in 2048 bytes of ram ? I consider it a minor miracle that an Arduino can take pictures at all, I haven't seen anything anywhere about an Arduino flying autonomously (balancing a chopper whilst somebody flies it perhaps).
And you want to do both at the same time...........
Arrrggghhh.