Turn on LED > push button > take and transfer picture

As my first project I would like to use an Arduino to turn on an LED, push a button, then take a picture and transfer that picture to a computer. I have several questions:

  1. Will the USB provide enough power for the Arduino and the required hardware? (LED, servo, camera)

  2. What parts do I need to make this as easy and cheap as possible? These are the parts I've been considering:

  1. I believe the tricky part is related to the camera. Which camera should I buy? Do I need additional parts to transfer the pictures from the camera to the computer? I cannot seem to find a good source of information for this online.

I found a very simple tutorial which shows how to connect and control the servo so I suppose that bit is pretty much as simple as it gets.

Once I get this working I'm hoping to eventually be able to perform some OCR on the resulting image.

Any additional tips or advice on how to get started with Arduino/Forum/Sparkfun/Electronics would also be appreciated.

Forget the first two cameras - they're analogue units.

I cannot seem to find a good source of information for this online.

So that has got to tell you something.

Basically the arduino and serial port will only be able to transfer a picture very slowly and by that I mean upwards of 30 seconds per picture. And that only if you can find a camera that will take a still and allow you to take your time extracting the information. In other words the camera has to have a buffer memory because the arduino hasn't enough to buffer the picture.

I would really prefer to use a camera sensor. If that's not feasible, I'll revert to plan B which involves using a standard webcam, so my gadget will consist of:

  • Arduino Uno
  • LED
  • Servo
  • Webcam

This should be an extremely simple setup and a good first project. Thank you so much both AWOL and Grumpy_Mike, you guys gave me a fantastic first impression of this forum!

I would really prefer to use a camera sensor. If that's not feasible,

It isn't feasible. The Arduino's analog to digital converter is too slow (by a few orders of magnitude) for video digitisation, and the processor doesn't have enough RAM.

(there are projects that grab very low res images, but they take many seconds to capture and transmit, and usually require the subject to stay still throughout the capture)

AWOL: Understood, thanks again!

Probably, it'd works with LinkSprite camera, if Arduino executes "controller" job and not involved in processing image.
Regarding slow link baudrate, I discovered in the manual:

  1. Compression Ratio
    Command (HEX)
    56 0 31 05 01 01 12 04 XX
    Return (HEX)
    76 00 31 00 00 XX (XX normally is 36)

command, that should improve transfer time of pics.

Magician: I think that's much too complicated to be of any use to me, thanks all the same. The solution with the webcam isn't nearly as elegant, but it's much simpler and costs no more.

I haven't receveid my Arduino UNO yet but I've written the code for the solution with the webcam and I'd like some feedback Will it work? Should anything be changed? I was thinking of writing a small Python/Processing program on the PC for communication with the Arduino over the USB.

/*
  1. Computer sends a "1" over the serial connection (USB)
  2. Arduino turns on LED
  3. Arduino servo pushes a button
  4. Arduino sends a "1" back to computer to let it now the cycle is complete
  5. Computer takes a snapshot with the USB webcam/microscope
  6. Computer OCRs image and returns 6 digits to user (e.g via internet or directly to clipboard)
 */

  //Includes
  #include <Servo.h> 


  //Constants
  const int PinServo = 9;      // 
  const int PinLed = 13;     // 

  //Objects
  Servo ServoButton


  //Setup
void setup() {                
  Serial.begin(9600);
  pinMode(PinLed, OUTPUT);
  ServoButton.attach(PinServo);
}

void loop() {
  if (Serial.available()){
   if ( Serial.read() == 1) {
     TurnOnLights();
     PushButton();
     InformPcComplete();
   }
  }
}


void TurnOnLights() {
  digitalWrite(PinLed, HIGH); // Turn on lights
}


void PushButton() {
  ServoButton.write(90);      // Servo moves to pos 90
  delay(1000);
  ServoButton.write(0);       // Servo returns to pos 0
  delay(1000);
}


void InformPcComplete() {
  Serial.print(1);            // Tell PC cycle is complete
}

P.S. This is stricly a programming question, but since it is relatively simple I figured there was no point in creating a separate thread in the programing section to ask this.

