Arduino で測定したデータを PyQt + Matplotlib でリアルタイムプロット その 3

昨日 の続きです。Arduino には ここ のプログラムを書き込んでいます。

前回からの変更点は以下の通りです。

  • ストップボタンを押すと計測終了と同時に example.csv に計測データを書き出す。
  • 時間と測定値をデジタル表示する。

これでとりあえずは Arduino で測定した電圧値の時系列データを取得することができるようになりました。
やっつけ感満載ですが。。。

気になる点としては、測定開始から約 1 分で積み上げ 32 μ s の誤差が発生することが挙げられます。
まあ 1 日測定したとしても 46 ms の誤差なので許容範囲ですが、もっと精度良くする方法がありそうです。

# coding: utf-8
import sys
import signal
import serial
import numpy as np
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import (QApplication, QWidget, QPushButton, QGridLayout,
			     QHBoxLayout, QVBoxLayout, QLCDNumber, QLabel)
import matplotlib as mpl
mpl.use("Qt5Agg")
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import csv

class ApplicationWindow(QWidget):
    def __init__(self):
	super().__init__()

	self.initUI()

    def initUI(self):
	self.timer = QTimer(self)
	self.timer.timeout.connect(self.updateFigure)

	self.initCanvas()

	self.lcd1 = QLCDNumber(self)
	self.lcd1.setStyleSheet("QWidget { background-color: rgb(100, 100, 255) }")

	self.lcd2 = QLCDNumber(self)
	self.lcd2.setStyleSheet("QWidget { background-color: rgb(100, 100, 255) }")

	startButton = QPushButton("Start")
	startButton.clicked.connect(self.onStartButton)
	stopButton = QPushButton("Stop")
	stopButton.clicked.connect(self.onStopButton)

	l1 = QHBoxLayout()
	l1.addWidget(self.canvas)

	l2 = QVBoxLayout()
	l2.addWidget(startButton)
	l2.addWidget(stopButton)

	l3 = QGridLayout()
	l3.addWidget(QLabel("Time:"), 0, 0)
	l3.addWidget(self.lcd1, 0, 1)
	l3.addWidget(QLabel("s"), 0, 2)
	l3.addWidget(QLabel("Voltage:"), 1, 0)
	l3.addWidget(self.lcd2, 1, 1)
	l3.addWidget(QLabel("V"), 1, 2)

	l23 = QVBoxLayout()
	l23.addLayout(l2)
	l23.addLayout(l3)
	l23.addStretch(1)

	lMain = QHBoxLayout()
	lMain.addLayout(l1)
	lMain.addLayout(l23)

	self.setLayout(lMain)

	self.setWindowTitle("Realtime Monitor")

    def initCanvas(self):
	self.fig = mpl.figure.Figure(figsize=(6, 5), dpi=100)
	self.axes = self.fig.add_subplot(111)
	self.axes.hold(False)
	self.canvas = FigureCanvas(self.fig)
	self.initFigure()

    def initTime(self):
	ser.write("*".encode())
	self.serData = ser.readline().strip().rsplit()
	self.t0 = float(self.serData[0])

    def initFigure(self):
	self.t = np.zeros(100)
	self.y = np.zeros(100)
	self.li, = self.axes.plot(self.t, self.y)
	self.axes.set_xlabel("Time[s]")
	self.axes.set_ylabel("Voltage[V]")
	self.axes.set_ylim(0, 5)

    def updateFigure(self):
	ser.write("*".encode())
	self.serData = ser.readline().strip().rsplit()
	self.serT = self.getT()
	self.serY = self.getY()

	self.data.append([self.serT, self.serY])

	self.t = np.append(self.t, self.serT)
	self.t = np.delete(self.t, 0)
	self.y = np.append(self.y, self.serY)
	self.y = np.delete(self.y, 0)
	self.li.set_xdata(self.t)
	self.li.set_ydata(self.y)
	self.axes.set_xlim(min(self.t), max(self.t))

	self.canvas.draw()

	self.lcd1.display(self.t[99])
	self.lcd2.display(self.y[99])

    def getT(self):
	return (float(self.serData[0])-self.t0)/10**6

    def getY(self):
	return float(self.serData[1])*5/1023

    def onStartButton(self):
	self.initFigure()

	self.f = open('example.csv', 'w')
	self.w = csv.writer(self.f)
	self.data = []

	self.initTime()        
	self.timer.start()

    def onStopButton(self):
	self.timer.stop()
	try:
	    for i in range(len(self.data)):
		self.w.writerow(self.data[i])
	    self.f.close()
	except:
	    pass

if __name__ == "__main__":
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    ser = serial.Serial(port="/dev/ttyACM0", baudrate=9600)
    app = QApplication(sys.argv)
    aw = ApplicationWindow()
    aw.show()
    app.exec_()

15070601.gif

コメント

Comments powered by Disqus
書籍更新情報
2016-10-21
Pythonによる科学技術計算 基礎編
PDF版の販売を開始しました。
販売ページはこちら

2016-09-09
Pythonによる科学技術計算 基礎編
1.2版への更新が可能になりました。
サポートページはこちら
電子書籍
Pythonによる科学技術計算 基礎編
Kindle ストア、Leanpubで販売中です
Pythonによる科学技術計算 基礎編
PDF版の販売はこちら
同人誌
技術書典(2016/6/25)
Emacs/org-modeのPDF作成術
電子版をBOOTHで販売中です
Emacs/org-modeのPDF作成術
Share