Overview of the Serial Communication Protocol

Setting Up the Arduino

Notice that the Arduino code (Listing 1) does not have much logic. The only thing it does is respond to incoming messages. In this case, whatever program is controlling the device makes all the decisions, so the logic lives elsewhere. The Arduino just follows the instructions it receives over the serial port and reports changes to the attached inputs.

Listing 1

Arduino Code

01 #include <Servo.h>
03 Servo servo;
04 int oldSwitch = 0;
05 int oldButton = 0;
07 void setup()
08 {
09   pinMode(2, INPUT_PULLUP );
10   pinMode(3, INPUT_PULLUP );
11   pinMode(13, OUTPUT);
12   Serial.begin ( 9600 );
13   Serial.setTimeout ( 5000 );
15   servo.attach ( 11 );
16 }
18 void loop()
19 {
20   char incoming=0;
21   int readState=0;
23   if ( Serial.available() )
24   {
25     incoming = Serial.read();
26     if ( incoming == 'L' ) digitalWrite ( 13 , HIGH );
27     else if ( incoming == 'l' ) digitalWrite ( 13 , LOW );
28     else
29     {
30       int i=0;
31       String fullNumber = String ( incoming );
32       String number;
34       number = Serial.readStringUntil ( '.' );
35       fullNumber.concat ( number );
36       i = fullNumber.toInt();
38       if ( i >= 0 && i <= 180 ) servo.write ( i );
39     }
40   }
42   readState = digitalRead ( 2 );
43   if ( readState != oldButton )
44   {
45     oldButton = readState;
46     Serial.print ( "Button:" );
47     Serial.println ( readState );
48   }
50   readState = digitalRead ( 3 );
51   if ( readState != oldSwitch )
52   {
53     oldSwitch = readState;
54     Serial.print ( "Switch:" );
55     Serial.println ( readState );
56   }
57 }

Lines 1-5 bring in the appropriate library and initialize global variables: servo from the Servo.h library represents a servo motor, and the integers oldSwitch and oldButton store previous states of the button and switch.

The Arduino calls the setup function (lines 7-16) once when the program is first run. As the name implies, it sets up any Arduino features that will be used and initializes any hardware that needs to be set up before the main loop runs. In this case, it sets up input and output pins and the serial port.

Lines 9-11 tell the Arduino whether the specified pin is used as an input or an output. The first argument is the pin number, and the second argument is the mode. The INPUT_PULLUP mode not only sets the pin to an input but also enables the Arduino's pull-up resistor.

Buttons and switches are passive components (not electrically active on their own) so the pull-up resistor provides the electrical equivalent of a default value. The pull-up resistor is relatively weak, so when the button or switch is connected to ground, the pin will see that instead, which guarantees a clean 0 or 1 each time the button or switch changes.

The Arduino Uno has one serial port located on pins 0 and 1. You'll notice, though, that nothing is connected to those pins. It also has a USB-to-serial converter as part of its onboard hardware, but everything happens behind the scenes, so you don't have to worry about it. I'll be using serial from the attached computer over the USB port.

The Serial.begin function tells the Arduino to turn on the serial port (as opposed to being a general-purpose I/O), and 9600 is the baud rate. Serial.timeout tells the Arduino that any code waiting for input from the serial port should stop waiting after 5,000msec, which prevents the program from stalling if a proper signal isn't received. Eventually, it will time out and move on with the program.

Servo Setup

The servo variable created in line 3 hasn't been connected to anything yet, so the servo.attach line tells the Arduino which pin the servo is on (11 in this case).

The special Arduino loop() function starts in line 18 and does exactly what its name implies: It runs continuously until power is removed from the Arduino.

After initializing two local variables, incoming and readState, a checking routine looks for any characters that are available from the serial port. Serial.available returns the number of characters waiting in the buffer. If it is not zero, the processing inside the if statement proceeds.

The Serial.read gets the first character from the serial port and saves it in the incoming variable. If the incoming character is an uppercase L, a call to digitalWrite turns the LED on; otherwise, the program checks for a lowercase l, which turns off the LED.

By line 28, if nothing has happened, the Arduino has probably received a number, which is processed in lines 29-39. After initializing the local variable i to 0, lines 31 and 32 set up strings for the incoming data from the serial port. The fullNumber variable is given an initial value of the string version of incoming – the first character received (i.e., the first digit).

The variable number is initialized to a blank string. Line 34 requests characters from the serial port until it receives a period. The received characters go into number, which is concatenated to fullNumber in the next line. Now fullNumber really does have the full number received from the port. Line 36 uses toInt to turn the string into an integer and stores it in i.

Finally, if i is greater than 0 and less than 180 (the valid range for a servo), servo.write asks the servo to move to the angle specified in i.

Buttons and Switches

Variable readState stores the state of Arduino pin 2, which determines whether the button is pressed or not. Note that a value of 0 is pressed and 1 is not pressed, which might seem backward.

If readState is different from oldButton, the button has changed state. In that case, line 45 updates oldButton, line 46 sends the string Button: out the serial port, and line 47 sends the new state of the button; Serial.println then tells the Arduino to add a newline after printing the readState variable.

Checking the switch works exactly the same as checking the button, except on pin 3 (line 50) and by checking and updating oldSwitch (lines 51 and 53) instead of oldButton and printing Switch: instead of Button: (line 54).

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Perl: Arduino Project

    With a few lines of self-written firmware and a simple Perl script, Perlmeister Mike Schilli trains one of his Linux computers with a plugged in Arduino board to switch electrical equipment on and off using a relay. Enchanting.

  • Web Serial API

    Upgrade your computer with LEDs, buttons, or sensors to control a microcontroller board over USB from your web browser.

  • Nerf Target Game

    A cool Nerf gun game for a neighborhood party provides a lesson in Python coding with multiple processors.

  • DIY Scoreboard

    We look at a broadcast video system network that uses Python code to control a video router and check out another program that creates a scoreboard.

  • Escape Room Puzzle

    A digital puzzle presents a challenge for young people in an escape room.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More