I hope this code can be useful to you.
Copy SerialReceiver.h and SerialReceiver.cpp in your sketch folder.
Change processMessage() function to suit your needs.
Make sure you call run() in loop().
SerialReceiver.h
#ifndef _SERIAL_RECEIVER_H
#define _SERIAL_RECEIVER_H
#if ARDUINO >= 100
#include
#else
#include
#endif
// ASCII codes - see http://www.asciitable.com/
#define CR 0x0D
#define LF 0x0A
// type of receive error
typedef enum {
ERR_NONE, // there was no error
ERR_TIMEOUT, // the next byte took too long to arrive
ERR_BUFFERFULL // the receive buffer was too small to store all the incoming bytes
} SerialRecvError;
typedef void (*receiveHandler)(const char* buf, SerialRecvError err);
class SerialReceiver {
public:
SerialReceiver(receiveHandler f, unsigned long receiveTimeout);
// receive buffer size (including null terminator)
static const byte RECV_BUF_SIZE = 30;
// is the specified char an end-of-message marker ?
boolean isEndOfMessage(char ch);
// to be called in loop()
void run();
private:
// receive buffer
char _recvBuf[RECV_BUF_SIZE];
// number of bytes currently storedn in the receive buffer
byte _recvBufCnt;
// whan was the last byte received ?
unsigned long _lastRecvTimeMs;
// max delay between two consecutive bytes in the serial stream
unsigned long _receiveTimeout;
// poiter to message processing function
receiveHandler _receiveHandler;
};
#endif
SerialReceiver.cpp
#include "SerialReceiver.h"
SerialReceiver::SerialReceiver(receiveHandler f, unsigned long receiveTimeout) {
_receiveHandler = f;
_receiveTimeout = receiveTimeout;
_recvBufCnt = 0;
}
boolean SerialReceiver::isEndOfMessage(char ch) {
return (ch == CR) || (ch == LF);
}
void SerialReceiver::run() {
if (Serial.available()) {
char ch = Serial.read();
if (isEndOfMessage(ch)) {
if (_recvBufCnt > 0) {
_recvBuf[_recvBufCnt] = 0;
if (_receiveHandler != NULL) {
(*_receiveHandler)(_recvBuf, ERR_NONE);
}
_recvBufCnt = 0;
}
}
else if (_recvBufCnt < (RECV_BUF_SIZE - 1)) { // notice - 1 to leave room for the NULL terminator
_recvBuf[_recvBufCnt] = ch;
_recvBufCnt++;
_lastRecvTimeMs = millis();
}
else {
// buffer full - byte lost
_recvBuf[_recvBufCnt] = 0;
if (_receiveHandler != NULL) {
(*_receiveHandler)(_recvBuf, ERR_BUFFERFULL);
}
_recvBufCnt = 0;
}
}
if (_recvBufCnt > 0) {
if (millis() - _lastRecvTimeMs > _receiveTimeout) {
_recvBuf[_recvBufCnt] = 0;
if (_receiveHandler != NULL) {
(*_receiveHandler)(_recvBuf, ERR_TIMEOUT);
}
_recvBufCnt = 0;
}
}
}
Example sketch
#include "SerialReceiver.h"
// called when a full messages has been received
void processMessage(const char* buf, SerialRecvError err) {
// do something with the received string
Serial.print("Received: ");
Serial.println(buf);
switch(err) {
case ERR_NONE:
break;
case ERR_TIMEOUT:
Serial.println("Timeout detected.");
break;
case ERR_BUFFERFULL:
Serial.println("Buffer full.");
break;
}
}
SerialReceiver rec(processMessage, 10);
void setup() {
Serial.begin(115200);
}
void loop() {
rec.run();
}