Serial communication "protocol" with Raspberry

Hy guys,

i found some problems in reading correctly messages sent from my raspberry pi thoward the serial port to my dear 2009:

for the purpose of my domotic system i would like to read messages in the form "l00:99" (light number 0 is on) "t05:26" (temperature sensor number 6 says 26 degrees).

I wont post the whole messy domotic code but just only the "matter" part:

char command[6], inChar;
int i = 0;
void setup() {
  Serial.begin(9600);
  Serial.flush();
  pinMode(13, OUTPUT);
}


void loop() {
  if ((Serial.available() > 0)) 
  {
  for (i = 0; i<=7; i++)
  {
    inChar = Serial.read();
    command[i] = inChar;
  }
  }
  
  if (command == "l00:99") {digitalWrite(13, HIGH);}
}

the problem is that even if i type the command (l00:99), it does not turn the led on, probably it is a \n \r matter, but i cant get it, anyone can help?

thanks

 for (i = 0; i<=7; i++)reads 8 characters into the command array, whether or not there are 8 characters available and doesn't terminate it, then you test the array against a literal that has only got 6 characters. Will that work ?

As a first step try printing your command array before doing the test. Print a delimiter immediately before and after so that can see how many characters are in the array.

Serial.print(">";
Serial.print(command);
Serial.println("<";

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=11425&page=1 would be a good page for you to read

if (command == "l00:99") {digitalWrite(13, HIGH);}

That is not how to check if strings are equal. "l00:99" creates the char array {'l','0','0',':','9','9','\0'} and then returns a pointer to it. When you type command=="l00:99" you are checking if the address of command is equal to the address of that array, which it definitely will not. The way to check strings is to either use a for loop checking your command variable character by character, or use a built in function like strcmp, which does this same process for you.
The other problem, as UKHeliBob mentioned, is that you try and read 8 characters from the Serial port but only check if there are 1 or more available, the rate at which this loop will run you'll read each character in a separate loop iteration

UKHeliBob:
  for (i = 0; i<=7; i++)reads 8 characters into the command array, whether or not there are 8 characters available and doesn't terminate it, then you test the array against a literal that has only got 6 characters. Will that work ?

no, i tried 5, 6 7 and 8 in order to avoid those problems but none worked

tobyb121:

if (command == "l00:99") {digitalWrite(13, HIGH);}

That is not how to check if strings are equal. "l00:99" creates the char array {'l','0','0',':','9','9','\0'} and then returns a pointer to it. When you type command=="l00:99" you are checking if the address of command is equal to the address of that array, which it definitely will not. The way to check strings is to either use a for loop checking your command variable character by character, or use a built in function like strcmp, which does this same process for you.

actually i have also tried before strcmp(command, "l00:99") == 0, but it did not worked too

tobyb121:
The other problem, as UKHeliBob mentioned, is that you try and read 8 characters from the Serial port but only check if there are 1 or more available, the rate at which this loop will run you'll read each character in a separate loop iteration

should i say if Serial.available == 6?

Why doesn't the Raspberry send data intelligently? That is, with start and end of packet marker, and delimiters between the values? That would make parsing a lot easier.

The code you have now is not creating strings. It is simply populating char arrays, so none of the string functions, like strcmp(), can be used.

Each time you store a character in the array, you need to store a NULL in the array, too.

If you get the Raspberry whipped into shape, some code like this will read all the serial data, as fast (or slow) as it arrives:

#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

Where it says "Process the packet" is where you would use strcmp() (or, more intelligently strtok() and atoi()) to deal with what was in the packet.

paul, thanks a lot your posts are always full of infos!

i tried to test your program but i am probably missing something in sending the command via serial:

#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(9600);
   pinMode(13, OUTPUT);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }
  if (strcmp(inData, "loo:99" ) == 0) {digitalWrite(13, HIGH);}
  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

i typed l00:99 and nothing happend, what's the deal?

You need to move the code to compare the string to INTO the if(started && ended) block.

thanks a lot, u solved my "deal of the day", now i can continue my domotic software XD