Using Serial.Read()

Hey there,

I am working on a project where a pro Trinket is sending data (32 values from 0-16) to an Arduino. The Programm does a check before the data is read and when it is finished. My Problem is that the Arduino doesn’t seem to read the checks or any data because it doesnt enter the if statements…

Here is a sample from the Serial Monitor, so you know what the arduino is being fed:

M161612119987677285762607270667660205
M1616121110988766625560565555022000005
M1616121110987777282665607262667556566
M161612119988575682570722550566860072
M1616121110886757577060656272667755000
M161612119978766660660655260555660252
M16161211101099989898662066055527676555
M161612119987676767560565060657765200
M161614141312121212111191010988887798765776256
M16161211109887676÷61615151414141413141412111313131212121212131291112121112111111
M1616151414141413131413121313121213131212131212121212121212121212
M161614141413131313131212121212121211111111111111101010109998
M1616151514131414131314131312131313121112131211121212121212121212
M1616151414141413131313131313131212131212121212121212121212121212
M1616151414141413131313131313121212121212121211111111111110997

/*
     Arduino - Processing Real Time Spectrum Analyzer
This program is intended output a FFT on a RGB matrix
The program is based on the adafruit RGB matrix library: https://learn.adafruit.com/32x16-32x32-rgb-led-matrix/
The FFT results in the complimentary processing code handles 32 bands 

More information, including full parts list and videos of the final product can be seen on 12vtronix.com
Youtube video sample: https://www.youtube.com/watch?v=X35HbE7k3DA
           Created: 22nd Sep 2013 by Stephen Singh
     Last Modified: 10th May 2014 by Stephen Singh
     
     Variables with the <-O-> symbol indicates that it can be adjusted for the reason specified
*/



#include <avr/pgmspace.h>
#include <Adafruit_GFX.h>   // Core graphics library
#include <RGBmatrixPanel.h> // Hardware-specific library

#define CLK 8  // MUST be on PORTB!
#define LAT A3
#define OE  9
#define A   A0
#define B   A1
#define C   A2
// Last parameter = 'true' enables double-buffering, for flicker-free,
// buttery smooth animation.  Note that NOTHING WILL SHOW ON THE DISPLAY
// until the first call to swapBuffers().  This is normal.
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, true);


// <-O-> the values after "matrix.Color333" represent the RGB values with 7 being the brightest value for that particular colour

void lightcolumns(int rownum, int amplitude)
{
  if(amplitude>15)  // <-O-> set the threshold for the band to turn red
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(7, 0, 0));
  }
  for(int y = amplitude; y <16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  }
  
  else if(amplitude>13) // <-O-> set the threshold for the band to turn yellow
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(4, 4, 0));
  }
  for(int y = amplitude; y < 16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  }
  
  else if(amplitude>9) // <-O-> set the threshold for the band to turn green
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(0, 5, 0));
  }
  for(int y = amplitude; y < 16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  } 
  
  else
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 7));
  }
  for(int y = amplitude; y < 16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  } 
}


void setup() 
{ 
  matrix.begin();  
  Serial.begin(115200);
  delay(1000);
}





