SerialCmd
A Wiring/Arduino library to tokenize and parse commands received over a phisical/software serial port or buffer.
Install / Use
/learn @gpb01/SerialCmdREADME
SerialCmd Library v1.1.6
© 2023 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.
• © 2023 Guglielmo Braguglia<br> • © 2012 Stefan Rado<br> • © 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
#define SERIALCMD_PUBBUFFER 0 // If set to 1 create a public double buffer
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.
SERIALCMD_PUBBUFFER: It can be either 0 or 1 and indicates whether or not a second buffer should be created so that the entered line can be retrieved from the program..
Public Variables
When the SERIALCMD_PUBBUFFER parameter is set to 1, a public, program-accessible variable named lastLine is created for the class. It will contain the entire line (up to the terminator) received by the library, before it was processed. See the demo program for an example of its use.
Customization
A further series of #define defines:
-
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.
-
the source from which the received command is considered valid (only from serial port, only from memory buffer, from both)
-
the character indicating the end of the command (CR = 0x0D, LF = 0x0A or NULL = 0x00)
-
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 <SerialCmd.h>
... 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
uint8_t 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). Returns and uint8_t to indicate whether the command was added (true/1 value) or not (false/0 value).
Starting from versioni 1.1.3 it is now possible to 'redefine' a command (calling the AddCmd() method several times), i.e., use the same command by dynamically associating it with another function or the NULL value.
This makes it possible, for example, to enable and disable a command at run-time, simply by changing the function to which it refers either to the NULL value or to the true value of the function to be executed. As another example, it is possible to start with a command that calls a certain function and, when certain conditions occur, replace it with another function.
Example:
ret = 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.
uint8_t AddCmd( const __FlashStringHelper *command, char allowedSource, void ( *function )() );
Valid only on AVR architecture, 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). Returns and uint8_t to indicate whether the command was added (true/1 value) or not (false/0 value).
Starting from versioni 1.1.3 it is now possible to 'redefine' a command (calling the AddCmd() method several times), i.e., use the same command by dynamically associating it with another function or the NULL value.
This makes it possible, for example, to enable and disable a command at run-time, simply by changing the function to which it refers either to the NULL value or to the true value of the function to be executed. As another example, it is possible to start with a command that calls a certain function and, when certain conditions occur, replace it with another function.
Example:
ret = mySerCmd.AddCmd( F ( "LEDON" ), SERIALCMD_FROMALL, set_LedOn );
... where F ( "LEDON" ) is the command (string is stored in PROGMEM instead of SRAM to reduce memory occupation), 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.
char* ReadNext( )
Returns 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( );
void 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), a signed/unsigned long (long, unsigned long) or a float/double (float, double), to the serial port (hardware or software) associated with the SerialCmd.
On AVR architecture it also allows the use of the macro F (), with constant strings, to reduce the SRAM occupation.
Example:
mySerCmd.Print( (char *) "This is a message \r\n" );
... or, with AVR MCU, you can use:
mySerCmd.Print( F ( "This is a message \r\n" ) );
int8_t ReadSer( )
It must be called continuously inside the loop () to receive and interpret the commands received from the serial port (hardware or software). Returns an int8_t that can take the following values: -1: terminator character not yet encountered; 0: command not recognized; 1: command recognized.
Example:
void setup( ) {
...
...
}
void loop( ) {
ret = mySerCmd.ReadSer( );
...
...
}
int8_t ReadString ( char * theCmd, uint8_t fValidate = false )
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). Returns and int8_t to indicate whether the command was recognized (true/1 value) or not (false/0 value). The optional fValidate parameter (default false) allows you to call the function only to check if the received command exists, without actually executing the associated function.
Example:
ret = mySerCmd.ReadString ( (char *) "LEDON" );
