Arduino & Processing: Final Project (IDD631)

Last week was my last summer class. As my final project, I create a data visualization base on the data from Arduino sensors. I used data from Shap IR Range and Photosensor to be my input. The function of the Arduino is when I move my hand closer to the Sharp IR Range sensor; the LED light will dim down and detected the light level by Photosensor. The output will display as a chart in Processing.

Here is my Arduino circuit:

At first, I created a diagram that displays a wave when the object is approaching the range sensor. I learned how to build a continuous sin wave three weeks ago, and I improvise to this project. As the sensor detect that no object within range, the amplitude will be small and shows a green color. When it detect the object is coming closer, the amplitude will increase, and the color turns from green to yellow and red. The meaning is to tell the user that there is a danger coming (like Earthquake detector).

Here is the result:

Here is the Code:

import processing.serial.*; // Must import Serial library in order to use serial interface
float sensorValue = 0;
float lightLevel = 0;
color rectColor = 0;
int lastTime = 0;
void setup()
{
size(800, 400);
background(255);
strokeWeight(1);
frameRate(45);
// noStroke();
Serial arduinoConnection = null; // set serial name
String [] ports = Serial.list(); // pull out serial port list into string array
printArray(ports);
arduinoConnection = new Serial(this, ports[5], 9600); // set new serial port that connect to Arduino board (port number can be difference)
}
void draw()
{
background(255);
// wave creator
float waveHeight = map(sensorValue, 100, 0, 0, height/2);
if (waveHeight > 110)
{
stroke(#FF0808);
} else if (waveHeight > 40)
{
stroke(#FAE100);
} else stroke(#09BC2B);
for (int j=height/2; j<height; j+=height/2)
{
for (int i=0; i<width; i++)
{
float waveLength = map(i, 0, width, 50, 75);
float m = i;
float waveFactor = frameCount;//mouseX;
float n = waveHeight*sin(m/waveLength+waveFactor)+j;
rect(m, n, 1, 1);
}
}
saveFrame(“wave####.png”);
}
void serialEvent(Serial port)
{
String data = port.readStringUntil(‘\n’); // read data from serial port and store it to string value
if (data != null) // the loop runs when data is not empty
{
//println(data);
data = trim(data); // try to sanitize whitespace away from input
float[] temp = float(split(data, “,”));
// String sensorChar = null;
try {
lightLevel = temp[0];
sensorValue = temp[1];
//sensorValue = Float.parseFloat(data); //try to get value from serial port to float
}
catch(Exception ex) {
println(“Error parsing data”); // in case the value can’t store in float, print out error
println(ex);
sensorValue = -1;
}
println(sensorValue + “ “ + lightLevel ); // print value from serial port
}
}

In my last class, I learned how to create bar Chart and other chart component. Then display the result repeatedly (10 seconds loop).

Here is the in-class workshop result:

As the final assignment for this class. I have modify the in-class workshop by adding another y-axis as line chart to display the output from photosensor (my project consist of 2 sensors). First, I retrieve the output from serial port and split the values into the array. Also I have to use try-catch exception to prevent any error that may occur. Then I moved the chart components code to be an independent function. By doing this, I can refresh the chart when it reached 10 seconds. I don’t want the chart to be so messy because I have secondary y-axis. As the chart refresh, the color of bar and line changed too(color random function). Finally I add the Chart title, axis label and chart legend. As usual, I comment the code to remind how the code works.

Here is my final project result:

Here is my code:

import processing.serial.*; // Must import Serial library in order to use serial interface
float sensorValue = 0;
float lightLevel = 0;
color rectColor, lineColor = 0;
int lastTime = 0;
int margin = 70;
int window = 10000; // window of time
float tempX, tempY =0; // temp valur for create line chart
void setup()
{
size(450, 450);
background(255);
Serial arduinoConnection = null; // set serial name
String [] ports = Serial.list(); // pull out serial port list into string array
printArray(ports);
arduinoConnection = new Serial(this, ports[5], 9600); // set new serial port that connect to Arduino board (port number can be difference)
drawLine();
}
void drawLine() // draw chart base 
{
stroke(0);
strokeWeight(1);
textSize(12);
line(margin-10, (height-margin)+10, width+10-margin, (height-margin)+10); // x-axis
line(margin-10, (height-margin)+10, margin-10, margin-10); // y-axis
line(width-margin+10, (height-margin)+10, width+10-margin, margin-10); // secondary y-axis
int step = (width- 2 * margin)/(window / 1000);
int seconds = 0;
fill(0);
// x-axis lable
for (int i = margin; i <= width-margin; i+=step)
{
int y = height-margin+25;
int x = i;
text(seconds++, x, y);
}
// y-axis lable
int distance = 0;
step = (height — 2 * margin)/(10);
for (int i = height-margin; i >= margin; i-=step)
{
int x = margin-35;
int y = i;
text(distance, x, y);
distance+=10;
}
// secondary y-axis lable
int percent = 0;
step = (height — 2 * margin)/(10);
for (int i = height-margin; i >= margin; i-=step)
{
int x = width-50;
int y = i;
text(percent+” %”, x, y);
percent+=10;
}
// create text
text(“Distance(cm.)”, margin-45, margin-25);
text(“Time(sec.)”, height-margin-20, height-30);
text(“Light Intensity(%)”, width-margin-50, margin-25);
textSize(16);
text(“Object Range and Light Intensity Chart”, width/2-margin*2, margin-50); // chart title
// create legend
textSize(10);
text(“Light Intensity”, width/2+30, height-15);
text(“Distance”, width/2-margin*2+20, height-15);
// line legend
stroke(lineColor);
strokeWeight(2);
fill(rectColor);
line(width/2, height-20, width/2+20, height-20);
ellipse(width/2, height-20, 5, 5);
// bar legend
fill(rectColor, 75);
noStroke();
rect(width/2-margin*2, height-30, 15, 15, 3);
}
void draw()
{
// Sharp IR range sensor can return value between 0–140 (as distance value in cm.) sometimes it return negative value
try {
if (sensorValue>140) sensorValue = 140;
}
catch(Exception range) {
println(“Error reading distance data”); // in case the value can’t store in float, print out error
println(range);
sensorValue = 0;
}
// create initial value
float x = 0;
float y = 0;
float yLine = 0;
int currTime = millis()%window;
if (currTime < lastTime)
{
reset(); // reset the chart when it reached the end (10 seconds)
}
fill(rectColor, 75);
float arrayTemp [];
if (currTime — lastTime > 500)
{
float lightIntensity = map(lightLevel, 1023, 0, 100, 0); // map light value to percentage (0–100%)
x = map(currTime, 0, window, margin, width-margin);
y = map(sensorValue, 140, 0, margin, height-margin);
yLine = map(lightIntensity, 100, 0, margin, height-margin);
drawLineChart(x, yLine); // draw line chart
float barHeight = (height-margin)-y;
noStroke();
rect(x, y, 10, barHeight, 3);
lastTime = currTime;
}
saveFrame(“frame####.png”);
}
void drawLineChart(float x, float y)
{
strokeWeight(2);
if (tempX == 0 && tempY == 0) // if it is the first time running => no line
{
tempX = x; // set current value to temp value
tempY = y;
} else {
stroke(lineColor);
ellipse(x, y, 5, 5);
line(tempX, tempY, x, y);
tempX = x;
tempY = y;
}
}
void reset()
{
background(255); // reset the chart
lastTime = 0;
tempX =0; // reset temp value for line chart
tempY =0; // reset temp value for line chart
rectColor = color(random(255), random(255), random(255)); // random color for bar chart
lineColor = color(random(255), random(255), random(255)); // random color for line chart
drawLine(); // recreate the chart component
}
void serialEvent(Serial port)
{
String data = port.readStringUntil(‘\n’); // read data from serial port and store it to string value
if (data != null) // the loop runs when data is not empty
{
data = trim(data); // try to sanitize whitespace away from input
float[] temp = float(split(data, “,”));
try {
lightLevel = temp[0];
sensorValue = temp[1];
}
catch(Exception ex) {
println(“Error parsing data”); // in case the value can’t store in float, print out error
println(ex);
sensorValue = -1;
}
println(sensorValue + “ “ + lightLevel ); // print value from serial port
}
}