I would really appreciate some feedback regarding the below code, does it look alright? Should I start a new thread in another section of the forum?

/*
  1. Computer sends a "1" over the serial connection (USB)
  2. Arduino turns on LED
  3. Arduino servo pushes button, waits, returns to starting position
  4. Arduino sends a "1" back to computer to let it now the cycle is complete
  5. Computer takes a snapshot with the USB webcam/microscope
  6. Computer OCRs image and returns 6 digits to user (e.g copied to clipboard or via webpage)
 */


  //Includes
  #include <Servo.h> ;


  //Constants
  const int PinServo = 9;
  const int PinLed1 = 13;
  const int PinLed2 = 14;
  const int PinLed3 = 15;


  //Setup
void setup() {                
  Serial.begin(9600);
  pinMode(PinLed1, OUTPUT);
  pinMode(PinLed2, OUTPUT);
  pinMode(PinLed3, OUTPUT);
  Servo ServoButton;
  ServoButton.attach(PinServo);
}


void loop() {
  if (Serial.available()){
   if ( Serial.read() == 1) {
     TurnOnLights();
     PushButton();
     InformPcComplete();
     delay(4000); //Allow PC sufficient time to take pictura. Value needs tweaking.
     TurnOffLights();
   }
  }
}


void TurnOnLights() { //TurnOnLights and TurnOffLights should be combined into ControlLights(Argument)
  digitalWrite(PinLed1, HIGH); // Turn on lights
  digitalWrite(PinLed2, HIGH); // Turn on lights
  digitalWrite(PinLed3, HIGH); // Turn on lights
}


void TurnOffLights() {
  digitalWrite(PinLed1, LOW); // Turn on lights
  digitalWrite(PinLed2, LOW); // Turn on lights
  digitalWrite(PinLed3, LOW); // Turn on lights
}


void PushButton() {
  Servo ServoButton;
  ServoButton.write(90);      // Servo moves to pos 90
  delay(1000);
  ServoButton.write(0);       // Servo returns to pos 0
  delay(1000);
}


void InformPcComplete() {
  Serial.print(1);            // Tell PC cycle is complete
}

Here is the python code which is meant to communicates with the Arduino:

##################################################
##################################################
#                Communicate with Arduino
##################################################
##################################################
import serial
print "Sending a 1 to Arduino..."
#Send a "1" over serial to the Arduino, telling it to turn on the lights and push the button
ser = serial.Serial('/dev/tty.usbserial', 9600)
ser.write('1')

print "Waiting to receive a 'finished' from the Arduino..."
#Wait until receive the OK from the Arduino, meaning it has finished all it's tasks.
while 1
 msgarduino = ser.readline()
 if msgarduino == "1"
  break

time.sleep(1) #Might be a good idea to sleep a bit after all that hard work.

Here is the diagram from Fritzing. I've never done anything like this before so I would also appreciate some feedback on this. What I find a little odd is that the breadboard type diagram (the image) is different from the schematic with regards to how this thing should be connected to ground. Which alternative is recommended?

void setup() {                
  Serial.begin(9600);
  pinMode(PinLed1, OUTPUT);
  pinMode(PinLed2, OUTPUT);
  pinMode(PinLed3, OUTPUT);
  Servo ServoButton;
  ServoButton.attach(PinServo);
}

Pretty short lifetime for ServoButton.
Not really much use, unless you just want to turn it to 90 degrees.

AWOL: I don't understand??

What I find a little odd is that the breadboard type diagram (the image) is different from the schematic

Is it, they look the same to me.

AWOL: I don't understand??

You create a local object, attach it to a pin, and then a few hundred nanoseconds later, it goes out of scope and is useless.
Later, in PushButton, you create another object of the same name, don't attach it, but still write to it.

Grumpy_Mike: On the breadboard image, the ground wires for the three LEDs go to the GND between AREF and pin 13, the ground wire goes to GND between 5V and VIM. On the schematic, the ground wires for the three LEDs seem to be somehow connected to the ground wire for the servo and they are all connected to the .... err.... GND on the arduino board. I suppose that means that any GND on the board is okay to connect to?

