C328 camera

I'm successfully communicating with the C328 camera in jpeg mode. I can even stream MJPEG video via the ethernet shield back :D so that you can even view live video in a browser from a webserver that runs directly on the arduino (with low resolution 160x128 or 80x64).

I'm pretty proud of myself now :D

There is one thing that bothers me a lot tho. Everything works fine as long as I keep the camera busy. After setting up everything I basically keep executing "Get Picture" commands all the time and send the "Data" packages I retrieve back over the ethernet.

But when I take a break - maybe around 5 seconds or longer - and then try to communicate with the camera again it simply won't respond with ACK or anything else anymore. I even tried to sync the camera again but it just seems to ignore everything. It's like it entered sleep mode or something :/

Any ideas? :'(

I'm using my own code to interface with the camera but I took a lot of inspiration from the C328 lib available here code.google.com/p/rogue-code/downloads/list?can=2&q=arduinomods. But all examples I've found just take a picture and then power off the camera without setting up the camera, waiting for some time and then taking a picture.

Sounds great! Please post code! I'd like to see what you did to generate MJPEGs (I assume you're doing the pseudo-MJPEG streaming - which is just sending a series of JPEGs to the browser).

Regarding the timeouts - I found that you need to explicitly re-sync the camera every time. The camera apparently goes into a sleep mode automatically (it's in the changelog, but no documentation anywhere). You don't necessarily need to re-sync if you're taking pictures rapidly, as you've found.

Let's see the code and then we can poke around to see what's happening.

b

Yes, thanks! I'll try the resync!

Exactly, it's using the pseudo mode and it's really just sending single jpeg messages back with the first message using: "Content-Type: multipart/x-mixed-replace; boundary=someseperator". The single images are then separated by "--someseperator" and each image gets its own "Content-Type: image/jpeg" and "Content-Length: ..." Header. It basically keeps sending back the images until eternity :)

I found that link very helpful to get the mjpeg stuff working: http://coweb.cc.gatech.edu/cs2340/1252

Here is the code:

http://www.lessvoid.com/arduino/ArduinoCameraMJPEGStreaming.zip

Some notes about that:

  • it's using a text LCD for debug messaging
  • it's a hack and it was a lot of learning :)
  • it currently only supports one single http connection and it will keep streaming even if that connection closes (you need to reset to start over again :)
  • I've removed the calculation of the checksum for the data package verification. This speed everything up.
  • mjpeg viewing is not supported by all browsers - firefox works great tho

Another thing I've noticed is that I had not much luck setting the package size bigger than about 120 bytes. Using bigger package sizes failed after receiving about 118 bytes.

Do you have any idea about that problem too? Is the arduino not fast enough to read the data so that the 128 byte serial buffer overflows? Package Size of 124 or lower did always work.

And here is a screenshot - that little jpeg image is continously refreshing in the browser :D

http://imagebin.org/91610

Wow!!

I almost posted a C328 question the same time you did :) Didn't know they are so popular ;)

Also take a look here: http://gizmologi.st/2009/04/taking-pictures-with-arduino/

It think re-syncing like bhagman mentioned before will help.

I've check the link you posted http://code.google.com/p/rogue-code/downloads/detail?name=CameraC328R-SerialBase.zip&can=2&q=arduinomods but what up with the "SerialBase class inheritance" Were is it for?

I will follow this post because I am really interested in MJEPEG video!

Cheers

