It is possible to use the serial port to receive commands directly in the Arduino code. We can for example control the GPIO from the serial monitor of a code editor such as the Arduino IDE or PlatformIO.
It is also possible to make several development boards or micro-controllers communicate with each other (STM32, ESP32, ESP8266) via the serial port.
Open the serial port in the Arduino code
Before being able to receive messages from the serial port, it is necessary to initialize the communication with the command Serial.begin(speed). This method takes the baud rate of the serial port as a parameter.
By default, it is set at 9600 baud .
You can choose one of these speeds 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, or 115200.
Most current development boards support the speed of 115200 baud without any problem.
Serial.begin(115200);
How to receive commands from the serial port?
Using the serial port as a command input is not much more complicated than the serial output.
We already know the Serial.print() command (and associated functions) which allows you to send characters to the serial port as well as the other derived commands presented in detail in this article.
To receive characters on the serial port, we have several commands (official documentation)
Serial.available() which allows to listen to everything that arrives on the serial port and to trigger a treatment.
availableForWrite() allows to know the number of bytes (characters) available for writing to the serial buffer without blocking the write operation.
The methods to read in the buffer memory of the serial port
Serial.read() read whatever comes in on the serial port.
4 other more specialized functions
Serial.find() reads data from the serial buffer until the search string is found. The function returns true if the string is found.
Serial.findUntil() reads data from the serial buffer until a target string of a given length or termination string is found. The function returns true if the target string is found.
Serial.setTimeout(duration) is used to modify the Timeout, the waiting time before the execution of blocking Serial functions are aborted. The Timeout is 1 second by default.
The wait time is in milliseconds. 1 second = 1000ms
The following functions are blocking: find(), findUntil(), parseInt(), parseFloat(), readBytes(), readBytesUntil(), readString(), readStringUntil().
Upload the project to drive an LED by sending commands to the serial port
Create a new sketch on the Arduino IDE or a new PlatformIO project and paste the following code.
The following orders are accepted
- led=on to turn on the LED
- led=off to turn off the LED
- ledstatus to know the state of the LED (ON or OFF) which is stored in the variable led_status
- Any other command returns the error Invalid command
Before uploading the code, modify the constant LED_PIN which indicates the pin on which the LED is connected
#include <Arduino.h>
#define LED_PIN 32
bool led_status = false;
String command;
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
}
void send_led_status(){
if ( led_status ) {
Serial.println("LED is ON");
} else {
Serial.println("LED is OFF");
}
}
void loop() {
if(Serial.available()){
command = Serial.readStringUntil('\n');
Serial.printf("Command received %s \n", command);
if(command.equals("led=on")){
digitalWrite(LED_PIN, HIGH);
led_status = 1;
} else if(command.equals("led=off")){
digitalWrite(LED_PIN, LOW);
led_status = 0;
} else if(command.equals("ledstatus")){
send_led_status();
} else{
Serial.println("Invalid command");
}
}
}
Project circuit
For this project, we will simply connect an LED to a digital output of an Arduino board. The code is compatible with any ESP32 or ESP8266 board. Just change the pin that the LED is connected to.
Here the LED is plugged into output 32 of an ESP32 development board.
Explanation of the code
The Serial.available() command changes to true whenever the serial port buffer contains new characters. By placing the function in the main thead of the program, the loop(), we can immediately receive incoming commands
if( Serial.available() ){
... processing of incoming commands on the serial port
}
As we saw in the introduction, there are several functions available to read from the serial port buffer.
The serial monitor finishes sending it with the \n control character corresponding to the end of the line .
You can use the Serial.readUntil(“\n”) method which allows you to read up to the string passed in parameter. We store the string in the command variable of type String.
command = Serial.readStringUntil('\n');
All that remains is to use the string processing functions to identify the command and the parameter.
All the String processing functions are detailed in this article
Here, we will simply test if we have just received one of the three commands led=on, led=off , ledstatus .
The state of the LED is stored in the variable led_status
if(command.equals("led=on")){
digitalWrite(LED_PIN, HIGH);
led_status = 1;
} else if(command.equals("led=off")){
digitalWrite(LED_PIN, LOW);
led_status = 0;
} else if(command.equals("ledstatus")){
send_led_status();
} else{
Serial.println("Invalid command");
}
The send_led_status function prints the status of the LED as a string to the serial port using the println() function. To learn more about all the methods to write to serial port, you can continue by reading this article
void send_led_status(){
if ( led_status ) {
Serial.println("LED is ON");
} else {
Serial.println("LED is OFF");
}
}
Test the project from the Arduino IDE serial monitor
Open the serial monitor from the Tools -> Serial monitor menu or using the icon
An input field is located above the serial monitor window. Press the Send button or the Enter key on your keyboard to send the string to the Arduino.
Now you can test the operation of the three commands led=on , led=off , ledstatus .
Video demonstration
Test the project from the PlatformIO serial monitor
By default, the PlatformIO serial monitor does not allow sending commands from the Terminal.
To be able to send commands (character strings) on the serial port, filters must be added using the monitor_filters option detailed here in the platformio.ini file.
Filtered | Description |
---|---|
default | Remove control codes |
colorize | Apply different colors for received and echo commands |
debug | Print what is sent and received |
direct | Do nothing, transfer all data unchanged |
hexlify | Display a hexadecimal representation of the data |
log2file | Log the data in a “platformio-device-monitor-% date% .log” file located in the working directory of the project |
nocontrol | Remove all control codes including CR and LF (Line Feed) |
printable | Show decimal code for all non-ASCII characters and replace most control codes |
time | Add a timestamp in milliseconds for each new row |
send_on_enter | Send a text to the device on ENTER |
esp32_exception_decoder | Custom filter for ESP32 which decodes the exception in the event of a crash |
esp8266_exception_decoder | Custom filter for ESP8266 which decodes the exception in the event of a crash |
Here is a sample configuration that you can use in your projects. The command is sent by pressing the enter key. The exchange log is written to a file at the root of the project.
monitor_filters = debug, send_on_enter, log2file
Save the configuration file then restart the serial monitor by clicking on the trash can.
Place the cursor (not visible) by clicking in the Terminal then enter the command. Send by pressing the enter key on the keyboard.
[TX:'l'] [TX:'e'] [TX:'d'] [TX:'='] [TX:'o'] [TX:'n'] [TX:'\r\n'] [RX:'C'] C [RX:'ommand received led=on \n'] ommand received led=on
[TX:'l'] [TX:'e'] [TX:'d'] [TX:'='] [TX:'o'] [TX:'f'] [TX:'f'] [TX:'\r\n'] [RX:'C'] C [RX:'ommand received led=off \n'] ommand received led=off
[TX:'l'] [TX:'e'] [TX:'d'] [TX:'s'] [TX:'t'] [TX:'a'] [TX:'t'] [TX:'u'] [TX:'s'] [TX:'\r\n'] [RX:'C'] C [RX:'ommand received ledstatus \nLED '] ommand received ledstatus
LED [RX:'i'] i [RX:'s OFF\r\n'] s OFF
Use CoolTerm for Windows, macOS or Linux
A final practical alternative is the CoolTerm open source software developed by Roger Meier which you can download here .
Open the Connection menu then Settings . Select the COM port of the Arduino board, ESP32, ESP8266, STM32 as well as the speed , here 115200 bauds.
Save the connection parameters and click on the Connect icon
Open the Connection -> Send String… menu.
Enter the desired command then click on Send to send
Attention, the Enter key on the keyboard returns the cursor to the line, which will pose a problem with the Arduino code.
Updates
23/10/2020 Publication of the article
- How to store data on a micro SD card. Arduino code compatible ESP32, ESP8266
- Getting started Arduino. Receive commands from the serial port (ESP32 ESP8266 compatible)
- C++ functions print•println•printf•sprintf for Arduino ESP32 ESP8266. Combine•format → serial port
- C++ String functions. concat•c_srt•indexOf•replace•subString… for Arduino, ESP32, ESP8266
- Get started with the I2C bus on Arduino ESP8266 ESP32. Wire.h library