Intro to Physical Computing Syllabus

Research & Learning

Other Class pages

Shop Admin

ITP Help Pages
Tom's pcomp site
DanO's pcomp site


Serial Out using an Arduino

Overview

In this lab, you'll send data from a single sensor to a program on a personal computer. The program will graph the output of the sensor onscreen. This is a common way to find out how a sensor's output corresponds to the physical events that it senses.

1.  Parts

For this lab you'll need:

hookup wire
22-AWG hookup wire
Arduino module
Arduino Microcontroller
module
potentiometer
10Kohm potentiometer (or a different
form of analog sensor)


2.  Connect the sensor

Connect your analog sensor to analog pin 0 like you did in the analog lab. A potentiometer is shown here because it's easy, but you might want to pick a sensor that's more interesting. IR distance rangers are fun for this exercise, for example. Force-sensing resistors are good as well.

3.  Read and send the serial data

Program the Arduino module as follows:

 int analogPin = 0;
 int analogValue = 0;

 void setup()
 {
   // start serial port at 9600 bps:
   Serial.begin(9600);
 }

 void loop()
 {
   // read analog input, divide by 4 to make the range 0-255:
   analogValue = analogRead(analogPin); 
   analogValue = analogValue / 4;
   Serial.print(analogValue, BYTE);
   // pause for 10 milliseconds:
   delay(10);                 
 }

When you open the serial monitor, you should see garbage characters. What's going on? The BYTE modifier doesn't format the bytes. It sends out the raw binary value of the byte. The Serial Monitor receives that binary value and assumes it should show you the ASCII character corresponding to that value. The garbage characters are characters corresponding to the ASCII values the Monitor is receiving. You'll learn more about that in the second serial lab.

You can use other programs besides serial monitor to see the serial communication, as described below:

Windows: Hyperterminal can be found in the Start Menu, under All Programs, Accessories, Communications, Hyperterminal. To configure Hyperterminal for serial communication, open the program and click on the File, Properties menu item. Choose the serial port you want to open from the popup menu in the Configuration tab. Click on Configure to bring up the Port Settings tab. Set the properties as needed for the device you’re talking to. For many projects, you’ll set the port settings to 9600 bits per second, 8 data bits, no parity, one stop bit, and no hardware flow control. Once you’ve applied those settings, click the Call button on the toolbar to open the serial port. Any bytes you type in the window will be sent out the serial port you opened. They won't show up on the screen, however. Any bytes received in the serial port will be displayed in the window. Click the Disconnect button to close the serial port.

OSX: There are a few ways to see serial data in OSX. The easiest is to use Tom Gerhardt's excellent serial application, Cornflake. It's similar to the Arduino serial terminal but much more powerful, in that it lets you choose whether you want to view data as binary or ASCII, lets you open and close multiple serial ports, and more.

You can also use Terminal. To configure Terminal for serial communication in OSX, open the program and type ls /dev/tty.* This will give you a list of available serial ports. The names of the serial port in OSX are more unique than the names that Windows uses. Pick your serial port and type screen portname datarate. For example, to open the serial port on an Arduino board at 9600 bits per second, you might type screen /dev/tty.usbserial-5B1 9600. The screen will cleared, and any bytes you type will be sent out the serial port you opened. They won't show up on the screen, however. Any bytes received in the serial port will be displayed in the window. To close the serial port, type control-A followed by control-\.

NOTE: only one program can control a serial port at a time. When you're not using a given program, remember to close the serial port. You won't be able to re-program the Arduino module if you don't, because the serial terminal program will have control of the serial port.

4.  Graph the sensor's values

The serial monitor in Arduino isn't the only program on your computer that can read data in from the microcontroller. Any program that can access the computer's serial ports can do it. Following is an example for Processing.

The first thing you need to do is to import the Processing Serial Library. This is a code library that adds functionality to Processing so it can read from and write to the computer's serial ports. You can do this by choosing the Sketch menu, then Import Library...-->serial, or you can type:

import processing.serial.*;

To use the serial library, you're going to create an instance of the library in a variable. You'll also need a variable to keep track of the horizontal position of the graph. So here are your global variables, to be declared at the top of your program:

Serial myPort;        // The serial port
int graphXPos = 1;    // the horizontal position of the graph:  

In the setup() method, you'll set the window size, and use the serial library to get a list of the serial ports:

void setup () {
  size(400, 300);        // window size

  // List all the available serial ports
  println(Serial.list());
}

If you run what you've typed so far, you should get a list of the serial ports in the monitor pane that looks a bit like this on a mac. On a Windows machine, the port list will have names like COM3, COM4, COM5, and so forth:

Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version   = RXTX-2.1-7
[0] "/dev/tty.usbserial-A6004osg"
[1] "/dev/cu.usbserial-A6004osg"
[2] "/dev/tty.Bluetooth-Modem"
[3] "/dev/cu.Bluetooth-Modem"
[4] "/dev/tty.Bluetooth-PDA-Sync"
[5] "/dev/cu.Bluetooth-PDA-Sync"
Experimental:  JNI_OnLoad called.

One of these ports is the same as the serial port name you use in the Arduino programming environment. That's the one you want. In the above list, it's port number 0. So to open that port, add the following line at the end of the setup:

  myPort = new Serial(this, Serial.list()[0], 9600);

Finally, set the background color. Pick a nice color, don't just use primary colors. You'll be looking at it a long time, so you might as well like it. Add this to the end of the setup:

 background(48,31,65);

You won't actually do anything in the draw() method for this sketch, but you need it for the program to do anything, so here's an empty draw() method:


void draw () {
  // nothing happens in draw.  It all happens in SerialEvent()
}

The serial library has a special method called serialEvent(). Every time a new byte arrives in the serial port, serialEvent() is called. So you can use it to read bytes from the microcontroller. Here's what it looks like:

void serialEvent (Serial myPort) {
  // get the byte:
  int inByte = myPort.read(); 
  // print it:
  println(inByte);
}

myPort.read() tells the program to read a byte from the serial port myPort. Bytes are read like peas coming out of a peashooter. Every time you read a byte, it's removed from the serial buffer. So it's good practice to read the byte into a variable as shown above, then never read again until you want another byte. If you want to do something with the byte you read (like graphing it), use the variable you read it into.

Now it's time to draw a graph with the bytes you read. To do this, you'll draw a line whose length corresponds to the byte's value. Add this at the end of the serialEvent() method:

  // set the drawing color. Pick a pretty color:
  stroke(123,128,158);
  // draw the line:
  line(graphXPos, height, graphXPos, height - inByte);

Finally you need to increment the horizontal position for drawing the next byte's line. This goes at the end of the serialEvent:

 // at the edge of the screen, go back to the beginning:
  if (graphXPos >= width) {
    graphXPos = 0;
    // clear the screen:
    background(48,31,65); 
  } 
  else {
    // increment the horizontal position for the next reading:
    graphXPos++;
  }

That's it! When you run this sketch, you'll see the sensor's value graphed on the screen like so:

Here's the Processing sketch in its entirety:

/*
Sensor Graphing Sketch

 This sketch takes raw bytes from the serial port at 9600 baud and graphs them.

 Created 20 April 2005
 Updated 5 August 2008
 by Tom Igoe
 */

import processing.serial.*;

Serial myPort;        // The serial port
int graphXPos = 1;    // the horizontal position of the graph:  

void setup () {
  size(400, 300);        // window size

  // List all the available serial ports
  println(Serial.list());
  // I know that the fisrt port in the serial list on my mac
  // is usually my Arduino module, so I open Serial.list()[0].
  // Open whatever port is the one you're using.
  myPort = new Serial(this, Serial.list()[0], 9600);

  // set inital background:
  background(48,31,65);
}
void draw () {
  // nothing happens in draw.  It all happens in SerialEvent()
}

void serialEvent (Serial myPort) {
  // get the byte:
  int inByte = myPort.read(); 
    // print it:
  println(inByte);
  // set the drawing color. Pick a pretty color:
  stroke(123,128,158);
  // draw the line:
  line(graphXPos, height, graphXPos, height - inByte);

  // at the edge of the screen, go back to the beginning:
  if (graphXPos >= width) {
    graphXPos = 0;
    // clear the screen:
    background(48,31,65); 
  } 
  else {
    // increment the horizontal position for the next reading:
    graphXPos++;
  }
}

If you get results like the screenshot above, congratulations! You're reading serial data. This would be a good time to stop and review what happened so you're clear on all the details.

This program is worth keeping around for every new analog sensor you work with. It will help you see how the sensor translates physical changes into digital changes. As you can see in the graph above, sometimes a sensor produces a noisy signal. That can interfere with your readings in some cases, so you'd need to filter out the noise. The simplest way to do this is to average the sensor readings over several readings.

This method of serial communication works great if you're only reading one byte at a time repeatedly. However, when you're reading multiple sensors, or sending data back to the microcontroller to control things attached to it, serial communication gets more complex. For more on that, see the second serial lab.

  Edit | View | History | Print | Recent Changes | Search Page last modified on October 14, 2009, at 08:58 AM