說明:
1.Arduino的輸出增加極大(小)值發生時的A0與A1值,共3個資料。
2.AirView程式接收3個資料存檔,且劃出水平0軸,便於長時間觀察。
3 多個Arduino同時進行觀測時,請修改runningNumber的值。
訊號圖:
存檔資料:順序為(訊號值,A0,A1),每一秒有最大值與最小值各一筆
2016-09-21 00:00:08, -7, 925, 918
2016-09-21 00:00:08, 7, 859, 866
2016-09-21 00:00:09, -10, 832, 822
2016-09-21 00:00:09, 10, 823, 833
2016-09-21 00:00:10, -7, 925, 918
2016-09-21 00:00:10, 7, 857, 864
2016-09-21 00:00:11, -7, 889, 882
2016-09-21 00:00:11, 7, 859, 866
2016-09-21 00:00:12, 7, 860, 867
2016-09-21 00:00:12, -7, 886, 879
|
Arduino程式:
// 測量A0對A1的空氣電壓
// 修改自地震預測研究所所長 林湧森 2016-07-28 04:29 UTC+8
// 修改者:ghostyguo
// 使用最快取樣速度, 每隔1000ms送出最大與最小值
// 紀錄最大與最小值時的A0與A1
// 2016-08-20 22:30 UTC+8 by
// 2016_09_20 22:00 UCT+8 by ghosty
#define runSimulation false
int sampleCount;
int maxValue, minValue; //keep extreme value
int maxA0, maxA1; //A0&A1 when maxValue is captures
int minA0, minA1; //A0&A1 when minValue is captures
int whoIsLast = 0; //-1=min, 1=max, 0=undefined;
int sampleCountLimit;
void setup()
{
Serial.begin(9600);
SetupRunningParameters();
startNewCycle();
}
void SetupRunningParameters()
{
// find sampleCountLimit in 1000ms
unsigned long startMicros=micros();
startNewCycle();
while (micros()-startMicros<1000000L) {
sampling();
}
sampleCountLimit = sampleCount;
// uncomment the following lines to see the sampleCountLimit
// Serial.print("#");
// Serial.println(sampleCountLimit);
}
void startNewCycle()
{
maxValue = maxA0 = maxA1 = -10000; //12bit ADC < -1024
minValue = minA0 = minA1 = 10000; //12bit ADC > 1024
whoIsLast = 0;
sampleCount = 0;
}
void loop()
{
sampling();
if (sampleCount>sampleCountLimit) {
#if (runSimulation)
outputRandomValue1();
outputRandomValue2();
#else
if (whoIsLast == -1) { //min is last
outputMaxValue();
outputMinValue();
} else if (whoIsLast == 1) { //max is last
outputMinValue();
outputMaxValue();
} else {
Serial.println("Extreme Value Error");
}
#endif
startNewCycle();
}
}
void outputMaxValue()
{
Serial.print(maxValue);
Serial.print(",");
Serial.print(maxA0);
Serial.print(",");
Serial.println(maxA1);
}
void outputMinValue()
{
Serial.print(minValue);
Serial.print(",");
Serial.print(minA0);
Serial.print(",");
Serial.println(minA1);
}
#if (runSimulation)
void outputRandomValue1()
{
Serial.print(random(1024));
Serial.print(",");
Serial.print(random(1024));
Serial.print(",");
Serial.println(random(1024));
}
void outputRandomValue2()
{
Serial.print(-random(512));
Serial.print(",");
Serial.print(random(1024));
Serial.print(",");
Serial.println(random(1024));
}
#endif
void sampling()
{
int A0 = analogRead(A0);
int A1 = analogRead(A1);
int sampleValue = A1 - A0;
if (minValue > sampleValue) {
minValue = sampleValue;
minA0 = A0;
minA1 = A1;
whoIsLast = -1;
}
if (maxValue < sampleValue) {
maxValue = sampleValue;
maxA0 = A0;
maxA1 = A1;
whoIsLast = 1;
}
++sampleCount;
}
|
Processing程式:
// AirView
// Plot the graph of the air voltage from Arduino
// to predict earthquakes.
// Dyson Lin dysonlin@gmail.com
// 2016-07-30 05:58 UTC+8 V1.0
// 2016-08-10 15:42 UTC+8 V2.1.3 20x data compression. Change background to Black.
// 2016-08-16 21:56 UTC+8 V2.1.9 Plot select range area.
// 2016-08-16 22:17 UTC+8 V2.2.0 Adjust text sizes.
// 2016-08-17 23:43 UTC+8 V2.2.1 Use noLoop() and redraw() to plot graph only after reading new data.
// 2016-08-19 18:40 UTC+8 V2.2.2 10K-Ohom-R Voltage!
// 2016-08-19 19:14 UTC+8 V2.2.3 Water Voltage!
// 2016-08-20 21:04 UTC+8 V2.2.4 220-Ohom-R Voltage!
// 2016-08-24 04:25 UTC+8 V2.2.5 Air Voltage.
// 2016-08-26 17:10 UTC+8 V2.2.6 Fix the minData and maxData bug.
// 2016-08-27 03:53 UTC+8 V2.2.7 Modify plotData(), plotSelectRange().
// 2016-08-29 01:31 UTC+8 V2.2.8 Comment out noLoop() and redraw().
// 2016-08-29 02:23 UTC+8 V2.2.9 Make the window resizable.
// 2016-09-05 22:39 UTC+8 V2.2.9g Save sampled data to file for analysis, modifided by ghosty
// 2016-09-20 22:30 UTC+8 V1.0.0 Save more data to file for analysis, modifided by ghosty
import processing.serial.*;
int runningNumber=1; //added by ghosty, modify this number for multiple arduino boards
int startTime = 0;
int currentTime = 0;
String timeStringStart = null;
String dateStringStart = null;
String timeStringNow = null;
String dateStringNow = null;
int graphLeft = 0;
int graphRight = 0;
int graphTop = 0;
int graphBottom = 0;
int selectRangeLeft = 0;
int selectRangeRight = 0;
int selectRangeTop = 0;
int selectRangeBottom = 0;
int isFirstRead = 1;
int maxData = 0;
int minData = 0;
int maxTime = 0;
int minTime = 0;
final int compressionRatio = 20;
final int bufferLimit = 2 * compressionRatio; // compression ratio = bufferLimit/2. So bufferLimit must be even.
int [] buffer = new int[bufferLimit];
int [] bufferTime = new int[bufferLimit];
int bufferNumber = 0;
int dataLimit = 1000000;
int[] data = new int[dataLimit];
int[] dataTime = new int[dataLimit];
int dataNumber = 0;
boolean mouseInZoomArea(int x, int y)
{
boolean inZoomArea = false;
int zoomAreaLength = 10;
int zoomLeft = width - zoomAreaLength;;
int zoomRight = width;
int zoomBottom = height;
int zoomTop = height - zoomAreaLength;
if ((x >= zoomLeft) && (x <= zoomRight) && (y <= zoomBottom) && (y >= zoomTop))
{
inZoomArea = true;
}
return inZoomArea;
}
//void mouseDragged()
//{
// if (mouseInZoomArea(mouseX, mouseY))
// {
// int newWidth = width + (mouseX - pmouseX);
// int newHeight = height + (mouseY - pmouseY);
// surface.setSize(newWidth, newHeight);
// }
//}
void setup()
{
size(1300, 720);
surface.setResizable(true);
openSerialPort();
setStartTimeStamp();
}
void openSerialPort()
{
Serial myPort; // The serial port
myPort = new Serial(this, "COM3", 9600);
myPort.clear(); // Clear buffer
myPort.bufferUntil(0x0A); // Trigger serialEvent() only after linefeed is read.
}
void setStartTimeStamp()
{
startTime = millis();
timeStringStart = nf(hour(), 2) + ":" + nf(minute(), 2) + ":" + nf(second(), 2);
dateStringStart = year() + "-" + nf(month(), 2) + "-" + nf(day(), 2);
}
void setTimeStamp()
{
currentTime = millis();
timeStringNow = nf(hour(), 2) + ":" + nf(minute(), 2) + ":" + nf(second(), 2);
dateStringNow = year() + "-" + nf(month(), 2) + "-" + nf(day(), 2);
}
void draw()
{
background(0); // black background
stroke(255);
fill(255);
// Set the location of graph
graphLeft = 50;
graphRight = width - 50;
graphTop = 50;
graphBottom = height - 100;
maxTime = graphRight - graphLeft;
background(0);
setTimeStamp();
plotSelectRange();
plotAxes();
//plotData();
plotData(graphLeft+3, graphRight, graphBottom-3, graphTop);
}
void plotData(int leftBorder, int rightBorder, int bottomBorder, int topBorder) {
float x1 = 0;
float y1 = 0;
float x2 = 0;
float y2 = 0;
if (dataNumber < 2) {
return;
}
stroke(255);
// set first point
//x1 = graphLeft+3;
//y1 = map(data[0], minData, maxData, graphBottom-3, graphTop);
x1 = leftBorder;
y1 = map(data[0], minData, maxData, bottomBorder, topBorder);
// plot lines
for (int i=1; i<dataNumber; i++)
{
//x2 = map(i, 0, dataNumber-1, graphLeft+3, graphRight); // auto range
//y2 = map(data[i], minData, maxData, graphBottom-3, graphTop); // auto range
x2 = map(i, 0, dataNumber-1, leftBorder, rightBorder); // auto range
y2 = map(data[i], minData, maxData, bottomBorder, topBorder); // auto range
line(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
}
}
void plotSelectRange()
{
// Set the location of graph
selectRangeLeft = 100;
selectRangeRight = width - 100;
selectRangeBottom = height - 15;
selectRangeTop = height - 48;
int textSize = 12;
textSize(textSize);
stroke(0, 128, 0, 128);
fill(0, 128, 0, 128);
rect(selectRangeLeft, selectRangeTop, selectRangeRight - selectRangeLeft, selectRangeBottom - selectRangeTop);
stroke(255);
fill(255);
textAlign(CENTER);
text(timeStringStart, graphLeft, selectRangeTop + textSize*1);
text(dateStringStart, graphLeft, selectRangeTop + textSize*2.5);
textAlign(CENTER);
text(timeStringNow, graphRight, selectRangeTop + textSize*1);
text(dateStringNow, graphRight, selectRangeTop + textSize*2.5);
plotData(selectRangeLeft, selectRangeRight, selectRangeBottom, selectRangeTop);
}
void plotAxes() {
int textSize = 12;
float minVoltage = 0;
float maxVoltage = 0;
textAlign(CENTER);
textSize = 24;
textSize(textSize);
text("Air Voltage "+runningNumber, (graphLeft+graphRight)/2, graphTop - textSize);
textSize = 16;
textSize(textSize);
text("Time", (graphRight + graphLeft)/2, graphBottom + textSize * 3);
text("V (mV)", graphLeft, graphTop - textSize);
// plot x-axis
textSize = 12;
textSize(textSize);
stroke(0, 128, 0);
line(graphLeft, graphBottom, graphLeft, graphTop);
textAlign(RIGHT);
minVoltage = map(minData, -1023, 1023, -5000, 5000);
text(round(minVoltage), graphLeft - textSize/2, graphBottom);
maxVoltage = map(maxData, -1023, 1023, -5000, 5000);
text(round(maxVoltage), graphLeft - textSize/2, graphTop + textSize);
textAlign(CENTER);
text(timeStringStart, graphLeft, graphBottom + textSize*1.5);
text(dateStringStart, graphLeft, graphBottom + textSize*2.5);
textAlign(CENTER);
text(timeStringNow, graphRight, graphBottom + textSize*1.5);
text(dateStringNow, graphRight, graphBottom + textSize*2.5);
// plot y-axis
line(graphLeft, graphBottom, graphRight, graphBottom);
textAlign(CENTER);
textSize = 16;
textSize(textSize);
textAlign(CENTER);
text("Time", (graphRight + graphLeft)/2, graphBottom + textSize * 3);
text("V (mV)", graphLeft, graphTop - textSize);
//--- modify by ghosty --- begin
// ploy x-zero line
if (maxData>minData) { //plot only if data is OK
int zero=(minData*graphTop-maxData*graphBottom)/(minData-maxData);
stroke(0, 128, 0);
line(graphLeft, zero, graphRight, zero);
textSize(12);
text("0", graphLeft - textSize/2, zero+textSize/2); //zero
}
//--- modify by ghosty --- end
}
void serialEvent(Serial whichPort) {
String inString = trim(whichPort.readStringUntil(0x0A)); // Input string from serial port
//println(inString); //debug
if (inString == null)
{
return;
}
//--- modify by ghosty --- begin
String[] list = split(inString, ',');
int voltage = int(trim(list[0]));
int A0 = int(trim(list[1]));
int A1 = int(trim(list[2]));
saveData(voltage, A0, A1);
//--- modify by ghosty --- end
if (isFirstRead == 1)
{
print("Discard first read: ");
println(inString);
isFirstRead = 0;
return;
}
buffer[bufferNumber] = voltage;
bufferTime[bufferNumber] = millis();
if (bufferNumber < bufferLimit-1)
{
bufferNumber++;
} else
{
// bufferNumber == bufferLimit-1
// That means buffer is full
// Compress data:
// keep the max and min
// also keep their order
int xMax = 0;
int yMax = 0;
int xMin = 0;
int yMin = 0;
int i = 0;
String s = null;
yMax = buffer[0];
xMax = 0;
yMin = buffer[0];
xMin = 0;
for (i=1; i<bufferLimit; i++)
{
if (buffer[i] > yMax)
{
yMax = buffer[i];
xMax = i;
}
if (buffer[i] < yMin)
{
yMin = buffer[i];
xMin = i;
}
}
bufferNumber = 0;
if (dataNumber == 0)
{
maxData = yMax;
minData = yMin;
} else {
if (yMax > maxData)
{
maxData = yMax;
}
if (yMin < minData)
{
minData = yMin;
}
}
if (xMin < xMax)
{
data[dataNumber] = yMin;
s = "data[" + dataNumber + "] = " + data[dataNumber] + " Max: " + maxData + " Min: " + minData;
println(s);
dataNumber++;
data[dataNumber] = yMax;
s = "data[" + dataNumber + "] = " + data[dataNumber] + " Max: " + maxData + " Min: " + minData;
println(s);
dataNumber++;
} else
{
data[dataNumber] = yMax;
s = "data[" + dataNumber + "] = " + data[dataNumber] + " Max: " + maxData + " Min: " + minData;
println(s);
dataNumber++;
data[dataNumber] = yMin;
s = "data[" + dataNumber + "] = " + data[dataNumber] + " Max: " + maxData + " Min: " + minData;
println(s);
dataNumber++;
}
}
}
/*
modify by ghosty : save data to file
*/
import java.io.*;
String rootDir="D:\\Earthquake Research\\SampledData\\";
void saveData(int voltage, int A0, int A1)
{
BufferedWriter output = null;
try {
String fileName = rootDir+String.format("air%d_%04d-%02d-%02d.txt", runningNumber, year(), month(), day());
output = new BufferedWriter(new FileWriter(fileName, true)); //the true will append the new data
output.write(String.format("%04d-%02d-%02d %02d:%02d:%02d, %5d, %4d, %4d", year(), month(), day(), hour(), minute(), second(),
voltage, A0, A1));
output.newLine();
}
catch (IOException e) {
println("It Broke");
e.printStackTrace();
}
finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
println("Error while closing the writer");
}
}
}
}
|
文章標籤
全站熱搜
留言列表