Go Down

Topic: Problem with the new stream findUntil() (Read 3046 times) previous topic - next topic

Targettio

I really like the idea of the new stream commands and I have just got round to try them out.
I made a simple test sketch just to check I understood how it all worked

Code: [Select]

/*
Testing the new stream searching commands in Arduino 1.0

Test phrase
/?pinD2=1&pinD3=0&pinA9=128&pinA11=255

Based on the WebServerParsing example in the text finder library but adapted for serial.

*/

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  if (Serial.available() > 0) {
    int digitalRequests = 0;  // counters to show the number of pin change requests
    int analogRequests = 0;
    while(Serial.findUntil("pin", "\n\r")){ 
      char type = Serial.read(); // D or A
      int pin = Serial.parseInt();
      int val = Serial.parseInt();
      if( type == 'D') {                 
        Serial.print("Digital pin ");
        pinMode(pin, OUTPUT);
        digitalWrite(pin, val);
        //digitalRequests++;
      }
      else if( type == 'A'){                 
        Serial.print("Analog pin "); 
        analogWrite(pin, val);
        //analogRequests++;
      }
      else { 
        Serial.print("Unexpected type ");
        Serial.print(type);               
      }               
      Serial.print(pin);
      Serial.print("=");
      Serial.println(val);
    }
  }
}


But I have a problem. The serial.read after the findUntil() reads jibberish. So the sketch doesn't work. Output:
Code: [Select]

Unexpected type ÿ2=1
Unexpected type ÿ3=0
Unexpected type ÿ9=128
Unexpected type ÿ11=255


The ÿ should be A or D. I have tried having the ardiuno just parrot the serial input (char c = serial.read(); serial.print(c);) and that does read all the characters correctly. So I can only surmise that the problem some how is related to the findUntil().

PaulS

Quote
So I can only surmise that the problem some how is related to the findUntil().

Or the stuff you are sending to the serial port. What ARE you sending to the serial port?

Targettio

Sorry I am sending the test phrase (/?pinD2=1&pinD3=0&pinA9=128&pinA11=255) that is in the notes section of the sketch.


PaulS

The data that you are sending arrives slowly. The findUntil() function blocks until the requested string or terminator arrives. As soon as it does, the function returns. The serial buffer is then empty. So, you immediately read a value. Hmmm, that's a problem, don't you think.

The parseInt() function block, too, until a digit arrives, followed by zero or more other digits arrive, followed by a non-digit, which is why the data after the D or A is processed correctly.

I cheated. I looked at the source code.

Targettio

That all makes sense. But I am not sure how to get around this? A parseChar() function would do it, but that doesn't exist.

PaulS

Quote
But I am not sure how to get around this?

    while(Serial.findUntil("pin", "\n\r")){ 
      while(Serial.available() == 0) ; // wait for a character to arrive
      char type = Serial.read(); // D or A
      int pin = Serial.parseInt();
      int val = Serial.parseInt();

Targettio


Quote
But I am not sure how to get around this?

    while(Serial.findUntil("pin", "\n\r")){ 
      while(Serial.available() == 0) ; // wait for a character to arrive
      char type = Serial.read(); // D or A
      int pin = Serial.parseInt();
      int val = Serial.parseInt();



Thanks, that worked. But I need to spend some time figurering out exactly why.

PaulS

Quote
Thanks, that worked. But I need to spend some time figurering out exactly why.

Suppose you are reading over my shoulder as a type. You can't read a character before I have typed it. You must wait until I have typed the character before you can read it.

Now suppose you are watching me type, and you are supposed to hit me on the head when I type your name and kick me when I type a number.

If you were watching for me to type your name, and then had to run get the bat to whack me with, you wouldn't run off until I typed your name. The findUntil() function is waiting, patiently, for a particular string (like your name) to arrive on the serial port (be typed). It returns as soon as that happens.

When it does, there is nothing else in the port buffer (I have typed nothing else).

So, if you want to see if I type your name, followed by a question mark, for instance, you must wait until I type another character before you can tell what that character is.

The speed at which data arrives on the serial port is not much faster than I can type (especially with all the backspacing to correct mistakes).

But, when you are reading what I type, it has all already arrived on your computer, and you forget that I entered the data very slowly - much slower than you can read.

Targettio

I see. I assumed that the buffer would be full with the entire string and the findUntil() would simply find the target string and then the read() read the next item in the buffer.

But as they block, I need to wait for the buffer to refil. The while(Serial.available() == 0) line makes the arduino do nothing until there is something for the read() to pick up.

(just saying it out loud to make sure I get it)

Thanks.

PaulS

Quote
(just saying it out loud to make sure I get it)

You do.

Go Up