How to communicate with Arduino using a command table

By | October 6, 2015

There are thousands of examples in the web showing how easy is to communicate with an Arduino board using the serial port. In this post, I would like to go one step forward and show how to communicate using a command table which is a method used by many commercial devices that allow communicating effectively and efficiently using the serial port.

A command table is a dictionary of instructions that can be divided into two categories: commands and queries. The first category corresponds to a direct order such as "move servo motor connected to pin 3, half-turn". The second type of command is used to ask information to the device about its status; for example the state of a digital variable, the value of an ADC or the identification string that contains relevant information about the device and its manufacturer.

In the next sections, I will show how to control the Arduino UNO digital pins using a command table composed of N commands. The code presented here can be easily extended to other Arduino functions that allow to control servo motors, stepper motors and to retrieve information from ADCs, among others.

Commands

In general, a command has the following structure:
Command:subCommand1:subCommand2...subCommandN:Value
Note that the command is composed of a set of substrings separated by the character ":". The principal instruction, Command, can be followed by any number of subCommands. The combination of strings Command:subCommand1:subCommand2...subCommandN is unique and corresponds to a very specific order that can control only a single degree of freedom of the device every time is sent. The value of the variable to control is specified in the last string: Value.

Examples:

  • SERVO:POSITION:120 (move servo to position 120º)
  • SERVO:SPEED:5 (set servo speed to 5)
  • SERVO:PORT1:OFF (turn off servo connected to port 1)

In some occasions, a single command may contain more than one variable so that the command string is Command:subCommand1:value1:subCommand2...subCommandN:valueN.

The instruction:

  • SERVO:PORT:1:POSITION:135 (move servo in PORT 1 to position 135º) is an example where is specified the SERVO channel (1) and its position (135º).

From my experience, a dictionary composed of two subCommand commands is more than enough to implement a large variety of functions in your device.

Queries

A query has the following structure:

Command:subCommand1:subCommand2...subCommandN?

The instruction is similar to a command; however, it has a question mark at the end to indicate that we are asking for information. From the query is returned the value that was previously specified for the instruction Command:subCommand1:subCommand2...subCommandN:Value (or its default value). As in the command case, a query may also contain more than one variable.

Examples:

  • SERVO:POSITION? (what is the position of the servo?) >> 358
  • SERVO:PORT1? (is the servo in port 1 active?) >> FALSE

A query command can be used also to retrieve information of the device such as its manufacturer, model, version among others. In may commercial devices the string "*IDN?" is reserved to retrieve this type of information.

  • *IDN? >> Servo control from command table - totesalaz@gmail.comnLuis Jose Salazar S. - 2015

Since the PC will receive an answer from the device to the command "*IDN?" only if the connection is successful, this query is typically sent to test if the communication is established correctly.

How to control an Arduino using a command table

The following code allows turning on/off any of the digital pins (0 to 13) using a command sent through the serial port. If you don't have any circuit to test the different ports, just used the built-in LED in port 13. In this example the dictionary is composed of three, not case-sensitive, instructions:

Instruction Task
pin:n:state:[0|1] sets pin n to the state [HIGH|LOW]
pin:n:state? queries the state of pin n
*idn? retrieve device information

The next code is based on the example SerialEvent that can be found on the Arduino web page. The function SerialEvent is called every time data is available in the serial port buffer. To start, open a new file and write the following lines to initialize the required variables

The commandString variable stores the incoming data from the serial port, whereas stringComplete changes to true every time string sent is complete.

The next two variables, commandSeparator and commandSplitted, are used to store the position of the separation character ":" within commandString and from this information the commandString is separated into substrings that are stored in the commandSplitted array.

The array pinStatus is used to determine the status of each pin. In this particular example, four pins can be controlled. By default, each pin is initialized to zero (LOW state).

After defining the global variables, copy the following lines corresponding to setup() and loop() functions.

Usage example

Open the serial monitor in the Arduino IDE (Ctrl+Shift+m) and used the commands pin:13:state:1 and pin:13:state? to turn on the LED on pin 13 and to retrieve information about its status. The serial monitor should look like the following image.

commandSequence

The code presented has been tested on an Arduino UNO board and on a DFRobot Romeo V1.0 board.