Arduino graph software

Arduino graph using Processing

Update: Here is a link to my source code. Some very simple examples, without the buttons, saving data etc. 

This code is for those that want to draw fancy graphs with processing, and use the fasted method to communicate with the Arduino.

Arduino side:

  • Serially sending arrays for different graphs from the chip
       void PlottArray(int Cmd,int Array1[],int Array2[])
           Cmd  -> which graph is this data for?
       Array1[] -> The real time array. Measured micro-seconds
       Array2[] -> Array of measured voltages
  • Serially sending updates for different graphs from the chip

Processing side:

  • A graph class that makes graphing simple with Processing. Drawing bar graphs, smooth  line graphs etc can be quite a mission..

You just have to declare a graph object:  Graph VoltageAndCurrent;

        VoltageAndCurrent.xMax=int(max(timeArray1));
        VoltageAndCurrent.yMax=int(max(voltageArray));

        VoltageAndCurrent.DrawAxis();
        VoltageAndCurrent.smoothLine(timeArray1,voltageArray,currentArray);
  • Saving and loading data to a text file
  • Efficient serial link to the Arduino (Error checking etc)

Arduino + Processing : Analogue bar graph

This is just a basic example of sending the arduino’s 6 analogue readings to a bar graph sketch made with processing. If you would like to use the more advanced graph, you can have a look at this newer source code, which allows you to draw much more advanced graphs from the arduino.

Arduino Code:

//Sending 8 bit reading (256) so analogue 
//reading can be sent in 1 byte
int Analogue0 = 0; // first analog sensor
int Analogue1 = 0; // second analog sensor
int Analogue2 = 0; // digital sensor
int Analogue3 = 0; // second analog sensor
int Analogue4 = 0; // second analog sensor
int Analogue5 = 0; // second analog sensor
int inByte = 0; // incoming serial byte
void setup()
{
 // start serial port at 9600 bps:
 Serial.begin(9600);
establishContact(); // send a byte to establish contact until Processing responds 
}
void loop()
{
 // if we get a valid byte, read analog ins:
 if (Serial.available() > 0) {
 // get incoming byte:
 inByte = Serial.read();
 // read first analog input, divide by 4 to make the range 0-255:
 Analogue0 = analogRead(0)/4;
 // delay 10ms to let the ADC recover:
 delay(10);
 // read second analog input, divide by 4 to make the range 0-255:
 Analogue1 = analogRead(1)/4;
 // read switch, multiply by 155 and add 100
 // so that you're sending 100 or 255:
 delay(10);
 Analogue2 = analogRead(2)/4;
 delay(10);
 Analogue3 = analogRead(3)/4;
 delay(10);
 Analogue4 = analogRead(4)/4;
 delay(10);
 Analogue5 = analogRead(5)/4;
 delay(10);
// send sensor values:
 Serial.write(Analogue0 );
 Serial.write(Analogue1 );
 Serial.write(Analogue2 );
 Serial.write(Analogue3 );
 Serial.write(Analogue4 );
 Serial.write(Analogue5 );
 }
}
void establishContact() {
 while (Serial.available() <= 0) {
 Serial.write('A'); // send a capital A
 delay(300);
 }
}
Processing code
// Feel Free to edit these variables ///////////////////////////
String xLabel = "Analogue Inputs";
String yLabel = "Voltage (V)";
String Heading = "The Graph Sketch";
String URL = "01/02/2010";
float Vcc = 5.0; // the measured voltage of your usb
int NumOfVertDivisions=5; // dark gray
int NumOfVertSubDivisions=10; // light gray
int NumOfBars=6; // you can choose the number of bars, but it can cause issues
 // since you should change what the arduino sends
