Read the last info sent in the Serial.

Hi, I am was wondering if there is a way the read ONLY the last info sent in the Serial communication.

I am testing with 2 Boards and RS-485. I don't want my Serial to overflow so I don't want to send the same information twice (or more) in a row. I only want to send a piece of info trough the Serial when a change of state occurs.

It would be apreciated to get help ! :slight_smile:

I only want to send a piece of info trough the Serial when a change of state occurs.

So what is the problem ?

Test the state and compare it with the state the previous time you checked
If it has changed then send the message and save the state to a variable ready to check for a change next time

See the StateChangeDetection example in the IDE

I think you are asking about flushing your RX buffer so you only read the last data?

There is a long version and a short version. In the short version, just call sfReader.skipToDelimiter(); whenever you want to clear the RX buffer upto the next delimiter OR until no more data received for the timeout period

Long version

// flushingInput.ino
// Reads chars into a String until newline '\n'
// https://www.forward.com.au/pfod/ArduinoProgramming/SoftwareSolutions/index.html
// Pros: Simple. Non-Blocking, Robust flushes the input until timeout or find a termination, until_c, char
// Cons: Nothing really.

String input;

// returns true if still flushing, else false if flushing finished either by finding until_c char or by timeout
bool flushUntil(bool flushing, char until_c) {
  static bool timerRunning; static unsigned long timerStart;     // timeout static variables
  static const unsigned long timeout_mS = 1000; // 1sec  set to 0 for no timeout
  if (!flushing) { // just return
    return false;
  } // else
  if ((timeout_mS > 0) && (!timerRunning)) {  // only start if we have a non-zero timeout
    timerRunning = true;
    timerStart = millis();
  }
  while (Serial.available()) {
    timerRunning = false; // set true below if don't return first
    char c = Serial.read();
    if (c == until_c) {
      return false;  // not flushing any more
    }
    // restart timer running
    if (timeout_mS > 0) {  // only start if we have a non-zero timeout
      timerRunning = true;
      timerStart = millis();
    }
  }
  if (timerRunning && ((millis() - timerStart) > timeout_mS)) {
    timerRunning = false;
    return false;  // not  flushing any more
  }
  return true;  // still flushing
}

void setup() {
  Serial.begin(9600);
  for (int i = 10; i > 0; i--) {
    Serial.print(' '); Serial.print(i);
    delay(500);
  }
  Serial.println();
  Serial.println(F("flushingInput.ino"));
  input.reserve(20); // expected line size

  bool stillFlushing = true; // start flushing
  while ((stillFlushing = flushUntil(stillFlushing, '\n'))) {
    // loop here until input is emptied or find a newline
  }
  // stillFlushing == false here
  Serial.println(F(" Finished flushing Input"));
}

// read Serial until until_c char found or limit char read or timeout, returns true when found/limited else false
// non-blocking, until_c, if found, is returned as last char in String, updates input String with chars read
bool readStringUntil(String& input, char until_c, size_t char_limit) { // call with char_limit == 0 for no limit
  static bool timerRunning; static unsigned long timerStart;     // timeout static variables
  static const unsigned long timeout_mS = 1000; // 1sec  set to 0 for no timeout

  while (Serial.available()) {
    timerRunning = false; // set true below if don't return first
    char c = Serial.read();
    input += c;
    if (c == until_c) {
      return true;
    }
    if (char_limit && (input.length() >= char_limit)) {
      return true;
    }
    // restart timer running
    if (timeout_mS > 0) {  // only start if we have a non-zero timeout
      timerRunning = true;
      timerStart = millis();
    }
  }
  if (timerRunning && ((millis() - timerStart) > timeout_mS)) {
    timerRunning = false;
    return true;
  }
  return false;
}

char terminatingChar = '\n';
void loop() {
  if (readStringUntil(input, terminatingChar, 20)) { // read until find newline or have read 20 chars, use 0 for unlimited no chars
    if (input.lastIndexOf(terminatingChar) >= 0) {   // could also use check  if (input[input.length()-1] == terminatingChar) {
      Serial.print(F(" got a line of input '")); Serial.print(input); Serial.println("'");
    } else {
      Serial.print(F(" reached limit or timeout without newline '")); Serial.print(input); Serial.println("'");
    }
    input = ""; // clear after processing for next line
  }
}

Or the short version

// SafeStringReader_timeoutFlushing.ino
// Reads chars into a SafeString until newline '\n'
// uses line limit, timeout and input flushing
// https://www.forward.com.au/pfod/ArduinoProgramming/SoftwareSolutions/index.html
//
// download SafeString library from Arduino library manager
// or from the tutorial page
// https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html
//
// Pros: Minimal Code. Non-Blocking, Robust flushes any initial partial input, if skipToDelimiter() called in setup(). 
//       Skips un-expected long input lines (missing terminator).
//       Returns un-terminated input, if a timeout is set. Option echoOn() setting to echo all input.
// Cons: Nothing really, except needs SafeString library to be installed.

#include "SafeStringReader.h"

createSafeStringReader(sfReader, 20, "\r\n"); // a reader for upto 20 chars to read lines terminated by \r or \n or nothing

void setup() {
  Serial.begin(9600);
  for (int i = 10; i > 0; i--) {
    Serial.print(' '); Serial.print(i);
    delay(500);
  }
  Serial.println();
  Serial.println(F("SafeStringReader_timeoutFlushing.ino"));
  //SafeString::setOutput(Serial);
  sfReader.setTimeout(1000); // set 1 sec timeout
  sfReader.skipToDelimiter(); // flush initial data until either find delimiter or timeout
  sfReader.connect(Serial); // read from Serial
}

void loop() {
  if (sfReader.read()) { // got a line or timed out  delimiter is NOT returned
    if (sfReader.hasError()) { // input length exceeded
      Serial.println(F(" sfReader hasError. Input overflowed and skipped to next delimiter."));
    }
    if (sfReader.getDelimiter() == -1) { // no delimiter so timed out
      Serial.println(F(" timeout without newline or carrage return"));
    }
    Serial.print(F(" got a line of input '")); Serial.print(sfReader); Serial.println("'");
    // no need to clear sfReader as read() does that
  }
}