asking
October 3, 2022, 10:02am
1
Hi,
I am using below code to read temperature and humidity values from Serial Sensor.
But while using this serial extraction ESP32 get's too slow even to detect the keypress by polling method it takes 2-3 seconds.
How to use non blocking read function to achieve the same results without affecting the speed of ESP32.
void serial_extraction()
{
if(Serial2.available() == 0)
{
Serial2.print("{F00R}\r"); // SEND read command to ready values from sensor
}
if(Serial2.available() > 0) {
i = Serial2.readBytesUntil('\n', values, sizeof(values) - 1);
values[i] = '\0'; // Now it's a string, so
for(i=0;i<6;i++)
{
temperature[i] = (values[i+19]);
}
temp = atof(temperature);
for(i=0;i<6;i++)
{
humidity[i] = (values[i+10]);
}
rh = atof(humidity);
}
}
I use serialized sentences, no blocking code.
void fReceiveSerial_LIDAR( void * parameters )
{
char OneChar;
char *str;
str = (char *)ps_calloc(300, sizeof(char) ); // put str buffer into PSRAM
bool BeginSentence = false;
sSerial.reserve ( StringBufferSize300 );
for ( ;; )
{
EventBits_t xbit = xEventGroupWaitBits (eg, evtReceiveSerial_LIDAR, pdTRUE, pdTRUE, portMAX_DELAY);
if ( LIDARSerial.available() >= 1 )
{
while ( LIDARSerial.available() )
{
OneChar = LIDARSerial.read();
if ( BeginSentence )
{
if ( OneChar == ‘>’)
{
if ( xSemaphoreTake( sema_ParseLIDAR_ReceivedSerial, xSemaphoreTicksToWait10 ) == pdTRUE )
{
xQueueOverwrite( xQ_LIDAR_Display_INFO, ( void * ) &sSerial );
xEventGroupSetBits( eg, evtParseLIDAR_ReceivedSerial );
//
}
BeginSentence = false;
break;
}
sSerial.concat ( OneChar );
}
else
{
if ( OneChar == ‘<’ )
{
sSerial = “”; // clear string buffer
BeginSentence = true; // found begining of sentence
}
}
} // while ( LIDARSerial.available() )
} //if ( LIDARSerial.available() >= 1 )
xSemaphoreGive( sema_ReceiveSerial_LIDAR );
}
vTaskDelete( NULL );
} //void fReceiveSerial_LIDAR( void * parameters )
//////////////////////////////////////////////////////////////////////////////////////////
The "<" marks the beginning of a new serial sentence and the ">" marks the end of a serialized sentence. A quick read of the serial buffer is done, if there is something there store it till the end of the sentence. At the end of the sentence send the received info to be parsed.
J-M-L
October 3, 2022, 10:07am
3
I would suggest to study Serial Input Basics to understand the typical way for dealing with asynchronous input
Take a look at Serial input basics - updated for some ideas
Alternatively, the ESP has a multitasking system (FreeRTOS )
See ESP32 Dual Core with Arduino IDE | Random Nerd Tutorials for examples
I used the following functions in one of my projects.
/*! Thread safe, memory safe non blocking read until delimiter is found.
*
* \param stream Stream.
* \param buf Receiving buffer.
* \param delim Delimeter.
* \param i Buffer index.
* \param j Delimiter index.
*
* \return true when delimiter is found or the buffer is full, false otherwise.
*/
template <size_t n> bool readUntil_r(
Stream& stream, char (&buf)[n], char const* delim, size_t& i, size_t& j) {
for (; i < n and delim[j]; i++) {
if (not stream.available()) {
return false;
}
buf[i] = stream.read();
if (buf[i] == delim[j]) {
j++;
}
else {
j = 0;
}
}
for (; i < n; i++) {
buf[i] = 0;
}
i = 0;
j = 0;
return true;
}
/*! Memory safe non blocking read until delimiter is found.
*
* \param stream Stream.
* \param buf Receiving buffer.
* \param delim Delimeter.
*
* \return true when delimiter is found or the buffer is full, false otherwise.
*/
template <size_t n> bool readUntil(Stream& stream, char (&buf)[n], char const* delim) {
static size_t i = 0;
static size_t j = 0;
return readUntil_r(stream, buf, delim, i, j);
}
Usage:
char buf[80];
// ...
void loop() {
if (readUntil(Serial, buf, "\r")) {
// `buf` contains the delimiter, it can now be used for parsing.
}
// ...
}
Juraj
October 3, 2022, 11:15am
6
you can set the timeout with setTimeout
gcjr
October 3, 2022, 12:29pm
7
consider which waits until a terminal char like readBytesUntil
char *
getInput (
char termChar )
{
static char buf [80];
static int idx = 0;
while (Serial.available ()) {
char c = Serial.read ();
buf [idx++] = c;
if (termChar == c) {
buf [idx] = '\0';
idx = 0;
return buf;
}
}
return NULL;
}
unsigned long msecLst;
void
loop (void)
{
unsigned long msec = millis ();
if ( msec - msecLst >= 1000) {
Serial.println (msec);
msecLst = msec - msec % 1000;
}
char *s = getInput (';');
if (s)
Serial.println (s);
}
void
setup (void)
{
Serial.begin (9600);
}
J-M-L
October 3, 2022, 12:33pm
8
careful on buffer overrun if the ';' does not come before the 80th byte
asking
October 3, 2022, 7:04pm
9
Juraj:
setTimeout
Worked Perfectly!! with 7ms timeout.
system
Closed
April 1, 2023, 7:05pm
10
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.