Hello, this is my first contribution.
Here is the Processing CODE and the Arduino CODE.
This code is for Data Acquisition and Data Analysis. Uses Arduino UNO and Processing. It also uses controlP5 library.
It's based on Maurice's Ribble Code, wich I found in this site
http://www.glacialwanderer.com/hobbyrobotics/?m=200906
This code allows you to graph the 6 analog inputs of Arduino in real time and to analyse all the information after the acquisition.
You can review all the graphics with a Range Bar, wich allows you to zoom in and zoom out in time, and you can know the specific value of any part of the graphic just positioning the mouse over it. Also shows the maximum of each of the inputs and there is a clock that shows the acquisition time of each value.
Arduino is programmed to take 17 samples per sec approximately, but it can take up to 130 sampels per second if you delete the delay() function.
With 17 Sampels per second the program can store up to 8 hours of measurement, but if you need more you can increase the maxSize parameter of the cVectors objects at the beginning of the code.
The winSize parameter defines the speed the graphic moves.
You can also change the Grid of the screen, just modify the gx and gy variables inside the Grilla class..
You can save all the data in a .csv file just pressing on "GUARDAR"
The buttons are in Spanish because I am Argentinian, and my grammar errors are because of the same
Its done on a mac so you might have to check the serial port before running it on a PC..
Hope you enjoy it!
Here is an screen shot of the application running.
Here is the Processing CODE and the Arduino CODE.
Processing CODE
- // Maurice Ribble
- // 6-28-2009
- // http://www.glacialwanderer.com/hobbyrobotics
- //
- // Modified by Facundo Ramón
- // 2-4-2013
- import processing.serial.*;
- import controlP5.*;
- PrintWriter output;
- //Globales
- //Dimensiones
- int sizex=1200;
- int sizey=740;
- int bordeTecho = 15;
- int bordePiso = 5;
- int bordeIzq = 5;
- int bordeDer = 100;
- int bordeLateral = bordeIzq+bordeDer;
- int bordeVertical = bordeTecho+bordePiso;
- int botonx = 80;
- int botony = 20;
- //Vector para grafica
- int mps=20; //muestras por segundo
- int maxSize=mps*3600*8; //tamaño maximo del vector (3600seg = 1h) seteado en 8hs
- int winSize=200; //cantidad de muestras que se grafican en la ventana
- int posicionInicial; //posicion inicial del vector ai# que se grafica en pantalla cuando no se esta monitoreando, responde a LowValue de la barra Range
- int posicionFinal; //posicion inicial del vector ai# que se grafica en pantalla cuando no se esta monitoreando, responde a HighValue de la barra Range
- //Máximos de cada vector para la funcion fMaximo
- float max0=0;
- float max1=0;
- float max2=0;
- float max3=0;
- float max4=0;
- float max5=0;
- String[] t1 = new String[maxSize]; //Vector que contiene el tiempo
- int i=0; //Contador para el vector de tiempo
- boolean monitorear=false; //boolean para activar o desactivar la entrada de datos al vector ai#
- //vectores para cada señal
- cVector ai0 = new cVector(maxSize, winSize);
- cVector ai1 = new cVector(maxSize, winSize);
- cVector ai2 = new cVector(maxSize, winSize);
- cVector ai3 = new cVector(maxSize, winSize);
- cVector ai4 = new cVector(maxSize, winSize);
- cVector ai5 = new cVector(maxSize, winSize);
- //areas de grafico para cada vector
- cGrafico g0 = new cGrafico(bordeIzq, bordeTecho+0*(sizey-bordeVertical)/6, sizex-bordeLateral, (sizey-bordeVertical)/6);
- cGrafico g1 = new cGrafico(bordeIzq, bordeTecho+1*(sizey-bordeVertical)/6, sizex-bordeLateral, (sizey-bordeVertical)/6);
- cGrafico g2 = new cGrafico(bordeIzq, bordeTecho+2*(sizey-bordeVertical)/6, sizex-bordeLateral, (sizey-bordeVertical)/6);
- cGrafico g3 = new cGrafico(bordeIzq, bordeTecho+3*(sizey-bordeVertical)/6, sizex-bordeLateral, (sizey-bordeVertical)/6);
- cGrafico g4 = new cGrafico(bordeIzq, bordeTecho+4*(sizey-bordeVertical)/6, sizex-bordeLateral, (sizey-bordeVertical)/6);
- cGrafico g5 = new cGrafico(bordeIzq, bordeTecho+5*(sizey-bordeVertical)/6, sizex-bordeLateral, (sizey-bordeVertical)/6);
- //grilla del grafico
- cGrilla grilla = new cGrilla();
- //declaracion de instancias de clases
- ControlP5 cp5;
- Serial arduino;
- Range range;
- ControlTimer c;
- Textlabel t;
- void setup()
- {
- size(sizex, sizey, P2D);
- background(150);
- println(Serial.list()); //imprime lista de puertos seriales disponibles
- arduino = new Serial(this, Serial.list()[0], 115200, 'N', 8, 1.0); //se crea el objeto Serial
- output=createWriter("Datos.csv"); //se crea datos.csn
- cp5 = new ControlP5(this); //se crea el objeto cp5 de la libreria ControlP5
- c = new ControlTimer(); //se crea un reloj
- t = new Textlabel(cp5, "", 100, 100); //el texto donde se muestra el tiempo
- for (int i=0;i<winSize;i++) //Se completa el vector tiempo para poder mirar mediciones mas cortas que el tamaño de una ventana
- {
- t1[i]=("00 : 00 : 00");
- }
- t.setPosition(sizex-bordeDer+15, 3);
- t.setValue("00 : 00 : 00");
- //BOTONES
- cp5.addButton("MONITOREAR")
- .setBroadcast(false)
- .setSize(botonx, botony)
- .setPosition(sizex-bordeDer+(bordeDer/2-botonx/2), sizey-1*(bordePiso+botony))
- .setBroadcast(true);
- cp5.addButton("GUARDAR")
- .setBroadcast(false)
- .setSize(botonx, botony)
- .setPosition(sizex-bordeDer+(bordeDer/2-botonx/2), sizey-2*(bordePiso+botony))
- .setBroadcast(true);
- //BARRA DE TIEMPO
- range = cp5.addRange("")
- // disable broadcasting since setRange and setRangeValues will trigger an event
- .setBroadcast(false)
- .setPosition(bordeIzq, 0)
- .setSize(sizex-bordeLateral, bordeTecho-2)
- .setHandleSize(20)
- .setRange(0, winSize)
- .setRangeValues(0, winSize)
- // after the initialization we turn broadcast back on again
- .setBroadcast(true)
- .setColorForeground(color(200))
- .setColorBackground(color(100));
- //NUMBERBOX VALOR PARAMETRO
- cp5.addNumberbox("Parametro 1:1")
- .setPosition(sizex-bordeDer+10, bordeTecho+0*(sizey-bordeLateral)/6)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- cp5.addNumberbox("Parametro 1:2")
- .setPosition(sizex-bordeDer+10, bordeTecho+1*(sizey-bordeVertical)/6)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- cp5.addNumberbox("Parametro 1:3")
- .setPosition(sizex-bordeDer+10, bordeTecho+2*(sizey-bordeVertical)/6)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- cp5.addNumberbox("Parametro 2:1")
- .setPosition(sizex-bordeDer+10, bordeTecho+3*(sizey-bordeVertical)/6)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- cp5.addNumberbox("Parametro 2:2")
- .setPosition(sizex-bordeDer+10, bordeTecho+4*(sizey-bordeVertical)/6)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- cp5.addNumberbox("Parametro 2:3")
- .setPosition(sizex-bordeDer+10, bordeTecho+5*(sizey-bordeVertical)/6)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- //NUMBERBOX MAXIMO REGISTRO
- cp5.addNumberbox("Maximo 1:1")
- .setPosition(sizex-bordeDer+10, bordeTecho+0*(sizey-bordeVertical)/6+1*30)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- cp5.addNumberbox("Maximo 1:2")
- .setPosition(sizex-bordeDer+10, bordeTecho+1*(sizey-bordeVertical)/6+1*30)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- cp5.addNumberbox("Maximo 1:3")
- .setPosition(sizex-bordeDer+10, bordeTecho+2*(sizey-bordeVertical)/6+1*30)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- cp5.addNumberbox("Maximo 2:1")
- .setPosition(sizex-bordeDer+10, bordeTecho+3*(sizey-bordeVertical)/6+1*30)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- cp5.addNumberbox("Maximo 2:2")
- .setPosition(sizex-bordeDer+10, bordeTecho+4*(sizey-bordeVertical)/6+1*30)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- cp5.addNumberbox("Maximo 2:3")
- .setPosition(sizex-bordeDer+10, bordeTecho+5*(sizey-bordeVertical)/6+1*30)
- .setSize(bordeDer-20, 15)
- .setValue(0);
- }
- void draw()
- {
- while (arduino.available () >= 2*6+2 && monitorear)
- {
- fProcesarData();
- }
- stroke(0, 0, 0);
- strokeWeight(1.5);
- g0.drawGraphBox();
- g1.drawGraphBox();
- g2.drawGraphBox();
- g3.drawGraphBox();
- g4.drawGraphBox();
- g5.drawGraphBox();
- grilla.dibujar();
- strokeWeight(1);
- stroke(200, 0, 0);
- g0.drawLine(ai0, 0, 1023);
- stroke(0, 200, 0);
- g1.drawLine(ai1, 0, 1023);
- stroke(0, 0, 200);
- g2.drawLine(ai2, 0, 1023);
- stroke(200, 0, 0);
- g3.drawLine(ai3, 0, 1023);
- stroke(0, 200, 0);
- g4.drawLine(ai4, 0, 1023);
- stroke(0, 0, 200);
- g5.drawLine(ai5, 0, 1023);
- fill(150);
- noStroke();
- rect(sizex-bordeDer, 0, bordeDer, bordeTecho);
- t.draw(this);
- if (!monitorear && mouseX>bordeIzq && mouseX<sizex-bordeDer && mouseY>bordeTecho && mouseY<sizey-bordePiso)
- {
- stroke(0);
- strokeWeight(.5);
- line(mouseX, bordeTecho, mouseX, sizey-bordePiso);
- int inf=int(range.getLowValue());
- int sup=int(range.getHighValue());
- int index=int(map(mouseX, bordeIzq, sizex-bordeDer, inf, sup));
- cp5.getController("Parametro 1:1").setValue(ai0.getVal(index));
- cp5.getController("Parametro 1:2").setValue(ai1.getVal(index));
- cp5.getController("Parametro 1:3").setValue(ai2.getVal(index));
- cp5.getController("Parametro 2:1").setValue(ai3.getVal(index));
- cp5.getController("Parametro 2:2").setValue(ai4.getVal(index));
- cp5.getController("Parametro 2:3").setValue(ai5.getVal(index));
- t.setValue(t1[index]);
- }
- }
- void MONITOREAR()
- {
- if (monitorear)
- {
- monitorear=false;
- }
- else
- {
- monitorear=true;
- c.reset();
- c.setSpeedOfTime(1);
- }
- }
- void GUARDAR()
- {
- for (int i=0; i<ai0.getCurSize(); i++)
- {
- output.println(ai0.getVal(i)+","+ai1.getVal(i)+","+ai2.getVal(i)+","+ai3.getVal(i)+","+ai4.getVal(i)+","+ai5.getVal(i)+","+"\t"+t1[i]);
- }
- output.flush();
- output.close();
- println("GUARDADO");
- }
- class cGrafico
- {
- float g_x, g_y; //posicion inicial de los areas de ploteo
- float g_ancho, g_alto; //ancho y alto de los areas de ploteo
- cGrafico(float x, float y, float ancho, float alto)
- {
- g_x = x;
- g_y = y;
- g_ancho = ancho;
- g_alto = alto;
- }
- void drawGraphBox()
- {
- stroke(0, 0, 0);
- fill(255, 255, 255);
- rect(g_x, g_y, g_ancho, g_alto); //se generan las areas de ploteo
- }
- void drawLine(cVector data, float minRange, float maxRange)
- {
- float graphMultX = g_ancho/winSize;
- float graphMultY = g_alto/(maxRange-minRange);
- if (monitorear)
- {
- if (data.getCurSize()<winSize)
- {
- for (int i=0; i<data.getCurSize()-1; i++)
- {
- float x0 = i*graphMultX+g_x;
- float y0 = g_y+g_alto-((data.getVal(i)-minRange)*graphMultY);
- float x1 = (i+1)*graphMultX+g_x;
- float y1 = g_y+g_alto-((data.getVal(i+1)-minRange)*graphMultY);
- line(x0, y0, x1, y1);
- }
- }
- else
- {
- for (int i=data.getCurSize()-winSize; i<data.getCurSize()-1; i++)
- {
- float x0 = (i-data.getCurSize()+winSize)*graphMultX+g_x;
- float y0 = g_y+g_alto-((data.getVal(i)-minRange)*graphMultY);
- float x1 = (i-data.getCurSize()+winSize+1)*graphMultX+g_x;
- float y1 = g_y+g_alto-((data.getVal(i+1)-minRange)*graphMultY);
- line(x0, y0, x1, y1);
- range.setRange(0, data.getCurSize());
- range.setRangeValues(data.getCurSize()-winSize, data.getCurSize());
- }
- }
- }
- else
- {
- posicionInicial = int( range.getLowValue() );
- posicionFinal = int( range.getHighValue() );
- arduino.clear(); //Mientras monitoreares falso, mantiene vacio el buffer de datos entrantes
- float MultX = g_ancho/(posicionFinal-posicionInicial);
- for (int i=posicionInicial; i<posicionFinal; i++)
- {
- float x0 = (i-posicionInicial)*MultX+g_x;
- float y0 = g_y+g_alto-((data.getVal(i)-minRange)*graphMultY);
- float x1 = (i-posicionInicial+1)*MultX+g_x;
- float y1 = g_y+g_alto-((data.getVal(i+1)-minRange)*graphMultY);
- line(x0, y0, x1, y1);
- }
- }
- }
- }
- class cGrilla
- {
- int ancho=sizex-bordeLateral;
- int alto=(sizey-bordeVertical)/6;
- int gx=60; //divisiones horizontales __
- int gy=17; //divisiones verticales ||
- cGrilla()
- {
- }
- void dibujar()
- {
- strokeWeight(.5);
- stroke(150);
- for (int i=1; i<gy; i++)
- {
- line(bordeIzq+(sizex-bordeLateral)/gy*i, bordeTecho, bordeIzq+(sizex-bordeLateral)/gy*i, sizey-bordePiso);
- }
- for (int i=1; i<gx; i++)
- {
- line(bordeIzq, bordeTecho+i*(sizey-bordeVertical)/gx, sizex-bordeDer, bordeTecho+i*(sizey-bordeVertical)/gx);
- }
- }
- }
- class cVector
- {
- float[] m_data;
- int m_maxSize;
- int m_endIndex = 0;
- int m_curSize;
- int m_winSize;
- cVector(int maxSize, int winSize)
- {
- m_maxSize = maxSize ;
- m_data = new float[maxSize];
- m_winSize = winSize;
- }
- void addVal(float val)
- {
- m_data[m_endIndex] = val;
- m_endIndex = (m_endIndex+1)%m_maxSize;
- m_curSize++;
- if (m_curSize>m_maxSize)
- {
- println("Memoria Llena");
- }
- }
- float getVal(int index)
- {
- return m_data[(index)%m_maxSize];
- }
- int getCurSize()
- {
- return m_curSize;
- }
- int getMaxSize()
- {
- return m_maxSize;
- }
- }
- void fMaximo(int vector)
- {
- float actual;
- int current=ai0.getCurSize()-1;
- switch(vector)
- {
- case 0:
- actual = ai0.getVal(current);
- if (actual>max0)
- {
- max0=actual;
- }
- cp5.getController("Maximo 1:1").setValue(max0);
- break;
- case 1:
- actual = ai1.getVal(current);
- if (actual>max1)
- {
- max1=actual;
- }
- cp5.getController("Maximo 1:2").setValue(max1);
- break;
- case 2:
- actual = ai2.getVal(current);
- if (actual>max2)
- {
- max2=actual;
- }
- cp5.getController("Maximo 1:3").setValue(max2);
- break;
- case 3:
- actual = ai3.getVal(current);
- if (actual>max3)
- {
- max3=actual;
- }
- cp5.getController("Maximo 2:1").setValue(max3);
- break;
- case 4:
- actual = ai4.getVal(current);
- if (actual>max4)
- {
- max4=actual;
- }
- cp5.getController("Maximo 2:2").setValue(max4);
- break;
- case 5:
- actual = ai5.getVal(current);
- if (actual>max5)
- {
- max5=actual;
- }
- cp5.getController("Maximo 2:3").setValue(max5);
- break;
- }
- }
- void fProcesarData()
- {
- int inByte = 0;
- int curMatchPos = 0;
- int[] intBuf = new int[2];
- intBuf[0] = 0xAD;
- intBuf[1] = 0xDE;
- while (arduino.available () < 2);
- inByte = arduino.read();
- //Sincroniza con arduino
- while (curMatchPos < 2)
- {
- if (inByte == intBuf[curMatchPos])
- {
- ++curMatchPos;
- if (curMatchPos == 2)
- break;
- while (arduino.available () < 2);
- inByte = arduino.read();
- }
- else
- {
- if (curMatchPos == 0)
- {
- while (arduino.available () < 2);
- inByte = arduino.read();
- }
- else
- {
- curMatchPos = 0;
- }
- }
- }
- //obtiene los datos y los almacena en un cVector
- while (arduino.available () < 2*6);
- {
- byte[] inBuf = new byte[2];
- int a0, a1, a2, a3, a4, a5;
- arduino.readBytes(inBuf);
- // Had to do some type conversion since Java doesn't support unsigned bytes
- a0 = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
- arduino.readBytes(inBuf);
- a1 = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
- arduino.readBytes(inBuf);
- a2 = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
- arduino.readBytes(inBuf);
- a3 = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
- arduino.readBytes(inBuf);
- a4 = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
- arduino.readBytes(inBuf);
- a5 = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
- ai0.addVal(a0);
- ai1.addVal(a1);
- ai2.addVal(a2);
- ai3.addVal(a3);
- ai4.addVal(a4);
- ai5.addVal(a5);
- t1[i]=c.toString(); //se escribe el tiempo correspondiente a las muestras en el vector t1 para que
- i++; //se pueda ver el tiempo al revisar los datos
- cp5.getController("Parametro 1:1").setValue(a0);
- cp5.getController("Parametro 1:2").setValue(a1);
- cp5.getController("Parametro 1:3").setValue(a2);
- cp5.getController("Parametro 2:1").setValue(a3);
- cp5.getController("Parametro 2:2").setValue(a4);
- cp5.getController("Parametro 2:3").setValue(a5);
- fMaximo(0);
- fMaximo(1);
- fMaximo(2);
- fMaximo(3);
- fMaximo(4);
- fMaximo(5);
- t.setValue(c.toString());
- }
- }
Arduino CODE
- // Maurice Ribble
- // 6-28-2009
- // http://www.glacialwanderer.com/hobbyrobotics
- #define AI0 0
- #define AI1 1
- #define AI2 2
- #define AI3 3
- #define AI4 4
- #define AI5 5
- void setup()
- {
- Serial.begin(115200);
- }
- // If this is defined it prints out the FPS that we can send a
- // complete set of data over the serial port.
- //#define CHECK_FPS
- void loop()
- {
- int ai0=0, ai1=0, ai2=0, ai3=0, ai4=0, ai5=0;
- unsigned int startTag = 0xDEAD; // Analog port maxes at 1023 so this is a safe termination value
- int loopCount = 12;
- //#ifdef CHECK_FPS
- // unsigned long startTime, endTime;
- // startTime = millis();
- //#endif
- // Can't do more than 64 loops or could overflow the 16 bit ints
- // This just averages together as many sensor reads as we can in
- // order to reduce sensor noise. Might want to introduce add
- // a smarter filter her in the future.
- // 12 gives a little over 100 FPS
- for(int i = 0; i< loopCount; ++i)
- {
- // It takes 100 us (0.0001 s) to read an analog input
- ai0 += analogRead(AI0);
- ai1 += analogRead(AI1);
- ai2 += analogRead(AI2);
- ai3 += analogRead(AI3);
- ai4 += analogRead(AI4);
- ai5 += analogRead(AI5);
- }
- ai0 /= loopCount;
- ai1 /= loopCount;
- ai2 /= loopCount;
- ai3 /= loopCount;
- ai4 /= loopCount;
- ai5 /= loopCount;
- Serial.write((unsigned byte*)&startTag, 2);
- Serial.write((unsigned byte*)&ai0, 2);
- Serial.write((unsigned byte*)&ai1, 2);
- Serial.write((unsigned byte*)&ai2, 2);
- Serial.write((unsigned byte*)&ai3, 2);
- Serial.write((unsigned byte*)&ai4, 2);
- Serial.write((unsigned byte*)&ai5, 2);
- delay(50);
- //#ifdef CHECK_FPS
- // endTime = millis();
- // Serial.print(" - FPS: ");
- // Serial.println(1.f/ (endTime-startTime) * 1000);
- //#endif
- }
1