void loop() {

    while (Serial.available() > 0) {

  if (Serial.read() == 'M'){
    
    int led1 = Serial.parseInt();    
    int led2 = Serial.parseInt(); 
    int led3 = Serial.parseInt();  
    int led4 = Serial.parseInt(); 
    int led5 = Serial.parseInt(); 
    int led6 = Serial.parseInt();  
    int led7 = Serial.parseInt(); 
    int led8 = Serial.parseInt(); 
    int led9 = Serial.parseInt();    
    int led10 = Serial.parseInt(); 
    int led11 = Serial.parseInt();  
    int led12 = Serial.parseInt(); 
    int led13 = Serial.parseInt(); 
    int led14 = Serial.parseInt();  
    int led15 = Serial.parseInt(); 
    int led16 = Serial.parseInt(); 
    int led17 = Serial.parseInt();    
    int led18 = Serial.parseInt(); 
    int led19 = Serial.parseInt();  
    int led20 = Serial.parseInt(); 
    int led21 = Serial.parseInt(); 
    int led22 = Serial.parseInt();  
    int led23 = Serial.parseInt(); 
    int led24 = Serial.parseInt(); 
    int led25 = Serial.parseInt();  
    int led26 = Serial.parseInt(); 
    int led27 = Serial.parseInt();  
    int led28 = Serial.parseInt(); 
    int led29 = Serial.parseInt(); 
    int led30 = Serial.parseInt();  
    int led31 = Serial.parseInt(); 
    int led32 = Serial.parseInt(); 

      
    if (Serial.read() == '\n'){

      lightcolumns(31, led1);
      lightcolumns(30, led2);
      lightcolumns(29, led3);
      lightcolumns(28, led4);
      lightcolumns(27, led5);
      lightcolumns(26, led6);
      lightcolumns(25, led7);
      lightcolumns(24, led8);
      lightcolumns(23, led9);
      lightcolumns(22, led10);
      lightcolumns(21, led11);
      lightcolumns(20, led12);
      lightcolumns(19, led13);
      lightcolumns(18, led14);
      lightcolumns(17, led15);
      lightcolumns(16, led16);
      lightcolumns(15, led17);
      lightcolumns(14, led18);
      lightcolumns(13, led19);
      lightcolumns(12, led20);
      lightcolumns(11, led21);
      lightcolumns(10, led22);
      lightcolumns(9, led23);
      lightcolumns(8, led24);
      lightcolumns(7, led25);
      lightcolumns(6, led26);
      lightcolumns(5, led27);
      lightcolumns(4, led28);
      lightcolumns(3, led29);
      lightcolumns(2, led30);
      lightcolumns(1, led31);
      lightcolumns(0, led32);
    
          matrix.swapBuffers(false);
           }    
        }
    }  
}

Thanks in Advance

Greetings Flitschi

    int led1 = Serial.parseInt();

In this stream of data, where does the int end?

M161612119987677285762607270667660205

Does that number look like it fits in an int? Not that it really matters, because the stupidly named function returns a long. But, that number won't fit in a long, either.

Whatever is sending this data needs a serious overhaul. When you get done with that, let us know what additional help, if any, you need.

What does the ÷ symbol signify?

Here is the Code from the trinket

/*
  fft_adc.pde
  guest openmusiclabs.com 8.18.12
  example sketch for testing the fft library.
  it takes in data on ADC0 (Analog0) and processes them
  with the fft. the data is sent out over the serial
  port at 115.2kb.  there is a pure data patch for
  visualizing the data.
*/

#define LOG_OUT 1 // use the log output function
#define FFT_N 64 // set to 64 point fft


#include <FFT.h> // include the library

int freq_array[32];

void setup() {
  Serial.begin(115200); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}

