// MAD Burster Strip Chart Display for Processing 1.1
// Copyright 2010 Glenn Powers <glennpowers@gmail.com>
// http://meaning.com/wiki/MAD_Burster
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 3 of the License.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
/* Includes "stripchart recorder" class by J David Eisenberg
* http://www.openprocessing.org/visuals/?visualID=6789
*/
import java.text.DecimalFormat;
/**
* Draws a stripchart recorder.
*/
class Stripchart {
int x; // horizontal position of chart
int y; // vertical position of chart
int nSamples; // number of samples to display (affects width)
int h; // height of chart
color colour; // color of dots to plot
int dataPos; // where does next data point go?
int startPos; // where do we start plotting?
int nPoints; // number of points currently in the array
int period; // how often to draw a gray line
float minValue; // minimum value to display
float maxValue; // maximum value to display
float [ ] points; // the data points to plot
private DecimalFormat d = new DecimalFormat("0.#");
private String minString; // minimum value as a string
private String maxString; // maximum value as a string
//private PFont legendFont = loadFont("ArialMT-10.vlw");
private float prevX; // remember previous point
private float prevY;
/*
rightSpace tells how much room there is for the chart
legend. VSPACE and HSPACE give the spacing from the border
of the stripchart to the point plotting area.
*/
private int rightSpace = 0;
final static int VSPACE = 2;
final static int HSPACE = 2;
Stripchart( int x, int y, int nSamples, int h, int period, color c,
float minValue, float maxValue)
{
this.x = x;
this.y = y;
this.nSamples = nSamples;
this.h = h;
this.period = period;
this.colour = c;
// make sure minimum and max are in proper order
this.minValue = min(minValue, maxValue);
this.maxValue = max(minValue, maxValue);
// and convert them to a string with minimal numbr of decimal places
this.minString = d.format(minValue);
this.maxString = d.format(maxValue);
nPoints = 0;
dataPos = 0;
startPos = 0;
points = new float[nSamples];
}
Stripchart( int x, int y, int w, int h, int period, color c)
{
this(x, y, w, h, period, c, h/2.0, -h/2.0);
}
/**
* Add a data point to be plotted.
* At this point you may be wondering why I am using an array
* instead of an ArrayList. Although programmaticaly it may
* be easier to add a new value to the list and remove the
* first one, it takes much less compute time to calculate
* a mod and keep track of where the oldest data is.
*
* @param value the value to plot
*/
void addData(float value)
{
value = constrain(value, minValue, maxValue);
points[dataPos] = value;
dataPos = (dataPos + 1) % nSamples; // wrap around when array fills
/*
* If the array isn't full yet, add to the end of the array
* Otherwise, the start point for plotting moves through
* the array.
*/
if (nPoints < nSamples)
{
nPoints++;
}
else
{
startPos = (startPos + 1) % nSamples;
}
}
void display()
{
int arrayPos;
float yPos;
stroke(0);
fill(255);
pushMatrix();
translate(x, y);
//textFont(legendFont);
// reserve space for the max/min value legend
rightSpace = max(int(textWidth(minString)), int(textWidth(maxString)));
rect(0, 0, nSamples + rightSpace + 2 * HSPACE, h + 2 * VSPACE);
stroke(192);
line(HSPACE, VSPACE + h / 2, nSamples + rightSpace - HSPACE, VSPACE + h / 2);
line(nSamples + 1, VSPACE, nSamples + 1, h - VSPACE);
// draw max and min values
//textFont(legendFont);
fill(0);
stroke(0);
text(minString, nSamples + 2, h - VSPACE);
text(maxString, nSamples + 2, VSPACE + 8);
for(int i = 0; i < nPoints; i++)
{
arrayPos = (startPos + i) % nSamples;
if (period > 0 && arrayPos % period == 0)
{
stroke(192);
line(nSamples - nPoints + i, VSPACE, nSamples - nPoints + i, h - VSPACE);
}
stroke(colour);
yPos = VSPACE + h * (1.0 - (points[arrayPos] - minValue) / (maxValue - minValue));
// Draw a point for the first item, then connect all the other points with lines
if (i == 0)
{
point(nSamples - nPoints + i, yPos);
}
else
{
line(prevX, prevY, nSamples - nPoints + i, yPos);
}
prevX = nSamples - nPoints + i;
prevY = yPos;
}
popMatrix();
}
/**
* Add a data value and re-display the strip chart.
* The addData() and display() methods are decoupled;
* this lets you "speed up" the chart by adding
* several points before displaying the chart.
* This method is a convenience method that does
* both actions.
*
* @param value the value to add and display
*/
void plot(float value)
{
addData(value);
display();
}
}
Stripchart s1;
Stripchart s2;
Stripchart s3;
int n = 0;
import processing.serial.*;
int lf = 10; // Linefeed in ASCII
String myString = null;
Serial myPort; // The serial port
void setup() {
size(400, 500, P2D); // animation is much smoother in P2D; text looks better with JAVA2D
background(255);
myPort = new Serial(this, "/dev/tty.usbserial-A800csXo", 115200);
myPort.clear();
// Throw out the first reading, in case we started reading
// in the middle of a string from the sender.
myString = myPort.readStringUntil(lf);
myString = null;
/* Stripchart setup
*
* Parameters to constructor are:
* x position, y position
* number of data points to display at any time
* height of "recording" area
* interval at which to draw the gray vertical bar; set to zero for no bar
* color of stripchart plot
* minimum and maximum values to plot (will constrain to those values)
*
* The actual height of the stripchart includes some extra vertical space
* above and below the recording area. The actual width of the stripchart
* includes room for the minimum and maximum values.
*/
s1 = new Stripchart(10, 50, 300, 100, 45, color(0, 128, 0), -4000, 4000);
s2 = new Stripchart(10, 160, 300, 100, 45, color(255, 0, 0), -4000, 4000);
s3 = new Stripchart(10, 270, 300, 100, 45, color(0, 128, 128), -4000, 4000);
frameRate(60);
}
void draw() {
int sensor = 0;
int value = 0;
int time = 0;
myString = myPort.readStringUntil(lf);
if (myString != null) {
//print(myString);
String[] pieces = split( myString, ',');
sensor = int(pieces[0]);
value = int(pieces[1]);
time = int(pieces[1]);
if (sensor == 0) {}
if (sensor == 1) { s1.plot(value); }
if (sensor == 2) { s2.plot(value); }
if (sensor == 3) { s3.plot(value); }
}
}