How to just take 5 sensor reading from serial and then stop program

Hi,

I'm acquiring sensor data on my arduino over the serial port. I'm using some for the serial basics tutorial below which writes characters to an array until an end marker is reached.

When I open the terminal I can see the data flowing in.

How could I make the program just take in 5 values and an get an average and then stop running? For my application I have a switch turning on/off the board at set intervals so I just want to turn it on take the measurements and then I'll time how long that takes and I'll then switch it off.

Many thanks

const byte numChars = 32;
char receivedChars[numChars];  // an array to store the received data

boolean newData = false;

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\r';
  char rc;
  
  // if (Serial.available() > 0) {
           while (Serial1.available() > 0 && newData == false) {
    rc = Serial1.read();

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

void showNewData() {
  if (newData == true) {    
      char* reading = receivedChars + 1;
      sensorReading = atoi(reading);
         newData = false;
   }

}

void setup() 
{ 
Serial.begin(9600); 
Serial1.begin(9600);
}

void loop() 
{ 
recvWithEndMarker();
showNewData();

}

Leave loop() empty and put the code at the end of setup().

Edit Oh! You don't have a setup(). Better fix that.

How could I make the program just take in 5 values

5 values as in 5 characters? Or 5 values as in a string containing a bunch of digits separated by delimiters, until 5 delimiters have arrived?

Hi,

Thank you for your reply, I've updated my the code with the showNewData() function which assigns each reading to the int variable sensorReading.

So to summarize, there are two functions recvWithEndMarker() and showNewData() being called in loop().

Basically, I just want these to run until 5 sensorReading values are read.

I don't think that I can put them in setup() as then they will only execute once and won't read in the characters from the serial.

As a starting point, how could I get the program to stop after receiving one reading. Then I can worry about getting 5.

Many thanks

As a starting point, how could I get the program to stop after receiving one reading. Then I can worry about getting 5.

Something like this?

int numRead = 0;

void loop()
{
   if(numRead < 5)
   {
      getAndShowReading();
      numRead++;
   }
}

void getAndShowReading()
{
   recvWithEndMarker();
   showNewData();
}

Yes, you can put them in setup(); just use a for loop or similar

for(int cnt=0;cnt<5;cnt++)
{
  // do what needs to be repeated
  ...
  ...
}

Hi guys,

I gather from here that the recvWithEndMarker() reads the data in the serial receive buffer and adds each character to an empty array until the end marker is reached. It then set the Boolean newData to true and when this is true the value is displayed by showNewData().

https://forum.arduino.cc/index.php?topic=288234.0

This is the datasheet for the senor.

The sensor has a TTL output. The output is an ASCII capital “R”, followed by four ASCII character digits representing the range in millimeters, followed by a carriage return (ASCII 13). The serial data format is 9600 baud, 8 data bits, no parity, with one stop bit (9600-8-N-1).

This is a screen shot of the data coming in.

How can I figure out how many times to loop to capture just one value.

Many thanks

How can I figure out how many times to loop to capture just one value.

Start with posting YOUR code.

This is a screen shot of the data coming in.

No, it isn't. That is a screen shot of data GOING OUT from the Arduino.

You need to loop as many times as you need to receive first an 'R' and then loop four times to read the four digits.
If any character isn't a digit, go back to waiting for an 'R'.

Sorry this is the code. Perhaps I've done a bad job explaining the issue, apologies for that.

const byte numChars = 32;
char receivedChars[numChars];  // an array to store the received data

boolean newData = false;

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\r';
  char rc;
  
  // if (Serial.available() > 0) {
           while (Serial1.available() > 0 && newData == false) {
    rc = Serial1.read();

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

void showNewData() {
  if (newData == true) {    
      char* reading = receivedChars + 1;
      sensorReading = atoi(reading);
      Serial.println(sensorReading);
      newData = false;
   }

}

void setup() 
{ 
Serial.begin(9600); 
Serial1.begin(9600);
}

void loop() 
{ 
recvWithEndMarker();
showNewData();

}

That code has no Serial.print() statements, so it is NOT the code that generated the screen shot. We are not getting anywhere...

Sorry PaulS, I've included the println() in the showNewData() function.

So, you want newData to be true 5 times?

int trueCnt = 0;

void loop()
{
   recvWithEndMarker();
   if(newData && trueCnt < 5)
   {
      showNewData();
      trueCnt++;
   }
}

The sensor has a TTL output. The output is an ASCII capital "R", followed by four ASCII character digits representing the range in millimeters, followed by a carriage return (ASCII 13). The serial data format is 9600 baud, 8 data bits, no parity, with one stop bit (9600-8-N-1).

On the basis of that information why not use the 3rd example in Serial Input Basics - recvWithStartEndMarkers() - and set the start marker to 'R' and the end marker to '\r'

...R

Hi,

This is working correctly. It discards the first 4 sensor readings and sends the 5th reading by calling the BuildPacket() function.

int trueCnt = 0;
void loop() 
{ 

recvWithEndMarker();
if(newData && trueCnt < 5)
   {
      showNewData();
      trueCnt++;
      if(trueCnt == 5)
      {
        BuildPacket();
        
      }
      
      }
      
  }

How could I modify it to discard the first 5 readings and then take an average of the next 5 reading instead.

This is what I've tried.

int trueCnt = 0;
void loop() 
{ 

recvWithEndMarker();
if(newData && trueCnt < 11) //Only run 11 times
   {
      showNewData();
      trueCnt++;
      if(trueCnt >= 5)
      {
       sensorReading = sensorReading + sensorReading.

       if(trueCnt == 10){
       BuildPacket();
       } 
        
      }
      
      }
      
  }

You need to show ALL of your code.