A Wiring/Arduino library to tokenize and parse commands received over a phisical/software serial port or buffer.

SerialCmd Library

© 2022 Guglielmo Braguglia


Another library to enable you to tokenize and parse commands received over a phisical/software serial port or from a memory buffer ('C' string). Based on the "SerialCommand" library originally written by Steven Cogswell in 2011 and after modified by Stefan Rado in 2012.

   • © 2022 Guglielmo Braguglia
   • © 2012 Stefan Rado
   • © 2011 Steven Cogswell

Virtually all Arduino boards have a serial connection, normally via USB, that is very convenient and simple to use, so it would be very convenient to simply be able to send commands (and possibly the parameters associated with them) through it to make Arduino perform specific functions, such as turning on and off a LED or relay, positioning a servo, adjusting the speed of a motor, and so on.

The SerialCmd library allows you to do just that, giving the programmer the ability to create "specialized functions" to execute when certain strings are received, optionally followed by a series of parameters, separated by a prefixed "separator".

Library usage and initialization

Memory optimization

Through a series of #define, present in the .h of the library, it is possible to optimize the use of the SRAM memory, so as to allow the use of the library even on MCUs with little memory.

#define SERIALCMD_MAXCMDNUM  8             // Max Number of Command
#define SERIALCMD_MAXCMDLNG  6             // Max Command Length
#define SERIALCMD_MAXBUFFER 30             // Max Buffer  Length

SERIALCMD_MAXCMDNUM: Indicates the maximum number of different commands that the library must be able to recognize.

SERIALCMD_MAXCMDLNG: Indicates the maximum length, expressed in characters, of the identifier of the single command.

SERIALCMD_MAXBUFFER: Indicates the maximum length, expressed in characters, of the buffer in which the command is stored together with all its parameters and separators.

Customization

A further series of #define defines:

  1. if you want to force upper-case (also if you type in lower case) the "command" sent on the serial port (hardware or software). The parameters are not involved. Value 0 does not convert, 1 converts to upper.

  2. the source from which the received command is considered valid (only from serial port, only from memory buffer, from both)

  3. the character indicating the end of the command (CR = 0x0D, LF = 0x0A or NULL = 0x00)

  4. the character used as a separator between the command identifier and the various parameters (comma, semicolon, period, space)

#define SERIALCMD_FORCEUC     0           // If set to 1 force uppercase for serial command

#define SERIALCMD_FROMSTRING -1           // Valid only as ReadString command
#define SERIALCMD_FROMALL     0           // Always valid
#define SERIALCMD_FROMSERIAL  1           // Valid only as ReadSer command

#define SERIALCMD_CR      0x0D            // Carriage Return (char)
#define SERIALCMD_LF      0x0A            // Line Feed       (char)
#define SERIALCMD_NULL    0x00            // NULL            (char)

#define SERIALCMD_COMMA   ","             // COMMA           (C string)
#define SERIALCMD_SEMICOL ";"             // SEMI COLUMN     (C string)
#define SERIALCMD_DOT     "."             // DOT             (C string)
#define SERIALCMD_SPACE   " "             // SPACE           (C string)

... values that you can use in your program to customize the values.

Please note that the class constructor has two default values:

SerialCmd ( Stream &mySerial, char TermCh = SERIALCMD_CR, char * SepCh = ( char * ) SERIALCMD_COMMA );

Initialization

To use this library first you have to add, at the beginning of your program:

#include 
   

   

... next you have to call the class constructor with, at least, the first parameter, that defines the serial port to use (hardware or software) and, if desired, two further parameters, the first to define the "terminator" character (default CR) and the second to define the "separator" character (default comma).

Example (using hardware serial "Serial"):

SerialCmd mySerCmd( Serial );

... or, if you want to specify both a different terminator and a different separator: :

SerialCmd mySerCmd( Serial, SERIALCMD_LF, (char *) SERIALCMD_SEMICOL );

Library methods

AddCmd ( const char *command, char allowedSource, void ( *function ) () )

Add a "command" to the list of recognized commands and define which function should be called. Parameter "allowedSource" can be one of those defined in .h (SERIALCMD_FROMSTRING, SERIALCMD_FROMALL, SERIALCMD_FROMSERIAL)