void loop() {
  while (1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 124 ; i += 2) { // save 64 samples
      while (!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fft_input[i] = k; // put real data into even bins
      fft_input[i + 1] = 0; // set odd bins to 0
    }
    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_log(); // take the output of the fft


    // Amplitude Ranges  if else tree

    for (int j = 0; j < 32; j++) {
    if (fft_log_out[j] < 2000 && fft_log_out[j] > 180) {
      freq_array[j] = 16;
    }
    else {
      if (fft_log_out[j] <= 180 && fft_log_out[j] > 160) {
        freq_array[j] = 15;
      }
      else {
        if (fft_log_out[j] <= 160 && fft_log_out[j] > 130) {
          freq_array[j] = 14;
        }
        else {
          if (fft_log_out[j] <= 130 && fft_log_out[j] > 110) {
            freq_array[j] = 13;
          }
          else {
            if (fft_log_out[j] <= 110 && fft_log_out[j] > 90) {
              freq_array[j] = 12;
            }
            else {
              if (fft_log_out[j] <= 90 && fft_log_out[j] > 70) {
                freq_array[j] = 11;
              }
              else {
                if (fft_log_out[j] <= 70 && fft_log_out[j] > 60) {
                  freq_array[j] = 10;
                }
                else {
                  if (fft_log_out[j] <= 60 && fft_log_out[j] > 50) {
                    freq_array[j] = 9;
                  }
                  else {
                    if (fft_log_out[j] <= 50 && fft_log_out[j] > 40) {
                      freq_array[j] = 8;
                    }
                    else {
                      if (fft_log_out[j] <= 40 && fft_log_out[j] > 30) {
                        freq_array[j] = 7;
                      }
                      else {
                        if (fft_log_out[j] <= 30 && fft_log_out[j] > 20) {
                          freq_array[j] = 6;
                        }
                        else {
                          if (fft_log_out[j] <= 20 && fft_log_out[j] > 15) {
                            freq_array[j] = 5;
                          }
                          else {
                            if (fft_log_out[j] <= 15 && fft_log_out[j] > 11) {
                              freq_array[j] = 4;
                            }
                            else {
                              if (fft_log_out[j] <= 11 && fft_log_out[j] > 8) {
                                freq_array[j] = 3;
                              }
                              else {
                                if (fft_log_out[j] <= 8 && fft_log_out[j] > 5) {
                                  freq_array[j] = 2;
                                }
                                else {
                                  if (fft_log_out[j] <= 5 && fft_log_out[j] > 2) {
                                    freq_array[j] = 1;
                                  }
                                  else {
                                    if (fft_log_out[j] <= 2 && fft_log_out[j] >= 0) {
                                      freq_array[j] = 0;
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

 
  Serial.write('M');
 for (int k = 0; k < 32; k++) {
  Serial.print(freq_array[k]);
 }
  Serial.write('\n');
  }

}
Serial.write('M');
for (int k = 0; k < 32; k++) {
  Serial.print(freq_array[k]);
}
Serial.write('\n');

Seriously how do you want to parse that once spit out this way??

M[color=red]16[/color][color=blue]16[/color][color=green]12[/color][color=red]11[/color]...
M[color=red]1[/color][color=blue]6[/color][color=green]1[/color][color=red]6[/color][color=blue]1[/color][color=green]2[/color]...

if you receive 161612 how do you know if it’s twice 16 and 12 or 1, 6, 1, 6, 1, 2 or 16,16,1,2…

Yeah that kinda makes sense

So If I change the code on the trinket to:

  Serial.write('M');
 for (int k = 0; k < 32; k++) {
  Serial.write('S');
  Serial.print(freq_array[k]);
 }
  Serial.write('\n');
  }

And on the Arduino to (I declared led as: int led[32]):

void loop() {

  if (Serial.read() == 'M'){
    
    for (int z=0; z<32;z++){
      if (Serial.read() == 'S'){
    led[z] = Serial.parseInt();    
    }}

      
    if (Serial.read() == '\n'){

      lightcolumns(31, led[0]);
      lightcolumns(30, led[1]);
      lightcolumns(29, led[2]);
      lightcolumns(28, led[3]);
      lightcolumns(27, led[4]);
      lightcolumns(26, led[5]);
      lightcolumns(25, led[6]);
      lightcolumns(24, led[7]);
      lightcolumns(23, led[8]);
      lightcolumns(22, led[9]);
      lightcolumns(21, led[10]);
      lightcolumns(20, led[11]);
      lightcolumns(19, led[12]);
      lightcolumns(18, led[13]);
      lightcolumns(17, led[14]);
      lightcolumns(16, led[15]);
      lightcolumns(15, led[16]);
      lightcolumns(14, led[17]);
      lightcolumns(13, led[18]);
      lightcolumns(12, led[19]);
      lightcolumns(11, led[20]);
      lightcolumns(10, led[21]);
      lightcolumns(9, led[22]);
      lightcolumns(8, led[23]);
      lightcolumns(7, led[24]);
      lightcolumns(6, led[25]);
      lightcolumns(5, led[26]);
      lightcolumns(4, led[27]);
      lightcolumns(3, led[28]);
      lightcolumns(2, led[29]);
      lightcolumns(1, led[30]);
      lightcolumns(0, led[31]);
    
          matrix.swapBuffers(false);
           }    
    }  
}

Should fix it right?

Why not use leading zeroes for numbers less than 10?
That way, you can assume numbers arrive as pairs of digits.
Unless they arrive as ÷ symbols.

Or as a single hex digit.

void loop() {

while (Serial.available() > 0) {

if (Serial.read() == 'M'){

int led1 = Serial.parseInt();

Revise your method to read the entire data stream into a buffer first than analyze your buffer.
The way you have it you assuming the first character is M and Serial.read() removes one character from its own buffer after it is read so you cannot access / analyze it again.
There are other options in API when you use buffer - number of characters expected, timeout , terminating character.
Depending on your requirement you can read all data in one shot (while loop) or one character at time ( combine while with if) if you need to have non- blocking collecting of data.

But the key is - collect data it into your own buffer first and when done collecting than analyze it.
Jim

You might get some ideas from Serial Input Basics - updated.

It basically contains examples how you can receive data but it also contains examples how to split and parse.

Create a sender that matches the receiver.

it's not a love letter :slight_smile: -> Just write in binary and read in binary. why do you want any ASCII in there? each byte will be a number between 0x00 and 0x10. computers don't need real text when they exchange information...

You will need a start and or end marker - since you are sending bytes of value between 0x00 and 0x10 you can't use CR (0x0D) or LF (0x0A) you could use anything with the most significant bit(s) set so that it's easy with a mask to sport start and end or use '[' and ']' which are 0x5B and 0x5D or {}

J-M-L:
Just write in binary and read in binary. why do you want any ASCII in there?

Sending data in human readable form makes debugging much easier. I would only send binary data if that is essential to achieve the required throughput. And it is not difficult to encode large numbers into printable characters to shorten messages.

Even if I was sending binary data I would surround it with start- and end-markers to make the transmission and reception reliable.

...R

I revised my code with the help of sterretje’s link. It’s still not working :confused:
How does the serial.read function know how much to read of the stream?
Send Code

/*
  fft_adc.pde
  guest openmusiclabs.com 8.18.12
  example sketch for testing the fft library.
  it takes in data on ADC0 (Analog0) and processes them
  with the fft. the data is sent out over the serial
  port at 115.2kb.  there is a pure data patch for
  visualizing the data.
*/

#define LOG_OUT 1 // use the log output function
#define FFT_N 64 // set to 64 point fft


#include <FFT.h> // include the library

int freq_array[33];

void setup() {
  Serial.begin(115200); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}

void loop() {
  while (1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 124 ; i += 2) { // save 64 samples
      while (!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fft_input[i] = k; // put real data into even bins
      fft_input[i + 1] = 0; // set odd bins to 0
    }
    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_log(); // take the output of the fft


    // Amplitude Ranges  if else tree

    for (int j = 0; j < 32; j++) {
    if (fft_log_out[j] < 2000 && fft_log_out[j] > 180) {
      freq_array[j] = 16;
    }
    else {
      if (fft_log_out[j] <= 180 && fft_log_out[j] > 160) {
        freq_array[j] = 15;
      }
      else {
        if (fft_log_out[j] <= 160 && fft_log_out[j] > 130) {
          freq_array[j] = 14;
        }
        else {
          if (fft_log_out[j] <= 130 && fft_log_out[j] > 110) {
            freq_array[j] = 13;
          }
          else {
            if (fft_log_out[j] <= 110 && fft_log_out[j] > 90) {
              freq_array[j] = 12;
            }
            else {
              if (fft_log_out[j] <= 90 && fft_log_out[j] > 70) {
                freq_array[j] = 11;
              }
              else {
                if (fft_log_out[j] <= 70 && fft_log_out[j] > 60) {
                  freq_array[j] = 10;
                }
                else {
                  if (fft_log_out[j] <= 60 && fft_log_out[j] > 50) {
                    freq_array[j] = 9;
                  }
                  else {
                    if (fft_log_out[j] <= 50 && fft_log_out[j] > 40) {
                      freq_array[j] = 8;
                    }
                    else {
                      if (fft_log_out[j] <= 40 && fft_log_out[j] > 30) {
                        freq_array[j] = 7;
                      }
                      else {
                        if (fft_log_out[j] <= 30 && fft_log_out[j] > 20) {
                          freq_array[j] = 6;
                        }
                        else {
                          if (fft_log_out[j] <= 20 && fft_log_out[j] > 15) {
                            freq_array[j] = 5;
                          }
                          else {
                            if (fft_log_out[j] <= 15 && fft_log_out[j] > 11) {
                              freq_array[j] = 4;
                            }
                            else {
                              if (fft_log_out[j] <= 11 && fft_log_out[j] > 8) {
                                freq_array[j] = 3;
                              }
                              else {
                                if (fft_log_out[j] <= 8 && fft_log_out[j] > 5) {
                                  freq_array[j] = 2;
                                }
                                else {
                                  if (fft_log_out[j] <= 5 && fft_log_out[j] > 2) {
                                    freq_array[j] = 1;
                                  }
                                  else {
                                    if (fft_log_out[j] <= 2 && fft_log_out[j] >= 0) {
                                      freq_array[j] = 0;
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

 freq_array[32]='n';
  Serial.write('M');
 for (int k = 0; k < 33; k++) {
  Serial.print(freq_array[k]);
 }

  }

}

Receiving Code

#include <Adafruit_GFX.h>   // Core graphics library
#include <RGBmatrixPanel.h> // Hardware-specific library

#define CLK 8  // MUST be on PORTB!
#define LAT A3
#define OE  9
#define A   A0
#define B   A1
#define C   A2
// Last parameter = 'true' enables double-buffering, for flicker-free,
// buttery smooth animation.  Note that NOTHING WILL SHOW ON THE DISPLAY
// until the first call to swapBuffers().  This is normal.
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);

const byte numChars = 33;
int led[numChars];


// <-O-> the values after "matrix.Color333" represent the RGB values with 7 being the brightest value for that particular colour

void lightcolumns(int rownum, int amplitude)
{
  if(amplitude>15)  // <-O-> set the threshold for the band to turn red
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(7, 0, 0));
  }
  for(int y = amplitude; y <16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  }
  
  else if(amplitude>13) // <-O-> set the threshold for the band to turn yellow
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(4, 4, 0));
  }
  for(int y = amplitude; y < 16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  }
  
  else if(amplitude>9) // <-O-> set the threshold for the band to turn green
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(0, 5, 0));
  }
  for(int y = amplitude; y < 16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  } 
  
  else
  {
  for( int y = 0; y < amplitude; y++){
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 7));
  }
  for(int y = amplitude; y < 16; y++)
  {
  matrix.drawPixel(rownum, y, matrix.Color333(0, 0, 0));  
  }
  } 
}


void setup() 
{ 
  matrix.begin();  
  Serial.begin(115200);
  delay(1000);
}

// Example 2 - Receive with an end-marke



void loop() {
    recvWithEndMarker();
}

void recvWithEndMarker() {
    static byte ndx = 0;
    int endMarker = '\n';
    int rc;
  
    while (Serial.available() > 0) {
      if (Serial.read() == 'M'){
        
        rc = Serial.read();

        if (rc != endMarker) {
            led[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
           led[ndx] = '\0'; // terminate the string
             if (led[ndx] == '\0'){

      lightcolumns(31, led[0]);
      lightcolumns(30, led[1]);
      lightcolumns(29, led[2]);
      lightcolumns(28, led[3]);
      lightcolumns(27, led[4]);
      lightcolumns(26, led[5]);
      lightcolumns(25, led[6]);
      lightcolumns(24, led[7]);
      lightcolumns(23, led[8]);
      lightcolumns(22, led[9]);
      lightcolumns(21, led[10]);
      lightcolumns(20, led[11]);
      lightcolumns(19, led[12]);
      lightcolumns(18, led[13]);
      lightcolumns(17, led[14]);
      lightcolumns(16, led[15]);
      lightcolumns(15, led[16]);
      lightcolumns(14, led[17]);
      lightcolumns(13, led[18]);
      lightcolumns(12, led[19]);
      lightcolumns(11, led[20]);
      lightcolumns(10, led[21]);
      lightcolumns(9, led[22]);
      lightcolumns(8, led[23]);
      lightcolumns(7, led[24]);
      lightcolumns(6, led[25]);
      lightcolumns(5, led[26]);
      lightcolumns(4, led[27]);
      lightcolumns(3, led[28]);
      lightcolumns(2, led[29]);
      lightcolumns(1, led[30]);
      lightcolumns(0, led[31]);
    
          matrix.swapBuffers(false);
           }    
            ndx = 0;
        }
    }
}
}

You should not have all that lightcolumns(31, led[0]); stuff in the recvWithEndMarker() function. That code should go into a separate function - perhaps called lightMyLEDs()

And you need to learn about arrays.

...R

Robin2:
Sending data in human readable form makes debugging much easier. I would only send binary data if that is essential to achieve the required throughput. And it is not difficult to encode large numbers into printable characters to shorten messages.

Even if I was sending binary data I would surround it with start- and end-markers to make the transmission and reception reliable.

...R

In global context I could agree, but here I disagree when it's for a short data message fitting in bytes of data at a time. Much easier to read than ASCII, no messing around with adding separators and parsing, less risk of stuffing the Serial buffer, etc... but Yes as I said "You will need a start and or end marker"

How does the serial.read function know how much to read of the stream?

It is rather simple - your can read convoluted write-ups by experts, than futz around with end markers etc . or use tools available to you.

Here is a more direct reference since my previous remarks did not take.
I guess because I did not put it in code brackets, my apology. .

https://www.arduino.cc/en/Serial/ReadBytesUntil

I'd still like to know what the ÷ symbol signifies.

julyjim:
How does the serial.read function know how much to read of the stream?

It is rather simple - your can read convoluted write-ups by experts, than futz around with end markers etc . or use tools available to you.

Here is a more direct reference since my previous remarks did not take.
I guess because I did not put it in code brackets, my apology. .

https://www.arduino.cc/en/Serial/ReadBytesUntil

Julyjim - this is true. that function exists and serves a purpose.

you call it this way:

readBytesUntil([color=red]char[/color] terminator, char *buffer, size_t length)

I don’t like it because

1/ you handover timeout management to the function rather than being able to do other things while waiting for your full string to arrive. (imagine getting GPS data while flying your quadcopter with that function !)

2/ in my view it has a bug/hidden limitation that is not in the documentation. this is the code

size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
{
  if (length < 1) return 0;
  size_t index = 0;
  while (index < length) {
    int c = timedRead();
    if (c < 0 || c == terminator) break;
    *buffer++ = (char)c;
    index++;
  }
  return index; // return number of characters, not including null terminator
}

Notice how c is declared as an int because that’s what the read() function returns to detect the -1

now try this code

void setup() {
  int c = 0x80; // an int like theirs
  char terminator = c;
  Serial.begin(115200);
  if ( c == terminator) Serial.println("they are equal");
  else Serial.println("they are different");

  if ( (char) c == terminator) Serial.println("Now they are equal");
  else Serial.println("Now they are different");
}

I initialize c to a value fitting on a byte.
I initialize terminator with c

then I compare terminator and c… want to make a guess what that prints?

try it out…

So now go back to the function code and notice this:

    if (c < 0 || [color=red]c == terminator[/color]) break;

==> so if you pass 0x80 (128 in decimal) as terminator then your function will not stop at your terminator fill up your buffer, timeout etc… (actually it will fail if your terminator is anything above 127 because char are signed and thus when you do terminator = c you are actually putting -128 in terminator)

so because of those two points, I prefer being in control and not use it

but it’s (mostly) a free world, so use it if you want - works as advertised when you are happy with active wait and dealing with non extended ASCII

J-M-L:
Julyjim - this is true. that function exists and serves a purpose.

you call it this way:

readBytesUntil([color=red]char[/color] terminator, char *buffer, size_t length)

I don’t like it because

1/ you handover timeout management to the function rather than being able to do other things while waiting for your full string to arrive. (imagine getting GPS data while flying your quadcopter with that function !)

2/ in my view it has a bug/hidden limitation that is not in the documentation. this is the code

size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)

{
  if (length < 1) return 0;
  size_t index = 0;
  while (index < length) {
    int c = timedRead();
    if (c < 0 || c == terminator) break;
    *buffer++ = (char)c;
    index++;
  }
  return index; // return number of characters, not including null terminator
}




Notice how `c` is declared as an `int` because that's what the `read()` function returns to detect the -1

now try this code

void setup() {
  int c = 0x80; // an int like theirs
  char terminator = c;
  Serial.begin(115200);
  if ( c == terminator) Serial.println(“they are equal”);
  else Serial.println(“they are different”);

if ( (char) c == terminator) Serial.println(“Now they are equal”);
  else Serial.println(“Now they are different”);
}





I initialize c to a value fitting on a byte.
I initialize terminator with c

then I compare terminator and c... want to make a guess what that prints?

try it out...

So now go back to the function code and notice this:



if (c < 0 || c == terminator) break;




==> so if you pass 0x80 (128 in decimal) as terminator then **your function will not stop at your terminator** fill up your buffer, timeout etc... (actually it will fail if your terminator is anything above 127 because char are signed and thus when you do terminator = c you are actually putting -128 in `terminator`)

so because of those two points, I prefer being in control and not use it


but it's (mostly) a free world, so use it if you want - works as advertised when you are happy with active wait and dealing with non extended ASCII

Good reply for discussion, I like that.
It seem that most application on this forum call for “read serial data” and seldom specify the code has to be non-blocking. I think it is deliberate so the following discussion, if any, can get on "blink without delay "
subject. Most of the time it is of no interest to OP , but adds points to ones score.

Yes, this API is blocking and it is all in the description of it.
Of course it does not spells it out, hence “unadvertised” to cut and paste coders.
Thanks for nice reply, appreciate that.
Jim