Arduino Communication

In Wednesday’s lab we programmed our Arduino to blink a LED. This is cool, but ultimately this is a class about tangible user interfaces. We need ways to communicate digital and physical information back and forth between our devices and our Arduino.

The simplest way to do this is via the Arduino’s builtin serial library. In today’s lab we will leverage this serial library to augment our blinking LED setup to be interactive. You will be able to send STOP and START commands from your laptop and your Arduino will start and stop its builtin light appropriately.

The serial library

The Arduino serial library allows us to communicate between the Arduino and our laptops while it is plugged in. Much like we need to set a pin to output mode before using it we need to start serial communications before we can use them. We do so with something like this in our setup function:

void setup() {
    Serial.begin(9600);
}

The Serial.begin part of this is reasonably straightforward. The 9600 number might not be. What that number tells the Arduino is how fast we would like information to be sent over the communications channel. This number can be as low as 300 and as high as 115200.

In practice using 9600 is likely to be more than fine for most of your projects. All we need to make sure to do is that when sending and receiving data from our laptops to our Arduino that we send and receive it at the same rate we specify in begin.

A quick example

Let’s put together a quick sample program using the serial library. We’ll write an “echo” program that runs on our Arduino and sends any information we send to it back unchanged.

Our setup function will look the same as it did above:

void setup() {
    Serial.begin(9600)
}

Our loop function on the other hand will be a little more complicated. We’ll start out our loop by checking if there is data available for us:

void loop() {
  if (Serial.available()) {
    // TODO - read the message
    // TODO - send it back
  }
}

We’ll then read in the message that we got with the Serial.readStringUntil function. For the “until” part of that function we’ll provide a newline character.

We’ve selected that character because when sending a message to the Arduino from your laptop the default is that messages will end in a new line. Later in this course you may want to design your own data exchange protocol and you’ll likely want to change that out.

We store the result of that function call in a variable called message which we’ll send back to the user.

String message = Serial.readStringUntil('\n');

Finally we can respond to the message. This is surprisingly simple. We add a : and a newline of our own for some stylistic flare.

Serial.print(": " + message + "\n");

Our final code for this section ends up looking like this:

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()) {
    String message = Serial.readStringUntil('\n');
    Serial.print(": " + message + "\n");
  }
}

Having uploaded that to your Arduino you can test it out by navigating to Tools -> Serial Monitor in the IDE’s context menu. From there you can type messages into the top bar and see the Arduino’s response in the primary section. Nice!

Serial and blinking lights

Now that we know how to send and receive data adding some user control to our light blinking code is reasonably simple. In our setup function we initialize both our output pin and our serial communication:

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
}

Next, above our setup function we create a variable that will store rather or not the LED should currently be blinking.

bool blink = true;

In our loop function we can make blinking conditional on blink being true as follows:

void loop() {
  if (blink) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(500);
    digitalWrite(LED_BUILTIN, LOW);
    delay(500);
  }
}

Finally, we can set the blink variable based on commands from the user by reading from the serial input, checking if it is a command, and taking action as appropriate. The code for this can be added to the top of our loop function.

if (Serial.available()) {
  String command = Serial.readStringUntil('\n');
  if (command == "START") {
    blink = true;
  }
  if (command == "STOP") {
    blink = false;
  }
}

Having done that we’re done! Our final code looks as follows:

bool blink = true;

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  if (Serial.available()) {
    String command = Serial.readStringUntil('\n');
    if (command == "START") {
      blink = true;
    }
    if (command == "STOP") {
      blink = false;
    }
  }

  if (blink) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(500);
    digitalWrite(LED_BUILTIN, LOW);
    delay(500);
  }
}

Sending the message START or STOP from the serial monitor should result in your Arduino’s builtin LED turning on and off.

Next steps

Having done this there are a number of interesting ways that you might be able to extend the project. Here are some ideas:

  1. Can this be extended to blink an external LED (i.e. not LED_BUILTIN)?
  2. What other commands could we add? Perhaps some commands to speed up or slow down the blink rate would be interesting.
  3. If you’re feeling particularity inspired what about sending “logic” to the Arduino that controls the blinks. For example (* 5 blink) might blink the LED five times or (dotimes (n 10) (* blink n) (sleep n)) might “count up” with blinks.

Don’t feel at all obligated to actually try these. Number three is probably a terrible but fun idea for all sorts of reasons.

Thanks for reading. Please submit any bugs in this write up or questions to via email.