Delimited data and com port problem

Hi

I'm using the program below to PWM 2 led's on pins 10 and 11. Using the serial monitor the code will accept strings of characters
like c100b220. the number following the "c" is what varies the brightness of the led on pin 11 and the number following the "b"
varies the brightness of an led on pin 10. This all works if I use the serial monitor to send in these strings ( with numbers between 0-255) - even if I put in strings like 12c200b30 (I put the serial read after the if( x >= '0' && x <='9') step to read spurious numbers like the leading 12 off the buffer to simulate how things would be if there was an initial mismatch between send signal and receive). It works even if I feed in a group like c200b230c30b220 etc. to simulate a continuous stream of data.

However if I use a sending program to send the strings to the arduino, it will set the brightnesses correctly - but only once - after receiving the first pair of numbers! After that, changing the sent string does nothing - the system sticks with the first set of brightnesses sent. I've used a setup like this for a single string like c200 and it works fine with a sending program but with two in I run into problems. Can anyone suggest where my error might lie. I know the sending program may be the problem but it's just a standard liberty basic program sending "c"+A$+"b"+B$ via the com port where A$ and B$ are the numbers to change the brightnesses. The code is

char x;
int result_c = 0;
int result_b = 0;//temporary store for data sent 
// a variable to store incoming integer serial data
int outputPin11 =11; // Use pin 11 (~ a PWM pin) as the output to an LED
// and 330 ohm resitor to GND.
int outputPin10 = 10;// Use pin 10 (~ a PWM pin) as the output to an LED
// and 330 ohm resitor to GND.

void setup() {
  Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
  pinMode(outputPin11, OUTPUT);
  pinMode(outputPin10, OUTPUT);
 
}

void loop() {


  while (Serial.available() > 0)// See if there are characters in 
    //the serial buffer
  {
    x = Serial.peek();

    if( x == 'c')  
    {                         
      Serial.read();  


      result_c = Serial.parseInt(); 
      Serial.println(x);

      Serial.println(result_c);  
      analogWrite(outputPin11, result_c); 

    }//end if
    if( x == 'b')  
    {                         
      Serial.read();  


      result_b = Serial.parseInt(); 

      Serial.println(x);
      Serial.println(result_b);  
      analogWrite(outputPin10, result_b); 

    }//end if


    if( x >= '0' &&  x <='9')  
    {                         
      Serial.read(); //empties the buffer of stray integers during the "while loop"

      
    } 

  }//wend                     


    // do more stuff here


}

Am I doing something wrong with the arduino code - does there need to be a delay somewhere to help the data through?

Thank you for any help.

A thought - does your sender program read the responses - if not they might be
buffered up and stall progress, and if so and you use blocking reads they might
block.

does there need to be a delay somewhere to help the data through?

Absolutely not. What is needed is an end of packet marker. You then read and store data until the end of packet marker arrives. When the end of packet marker arrives, you parse the data.

I use < as the start of packet marker, and > as the end of packet marker, and this code to collect the data:

#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';
  }
}

Sending something like "<c200,b150>" results in inData containing "c200,b150", which strtok() can parse into "c200" and "b150". Once you look at the first letter, to know how to use the value, change the first letter to a space, and then call atoi() on the token, to get an int. Use the int based on the overwritten first letter.

or you could set the serial monitor so that it does not send cr/lf which it does by default and which

    if( x >= '0' &&  x <='9')  
    {                         
      Serial.read(); //empties the buffer of stray integers during the "while loop"

      
    }

will stick on. Or you could fix the above code so that you ignore any thing until peek() sees a 'b' or 'c'.

Mark

Hi Mark
Thank you.
The sender program doesn't read the responses. I also thought I'd set peek to ignore anything except a "c" or a "b"?

Thank you PaulS I will study your program in detail and try it out. Also I have not used the atoi() and strtok() yet to parse data.