Seeing Sensors: How to visualize and save Arduino-sensed data

Sometimes when you’re prototyping a project it’s nice to see what’s going on with your sensors or variables in your code. Sure you can watch analogRead() values scroll at warp speed on your Arduino Serial Monitor, but what if you want to save that data? Or look at a graph you make in real time instead of numbers? Maybe you want to do some self tracking and visualize your Fitbit stats, or compare two different light sensors or force sensing resistors? In this class I’ll demonstrate two workflows that help us do this…

The Basics
Check out the Analog In lab. Using this code:

int sensorPin = A0;    // analog input pin to hook the sensor to
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup() { 
  Serial.begin(9600); // initialize serial communications 
}

void loop() {
  sensorValue = analogRead(sensorPin); // read the value from the sensor
  Serial.println(sensorValue); // print value to Serial Monitor
  delay(50); // short delay so we can actually see the numbers
}

With a potentiometer (or other sensor) hooked up to analog pin 0, you should be able to click the magnifying glass icon on the top right of the Arduino screen and see something like this:

Graphing Serial Data in Processing
Okay so now you have data streaming in from your Arduino through your USB cable, and can see the values on the Serial Monitor. But unless you have Matrix-like visual skillz, these streaming numbers might be hard to keep track of. The next step is to use another program called Processing to visualize this data.

Check out step 4 of the Serial Out Lab. Load this code onto the Arduino:

int sensorPin = A0;    // analog input pin to hook the sensor to
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup() { 
  Serial.begin(9600); // initialize serial communications 
}

void loop() {
  sensorValue = analogRead(sensorPin)/4; // read the value from the sensor
  Serial.write(sensorValue); // print bytes to serial
  delay(10);
}

Then use this code in Processing:

// at the top of the program:
float xPos = 0; // horizontal position of the graph
float yPos = 0; // vertical position of the graph

import processing.serial.*;
Serial myPort;        // The serial port
 
