Treating Serial Incoming Data + CR + LF

Hi!
I'm trying to receive data from monitor serial with CR+LF endings but it doesn't work. I already tryied a lot of changes in my code but it only works with stability when I use only CR as ending char. It seems very strange behavior and since last week I'm stucked with that!Could anybody give me some help on how I can solve this problem?

#include <LowPower.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// === Tempo em [ms] de ficar acordado escutando radio
#define SERIAL_SLEEP_TIMEOUT  5000
#define SERIAL_BUFFER_SIZE    20
#define ACK                   0x06
#define NAK                   0x15

// ==== Configuração portas interface HC-12
const unsigned int hc12SetPin = 16;
const unsigned int hc12RxdPin =  0;

// ==== Configuração portas interface DS18B20
const unsigned int ds18PwrPin = 10;
const unsigned int ds18DatPin =  9;

OneWire oneWire(ds18DatPin);
DallasTemperature DS18B20(&oneWire);//
DeviceAddress idNode;

// ==== Configuração portas interface geral
const unsigned int led1SetPin = 13;

// ==== VariƔveis de uso geral
char incByte;
char incStrBuffer[SERIAL_BUFFER_SIZE];
byte incStrBfSize = 0;
bool isStrAvailable = false;
unsigned long g_uCurreTimeMs;

void setup() {

  // ==== Configuração portas digitais
  pinMode(led1SetPin, OUTPUT);
  digitalWrite(led1SetPin, LOW);
  pinMode(hc12SetPin, OUTPUT);
  digitalWrite(hc12SetPin, HIGH);
  pinMode(ds18PwrPin, OUTPUT);
  digitalWrite(ds18PwrPin, LOW);
  // ==== Configuração porta de comunicação serial
  Serial.begin(4800);
  // ==== Atualiza tempo decorrido
  g_uCurreTimeMs = millis();
}

void loop() {
  // ==== Recebe dados serial
  if (millis() - g_uCurreTimeMs < SERIAL_SLEEP_TIMEOUT){
    if (Serial.available()) {
      incByte = Serial.read();
      if (incByte >= 0x20) {
        // ==== Armazena dado no buffer se vƔlido
        if (incStrBfSize < (SERIAL_BUFFER_SIZE-1))
          incStrBuffer[incStrBfSize++] = incByte;
      } else if (incByte == 0x0D) {
        if (!strcmp(incStrBuffer, "LOF")) {
          digitalWrite(led1SetPin, LOW);
          // ==== Limpa buffer de recepção e indexador
          incStrBfSize = 0;
          memset(incStrBuffer, 0, SERIAL_BUFFER_SIZE);
        } else if (!strcmp(incStrBuffer, "LON")) {
          digitalWrite(led1SetPin, HIGH);
          // ==== Limpa buffer de recepção e indexador
          incStrBfSize = 0;
          memset(incStrBuffer, 0, SERIAL_BUFFER_SIZE);
        } else if (!strcmp(incStrBuffer, "TMP")) {
          // ==== Configuração sensor de temperatura
          digitalWrite(ds18PwrPin, HIGH);
          delay(10);
          DS18B20.begin();
          DS18B20.requestTemperatures();
          float tempC = DS18B20.getTempCByIndex(0);
          Serial.println(tempC);
          digitalWrite(ds18PwrPin, LOW);
          // ==== Limpa buffer de recepção e indexador
          incStrBfSize = 0;
          memset(incStrBuffer, 0, SERIAL_BUFFER_SIZE);
        }
      }
      g_uCurreTimeMs = millis();
    }
  } else {
    Serial.flush();
    pinMode(hc12RxdPin, INPUT_PULLUP);
    PCMSK2 |= bit (PCINT16);
    PCIFR  |= bit (PCIF2);
    PCICR  |= bit (PCIE2);
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);  
    PCICR  &= ~bit (PCIE2);
    Serial.begin(4800);
    g_uCurreTimeMs = millis();
  }
}

I would suggest to study Serial Input Basics to handle this

CR = 0x0D
LF = 0x0A

Your code is only testing for CR to signal then end of the input string so if you send "LOF", your code will consume "LOF", see the CR and act accordingly BUT it will leave LF in the buffer so if you send "LON", it will look like "LON" which is NOT the same as "LON"

You are not putting a terminator on your buffer before you use it with strcmp().

      incByte = Serial.read();
      if (incByte >= 0x20)
      {
        // ==== Armazena dado no buffer se vƔlido
        if (incStrBfSize < (SERIAL_BUFFER_SIZE - 1))
          incStrBuffer[incStrBfSize++] = incByte;
        incStrBuffer[incStrBfSize]  = '\0'; // Terminator
      }
1 Like

The following sketch demonstrates how to receive a "LF+CR" (Both NL & CR in Arduino Serial Monitor) terminated string from the Serial Monitor.

char myArray[20];
int i = 0;

void setup()
{
  Serial.begin(57600);  //Bd must be as high as permissible
}

void loop()
{
  while (Serial.available() > 0)
  {
    myArray[i] = Serial.read();
    if ((myArray[i] == '\n') && (myArray[i - 1] == '\r')) //both NL & CR
    {
      myArray[i - 1] = '\0'; //null-byte at position of '\r'
      Serial.println(myArray);
      memset(myArray, 0x00, 20);
      i = 0;
    }
    else
    {
      i++;
    }
  }
}

Hi John!
Thank you to reply me! I did the suggested changes but stil is not working accordingly!

Post your code

This says "look for a character if it has been less than 5 seconds since the last character." If the time between character is ever more than 5 seconds you will never look for input again. I think you want to look for characters if it has been MORE than five seconds. While you are at it, you may want to not wait five seconds between each character.

  // ==== Recebe dados serial
  if (millis() - g_uCurreTimeMs > SERIAL_SLEEP_TIMEOUT)
  {
    while (Serial.available())
    {
      incByte = Serial.read();

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.