Pages: [1]   Go Down
Author Topic: Serial communication "protocol" with Raspberry  (Read 553 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 34
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
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
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 90
Posts: 3527
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
 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.

Code:
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
« Last Edit: April 25, 2013, 06:02:27 am by UKHeliBob » Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Offline Offline
Sr. Member
****
Karma: 9
Posts: 254
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 34
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  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

Code:
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

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
Code:
if Serial.available == 6
?
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 553
Posts: 46297
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
#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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 34
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

Code:
#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?
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 553
Posts: 46297
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 0
Posts: 34
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks a lot, u solved my "deal of the day", now i can continue my domotic software  smiley-lol
Logged

Pages: [1]   Go Up
Jump to: