|
Intro to Physical Computing Syllabus Research & Learning Other Class pages
ITP Help Pages |
Serial Out using an ArduinoOverviewIn 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. Table of Contents (hide) 1. PartsFor this lab you'll need:
2. Connect the sensorConnect 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 dataProgram 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 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 valuesThe 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 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
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
void draw () {
// nothing happens in draw. It all happens in SerialEvent()
}
The serial library has a special method called
void serialEvent (Serial myPort) {
// get the byte:
int inByte = myPort.read();
// print it:
println(inByte);
}
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 // 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. |