I wanted to optimize the runtime of my functions for receiving and analyzing data from a GNSS receiver.
To do this, I replaced all string commands with char arrays, which, for example, reduced the analysis of the NMEA dataset from 328 µs to 40 µs (oscilloscope measurement).
However, reading the 83-byte RMC dataset with the ESP32 functions avaiable() and read() took about 1.8 ms.
This is obviously due to the FreeRTOS operating system, which manages the ESP32's serial interfaces.
The combination of avaiable() and readBytes() brought about a big improvement from 1.8 ms to 27.4 µs !
The data buffered by the operating system is provided in larger blocks anyway.
A disadvantage of this block-by-block reading is that readBytes() could return multiple or incomplete records. This means that at the end of the received block there is an incomplete record that is only completed with the next call. However, this can be managed with little additional code.
A simplified version of both methods is shown below:
// Board: ESP32 / ESP32 Dev Module
#define TestPin 12 // Test-Output
HardwareSerial SerialGNSS(1); // serial interface to the GNSS-Receiver
//---------------------------------------------------------
void setup() {
Serial.begin(115200);
delay(2000);
pinMode(TestPin, OUTPUT);
digitalWrite(TestPin, LOW); // for time measurement
SerialGNSS.setRxBufferSize(1024);
SerialGNSS.begin(115200, SERIAL_8N1, 13, 14);
}
//---------------------------------------------------------
void loop() {
int cnt;
if (SerialGNSS.available()) {
digitalWrite(TestPin, HIGH); // start time measurement
//cnt = receiveRec1(); // serial receiving byte by byte
cnt = receiveRec2(); // serial receiving block by block
digitalWrite(TestPin, LOW); // stop time measurement
Serial.print(" " + String(cnt)); // number of received chars
}
delay(10);
}
//---------------------------------------------------------
int receiveRec1() { // run time: 1,78ms
char rc;
int i = 0;
while (SerialGNSS.available()) { // if chars received
rc = SerialGNSS.read(); // get one char
if (rc == '\n') return i; // and check it
i++;
}
return -i;
}
//---------------------------------------------------------
int receiveRec2() { // runtime 27,4µs
char rc;
int i = 0;
char buf[256];
int cnt = SerialGNSS.available();
if (cnt <= 0) return 0; // exit, if nothing received
SerialGNSS.readBytes(buf, cnt); // get all received chars
for (i=0; i<cnt; i++) {
rc = buf[i];
if (rc == '\n') return i; // and check them
}
return -i;
}