Example:

mySerCmd.AddCmd( "LEDON", SERIALCMD_FROMALL, set_LedOn );

... where "LEDON" is the command, SERIALCMD_FROMALL indicates that is valid both from serial port or from memory buffer ('C' string) and set_LedOn is a function defined as:

void set_LedOn ( void ) {
   ...
}

... which is called upon receipt of the LEDON command.


ReadNext( )

Return the address of the string that contains the next parameter, if there is no next parameter, it contains the value NULL. It is normally used within the function called by the "command" to retrieve any parameters.

Example:

char * cPar;
...
...
cPar = mySerCmd.ReadNext( );

Print( )

It allows to send a String (class String), a character string (char*), a signed/unsigned character (char, unsigned char), a signed/unsigned integer (int, unsigned int) or a signed/unsigned long (long, unsigned long) to the serial port (hardware or software) associated with the SerialCmd.

Example:

mySerCmd.Print( (char *) "This is a message \r\n" );

ReadSer( )

It must be called continuously inside the loop () to receive and interpret the commands received from the serial port (hardware or software)

Example:

void setup( ) {
   ...
   ...
}

void loop( ) {
	mySerCmd.ReadSer( );
   ...
   ...
}

ReadString ( char * theCmd )

It is used to send a command from the application as if it had been received from the serial line. The content of the string must be the same as it would have been sent through the serial port (including parameters).

Example:

mySerCmd.ReadString ( (char *) "LEDON" );

Demo Program

The following example uses the "Serial" serial port to manage three commands: "LEDON" which turns on the LED on the board, "LEDOF" which turns off the LED on the board and the command "LEDBL,time" which makes the LED blinking with half-period equal to the "time" parameter (in milliseconds). The number of flashes is counted and when a certain number is reached, the LED, by means of a command from the "buffer" (therefore from the application program), is switched off.

blinkingTime ) ) { ledStatus = !ledStatus; digitalWrite ( LED_BUILTIN, ledStatus ); blinkingCnt++; blinkingLast += blinkingTime; } // if ( blinkingCnt >= 10 ) { blinkingCnt = 0; mySerCmd.ReadString ( ( char * ) "LEDOF" ); } // mySerCmd.ReadSer(); }">
#include 
   
    
#include 
    
     

bool     isBlinking   = false;      // Indicates whether blinking is active or not
uint8_t  ledStatus    = LOW;        // BUILTIN_LED status (OFF/ON)
uint8_t  blinkingCnt  = 0;          // Number of led status changes before turning off blinking
uint32_t blinkingTime = 0;          // Time of led status change
uint32_t blinkingLast = 0;          // Last millis() in which the status of the led was changed

SerialCmd mySerCmd ( Serial );      // Initialize the SerialCmd constructor using the "Serial" port

void sendOK ( void ) {
   mySerCmd.Print ( ( char * ) "OK \r\n" );
}

void set_LEDON ( void ) {
   isBlinking = false;
   ledStatus  = HIGH;
   digitalWrite ( LED_BUILTIN, HIGH );
   sendOK();
}

void set_LEDOF ( void ) {
   isBlinking = false;
   ledStatus  = LOW;
   digitalWrite ( LED_BUILTIN, LOW );
   sendOK();
}

void set_LEDBL ( void ) {
   char *   sParam;
   //
   sParam = mySerCmd.ReadNext();
   if ( sParam == NULL ) {
      mySerCmd.Print ( ( char * ) "ERROR: Missing blinking time \r\n" );
      return;
   }
   blinkingCnt  = 0;
   blinkingTime = strtoul ( sParam, NULL, 10 );
   blinkingLast = millis();
   isBlinking = true;
   sendOK();
}

void setup() {
   delay ( 500 );
   pinMode ( LED_BUILTIN, OUTPUT );
   digitalWrite ( LED_BUILTIN, ledStatus );
   Serial.begin ( 9600 );
   //
   mySerCmd.AddCmd ( "LEDON" , SERIALCMD_FROMALL, set_LEDON );
   mySerCmd.AddCmd ( "LEDOF" , SERIALCMD_FROMALL, set_LEDOF );
   mySerCmd.AddCmd ( "LEDBL" , SERIALCMD_FROMALL, set_LEDBL );
   //
   mySerCmd.Print ( ( char * ) "INFO: Program running ... \r\n" );
}

