The best and most intuitive way is to use serialEvent() callback Arduino defines along with loop() and setup().
I've built a small library a while back that handles message reception, but never had time to opensource it. This library receives \n terminated lines that represent a command and arbitrary payload, space-separated. You can tweak it to use your own protocol easily.
First of all, a library, SerialReciever.h:
#ifndef __SERIAL_RECEIVER_H__ #define __SERIAL_RECEIVER_H__ class IncomingCommand { private: static boolean hasPayload; public: static String command; static String payload; static boolean isReady; static void reset() { isReady = false; hasPayload = false; command = ""; payload = ""; } static boolean append(char c) { if (c == '\n') { isReady = true; return true; } if (c == ' ' && !hasPayload) { hasPayload = true; return false; } if (hasPayload) payload += c; else command += c; return false; } }; boolean IncomingCommand::isReady = false; boolean IncomingCommand::hasPayload = false; String IncomingCommand::command = false; String IncomingCommand::payload = false; #endif // #ifndef __SERIAL_RECEIVER_H__
To use it, in your project do this:
#include <SerialReceiver.h> void setup() { Serial.begin(115200); IncomingCommand::reset(); } void serialEvent() { while (Serial.available()) { char inChar = (char)Serial.read(); if (IncomingCommand::append(inChar)) return; } }
To use the received commands:
void loop() { if (!IncomingCommand::isReady) { delay(10); return; }
executeCommand(IncomingCommand::command, IncomingCommand::payload); // I use registry pattern to handle commands, but you are free to do whatever suits your project better. IncomingCommand::reset();