Connecting Linksprite JPEG Camera to Arduino Leonardo

Hi there,

Please bear with me, I’m still a newbie ;).

I’m currently trying to connect a Linksprite JPEG Camera (> http://www.evola.fr/product_info.php/en/linksprite-jpeg-color-camera-ttl-interface-p-172) to my Arduino Leonardo.
Because I’ve never used a camera before, I basically have no idea what exactly to do. Searching through the internet revealed the following example code:

#include <SoftwareSerial.h>

byte incomingbyte;
SoftwareSerial mySerial(4,5);                     //Configure pin 4 and 5 as soft serial port
int a=0x0000,j=0,k=0,count=0;                    //Read Starting address       
uint8_t MH,ML;
boolean EndFlag=0;
                               
void SendResetCmd();
void SendTakePhotoCmd();
void SendReadDataCmd();
void StopTakePhotoCmd();

void setup()
{ 
  Serial.begin(19200);
  mySerial.begin(38400);
}

void loop() 
{    
     SendResetCmd();
     delay(4000);                               //After reset, wait 2-3 second to send take picture command
      SendTakePhotoCmd();
     while(mySerial.available()>0)
      {
        incomingbyte=mySerial.read();

      }   
      byte a[32];
      while(!EndFlag)
      {  
         j=0;
         k=0;
         count=0;
         SendReadDataCmd();
         delay(25);
          while(mySerial.available()>0)
          {
               Serial.println(Serial.available());
               incomingbyte=mySerial.read();
               k++;
               if((k>5)&&(j<32)&&(!EndFlag))
               {
               a[j]=incomingbyte;
               if((a[j-1]==0xFF)&&(a[j]==0xD9))      //Check if the picture is over
               EndFlag=1;                           
               j++;
	       count++;
               }
          }
         
          for(j=0;j<count;j++)
          {   if(a[j]<0x10)
              Serial.print("0");
              Serial.print(a[j],HEX);
              Serial.print(" ");
          }                                       //Send jpeg picture over the serial port
          Serial.println();
      }      
     while(1);
}

//Send Reset command
void SendResetCmd()
{
      mySerial.write(0x56);
      mySerial.write((byte)0x00);
      mySerial.write(0x26);
      mySerial.write((byte)0x00);
}

//Send take picture command
void SendTakePhotoCmd()
{
      mySerial.write(0x56);
      mySerial.write((byte)0x00);
      mySerial.write(0x36);
      mySerial.write(0x01);
      mySerial.write((byte)0x00);  
}

//Read data
void SendReadDataCmd()
{
      MH=a/0x100;
      ML=a%0x100;
      mySerial.write(0x56);
      mySerial.write((byte)0x00);
      mySerial.write(0x32);
      mySerial.write(0x0c);
      mySerial.write((byte)0x00); 
      mySerial.write(0x0a);
      mySerial.write((byte)0x00);
      mySerial.write((byte)0x00);
      mySerial.write(MH);
      mySerial.write(ML);   
      mySerial.write((byte)0x00);
      mySerial.write((byte)0x00);
      mySerial.write((byte)0x00);
      mySerial.write(0x20);
      mySerial.write((byte)0x00);  
      mySerial.write(0x0a);
      a+=0x20;                            //address increases 32£¬set according to buffer size
      Serial.println("photo");

}

void StopTakePhotoCmd()
{
      mySerial.write(0x56);
      mySerial.write((byte)0x00);
      mySerial.write(0x36);
      mySerial.write(0x01);
      mySerial.write(0x03);        
}

The code runs without debugging errors, but it can’t get into the while(Serial.available()>0)... loops, because Serial.available constantly remains 0. I know that this means there aren’t any bytes to read, but why is that?
Btw: I have connected the RX-Output to pin 4 and the TX-Output to pin 5.

Thanks for any help in advance,

Kotton

It isn't Serial you're reading from - it is mySerial. The distinction is very important here.

I am not familiar with that camera but I would look at the interface spec to see whether it is expected to give any response to the commands you're giving it, especially during initialisation where you essentially discard everything the camera sends you. Double check that you are using the correct pins and have got them connected the right way round, and that the speed you're using for mySerial is the same speed the camera defaults to. Are there any examples sketches from the camera vendor demonstrating how to use it?

but it can't get into the

Which one? The first one reads and throws away all the data. The second one doesn't have anything to do, because when you get there, you've already dumped all the serial data.

It appears as though you think that the response from the camera will be instantaneous. I can assure you that this is not the case.

Hi there,

thanks for the fast reply!
@PeterH: The could should actually print the image hex code to the Serial monitor. There also are some examples (https://docs.google.com/file/d/0B6Qn4nam5VvfZGY5YWZkMWItNjk2Ny00NDU2LTlkMTctOWU1MWYwMWNmYjA4/edit?pli=1, http://2byt.es/linksprite-jpeg-uart-camera-arduino/ and https://docs.google.com/file/d/0B6Qn4nam5VvfYzJmNGQ0NzMtMTVlZS00NTMyLWFkZTAtNjdiY2YyYzViMmRl/edit?usp=drive_web&pli=1), but they either are made for the arduino Uno or are obsolete.
It says somewhere that I should connect the Tx-Output to the Rx-Input of the Arduino and vice versa (Rx to Tx input),which would correspond to the Serials 0 and 1 (which I changed in the Code).

#include <SoftwareSerial.h>

byte incomingbyte;
SoftwareSerial mySerial(0,1);                     //Configure pin 4 and 5 as soft serial port
int a=0x0000,j=0,k=0,count=0;                    //Read Starting address       
uint8_t MH,ML;
boolean EndFlag=0;
                               
void SendResetCmd();
void SendTakePhotoCmd();
void SendReadDataCmd();
void StopTakePhotoCmd();

void setup()
{ 
  Serial.begin(19200);
  mySerial.begin(38400);
}

void loop() 
{    
     SendResetCmd();
     delay(4000);                               //After reset, wait 2-3 second to send take picture command
      SendTakePhotoCmd();
     while(mySerial.available()>0)
      {
        incomingbyte=mySerial.read();

      }   
      byte a[32];
      while(!EndFlag)
      {  
         j=0;
         k=0;
         count=0;
         SendReadDataCmd();
         delay(25);
         Serial.println(mySerial.available());
         while(mySerial.available()>0)
          {
               Serial.println(Serial.available());
               incomingbyte=mySerial.read();
               k++;
               if((k>5)&&(j<32)&&(!EndFlag))
               {
               a[j]=incomingbyte;
               if((a[j-1]==0xFF)&&(a[j]==0xD9))      //Check if the picture is over
               EndFlag=1;                           
               j++;
	       count++;
               }
          }
         
          for(j=0;j<count;j++)
          {   if(a[j]<0x10)
              Serial.print("0");
              Serial.print(a[j],HEX);
              Serial.print(" ");
          }                                       //Send jpeg picture over the serial port
          Serial.println();
      }      
     while(1);
}

//Send Reset command
void SendResetCmd()
{
      mySerial.write(0x56);
      mySerial.write((byte)0x00);
      mySerial.write(0x26);
      mySerial.write((byte)0x00);
}

//Send take picture command
void SendTakePhotoCmd()
{
      mySerial.write(0x56);
      mySerial.write((byte)0x00);
      mySerial.write(0x36);
      mySerial.write(0x01);
      mySerial.write((byte)0x00);  
}

//Read data
void SendReadDataCmd()
{
      MH=a/0x100;
      ML=a%0x100;
      mySerial.write(0x56);
      mySerial.write((byte)0x00);
      mySerial.write(0x32);
      mySerial.write(0x0c);
      mySerial.write((byte)0x00); 
      mySerial.write(0x0a);
      mySerial.write((byte)0x00);
      mySerial.write((byte)0x00);
      mySerial.write(MH);
      mySerial.write(ML);   
      mySerial.write((byte)0x00);
      mySerial.write((byte)0x00);
      mySerial.write((byte)0x00);
      mySerial.write(0x20);
      mySerial.write((byte)0x00);  
      mySerial.write(0x0a);
      a+=0x20;                            //address increases 32£¬set according to buffer size
      Serial.println("photo");

}

void StopTakePhotoCmd()
{
      mySerial.write(0x56);
      mySerial.write((byte)0x00);
      mySerial.write(0x36);
      mySerial.write(0x01);
      mySerial.write(0x03);        
}

(Sorry posting the whole code again).
I also added some debug commands to the methods, and it really seems that it can’t get into the second while(mySerial.available()>0) Loop, which is needed to print out the Image Hex code, and I have no idea why…

Kotton

SoftwareSerial mySerial(0,1);                     //Configure pin 4 and 5 as soft serial port

There really is no excuse for this. Pins 0 and 1 are the hardware serial pins. If you are going to use them, you don't need SoftwareSerial.

And, you can NOT do software serial while doing hardware serial on the same pins.

Yes I noticed that so I replaced all the "mySerial"s with Serial1 (and removed SoftwareSerial). I also connect the Camera Vcc-input to the 5-Volt Pin of the Arduino and the Ground to the corresponding one on the Arduino. The Cameras Tx-Output goes to the Arduino Receive-input (Rx) and the other way around. But still, Serial1.available() remains zero, meaning there's nothing to read, even after waiting some time. Is this still a coding problem or something hardware-specific?

Appreciate all the help given so far.

Kotton

Is this still a coding problem

At the very least, it's a "you didn't post the code" problem. So, yes, it is a problem involving code.

Have you sent the camera anything asking it to send you data?

Now, that's not to say that it isn't also a hardware problem.

First, the code:

#include <SoftwareSerial.h>

byte incomingbyte;
// SoftwareSerial mySerial(4,5);                     //Configure pin 4 and 5 as soft serial port
int a=0x0000,j=0,k=0,count=0;                    //Read Starting address       
uint8_t MH,ML;
boolean EndFlag=0;
                               
void SendResetCmd();
void SendTakePhotoCmd();
void SendReadDataCmd();
void StopTakePhotoCmd();

void setup()
{ 
  Serial.begin(9600);
  Serial1.begin(9600);
  //mySerial.begin(38400);
}

void loop() 
{    
     SendResetCmd();
     delay(4000);                               //After reset, wait 2-3 second to send take picture command
      SendTakePhotoCmd();
     while(Serial1.available()>0)
      {
        incomingbyte=Serial1.read();

      }   
      byte a[32];
      while(!EndFlag)
      {  
         j=0;
         k=0;
         count=0;
         SendReadDataCmd();
         Serial.println(Serial1.available());
         while(Serial1.available()>0)
          {
               Serial.println(Serial.available());
               incomingbyte=Serial1.read();
               k++;
               if((k>5)&&(j<32)&&(!EndFlag))
               {
               a[j]=incomingbyte;
               if((a[j-1]==0xFF)&&(a[j]==0xD9))      //Check if the picture is over
               EndFlag=1;                           
               j++;
	       count++;
               }
          }
         
          for(j=0;j<count;j++)
          {   if(a[j]<0x10)
              Serial.print("0");
              Serial.print(a[j],HEX);
              Serial.print(" ");
          }                                       //Send jpeg picture over the serial port
          Serial.println();
      }      
     while(1);
}

//Send Reset command
void SendResetCmd()
{
      Serial1.write(0x56);
      Serial1.write((byte)0x00);
      Serial1.write(0x26);
      Serial1.write((byte)0x00);
}

//Send take picture command
void SendTakePhotoCmd()
{
      Serial1.write(0x56);
      Serial1.write((byte)0x00);
      Serial1.write(0x36);
      Serial1.write(0x01);
      Serial1.write((byte)0x00);  
}

//Read data
void SendReadDataCmd()
{
      MH=a/0x100;
      ML=a%0x100;
      Serial1.write(0x56);
      Serial1.write((byte)0x00);
      Serial1.write(0x32);
      Serial1.write(0x0c);
      Serial1.write((byte)0x00); 
      Serial1.write(0x0a);
      Serial1.write((byte)0x00);
      Serial1.write((byte)0x00);
      Serial1.write(MH);
      Serial1.write(ML);   
      Serial1.write((byte)0x00);
      Serial1.write((byte)0x00);
      Serial1.write((byte)0x00);
      Serial1.write(0x20);
      Serial1.write((byte)0x00);  
      Serial1.write(0x0a);
      a+=0x20;                            //address increases 32£¬set according to buffer size
//      Serial.println("photo");

}

void StopTakePhotoCmd()
{
      Serial1.write(0x56);
      Serial1.write((byte)0x00);
      Serial1.write(0x36);
      Serial1.write(0x01);
      Serial1.write(0x03);        
}

Through the SendTakePhotoCmd()/method I ask the arduino to write the specific Hex Codes (see here: https://docs.google.com/file/d/0B6Qn4nam5VvfZGY5YWZkMWItNjk2Ny00NDU2LTlkMTctOWU1MWYwMWNmYjA4/edit?usp=drive_web&pli=1, p.5) to the Camera, which, and now I could be mistaking, should return the image values to be read out via Serial1.read().

Kotton

boolean EndFlag=0;

Why are you not assigning true or false to EndFlag?

     while(Serial1.available()>0)
      {
        incomingbyte=Serial1.read();

      }

You asked the camera to take a picture. Then, you expect an immediate response. I’d ask how that’s working for you, but I already know the answer.

Even if the camera were capable of generating an immediate response, you ignore whatever that response is. Why?

              Serial.print("0");
              Serial.print(a[j],HEX);

Should be printing “0x” in front of the hex value.

Thanks for the quick response again :).

So as far as I understand you, there needs to be a delay (depending on the read/write speed) after taking the picture and that the first "serial.print("0")" should be "serial.print("0x") (typo). What I don't understand is what you mean with "ignoring the response"? That'd be the last thing I wanted to do... :)

Kotton

What I don't understand is what you mean with "ignoring the response"?

Here's the code that would, if the response was instantaneous, get the response:

     while(Serial1.available()>0)
      {
        incomingbyte=Serial1.read();
      }

Now, can you explain how you are NOT ignoring the response? Except, of course that no response actually arrives in the nanoseconds between sending the command and expecting a response.

Ok thanks, now I get it :). Would a solution to this then involve adding a delay before reading Serial1?

Ok so it really was a missing delay before reading out the data. Now it’s finally outputing Hex-data :slight_smile:

Here the code:

#include <SoftwareSerial.h>

byte incomingbyte;
// SoftwareSerial mySerial(4,5);                     //Configure pin 4 and 5 as soft serial port
int a=0x0000,j=0,k=0,count=0;                    //Read Starting address       
uint8_t MH,ML;
boolean EndFlag=0;
                               
void SendResetCmd();
void SendTakePhotoCmd();
void SendReadDataCmd();
void StopTakePhotoCmd();

void setup()
{ 
  Serial.begin(9600);
  Serial1.begin(38400);
  //mySerial.begin(38400);
}

void loop() 
{  
    int counter=0;  
     SendResetCmd();
     delay(3000);                               //After reset, wait 2-3 second to send take picture command
     SendTakePhotoCmd();
     while(Serial1.available()<1) {}
     while(Serial1.available()>0) {
     incomingbyte=Serial1.read();
     }

      byte a[32];
      int count=0;
      while(!EndFlag)
      {  
         j=0;
         k=0;
         count=0;
         SendReadDataCmd();
         delay(100);
         while(Serial1.available()>0)
          {
               incomingbyte=Serial1.read();
               k++;
               if((k>5)&&(j<32)&&(!EndFlag))
               {
               a[j]=incomingbyte;
               if((a[j-1]==0xFF)&&(a[j]==0xD9))      //Check if the picture is over
               EndFlag=1;                           
               j++;
	       count++;
               }
          }
         counter++;
          for(j=0;j<count;j++)
          {   if(a[j]<0x10)
              Serial.print("0");
              Serial.print(a[j],HEX);
              Serial.print(" ");
          }                                       //Send jpeg picture over the serial port
          Serial.println();
      }    
    Serial.println(counter);  
     while(1);
}  

//Send Reset command
void SendResetCmd()
{
      Serial1.write(0x56);
      Serial1.write((byte)0x00);
      Serial1.write(0x26);
      Serial1.write((byte)0x00);
}

//Send take picture command
void SendTakePhotoCmd()
{
      Serial1.write(0x56);
      Serial1.write((byte)0x00);
      Serial1.write(0x36);
      Serial1.write(0x01);
      Serial1.write((byte)0x00);  
}

//Read data
void SendReadDataCmd()
{
      MH=a/0x100;
      ML=a%0x100;
      Serial1.write(0x56);
      Serial1.write((byte)0x00);
      Serial1.write(0x32);
      Serial1.write(0x0c);
      Serial1.write((byte)0x00); 
      Serial1.write(0x0a);
      Serial1.write((byte)0x00);
      Serial1.write((byte)0x00);
      Serial1.write(MH);
      Serial1.write(ML);   
      Serial1.write((byte)0x00);
      Serial1.write((byte)0x00);
      Serial1.write((byte)0x00);
      Serial1.write(0x20);
      Serial1.write((byte)0x00);  
      Serial1.write(0x0a);
      a+=0x20;                            //address increases 32£¬set according to buffer size
//      Serial.println("photo");

}

void StopTakePhotoCmd()
{
      Serial1.write(0x56);
      Serial1.write((byte)0x00);
      Serial1.write(0x36);
      Serial1.write(0x01);
      Serial1.write(0x03);        
}

Now, the hex-Code which is printed gives rise to an image like this (see attachment, I simply changed the Hex-values to Grayscale values…). Any idea why?

sdf.jpg

Now, the hex-Code which is printed gives rise to an image like this

How was the hex data (it really wasn't hex data) converted to an image? Printing "0xF0", for instance, is not the same as writing F0 to the serial port. Perhaps the image creation software is expecting F0, rather than "0xF0".

Basically what the Arduino outputs is a list with values such as "F0 FF D9 09" and so on. Then I just used Labview to transform the list into a 160x80 Image-Array, which changes the Hex-Values to their corresponding 8-Bit Int, which then is turned to a Grayscale Image.

         SendReadDataCmd();
         delay(100);
         while(Serial1.available()>0)

Suppose 100 milliseconds is too long. Or not long enough. You should probably have a while loop that simply waits for the requested number of bytes (32) to become available.

Sorry to sound like a beginner (what I actually am :D), but that’d just mean to put a while(Serial1.available()<32){} in front of the other while-loop, doesn’t it? Unfortunately, it still returns similiar data:

     while(Serial1.available()<32){delay(25);}
         while(Serial1.available()>0)
          {
               incomingbyte=Serial1.read();
               k++;
               if((k>5)&&(j<32)&&(!EndFlag))
               {
               a[j]=incomingbyte;
               if((a[j-1]==0xFF)&&(a[j]==0xD9))      //Check if the picture is over
               EndFlag=1;                           
               j++;
	       count++;
               }
          }

The expected output should consist of, at minimum, 16080 numbers, which it, in addition, doesn’t. Or to be more precise: The size of the output changes, between 38032 and 410320 (desired are 40032). It’s really weird.

Kotton:
that’d just mean to put a while(Serial1.available()<32){} in front of the other while-loop, doesn’t it?

In an ideal world that would be sufficient, and I don’t know why it isn’t working in your case, but it was me I’d prefer to loop reading characters as they became available until either a complete response had been received or a timeout had expired. Async serial interfaces aren’t infinitely reliable and will occasionally corrupt or drop a byte. If your camera thinks it has sent a complete response and won’t do anything else until it gets the next command, and your sketch thinks it is still waiting for the response to the previous command, then you would have a deadlock.

If your camera interface isn’t doing what you expect then I suggest that the first step should be logging exactly what was sent to and received from the camera and see if you can understand what the responses mean.

Kotton: Basically what the Arduino outputs is a list with values such as "F0 FF D9 09" and so on. Then I just used Labview to transform the list into a 160x80 Image-Array, which changes the Hex-Values to their corresponding 8-Bit Int, which then is turned to a Grayscale Image.

So you are looking at the greyscale representation of a jpeg compresses image, what else do you expect to see. You have to decode the jpeg to see the image.

Hola, yo recién estoy probando una cámara LinkSprite (infrarojo) con arduino uno. Me pueden enviar un esquemático sobre la camara, porque aun no se quien es VCC, PWD, RX y TX , asi poderla probar. O si tuvieran un link donde me explique. Muchas Gracias.