void loop() {
   if ( isBlinking && ( millis() - blinkingLast > blinkingTime ) ) {
      ledStatus = !ledStatus;
      digitalWrite ( LED_BUILTIN, ledStatus );
      blinkingCnt++;
      blinkingLast += blinkingTime;
   }
   //
   if ( blinkingCnt >= 10 ) {
      blinkingCnt  = 0;
      mySerCmd.ReadString ( ( char * ) "LEDOF" );
   }
   //
   mySerCmd.ReadSer();
}

    
   

Owner
Similar Resources

ArduinoIoTCloud library is the central element of the firmware enabling certain Arduino boards to connect to the Arduino IoT Cloud

ArduinoIoTCloud What? The ArduinoIoTCloud library is the central element of the firmware enabling certain Arduino boards to connect to the Arduino IoT

Dec 16, 2022

Unified interface for selecting hardware or software SPI implementations on Arduino platforms

AceSPI Unified interface for selecting hardware or software SPI implementations on Arduino platforms. The code was initially part of the AceSegment li

Oct 22, 2021

Arduino software emulation of a real-time clock based on the milliseconds timer of the CPU

Clock-Library Arduino software emulation of a real-time clock based on the milliseconds timer of the CPU. The clock works with a resolution of one min

Jun 25, 2022

Send and receive MIDI messages over Ethernet (rtpMIDI or AppleMIDI)

Send and receive MIDI messages over Ethernet (rtpMIDI or AppleMIDI)

AppleMIDI (aka rtpMIDI) for Arduino Enables an Arduino with IP/UDP capabilities (Ethernet shield, ESP8266, ESP32, ...) to participate in an AppleMIDI

Dec 29, 2022

The Approximate Library is a WiFi Arduino library for building proximate interactions between your Internet of Things and the ESP8266 or ESP32

The Approximate Library is a WiFi Arduino library for building proximate interactions between your Internet of Things and the ESP8266 or ESP32

The Approximate Library The Approximate library is a WiFi Arduino Library for building proximate interactions between your Internet of Things and the

Dec 7, 2022

JerryScript port to ArduinoCore-Mbed

JerryScript port to ArduinoCore-Mbed Overview Integrate ArduinoCore-mbed and modern JavaScript standards (ECMAScript 5/6/6+) powered by JerryScript. W

Jul 20, 2022

Arduino library for interfacing with any GPS, GLONASS, Galileo or GNSS module and interpreting its NMEA messages.

Arduino library for interfacing with any GPS, GLONASS, Galileo or GNSS module and interpreting its NMEA messages.

107-Arduino-NMEA-Parser Arduino library for interfacing with any GPS, GLONASS, Galileo or GNSS module and interpreting its NMEA messages. This library

Jan 1, 2023

Arduino, esp32 and esp8266 library for ABB (ex PowerOne) Aurora Inverter, implement a full methods to retrieve data from the Inverter via RS-485

Arduino, esp32 and esp8266 library for ABB (ex PowerOne) Aurora Inverter, implement a full methods to retrieve data from the Inverter via RS-485

ABB Aurora protocol You can refer the complete documentation on my site ABB Aurora PV inverter library for Arduino, esp8266 and esp32 I create this li

Nov 22, 2022

Arduino library to access Adafruit IO from WiFi, cellular, and ethernet modules.

Arduino library to access Adafruit IO from WiFi, cellular, and ethernet modules.

Adafruit IO Arduino Library This library provides a simple device independent interface for interacting with Adafruit IO using Arduino. It allows you