MJPEG is very easy but as I'm learning right now not very well supported in browsers it seems. I've corrected some things about my code, especially sending CRLF after the boundary and some things like that and now I get stupid "save as" dialogs in firefox from time to time :(

With the current changes - which actually should make my HTTP-Headers more correct - it works now in Safari which only showed garbage with the original version.

Chrome seems to handle all the versions.

There is no progressive displaying of the frames in safari/chrome but there is in firefox. That means when it downloads single frames you can see the downloading and some flicker in firefox but not in safari/chrome.

Just some update about what I've learned :)

void256: The problem with the packet size is exactly what you are thinking. Especially with NewSoftSerial, the buffer will overflow faster than you can manage the data.

The bit-bang software serial receiver has to spend a LOT of CPU clocks in the ISR while receiving each and every byte. So you will have to boost the receive buffer on NSS to get larger packets through a software serial port. A hardware serial port would fair much better.

OpenSource: The SerialBase class will make it easier to interchange which type of serial port you use in libraries which use serial ports. See here for more info.

b

Hi all,

recently I have purchased C328 JPEG camera module from Comedia Ltd. Before purchasing the camera, I have searched the web to see if anyone else have done interfacing with Arduino Duemilanove and C328 camera. I have found several links with available libraries. Now, the first thing that one must do after powering camera with 3.3 V is to issue a SYNC command. I have the following code, which attempts to sync with camera, but to no avail :frowning:

// Includes library for making any digital I/O pins to communicate like serial ports
#include <NewSoftSerial.h>
#define CMD_SIZE 6

NewSoftSerial camera(12,7); // Defines Rx/Tx pins on Arduino

// command bytes
static const byte CMD_PREFIX = 0xAA;
static const byte CMD_SYNC = 0x0D;
static const byte CMD_ACK = 0x0E;

byte _command[CMD_SIZE];
byte _receive_cmd[CMD_SIZE];

// Defines functuion sync and returns boolean value (either true or false)
boolean sync() {
  bool success = false;
  int attempts = 0;
  // manual indicates we might need 60 attempts at syncing
  while(attempts < 60) {
    createCommand(CMD_SYNC, 0x00, 0x00, 0x00, 0x00);
    sendCommand();
    receiveReply();
   
    if(_receive_cmd[1] == CMD_ACK && _receive_cmd[2] == CMD_SYNC) {
      receiveReply();
      if(_receive_cmd[1] == CMD_SYNC) {
        camera.flush();
        createCommand(CMD_ACK, CMD_SYNC, 0x00, 0x00, 0x00);
        sendCommand();
        return true;
      } 
      else {
        return false; 
      }
    }
    attempts++;
  }
  return success;
}

boolean receiveReply() {
  delay(100);
  if( camera.available() > 0 )
  {
    for(int i = 0;i < 6; i++) {
      _receive_cmd[i] = camera.read(); 
    }
    return true;
  } 
  else {
    return false; 
  }
}


// Creates command for sending data to the camera
void createCommand(byte cmd, byte param1, byte param2, byte param3, byte param4 ) {
  _command[0] = CMD_PREFIX;
  _command[1] = cmd;
  _command[2] = param1;
  _command[3] = param2;
  _command[4] = param3;
  _command[5] = param4;
}

void sendCommand() {
  for(int i = 0; i < 6; i++) {
    camera.print(_command[i],BYTE);
   Serial.println(_command[i]); 
  }
}

void setup()
{  
  delay(3000);
  Serial.begin(9600);
  camera.begin(9600);
  Serial.println(camera.available());
  Serial.println("Starting ...");
  delay(10000);
  if(!sync()) {
    Serial.println(" failed");
  }
  
  
}

void loop()
{
}

I am aware that the camera functions using 3.3V logic, hence I am using a voltage divider to step down Arduino’s 5V during transmission (Tx pin 7) to acceptable 3.3V level of the camera. The Tx wire from camera is directly plugged in to Rx pin (12) in the microcontroller. I have verified that 60 mA at 3.3 V is reaching the camera’s Vcc and GND pins. I cannot figure out what I am doing wrong. I hope its not the camera.

Any help would be greatly appreciated.

Viktar

Please check this site to see the library that I used (and many others) to interface their c328 camera:

http://gizmologi.st/2009/04/taking-pictures-with-arduino/

This library including the example should be self-explaining.

/me

Hi thanks for reply,

I have used gizmologist code before but with no luck. In my previous setup I have connected camera's Tx pin into Rx pin (0) of Arduino and camera's Rx pin, through some voltage divider manipulation to get 3.3V logic, to Tx pin (1) of Arduino. I just wanted to sync the camera. I have the following code:

  #include "CameraC328R.h"
  
  
  CameraC328R camera;

  
  void setup()
  {
  if( !camera.sync() )
  {
    Serial.begin(9600);
    Serial.println( "Sync failed." );
    return;
  }
  }
  
  void loop()
  {
  }

The code compiles fine, but WILL NOT upload to the board, with the following errors:

avrdude: stk500_getsync(): not in sync: resp=0x00 avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x51

I have been having these errors if I use hardware serial on Arduino board, that is why in my previous post I have tried to use Soft aerial to eliminate the problem.

Viktar

hi, i've got some little question: 1. where i can find th camera? sparkfun say it's discontinued! 2. how much big is the output video file in kb/s? if the answer to 2° question is less than 100kb/s i love you :)