// if these are changed, background image has problems
// a plain background solves the problem
int ScreenWidth = 600, ScreenHeight=400;
/////////////////////////////////////////////////////////
// Serial port stuff ///////////////////////
import processing.serial.*;
Serial myPort;
boolean firstContact = false;
int[] serialInArray = new int[6];
int serialCount = 0;
///////////////////////////////////////////////
int LeftMargin=100;
int RightMArgin=80;
int TextGap=50;
int GraphYposition=80;
float BarPercent = 0.4;
int value;
PFont font;
PImage bg;
int temp;
float yRatio = 0.58;
int BarGap, BarWidth, DivisounsWidth;
int[] bars = new int[NumOfBars];
void setup(){
// bg = loadImage("BG.jpg");
/// NB SETTINGS ////////////////////////////////////////////////////////
 myPort = new Serial(this, Serial.list()[2], 9600);
 ////////////////////////////////////////////////////////////////////////
DivisounsWidth = (ScreenWidth-LeftMargin-RightMArgin)/(NumOfBars);
 BarWidth = int(BarPercent*float(DivisounsWidth));
 BarGap = DivisounsWidth - BarWidth;
size(ScreenWidth,ScreenHeight);
 font = createFont("Arial",12);
textAlign(CENTER);
 textFont(font);
}
void draw(){
// background(bg); // My one used a background image, I've
 background(250); // commented it out and put a plain colour
// Headings(); // Displays bar width, Bar gap or any variable.
 Axis();
 Labels();
 PrintBars();
}
// Send Recieve data //
void serialEvent(Serial myPort) {
// read a byte from the serial port:
 int inByte = myPort.read();
if (firstContact == false) {
 if (inByte == 'A') {
 myPort.clear(); // clear the serial port buffer
 firstContact = true; // you've had first contact from the microcontroller
 myPort.write('A'); // ask for more
 }
 }
 else {
 // Add the latest byte from the serial port to array:
 serialInArray[serialCount] = inByte;
 serialCount++;
// If we have 6 bytes:
 if (serialCount > 5 ) {
for (int x=0;x<6;x++){
bars[x] = int (yRatio*(ScreenHeight)*(serialInArray[x]/256.0));
}
// Send a capital A to request new sensor readings:
 myPort.write('A');
 // Reset serialCount:
 serialCount = 0;
 }
 }
}
/////// Display any variables for testing here//////////////
void Headings(){
 fill(0 );
 text("BarWidth",50,TextGap );
 text("BarGap",250,TextGap );
 text("DivisounsWidth",450,TextGap );
 text(BarWidth,100,TextGap );
 text(BarGap,300,TextGap );
 text(DivisounsWidth,520,TextGap );
}
void PrintBars(){
int c=0;
 for (int i=0;i<NumOfBars;i++){
fill((0xe4+c),(255-bars[i]+c),(0x1a+c));
 stroke(90);
 rect(i*DivisounsWidth+LeftMargin, ScreenHeight-GraphYposition, BarWidth, -bars[i]);
 fill(0x2e,0x2a,0x2a);
 text(float(bars[i])/(yRatio*(ScreenHeight))*Vcc, i*DivisounsWidth+LeftMargin+BarWidth/2, ScreenHeight-bars[i]-5-GraphYposition );
 text("A", i*DivisounsWidth+LeftMargin+BarWidth/2 -5, ScreenHeight-GraphYposition+20 );
 text(i, i*DivisounsWidth+LeftMargin+BarWidth/2 +5, ScreenHeight-GraphYposition+20 );
 }
}
void Axis(){
strokeWeight(1);
 stroke(220);
 for(float x=0;x<=NumOfVertSubDivisions;x++){
int bars=(ScreenHeight-GraphYposition)-int(yRatio*(ScreenHeight)*(x/NumOfVertSubDivisions));
 line(LeftMargin-15,bars,ScreenWidth-RightMArgin-DivisounsWidth+50,bars);
 }
 strokeWeight(1);
 stroke(180);
 for(float x=0;x<=NumOfVertDivisions;x++){
int bars=(ScreenHeight-GraphYposition)-int(yRatio*(ScreenHeight)*(x/NumOfVertDivisions));
 line(LeftMargin-15,bars,ScreenWidth-RightMArgin-DivisounsWidth+50,bars);
 }
 strokeWeight(2);
 stroke(90);
 line(LeftMargin-15, ScreenHeight-GraphYposition+2, ScreenWidth-RightMArgin-DivisounsWidth+50, ScreenHeight-GraphYposition+2);
 line(LeftMargin-15,ScreenHeight-GraphYposition+2,LeftMargin-15,GraphYposition);
 strokeWeight(1);
}
void Labels(){
 textFont(font,18);
 fill(50);
 rotate(radians(-90));
 text(yLabel,-ScreenHeight/2,LeftMargin-45);
 textFont(font,16);
 for(float x=0;x<=NumOfVertDivisions;x++){
int bars=(ScreenHeight-GraphYposition)-int(yRatio*(ScreenHeight)*(x/NumOfVertDivisions));
 text(round(x),-bars,LeftMargin-20);
 }
textFont(font,18);
 rotate(radians(90));
 text(xLabel,LeftMargin+(ScreenWidth-LeftMargin-RightMArgin-50)/2,ScreenHeight-GraphYposition+40);
 textFont(font,24);
 fill(50);
 text(Heading,LeftMargin+(ScreenWidth-LeftMargin-RightMArgin-50)/2,70);
 textFont(font);
fill(150);
 text(URL,ScreenWidth-RightMArgin-40,ScreenHeight-15);
 textFont(font);
}