說明:
- AirView 新增資料存檔功能,紅字為修改部分,可套用未來版本
- Processing程式:(新增的修改碼用紅字標示)
- 套用時請將原本的 rootDir="D:\\Earthquake Research\\SampledData\\" 改成自己欲存檔的目錄。
// 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, modified by ghosty
import processing.serial.*;
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() { int lf = 10; // Linefeed in ASCII Serial myPort; // The serial port
// List all the available serial ports print("Available serial ports: "); printArray(Serial.list());
myPort = new Serial(this, "COM5", 9600); myPort.clear(); // Clear buffer myPort.bufferUntil(lf); // 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(204); // gray background 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", (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); }
void serialEvent(Serial whichPort) { int lf = 10; // Linefeed in ASCII String inString = null; // Input string from serial port int voltage = 0;
inString = whichPort.readStringUntil(lf); if (inString == null) { return; }
inString = trim(inString); voltage = int(inString); saveData(voltage); //modified by ghosty
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++; } } }
/* modified by ghosty : save data to file */ import java.io.*; String rootDir="D:\\Earthquake Research\\SampledData\\"; void saveData(int voltage) { BufferedWriter output = null; try { String fileName = rootDir+String.format("air%04d-%02d-%02d.txt", 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, %d", year(), month(), day(), hour(), minute(), second(), voltage)); 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"); } } } } |
Arduino程式:
// 測量A0對A1的空氣電壓 // 修改自地震預測研究所所長 林湧森 2016-07-28 04:29 UTC+8 // 修改者:ghostyguo // 使用最快取樣速度, 每隔400ms送出最大與最小值 // 2016-08-20 22:30 UTC+8 by
int sampleCount; int maxValue, minValue; //keep extreme value 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) { //原本為400000L, 400ms sampling(); } sampleCountLimit = sampleCount; // uncomment the following lines to see the sampleCountLimit // Serial.print("#"); // Serial.println(sampleCountLimit); }
void startNewCycle() { maxValue = -10000; //12bit ADC < -1024 minValue = 10000; //12bit ADC > 1024 whoIsLast = 0; sampleCount = 0; }
void loop() { sampling(); if (sampleCount>sampleCountLimit) { if (whoIsLast == -1) { Serial.println(maxValue); Serial.println(minValue); } else if (whoIsLast == 1) { Serial.println(minValue); Serial.println(maxValue); } else { Serial.println("Extreme Value Error"); } startNewCycle(); } } void sampling() { int sampleValue = analogRead(A1) - analogRead(A0); if (minValue > sampleValue) { minValue = sampleValue; whoIsLast = -1; } if (maxValue < sampleValue) { maxValue = sampleValue; whoIsLast = 1; } ++sampleCount; } |
留言列表