ก่อนหน้านี้ก็ได้ศึกษาชอฟต์แวร์ที่ชื่อ Processing มาระยะหนึ่งเพราะต้องใช้ ดังนั้นผมเลยถือโอกาศอันดีนี้พัฒนาตนเองในการใช้งาน Processing เพื่อรับค่าจาก Arduino โดยอ่านจาก serial communication แล้วนำมาเขียนกราฟแบบออโตสเกลด้วย บันทึกค่าลง text file ด้วย แม้ไม่ได้พัฒนาขึ้นเองทั้งหมดแต่การศึกษาครั้งทำให้ได้ความรู้เพิ่มขึ้นอีกขั้นหนึ่ง และนำมาเขียนเป็นบันทึกไว้ก่อนกันลืม
ขอขอบคุณไฟล์ต้นฉบับที่นำมาปรับปรุงมาจาก Interactive Matter Lab
ไฟล์ sketch ใน Arduino จาก example เลย ส่วนวงจรก็ใช้ตัวต้านทานปรับค่าได้ ปรับโวลต์จาก 0 ถึง 5 โวลต์ จำลองว่าเป็นค่าจากเซนเซอร์ (ในที่นี้จะไม่ปรับ ให้เป็นตัวเลข 5 โวลต์ตามแหล่งจ่ายยังคงใช้ตัวเลขจาก ADC 10-bit) ทดลองกันเลยครับ ดูภาพกราฟที่ได้เป็นตัวอย่าง (แต่ไม่ได้ใส่สเกลแกนนอน)
ภาพบนค่าที่รับมาเป็นช่วงกว้าง แกน y จะปรับให้ครอบคุมข้อมูลที่รับมา
ภาพด้านล่าง เกิดขึ้นเมื่อทิ้งค่าโวลต์ที่รับมาให้คงที่กราฟจะปรับสเกลให้อัตโนมัติ (คำนวณจากค่า max min ของข้อมูล) ไฟล์ต่างเข้าไปดาวโหลดที่นี่ได้เลย SerailRead_ArduinoProcessing
(ในรูปลืมเปลี่ยนหน่วย พอทดลองใช้วัดความถี่ของสัญญาณเพาส์เลยติดมา)
สำหรับรายละเอียดของ source code จะมาอธิบายเพิ่มเติมใน ภาคต่อไปครับ
/////////////////////////////////////////////////////////////////////////////
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(115200);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// print out the value you read:
Serial.println(sensorValue);
delay(20); // delay in between reads for stability
}
///////////////////////////////////////////////////////////////////////////
และที่ยืดยาวคือส่วนของ processing ตามนี้เลย
///////////////// SerialRead_ArduinoProcessing.pde ////////////////
import processing.serial.*;
import processing.opengl.*;
import java.io.*;
Serial myPort;
int current;
float dataFreq;
Thread serialThread;
//int[] yValues;
//int w;
//color axisColor = 200;
//float axisStroke = 1;
//PrintWriter output;
/////////////////////////////////////
int viewHeight = 800;
int viewWidth = 1650;
float viewAreaX = 90;
float viewAreaY = 90;
color backLight=255; // original 0
color titleColor=0;//255;
int titleSize=18;
int titleY=20;
color axisColor = 20;//200;
float axisStroke = 1;
color gridTextColor =20;//200;
float leftBorder = 0.05; // original 0.035
float gridTextOffset = 7;
int gridTextSize=14;
color gridColor=150;//150;
float gridStart=-0.005;
color lineColor=0; // original 255
float lineStroke = 0.015;
String unit="Unit"; //ใช้หน่วยตามปริมาณที่วัด เช่น mV V Hz kHz MHz ms s
PFont font;
float changeThreshold = 0.001;
float lightThreshold = 0.5;
PrintWriter output;
float viewRatio = (viewWidth*viewAreaX/100.0)/(viewHeight*viewAreaY/100.0);
DataSet dataSet = new DataSet(500);
/////////////////////////////////////
void setup()
{
size(1650, 800, OPENGL);
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 115200);
output = createWriter( "TSL230_data.txt" );
font = loadFont("LucidaGrande-48.vlw");
}
void draw()
{
String inString = myPort.readStringUntil('\n');
if(inString != null){
inString = trim(inString);
dataFreq = float(inString);
//println(dataFreq);
output.println(dataFreq);
current = int(dataFreq);//int(map(inByte, 0, 1023, 0, height));
println(current);
dataSet.addSample(current);
}
background(backLight);
synchronized(dataSet) {
//can this be done simpler?
float border = min((viewWidth*(100-viewAreaX)/100.0)/2.0,(viewHeight*(100-viewAreaY)/100.0)/2.0);
float left = (int)(border)+viewWidth*leftBorder;
float right = viewWidth - border;
float bottom = (int)(border);
float top = viewHeight - border;
float arrowLong = (float)bottom*0.5;
float arrowShort = (float)bottom*0.2;
stroke(axisColor);
strokeWeight (axisStroke);
textMode(MODEL);
textFont(font,titleSize);
textAlign(CENTER);
fill(titleColor);
text(" ",viewWidth/2,titleY);
//draw the axis
//viewport is mirrored – 0 is at top
line (left,bottom,left,top);
line ((float)left,(float)bottom,left+arrowShort,bottom+arrowLong);
line ((float)left,(float)bottom,left-arrowShort,bottom+arrowLong);
line (left,top,right,top);
line ((float)right,(float)top,right-arrowLong,top+arrowShort);
line ((float)right,(float)top,right-arrowLong,top-arrowShort);
float mi = dataSet.getMin();
float ma = dataSet.getMax();
float span = ma-mi;
double magnitude = round((float)Math.log10(span));
float factor = (float)Math.pow(10,1-magnitude);
float lower = round((float)(mi*factor)-1.0)/factor;
float upper = round((float)(ma*factor)+1.0)/factor;
int steps = round((float)(span*factor));
int textSteps = 1;
if (steps>10) {
textSteps=round(((float)steps+1.5)/10.0);
}
// println(mi+" ("+lower+") - "+ma+" ("+upper+") = "+span+" ("+steps+" / "+textSteps+") @ "+magnitude+","+factor);
float stepLength = (upper - lower) / steps;
//Y-axis texts
stroke(gridTextColor);
textFont(font,gridTextSize);
textAlign(RIGHT);
//viewport is not normalized yet - we have to doit ourself
//draw the grid
for (int i=1; i
int valueText = (int)((lower+(stepLength*i))*factor);
float value =(float)valueText/factor;
//normalize between top & bottom
float pos = map(value,lower,upper,top,bottom);
if ((i % textSteps) == 0) {
fill(gridTextColor);
text(value+unit,left-gridTextOffset,pos);
}
stroke(gridColor);
line (left+gridStart,pos,right,pos);
}
//prepare the viewport so that it is 0-1 with 0,0 at bottom
rotateX(PI);
translate(0,-viewHeight);
translate (left,bottom);
scale (right-left,top-bottom);
//draw the actual data
float sampleSteps = 1.0 / dataSet.getNumberOfSamples();
for (int i=1; i < dataSet.getNumberOfSamples(); i++) {
//float RawData = dataSet.getSample(i);
float sample = norm(dataSet.getSample(i), lower, upper);
float previous = norm(dataSet.getSample(i-1), lower, upper);
float lineLeft = (i-1)*sampleSteps;
float lineRight = i*sampleSteps;
// save data to position filename
//output.print(lineRight + " , "); // Write the time to the file
//output.println(RawData); // Write the capacitance to the file
stroke(255,0,0);//(lineColor);
strokeWeight(lineStroke);
line(lineLeft,previous,lineRight,sample);
}
}
translate(viewWidth*viewAreaX/100.0, viewHeight*viewAreaY/100.0);
}
float[] numbers;
float[] changes;
int maxSamples;
float minimum = 0;
float maximum = 0;
int samplePosition = 0;
public DataSet(int numberOfSamples) {
numbers = new float[numberOfSamples];
changes = new float[numberOfSamples];
maxSamples = numberOfSamples;
}
public synchronized void addSample(float sample) {
//store the sample
numbers[samplePosition] = sample;
//calculate min & max
minimum = Float.MAX_VALUE;
maximum = - Float.MAX_VALUE;
for (int i=0; i
maximum=Math.max(maximum,numbers[i]);
}
//println(minimum+" - "+maximum);
//increase sample position
samplePosition++;
if (samplePosition==maxSamples) {
samplePosition = 0;
}
}
public float getMax() {
return maximum;
}
public float getMin() {
return minimum;
}
public int getNumberOfSamples() {
return maxSamples;
}
public float getSample(int position) {
int arrayPosition = samplePosition + position;
//wrap around if too big
if (arrayPosition>=maxSamples) {
arrayPosition -=maxSamples;
}
return numbers[arrayPosition];
}
}