Serial Communication (Verifying Incoming data)

Hello All,

I am working on a project which is using 2 serial devices, in particular a finger print scanner and a camera as well as both of these devices use the RS232 communication protocol. The communication type they use is packet communication, where you have a header -> command -> data -> etc.. With each packet sent to the device for certain commands there will be an acknowledgement. I have most of this working.. however; I have encountered a small problem.

As I stated above, the devices use packet communication where if I send a command to it then it will acknowledge that command as well as pass some information like: successs/fail. Here is a picture from my logic analyzer:

( the image seems to clip off... go here for the full image: http://i26.tinypic.com/1dyixw.jpg )

Here is some information about the labels:

(ALL TTL LOGIC BELOW)
Tx : This is the data coming from my Arduino Mega to the device
Rx : What the device is sending back (converted from rs232 to TTL using a MAX232 SIPEX IC)
ARR OUT : This is the information I have stored into an array (res) which is defined in the code below...

// This function is to synchronize with the camera

void cam_sync()
{
  char test[20];
  char res[12]={
    0  };
  char com[6] = { 
    0xAA, 0x0D, 0x00, 0x00, 0x00, 0x00   };
  int count = 0;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("-Synchronization-");
  lcd.setCursor(0,1);
  lcd.print("Att Connection");
  lcd.setCursor(0,2);
  lcd.print("Please wait...");
  //delay(1000);


  // send until a response is returned
  Serial3.flush();
  for(int i =0;i<6;i++)
    Serial3.print(com[i]);

  while(Serial3.available() < 0)
  {
    for(int i =0;i<6;i++)
      Serial3.print(com[i]);
    lcd.setCursor(0,3);
    lcd.print("Waiting for response");
    delay(1000);
    count++;

    //if(count == 10)
     // break;
  }
  lcd.setCursor(0,3);
  lcd.print("Data Found...");
  for(int i =0; i<12;i++)
    res[i]=char(Serial3.read());
  if((res[0] == 0xAA) && (res[1] == 0x0E) && (res[2] == 0x0D) && (res[4] == 0x00) && (res[5] == 0x00)
    && (res[6] == 0xAA) && (res[7] == 0x0D) && (res[8] == 0x00) && (res[9] = 0x00) && (res[10] == 0x00) && (res[11] == 0x00))
    {
      lcd.setCursor(0,3);
      lcd.print("Connection Successful");
      delay(4000);
    }
    // print what is in the array to serial port # 2
    for(int i =0; i<12;i++)
    Serial2.print(res[i]);
  //for(int i =0; i<12;i++)
    //Serial.print(res[i]);

  Serial3.flush();
  delay(5000);
}

When executing this function all I see is "Data Found..." when according to the output of my logic analyzer, it should be going into the if statement that checks all the bytes and outputs "Connection Successful" Here is the datasheet to the camera:

*NOTE XX means that it does not matter what that byte it (According to the datasheet) which can be found here:

http://www.saelig.com/product/BOVI001.htm

I am stumped as to why it's not going into the if statement, if infact all that information is exactly what is output onto the serial port, which i display for debugging purposes.

If anyone could potentially lend a hand to help me solve this problem I would be eternally grateful.

Thanks,
Jox :slight_smile:

A few things:
First, when posting code, please use the # button on the editor's toolbar.

 while(Serial3.available() < 0)

I thought "available" only returned zero or positive values.

for(int i =0; i<12;i++)
   res[i]=char(Serial3.read());

You haven't checked to see if you have 12 characters to read, but you read them anyway.

if((res[0] == 0xAA) && (res[1] == 0x0E) && (res[2] == 0x0D) && (res[4] == 0x00) && (res[5] == 0x00)
   && (res[6] == 0xAA) && (res[7] == 0x0D) && (res[8] == 0x00) && (res[9] = 0x00) && (res[10] == 0x00) && (res[11] == 0x00))

We programmers are a lazy bunch - have a look to see if memcmp would decrease the amount of typing here.

A couple more points. You have an lcd attached. Echo the characters read from the serial port. That may give you a big clue right there.

Using Serial.flush() is a sure sign that you don't know what you are doing. If something is sending you data, and you are writing code to receive that data, why are you randomly dumping unread data?

@ Groove

Thank you I will use the "#" to submit my code from now on.

As for the question about my code, the main idea is that I continue sending that command until I get a response from the device, which should fill the input buffer on Serial port #3. Should there be bytes available from a response, which is determined by Serial3.Available(), then break from that while loop and begin reading them. Otherwise should NOTHING be in the input buffer continue sending that command.

@ PaulS

The Serial3.flush() was merely a safety precaution from the results that I observed from my logic analyzer. During the first time I was sending the command, nothing would be received and serial2 would have 0xFF 12 times (empty). As for the last Flush at the end, I did this to ensure that if it was not (0xFF), which is why i dump it at the end. During the second time, I would get the response I was looking for. However; I don't claim to be an expert in hardware interfacing, so please don't be too rough on me, there is always things to learn and techniques to utilize. Which can be learned from other people.

Also the Serial3.flush() was one of the last things I added, which was probably also a result of frustration and not thinking straight... :-/

Groove's (valid) point was that Serial::available() only returns 0 or positive, so the while(Serial3.available() < 0) block will never be executed. That is, your code is not waiting for a response. As soon as Serial3.available() reports that there is no data available, you start reading that (non-existent) data.

You need to assure that there is data available, first. I think that once you take care of that problem (whether it is a coding issue, the wrong command sent to the camera, a wiring issue that prevents communicating with the camera, etc.), the rest of the problems will be resolved, too.

How are the finger-print detector and camera connected to the Arduino?

@PaulS

I'll look into groove's recommendation. As for the data issue, each device is connected to its own serial port. In particular, the finger print scanner is connected to 0th Serial port(RX and TX) where as the Camera is connected to the 3rd Serial Port (RX3 and TX3).

Also how would I go about using memcmp() in my if statement which checks all the bytes?

Are the grounds of all three devices connected?

Also how would I go about using memcmp() in my if statement which checks all the bytes?

Have you met my friend google?

Yes, they are all sharing the same common ground.

Well, I'm a tad confused, I've been looking up memcmp() and it shows that you can compare an array with another array.

However this is my situation:

I send (6 Bytes):

0xAA 0x0D 0x00 0x00 0x00 0x00

I should receive (12 Bytes):

0xAA 0x0E 0x0D xx 0x00 0x00 0xAA 0x0D 0x00 0x00 0x00 0x00

** Where xx is the neglect-able byte.

However there is an immediately problem: I can't do array to array comparison because I need to negate the 4th byte in the response. I tried to do just do a comparison of the results in the direct array. However; this does not work. I'm trying to use memcmp() but can't seem to wrap my head around how to implement it in this particular situation.

As can be noted in my code in this segment:

while(!Serial3.available())
  {
    for(int i =0;i<6;i++)
      Serial3.print(com[i],BYTE);
    lcd.setCursor(0,3);
    lcd.print("Waiting for response");
    delay(1000);
    //count++;

    //if(count == 10)
     // break;
  }
  lcd.setCursor(0,3);
  lcd.print("Data Found...");
  for(int i =0; i<12;i++)
    res[i]=Serial3.read();
    lcd.setCursor(0,3);
    lcd.print("Data Found...A");
  if((res[0] == 0xAA) && (res[1] == 0x0E) && (res[2] == 0x0D) && (res[4] == 0x00) && (res[5] == 0x00)
    && (res[6] == 0xAA) && (res[7] == 0x0D) && (res[8] == 0x00) && (res[9] = 0x00) && (res[10] == 0x00) && (res[11] == 0x00))
    //if( memcmp(
    {
      lcd.setCursor(0,3);
      lcd.print("Connection Successful");
      delay(4000);
    }

While there is no serial information available, keep sending the command until I get a response, which is what this segment should be doing.

You are comparing res[0] through res[2] to fixed values. The memcmp function can do that.

Then, you are comparing res[4] through res[11] to fixed values. The memcmp function can do that.

The arguments to the memcmp function are the start of the arrays to compare, and the number of elements.

int part1 = memcmp(res[0], goodRes1, 3);
int part2 = memcmp[res[4], goodRes2, 8);

I tried that exact code, however it complains about an invalid conversion from 'unsigned char' to 'const void'. Been doing reading and it looks like you need to have pointers pointing to the arrays. I'm trying to do this, but to no avail.

You could create a pointer to point to the 4th position of the res array, and pass that pointer to memcmp. Try this:

char *res0 = res[0];
char *res4 = res[4];
memcmp(res0, goodRes1, 3);
memcmp(res4, goodRes2, 8);