Hi,

Maybe you can send this store an email about the c328 stock:

http://www.electronics123.com/s.nl/sc.8/category.207684/.f

I have never used the video output (although, I would like to see a working example).

/me

Hi,

Please note: Always declare the Serial.begin separate in the setup. So no inside an IF statement.

Maybe it is better to test the following code:

#include "CameraC328R.h"


  CameraC328R camera;


  void setup()
  {
 Serial.begin(9600);
  }

  void loop()
  {

Camera.reset(true);

delay(1000);

if( !camera.sync() )
  {
    Serial.println( "Sync failed." );
    return;
  }

delay(5000);

  }

Let this run for a few cycles. The advantage of this is it runs multiple cycles so you don't have to reset it every time the setup code has run. This is off course only for debugging purpose!

/me

also it’s nice to know if there is a lag betwen the photo and the output from arduino, and how much big it is…
i think if this lag is < 40/50hz you have a basic video :), but i don’t know if it’s the right way ;D

OpenSource, I very much appreciate your prompt response. The code you have proposed works (Thank God I thought my camera was toasted :D), but I need to do the following modifications to allow this to happen:

  • When Tx and Rx lines of camera are plugged in Arduino's Rx and Tx pins, the code WILL NOT UPLOAD, in order to bypass that I have added more delay in the programs main loop to 5000ms. This allows me to upload the code to the board and after that plug the camera's Tx pin into Rx pin of Arduino (sounds ridiculous isn't it?). I cannot understand why would the camera's Tx pins cause this kind of havoc while the code is uploading.
  • I have to power camera off and on, run the code with the mod described above for it to sync successfully.

I would really much appreciate some input regarding this issue

Viktar

What kind of Arduino board do you use?

/me

Instead of using the arduino hardware serial use newsoftserial.

This allows you to make any pins on your arduino into a serial port.

It's simple to implement. See: http://arduiniana.org/libraries/NewSoftSerial/ for info.

Mowcius

I am using Arduino Mega at the instant; however, I have tried Arduino Duemilanove, and the same problem occurs…

I have tried using NewSoftSerial in the following way:

#include "NewSoftSerial.h"

NewSoftSerial camera(22,27)

void setup()
{ 
  Serial.begin(9600);
  delay(3000);
  camera.begin(9600);
  delay(3000);
 if (!camera.available())
 {
 Serial.println("Camera is not responding...");
 return;
 }

void loop() {}

Unfortunately, I get "Camera is not responding...", so yeah... :(

Ah well if you are using the arduino mega you can either use newsoftserial or you can use the second (or third or fourth) hardware serial port.

http://www.arduino.cc/en/Serial/Begin

Serial.begin(9600);
  Serial1.begin(38400);
  Serial2.begin(19200);
  Serial3.begin(4800);

  Serial.println("Hello Computer");
  Serial1.println("Hello Serial 1");
  Serial2.println("Hello Serial 2");
  Serial3.println("Hello Serial 3");

as an example

Mowcius

#include "NewSoftSerial.h"

NewSoftSerial camera(22, 27);

void setup()
{
  Serial.begin(9600);
  delay(3000);
  camera.begin(9600);
  delay(3000);
 if (!camera.available())
 {
 Serial.println("Camera is not responding...");
 return;
 }

void loop() {}

Try that...

You had missed a semicolon...