void setup () {
  size(800, 600);        // (Width, Height) window size
 
  // List all the available serial ports
  println(Serial.list());
 
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
 
  background(#EDA430);
}
 
void draw () {
   // draw the line in a pretty color:
  stroke(#A8D9A7);
  line(xPos, height, xPos, yPos); // (x1,y1,x2,y2) Origin located at top left corner
 
  // at the edge of the screen, go back to the beginning:
  if (xPos >= width) {
    xPos = 0;
    // clear the screen by resetting the background:
    background(#081640);
  }
  else {
    // increment the horizontal position for the next reading:
    xPos++;
  }
}
 
void serialEvent (Serial myPort) {
  // get the byte:
  int inByte = myPort.read();
  // print it:
  println(inByte);
 
  yPos = height - inByte;
}

If everything goes well, you should get a quickly scrolling graph that looks something like this:

Saving Data with CoolTerm and Graphing with Excel (or OpenOffice/Google Docs equivalent)
Sweet! Now you can “see” the numbers coming through the serial port in two different ways. Suppose you want to save that data to visualize, use as an outline for a laser cut data guru trophy, compare sensors, etc. One of the easiest ways to do this is through CoolTerm.

Check out step 3 of the Serial Out lab. Now upload this code to the Arduino:

int sensorPin = A0;    // analog input pin to hook the sensor to
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup() { 
  Serial.begin(9600); // initialize serial communications 
}

void loop() {
  sensorValue = analogRead(sensorPin); // read the value from the sensor
  Serial.print(millis()); // print the time in milliseconds since the program started
  Serial.print(',');
  Serial.println(sensorValue); // print to serial
}

Notice we’re printing two values separated by a comma. This will come in handy in a minute. Now open CoolTerm, and you should see something like this:

Big deal, right? Same thing as on the Arduino Serial Monitor pretty much, right? Well as far as the viewer goes, you’re pretty much right. However, CoolTerm has a built in function to allow you to save data to a text file that we can open up later in a dozen different programs to have a look. While your data is scrolling past, navigate to Connections–>Capture to Textfile–>Start (like this):

Note the short cut keys. After you start, a screen will pop up asking you where and how to save the file. Just choose the defaults for now – the timestamp in the file name is super helpful. After you start, do something interesting to your sensor (twist the potentiometer, cover the light sensor, etc.).

Okay! Now, open Excel or your spreadsheet program of choice (OpenOffice Calc, Google Spreadsheet, etc.) – they will have similar workflows. I’m on Excel 2007 on a Windows 7 machine, fyi. Go through the motions to open the txt file you just created (note you may have to make sure All Files is selected in the drop down menu shown on the bottom right of the screenshot below, or you’ll only see .xls files and not .txt files).

Excel will be a little confused at first as to why you’re opening a txt file, so it will make you go through a few steps. The first one looks like this:

Just leave the defaults and hit next. On this screen, check the box next to Comma as shown below:

Then click on Finish. If everything worked out, you should now be looking at two columns of data neatly separated where the comma used to be. Score! Almost done. Now, let’s graph this data. Highlight columns A and B, then choose Insert–>Scatter–>Scatter with Smooth Lines:

This will insert a graph into your spreadsheet and look something like this:

DONE! Now you can save it, add a title, label your axes, whatever you want. And you have a digital diary of what was going on at a particular moment in time with your sensor.

13 thoughts on “Seeing Sensors: How to visualize and save Arduino-sensed data”

  1. i have some when i used this code exactly in Graphing Serial Data in Processing
    i found some code errors like:
    – ‘EDA430’ was not declared in this scope.
    – ‘class HardwareSerial’ has no member named ‘list’
    ..
    can you help or give me an idea to correct this errors

  2. The program doesn’t work in processing. There is no output because you’ve not specified anything under draw().
    All instructions of SerialEvent should be under draw function in order to get graphical output.

      1. Only the code under the serial monitor need to be pasted in draw() function. If you’re still facing the problem please paste the error or whole code here.

  3. Cut and paste from the arduino terminal also works. It’s not elegant or realtime but good enough for spot checks and debugging.
    Thank you Dustyn for this admirable presentation.

  4. Hi there. I have an issue with graphing, but I think it is something stupid I am doing – especially seeing as I’m (ha, or think I am…) an old hand at Arduino, but very new to processing. This example should be a piece of cake, but its just not doing it for me.
    I have a similar issue with every single graphing program I seem to find on the internets, and it goes like this:
    Arduino is happily pumping out serial data, its all displaying in the Processing monitor bar, the baud rates all match, COM4 is set up fine in the processing code….then I run the code, the window displays, but there is… fig all.
    No graphing going on.
    However, after a while, some single line appears at the lower seventh of the screen, and maybe after a while, another, and another, all spaced apart.
    So it wants to be a graph, but fragmented.
    What do you think I am doing wrong? Any ideas?
    Its frustrating, because I can see the serial data at the bottom of the screen, enticingly close teasing me, but just out of reach….
    **By the time I finished writing this text, there are ten or so of these lonely-looking, single pixel lines on the screen, that’s how sluggish it is.

    1. I’m not sure if it seems obvious but replace delay (50) with delay (1) in arduino code. Fragmented graphs are coming due to delay in the code somewhere either in arduino code or processing code.

      1. Nope. Tried that. It’s almost the opposite problem – the graph is almost getting no data at all.

        Some other examples I try (and the coding is… almost the same really) throw up a problem saying “map(NaN, 0, 1023, 0, 300) called, which returns NaN (not a number)” in the monitor bar.
        But still it runs, and sparse bars appear.

        Coding is as such:
        import processing.serial.*;
        Serial myPort; // The serial port
        int xPos = 1; // horizontal position of the graph
        void setup () {
        // set the window size:
        size(1000, 300);

        println(Serial.list());// List all the available serial ports
        myPort = new Serial(this, “COM4”, 9600); // don’t generate a serialEvent() unless you get a newline character:
        myPort.bufferUntil(‘\n’);

        background(0); // set inital background:
        }
        void draw () {

        }
        void serialEvent (Serial myPort) {// get the ASCII string:
        String inString = myPort.readString();
        if (inString != null) { // trim off any whitespace:

        inString = trim(inString);// convert to an int and map to the screen height:

        float inByte = float(inString);
        inByte = map(inByte, 0, 1023, 0, height);//map incomming value to height of screen

        line(xPos, height, xPos, height – inByte);
        stroke(255, 0, 0 );// draw the line:

        // at the edge of the screen, go back to the beginning:
        if (xPos >= width) {
        xPos = 0;
        background(0, 0, 0);
        }
        else {
        // increment the horizontal position:
        xPos++;
        }
        }
        }

Leave a Reply

Your email address will not be published. Required fields are marked *