AWOL: Thanks for the feedback. I was under the impression that the scope of variables and objects created in the void setup meant they were accessible throughout the rest of the code, but by the sounds of it that's quite wrong. I've removed the code relating to the variable and object from the void setup and moved them both into PushButton() like so. Will this work as intended now?

/*
  1. Computer sends a "1" over the serial connection (USB)
  2. Arduino turns on LED
  3. Arduino servo pushes button, waits, returns to starting position
  4. Arduino sends a "1" back to computer to let it now the cycle is complete
  5. Computer takes a snapshot with the USB webcam/microscope
  6. Computer OCRs image and returns 6 digits to user (e.g copied to clipboard or via webpage)
 */


  //Includes
  #include <Servo.h> ;


  //Constants
  const int PinServo = 9;
  const int PinLed1 = 11;
  const int PinLed2 = 12;
  const int PinLed3 = 13;


  //Setup
void setup() {                
  Serial.begin(9600);
  pinMode(PinLed1, OUTPUT);
  pinMode(PinLed2, OUTPUT);
  pinMode(PinLed3, OUTPUT);
}


void loop() {
  if (Serial.available()){  
   if ( Serial.read() == 1) {
     TurnOnLights();
     PushButton();
     InformPcComplete();
     delay(4000); //Allow PC sufficient time to take picture. Value needs tweaking.
     TurnOffLights();
   }
  }
}


void TurnOnLights() { //TurnOnLights and TurnOffLights should be combined into ControlLights(Argument)
  digitalWrite(PinLed1, HIGH);
  digitalWrite(PinLed2, HIGH);
  digitalWrite(PinLed3, HIGH);
}


void TurnOffLights() {
  digitalWrite(PinLed1, LOW);
  digitalWrite(PinLed2, LOW);
  digitalWrite(PinLed3, LOW);
}


void PushButton() {
  Servo ServoButton;
  ServoButton.attach(PinServo);
  ServoButton.write(90);      // Servo moves to pos 90
  delay(1000);
  ServoButton.write(0);       // Servo returns to pos 0
  delay(1000);
}


void InformPcComplete() {
  Serial.print(1);            // Tell PC cycle is complete
}
ser.write('1')

will send the character 1 to the Arduino.

   if ( Serial.read() == 1) {

which then expects the integer value 1, which is not the same as the character '1'.

byte b = Serial.read() - '0';
if(b == 1)
{
  // The character '1' arrived...
}

or

   if ( Serial.read() == '1') {

PaulS: That makes perfect sense, well done! That's exactly the sort of thing that might have been very difficult for me to figure out on my own. I think I'll try your second recommendation "if ( Serial.read() == '1') {".

I was under the impression that the scope of variables and objects created in the void setup meant they were accessible throughout the rest of the code

No, quite the wrong impression.
"loop" and "setup" are functions just like any other; no special scope rules apply to them.

AWOL: Understood, thanks.

PaulS: I've tried to correct the code of the Arduino and Python to only use integers. I think I've got it for now. Still waiting to receive my first Arduino...

void loop() {
  if (Serial.available()){  
   if ( Serial.read() == 1) {
     TurnOnLights();
     PushButton();
     InformPcComplete();
     delay(4000); //Allow PC sufficient time to take picture. Value needs tweaking.
     TurnOffLights();
   }
  }
}

void InformPcComplete() {
  Serial.print(1);            // Tell PC cycle is complete
}

python code:

##################################################
##################################################
#                Communicate with Arduino
##################################################
##################################################
print "Sending a 1 to Arduino..."
#Send a 1 (integer!) over serial to the Arduino, telling it to turn on the lights and push the button
ser = serial.Serial('/dev/tty.usbserial', 9600)
ser.write(1)

print "Waiting to receive a 'finished' from the Arduino..."
#Wait until receive the OK from the Arduino, meaning it has finished all it's tasks.
while 1
 msgarduino = ser.readline()
 if msgarduino == 1
  break