2016年7月5日

利用Arduino+gnuplot作數據即時繪圖

如何將Arduino的數據拿出來即時繪圖呢?

用手機的話
《以手機藍牙接收Arduino感測器訊號,進行即時紀錄與繪圖》

用電腦的話
《RS232初體驗--二氧化碳濃度計》使用Tera Term紀錄
《用Arduino製作溫濕度記錄器》使用Gobetwino紀錄
《Arduino+兩個DS18B20溫度感應器的應用》使用Excel外掛PLX-DAQ紀錄


雖然已經有了方法,不過,我還不滿足,因為現有的方法在繪圖部份都不能完美地整合在一起,雖然PLX-DAQ已經能將數據直接紀錄在excel裡,還能夠直接繪圖。但是在處理大筆數據的時候,excel就不一定能用了。

如果有組sensor,一秒紀錄一個資料,光是紀錄一週,就有60萬筆資料了!更何況用的sensor可能會是三四組,這樣可是有數百萬筆資料,我覺得excel處理這麼大筆數據可能會很卡啊。
找了別人寫的資料,Excel2003資料列可達65536,Excel2007資料列可達1048576。1048576筆資料,算一算如果每秒紀錄一次,可紀錄12天,如果是兩個sensor,就是只能紀錄6天。或者反過來想,如果要紀錄很多天,可能就要改成每十分鐘紀錄一筆,但是就會降低時間的解析度。

有沒有兩全其美的方法呢?又想擁有時間的解析度,又希望能處理大筆資料?看來就是用linux來解決吧,因為linux可以直接用文字列工具來處理數據與繪圖,在搜尋過程中,看到這則討論串,發現gnuplot可以達成我的需求。在數據方面還能夠充分客製化,當然這就代表了使用上有一定的門檻。

以下就分三個部份來談,怎麼將Arduino蒐集到的資料作即時繪圖。

1.Arduino蒐集資料

以兩組sensor同時記錄為例子,在Arduino的程式設計中,從Serial印出的資料,需要用逗號來分隔,然後最後要有分行。

例如
在void loop() 的迴圈中
Serial.print(value1);
Serial.print(",");
Serial.println(value2);


2.Arduino的資料即時匯入電腦作記錄
開啟終端機,用cat去蒐集arduino的資料。在此範例中,arduino是連接/dev/ttyACM0
 cat /dev/ttyACM0

順利的話,會在終端機看到一行一行從arduino傳來的資料。但是有些情況是cat去連接arduino的時候,會讓arduino重置,以至於資料流中斷。這時可用一個招式,先開啟cutecom,讓cutecom去連接/dev/ttyACM0,讓資料導入cutecom,然後在終端機去用cat把/dev/ttyACM0的資料搶過來,這樣就不會有reset的問題。

如果使用cat順利的話,就可以按下ctrl+c,先中斷cat

接著我們希望在匯入的資料裡都加上時間戳記,會用到ts,這是在moreutils這個套件裡的功能,你必須先安裝moreutils

sudo apt-get install moreutils

接著使用這個指令
ts '%Y-%m-%d %H:%M:%S',</dev/ttyACM0 >>logfile

你可以先用  ts < /dev/ttyACM0  來試試看,它會在每筆資料的前方加上時間戳記,但是預設的時間戳記可能會有中文,這在數據處理上不太方便。所以會在ts後面加上'%Y-%m-%d %H:%M:%S' 這是用來限定時間戳記的格式。而在格式後面跟著一個逗點,這是讓時間戳記和資料中間用逗號分隔,之後才好區分哪些是時間戳記,哪些是資料。

接著在/dev/ttyACM0的前後,有一個<和一個>>,前者是用來把/dev/ttyACM0導入ts,後者是把產生的資料導入 logfile這個資料裡頭。用>>是為了把資料不斷加在此logfile的後面。

如果想看看那個文字檔是不是順利紀錄,可以用下面這個指令。tail可以把文字檔案最底部顯示出來,如果一直有資料進去,它就會一直顯示出來。
tail -f logfile

想知道紀錄了幾筆,可以用這個來顯示行數
 wc -l logfile 



3.gnuplot的即時繪圖
現在已經有了時間戳記的即時記錄了,如果要作即時繪圖,就是利用gnuplot不斷地去撈logfile的資料,一直重複繪圖,這樣就可以做出即時繪圖了。

這裡有個《Gnuplot 中文教程》,寫得相當仔細,可以當作使用參考

將以下文字存成檔名為plotData的文字檔之後,另外開一個終端機,鍵入
gnuplot plotData
就可以一直繪製即時圖表了

#!/usr/local/bin/gnuplot -rv
set xdata time
set datafile separator ","
set timefmt "%Y-%m-%d %H:%M:%S"
#set format x "%H:%M:%S"
set format x "%H:%M"
#set xrange ["2016-07-02 23:00:00":"2016-07-02 24:00:00"]
#set xtics "2016-07-02 20:00:00",600,"2016-07-02 24:00:00"
unset mxtics
set xlabel "time"
set ylabel "voltage"
set title "時間變化"
set grid
#unset key
#set term pngcairo size 800,600
#set output "test.png"
plot "logfile" using 1:2 with lines title "value1" linetype rgb "blue",\
       "logfile" using 1:3 with lines title "value2" linetype rgb "red",\
pause 1
refresh
reread

幾個程式碼的注意事項
set xdata是因為x軸是時間戳記,所以要用這個功能去設定,這樣才能依據自己需求變換x軸的顯示方式,利用set format x來設定格式,像是顯示時分,或是顯示日期。

每行前面有#的都是被註解掉的,如果想要特別設定x軸的範圍或是刻度可以設定xrange和xtics。並且把前面的#刪掉

上面程式是把曲線圖不斷重繪,如果是想要把圖片存起來,有兩個方式,一個是把pause 1和refresh註解掉(加上#),這樣就能從繪圖視窗中的按下第一個icon把圖片存在剪貼簿,再送去繪圖軟體儲存。

第二種方式是改變term,把下面這兩行取消註解,這是設定存檔的格式,存成png。你也可以存成pdf,就把整行改成set term pdfcairo
set term pngcairo size 800,600
set output "test.png"
因為存圖檔就存一次,所以要把以下這三行註解掉,不然它就會一直重複匯出圖檔。
pause 1
refresh
reread