Accessing serial data stored in a buffer using a char pointer ?

Hi there,

My arduino application requires the ability to read in various commands on the arduino UART, some comprising of letters i.e. “abcON”, “abcOFF” and some alphanumeric, “sonicRead850”.

I have discovered code examples as described here: Gammon Forum : Electronics : Microprocessors : How to process incoming serial data without blocking and found them to be of great help.

// how much serial data we expect before a newline
const unsigned int MAX_INPUT = 50;    // the const variable qualifier basically makes the variable read-only

void setup ()
{
  
  Serial.begin(9600);
} // end of setup

// here to process incoming serial data after a terminator received
void process_data (char * data)    //function called process_data.  - data is declared as a pointer of type char, 
  {
    
    Serial.println (data);      // i think this works as process_data is an array which is basically a dereference to the first value of the array

  }  // end of process_data
  

void loop()  //called every clock cycle or whatever is used to determine it !!
{
static char input_line [MAX_INPUT];    //array size 50 called input_line, NB:note static pre qualifier !!!local variables are created & destroyed every time a function is called 
static unsigned int input_pos = 0;     //array index again note static qualifier, static variables persist beyond the function call & are initialised the first time the function is called
static boolean valid_Flag = false;

  if (Serial.available () > 0)         // when bytes are in the hardware buffer we run this loop,
    {
      char inByte = Serial.read ();
      if (inByte == '<')               // watch for '<' indicating start of valid command & set flag true
      {
        //Serial.println(inByte);
        valid_Flag = true;
      }
        if (valid_Flag)                // flag lets us process switch statement if true!
        {
          switch (inByte)
          {

            case '>':   // end of text
            input_line [input_pos++] = inByte;
            input_line [input_pos] = 0;  // write terminating null byte
            //input_line [0] = ' ';
            // terminator reached! process input_line here ...
            process_data (input_line);
        
            // reset buffer for next time
            input_pos = 0;  // reset index to 0 
            valid_Flag = false;
            break;
  
            case '\r':   // discard carriage return
            break;
  
            default:
            // keep adding if not full ... allow for terminating null byte
            if (input_pos < (MAX_INPUT - 1)) //-1 allows for null terminator, if input_pos index is less 49
              input_line [input_pos++] = inByte;  //write serial read inbyte to input_line and increment input_pos (index)
            break;

          }  // end of switch
        }  // end of if valid command '<'

  }  // end of incoming data

  // do other stuff here like testing digital input (button presses) ...

}  // end of loop

comments are just to help me understand, I have modifyed the original code as I want to ensure that only commands enclosed with < > tags will be accepted, the original code runs the following function to serial.print the data,

// here to process incoming serial data after a terminator received
void process_data (char * data)
  {
  // for now just display it
  Serial.println (data);
  }  // end of process_data

The char array being pointed to by a char pointer data, I am confused as how to manipulate / parse for numerials or strings using the pointer data.
Serial.print(data) can access the buffer, but when I try the following

char x = *data;
  int i=0;
  while (isdigit(x))
   { 
     i++;
     x++;

It just prints 0, I think that x = *data; is just dereferencing position 0 if the char array thus ‘<’ character, I am unsure how to increment and to parse this data, any suggestions would be most welcome.

regards
Denis

well that is not going to work.

You read a character, check if it is <, and then go and look at whether it is something else.

You can set a char * to the start of a char array:

char buffer[ 32 ]; char *buf = buffer;

You can index the pointer: buf++; // move 1 byte to the next char, if it was an int pointer it would move 2 bytes to the next int buf--; // you can go back

You can do pointer math: buf += 8; buf -= 2;

You can use string (not C++ String object but C string.h) commands to set pointers to say... find a character withing a string or a string within a string or to parse a string.

There's too many to list here when they're listed and explained elsewhere: http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html

You can treat pointers as variable memory addresses.

A valid C string ends with a NULL ( == 0 ) character.

Hi there, thanks for your suggestions, I have a grasp of what you outline

You can set a char * to the start of a char array:

char buffer[ 32 ]; char *buf = buffer;

You can index the pointer: buf++; // move 1 byte to the next char, if it was an int pointer it would move 2 bytes to the next int buf--; // you can go back

You can do pointer math: buf += 8; buf -= 2;

However in my case the pointer resides in a function "process_data()" called from, "loop()" where the char array, "static char input_line [MAX_INPUT" also resides

void process_data (char * data)    //function called process_data.  - data is declared as a pointer of type char, 
  {
    char * buff = buffer; // should buffer now = memory location 0 in char array input_line[] ? 
   
    Serial.println (data); 

}  // end of process_data

I guess I am wondering if the fact that the pointer resides within a function called by loop() & that char array is also in function loop() is this preventing me from accessing (dereferencing) indvidual memory locations within the array.

Thanks for the reference for the standard c string commands, they look much better for parsing my data

regards

Ok, looked at GoForSmoke’s post again and tried the following,

void process_data (char * data)    //function called process_data.  - data is declared as a pointer of type char, 
  {
    
    char * buffer = data;
    buffer = buffer +3;
    Serial.print("how many digits ");
    Serial.println(buffer);
    Serial.println (data);      // i think this works as process_data is an array which is basically a dereference to the first value of the array

  }  // end of process_data

In serial monitor I enter <123456789>
output
how many digits 3456789>
<123456789>

so cool buffer shifted 3 places,
tks GoForSmoke !

And a Happy Saint Patrick's Weekend to ya! Drink a Jameson's for me, willya?

One thing, just to make sure as I'm not. Make buffer[], and any arrays and variables referred to by different functions as global by defining them right up near the top above setup() even. A static inside loop() should not be visible outside loop().

Tks for the tip GoForSmoke !

I think I will manage a "drop" of Jameson or Paddy over the weekend just for yourself ;)

And I'll toast ya with ale next time I'm down at Big Jim's. It's cups there but at least it's ale.