by Jamie Allen Feb 1st, 2007

This is Processing code (Arduino code commented in at the bottom) for graphing data. This code includes a FAKE data trail indicating a visual history of samples.

This code might be a good starting point for Sensors and Time assignments, among other things.


/*
psychadelic dataviewer with FAKE hysteresis 
for two values based on Tom Igoe's & Melvin Ochsmann's work
by Jamie Allen 2007

This program takes raw bytes from the serial port that are seperated by headers
"A", "B", etc. at 9600 baud and graphs them. 

Note that the data protocol in this case is not very efficient.  We're taking in
a byte for each character in the incoming number (i.e.: worst case, we're actually
reading in "A,X,X,X,X,_,B,X,X,X,X,_" or TWELVE BYTES, 12 x 8 = 96 bits.  The 
'information content of this data is actually 2 x 10 bits = 20 bits (the ADC results 
themselves, at 10 bits each).  We're therefore adding an overhead of 76 bits in our 
protocol!  There are better ways to approach this, but this method is good because 
it allows us to 'see' the incoming data in an inteligible way in the Arduino serial
monitor or other terminal programs. 

The reason this is 'fake' hysteresis is that the data 'trails' in this example
are being generated by the graphics context.  The data is not being used in the
creation of what appears to be a data history.

Arduino code for sending this data in the first place from the board is 
commented in below the Processing code

*/

import processing.serial.*;

Serial myPort;  // The serial port
PFont myFont;     // The display font: 

// initial variables:

String buff = "";
int val = 0;
int NEWLINE = 10;
int i = 1;                   // counter
int valueA, valueB;          // the converted data from serial port

int[] valuesA = new int[10];
int[] valuesB = new int[10];

float valNormA, valNormB;     // normalized values of A and B

String bufA="", bufB="";     // buffers in which to store ascii data as it comes in
//String inString;
boolean buf;

int wrote = 0;
int offset = 0;
int offsettext = 25;
int lf = 10;


void setup () {
  size(500, 500);        // window size
  frameRate(60);

  myFont = loadFont("Courier-Bold-12.vlw"); 
  textFont(myFont, 16); 
  textAlign(CENTER);
  textMode(SCREEN);
  fill(#E9FF5B, 200);
  smooth(); 

  // set inital background:
  background(#000000, 200);
  strokeCap(ROUND);
  ellipseMode(CENTER);
  strokeWeight(3);

  // List all the available serial ports
  println(Serial.list());
  // I know that the third port in the serial list on my mac
  // is always my  Keyspan adaptor, so I open Serial.list()[2].
  // Open whatever port is the one you're using.
  myPort = new Serial(this, Serial.list()[2], 9600);
  //myPort.bufferUntil(lf);
}

void draw()
{

  fill(0,1);
  rect(0,0, width, height); 

  while (myPort.available() > 0) {
    serialEvent(myPort.read());
  }

  valNormA = valueA/1023.0;
  valNormB = valueB/1023.0;

  stroke(#555FFF,200);
  fill(#55F555);
  ellipse(i, height - valNormA*height, 10, 10);

  stroke(#FF55FF,70);
  fill(#222222);
  ellipse(i, height - valNormB*height, 2+(50*(1-valNormB)), 2+(50*(1-valNormB)));

  // at the edge of the screen, go back to the beginning:
  if (i > width) {
    i = 0;
    //background(#000000);
    fill(0,1);
    rect(0,0, width, height); 
  } 
  else {
    i++;
  }

  //only display the value once every 25 readings
  //just to keep things clean 
  if (wrote > 50)
  {
  fill(#FFFFFF);
  text(valNormA, i, (height - valNormA*height)-15);
  text(valNormB, i, (height - valNormB*height)-30);
  wrote = 0;
  }
  wrote++;
}

//Serial parsing stuff to get the raw values from 
//the serial event
void serialEvent(int serial){
  if(serial!=10) {      
      if (serial=='A') buf = true;
      if (serial=='B') buf = false;
      if (buf){ if (serial!='A') bufA += char(serial);
                }else{
                if (serial!='B') bufB+= char(serial);
                }
      } else {
                if (buf){  valueA = int(bufA); bufA="";
                } else {   valueB = int(bufB); bufB="";
                }
      }      
     // println(valueA);      
     // print(valueB);
}

/*
Arduino code to send data to this Processing program:
*/

/*
//  Sending two pieces of data, deliminated by a header - "A", "B", at the beginning -
//  and a line break at the end.

// based on stuff from Melvin Ochsmann and Tom Igoe. 
// reworked a bit for Sensor Workshop class by Jamie Allen, 2007

int sensorPin1 = 4;    // select the input pin for sensor
int sensorPin2 = 5;    // select the input pin for other sensor
int ledPin = 13;   // select the pin for the LED
int val1 = 0;       // variable to store the value coming from the sensor
int val2 = 0;       // variable to store the value coming from the sensor

void setup() {
  pinMode(ledPin, OUTPUT);  // declare the ledPin as an OUTPUT

  Serial.begin(9600);	// opens serial port, sets data rate to 9600 bps
}

void loop() {

  digitalWrite(ledPin, HIGH);    // sets the LED on

  val1 = analogRead(sensorPin1);    // read the value from the sensor
  val2 = analogRead(sensorPin2);    // read the value from the sensor

  Serial.print("A");  //header variable, so we know which sensor value is which
  Serial.print(val1, DEC);  //send as a ascii encoded number - we'll turn it back into a number at the other end
  Serial.print(10, BYTE);  //terminating character

  Serial.print("B");  //header variable, so we know which sensor value is which
  Serial.print(val2, DEC);  //send as a ascii encoded number - we'll turn it back into a number at the other end
  Serial.print(10, BYTE);  //terminating character

  delay(10);
}

*/