1

I am working on a university final project and have run into a problem with programming Arduino, after a 3 year hiatus. I have a pressure transducer that is sending pressure data at 10Hz. I have successfully programmed my Arduino Pro Micro to read the data as it is coming in. I'm using the SoftwareSerial library to set digital pins 8 and 9 to RX and TX, respectively. As the pressure transducer is continuously streaming data values, I read each character, store them in an array, and print them to the Serial Monitor. I'm using a start and end-marker to recognize each incoming character and put them into the array. The raw data output from the transducer is in the form:

*000114.2927
*000114.2926
*000114.2927

And this is the code I am using.

#include <SoftwareSerial.h>
#define paroRX 8
#define paroTX 9

SoftwareSerial paroSerial(paroRX, paroTX);

const byte numChars = 16;
char paroChars[numChars];     //array to store received data
char paroToSend[numChars];      //array to transmit
boolean newParoData = false;

void setup(){
  Serial.begin(9600);     //with transmitter radio
  paroSerial.begin(9600);
}

void loop(){
  paroSerial.listen();
  readParo();      //read from Paro and store values in paroChars
  if(newParoData == true){
    for(int i=0; i<16; i++){
      paroToSend[i] = paroChars[i];
    }
    Serial.print(paroToSend); Serial.print('\n');     //transmit Paro data with a new line for each value
    newParoData = false;
  }
}

void readParo(){
  static boolean receiveInProgress = false;
  static byte index = 0;
  char startMarker = '*';
  char endMarker = '\n';
  char pd;
  while(paroSerial.available() && newParoData == false){
    pd = paroSerial.read();
    if(receiveInProgress == true){
      if(pd != endMarker){
        paroChars[index] = pd;
        index++;
        if(index >= numChars){
          index = numChars - 1;
        }
      }else{
        paroChars[index] = '\0';      //terminate string
        receiveInProgress = false;
        index = 0;
        newParoData = true;
      }
    }else if(pd == startMarker){
      receiveInProgress = true;
    }
  }
}

And this is the output that I get, which is correct. I don't really want that * in front anyways.

000114.2927
000114.2928
000114.2927
000114.2929

But all of this happens at 10Hz, which means I get a constant stream of readings on the Serial Monitor. I want to slow this down to 1Hz, or just one reading per second. The obvious solution that occurred to me was to put a delay in the loop. So I tried to implement this with delay(1000) and using the millis() function as well, but I get strange readings like:

000114.2927
***000114
**2928
***.000114
000114.2928

How can I read at 1Hz from the 10Hz data stream? I want to just store one data value from the stream per second in the form of 000114.2927, then ignore the rest while the Arduino does something else.

Thanks!

  • How can I read at 1Hz from the 10Hz data stream? ... discard 9 readings – jsotola May 21 '18 at 21:07
2

You're thinking backwards. You don't want to read slower (which is what delay does), you want to only send every 10th entry.

That is, count the lines as they come in. When you hit 10 you print one and reset your count.

In other words:

static int count = 0;

if(newParoData == true){

  count ++;
  if (count == 10) {
      count = 0;

      // (Why copy the line just to send the copy...?)
      for(int i=0; i<16; i++){
        paroToSend[i] = paroChars[i];
      }
      Serial.print(paroToSend); Serial.print('\n');     //transmit Paro data with a new line for each value
  }
  newParoData = false;
}
1

I would use Stream class timed functions. Serial is implementation of Stream. The property timeout (setTimeout) sets how long will the blocking functions wait for the next byte/character. Default timeuot is 1000 ms.

Timed functions of Stream are find, parseInt, parseFloat, readBytes, readBytesUntil, readString and readStringUntil. (Non blocking read functions are available, read and peek.)

1

Majenko’s answer is spot on: you just have to count the sentences you read and repeat one every ten sentences. And you don't need two copies of the sentence you are reading: one is enough. But I would add that you don't even need a single copy: you can just echo back the characters you read, without ever storing them, until you hit a '*':

void loop()
{
    static uint8_t sentence_count;
    if (paroSerial.available()) {
        char c = paroSerial.read();
        if (c == '*') {
            // Increment the sentence count modulo 10.
            if (++sentence_count == 10)
                sentence_count = 0;
        } else if (sentence_count == 0) {
            // This is one sentence we have to repeat.
            Serial.write(c);
        }
    }
}

As a side note, if your program doesn't read input from the computer, and if it doesn't send anything to the transducer, then you may consider getting rid of SoftwareSerial and using only the hardware serial port:

  • the receiver part of the port for reading the data from the transducer
  • the emitter part to send the data to the computer.

Yes, it is perfectly fine to use the receiver and the transmitter for different links. The only caveat is that you will have to use the same port configuration on both sides: if the transducer talks at 9600 bps, then the whole port will have to run at 9600 bps.

  • Thanks everyone for the helpful responses. I'm asking my question because I actually have two pressure transducers hooked up to my Arduino via the SoftwareSerial implementation, and I need to send the pressure data from one after the other. So far, I've only had luck sending data from one at a time. I read that the Arduino Pro Micro cannot receive from more than one Serial port simultaneously when SoftwareSerial is used, so I was thinking if I could strictly read one data value from the first transducer, then read another one from the second transducer. Maybe I should start a new topic? – bf109k4 May 21 '18 at 22:11
  • @bf109k4: Or you can use the hardware serial receiver and only one software serial. – Edgar Bonet May 22 '18 at 7:16

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.