Dec 23, 2022
Comments
  • Suggested enhancement

    Suggested enhancement

    Thanks for SerialCmd. This is not an 'issue', but a suggested enhancement. Itshould probably be a 'pull request', but I don't really do / understand GitHub, sorry.

    I'm using SerialCmd, but have other traffic on the serial port that is not amendable to processing with SerialCmd. Accordingly, it's useful to make anything SerialCmd doesn't recognise available to the rest of my sketch. Therefore, I copy the received command into a second buffer immediately after it's recognised as an input line and just before trying to strtok_r it. It's an easy code change, but it does add more RAM consumption, so if you were to add it, it probably needs to be a conditional option. This can be done as follows:

    In SerialCmd.h add to the 'configuration' block #define SERIALCMD_PUBBUFFER 1 // If set to 1 double buffer read lines to a public

    Also in SerialCmd.h add at the end of the public: section: #if ( SERIALCMD_PUBBUFFER ) char lastLine[SERIALCMD_MAXBUFFER + 1]; #endif

    In SerialCmd.cpp add into SerialCmd::ReadSer() immediately after the the 'if ( SerialCmd_InChar == SerialCmd_Term ) {' if ( SERIALCMD_PUBBUFFER ) strcpy(lastLine,SerialCmd_Buffer); // copy to public buffer #endif

    This all results in creation of a new public char SerialCmd.lastLine[] which contains whatever the last received serial line was, whether SerialCmd recognised it as a line or not, so then (for example) Demo_SerialCmd.ino can do something like: ret = mySerCmd.ReadSer(); if ( ret == 0 ) { mySerCmd.Print ( ( char * ) "ERROR: Urecognized command: " ); mySerCmd.Print (mySerCmd.lastLine); mySerCmd.Print ( ( char * ) "\r\n"); }

Related tags
Easily and asynchronously interact with a serial device requiring call-and-response style commands.

Arduino Managed Serial Device Note This library was formerly less-descriptively named "Arduino Async Duplex" This library allows you to asynchronously

Nov 20, 2022
Easily and asynchronously interact with a serial device requiring call-and-response style commands.

Arduino Managed Serial Device Note This library was formerly less-descriptively named "Arduino Async Duplex" This library allows you to asynchronously

Nov 20, 2022
A library to control esp-8266 from Arduino by AT commands easier.
A library to control esp-8266 from Arduino by AT commands easier.

ArduinoESPAT A library to control esp-8266 from Arduino by AT commands easier. Wiring Diagram Arduino Uno ESPr 5V Vin GND GND D2 TX D3 RX Usage Defini

Dec 18, 2022
An Arduino library with additions to vanilla Serial.print(). Chainable methods and verbosity levels. Suitable for debug messages.

advancedSerial This library provides some additions to vanilla Serial.print(): 1. Chainable print() and println() methods: // you can chain print() a

Dec 13, 2022
Software emulated serial using hardware timers for improved compatibility
Software emulated serial using hardware timers for improved compatibility

AltSoftSerial Library Improved software emulated serial, using hardware timers for precise signal timing and availability of CPU time for other librar

Dec 12, 2022
Arduino client for the Serial To TCP Bridge Protocol PC side service

Arduino Serial to TCP Bridge Client Arduino client for the Serial To TCP Bridge Protocol gateway service. Open a TCP connection to a server from the A

Apr 12, 2022
Arduino Arduino library for the CloudStorage server project. The library provides easy access to server-stored values and operations.

Arduino-CloudStorage Arduino/ESP8266 library that allows you to easly store and retreive data from a remote (cloud) storage in a key/value fashion. Cl

Jan 30, 2022
Minimal bit-bang send serial 38400/115200 baud for 1MHz or 115200/230400 baud for 8 or 16MHz ATtiny clock
Minimal bit-bang send serial 38400/115200 baud for 1MHz or 115200/230400 baud for 8 or 16MHz ATtiny clock

Attiny Serial Out Available as Arduino library "ATtinySerialOut" Version 2.0.1 - work in progress Minimal bit-bang send serial 115200 baud for 1/8/16

Jan 4, 2023
Port of BearSSL to Arduino

ArduinoBearSSL Port of BearSSL to Arduino. This library depends on ArduinoECCX08. This dependency could be disabled by defining ARDUINO_DISABLE_ECCX08

Dec 14, 2022
Arduino library for making an IHC in or output module using an Arduino

Introduction This is an Arduino library for making an IHC in or output module using an Arduino. (IHC controller is a home automation controller made b

Mar 26, 2020