4

I would like to test the contents of data received over a serial connection. In my loop() I store the data in bffr; and afterwards I would like to test to see if there are some predefined words in it.

#define BFFSZ 90
char bffr[BFFSZ];
char bffridx; 

void loop()
{
   readline();

   //- Test the bffr
       if(strstr(bffr, "CLOSED")){ //- WORKS
          Serial.println("> conn. closed");
          digitalWrite(A1, HIGH); 
       }else if(strstr(bffr, "RING")){ //- WORKS
          Serial.println("> Someone is ringing");
          digitalWrite(A2, HIGH);
       }else if(strstr(bffr, "0,7,j,BLINK")){ //- Doesn't work
          Serial.println("> Blink");
          digitalWrite(A2, HIGH);
          delay(300);
          digitalWrite(A2, LOW);
       }
}


void readline()
{
   memset(bffr,0,sizeof(bffr));
   char c;
   int i =0;
   bffridx = 0; // start at beginning


   long previousMillis = millis();
   while (1) {
     unsigned long currentMillis = millis();
     if(currentMillis - previousMillis > 20000) {
       Serial.println("TIMEOUT");
       return;
     }
     delay(2);

     c=gsm.SimpleRead2();
     //- debug only, to see if there is something received.     
     Serial.write(c);

     if (c == -1)
       continue;
     if (c == '\n')
       continue;
     if ((bffridx == BFFSZ-1) || (c == '\r')) {
       bffr[bffridx] = 0;
       return;
     }

     bffr[bffridx++]= c;
     delay(2);
   }
}

The debug-line makes that I can see the data flowing, eg when I phone the SIM.

But it looks like the buffer isn't tested properly. The first two will work, but the last test fails. It is part of a larger string: $0,7,j,BLINK,567^ But I thought the strstr(1,2) searches for 2 in 1. And as 0,7,j,BLINK, is within the haystack I assume it wil return true. But apparently not...

The gsm.SimpleRead2() comes from GSMlib and is my altered version of gsm.SimpleRead(). Instead of printing the char, I just return it so we can buffer it in the readline function.

void SIMCOM900::SimpleRead()
{

 char datain;
 if(_cell.available()>0){
   datain=_cell.read();
   if(datain>0){
     Serial.print(datain);
   }
 }
}
char SIMCOM900::SimpleRead2()
{

 char datain;
 if(_cell.available()>0){
   datain=_cell.read();
   if(datain>0){
     return datain;
   }
 }
}

Does anyone know the answer to this?

5
  • Did you check that gsm.SimpleRead2() never returns non-printable characters (ASCII 0x00-0x1F)? That could explain why you don't see anything in the debug with Serial and the searched string can then not be found.
    – jfpoilpret
    Apr 25, 2014 at 5:30
  • By the way, where does this GSM library SimpleRead2 come from? Could you provide a link?
    – jfpoilpret
    Apr 25, 2014 at 5:31
  • @jfpoilpret I've added the simpleread functions and a link to the library.
    – stUrb
    Apr 25, 2014 at 9:13
  • So there might be some strange characters in the bffr which causes the test to fail. How can I strip a string with non-printable characters?
    – stUrb
    Apr 25, 2014 at 9:13
  • 1
    If there are strange characters in the GSM output, then it is quite easy to check and skip: you can use isPrintable(c) to check it and add c to bffr only in that case. This is part of standard C library, there are many other isXxxx(c) functions defined in WCharacter.h.
    – jfpoilpret
    Apr 26, 2014 at 8:48

1 Answer 1

1

After a serial.read();, the data [as far as I can tell] is pretty much destroyed. You have two main options to accomplish this:

  • Store the data in a string when read and then reference this later. I'd do this with a global variable, that is declared outside of a method and accessible throughout your whole sketch.
  • I haven't read throughout your whole code, but, if you only need to read one character, you can use serial.peek();. This only works if you need the first character of the buffer.

Most likely, your only option would be the first bullet. I'd implement this by adding a method something like this:

String buffer_string_serial;

void setup() { //code here }

void loop() { //code here }

int serial_read_buffer() {
  while(serial.avaliable() > 0) {
    buffer_string_serial = buffer_string_serial + serial.peek();
    return serial.read();
  }
}

Then, just use serial_read_buffer();. That will act similar to serial.read();. The only difference is it will fill up the buffer_string_serial string. You'll have to clear that out after you used all the data so it doesn't get full.

4
  • That's what I've done with the readline() It stores everything in a global bffr. And afterwards I try to test it; but the testing doesn't work.
    – stUrb
    Apr 24, 2014 at 21:43
  • @stUrb Test it with expressions? I'd recommend verifying the string is exactly what you want and revisiting your testing code. Maybe print the string before testing to the serial window? Apr 24, 2014 at 21:48
  • Checking for an exact match is not easy. The protocol consists of an unique integer at the end, describing a job id: $0,7,j,JOB,ID^ so everything except the ID is know and can be tested. Does Arduino/C has some kind of regular expression test/match?
    – stUrb
    Apr 24, 2014 at 22:26
  • @stUrb I can't find built in support in the Arduino core libraries for regex, but this library here for Arduino (with pretty good documentation) might help you. Apr 24, 2014 at 22:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.