使用Pyserial将时间与Arduino串行端口的电压进行对比

时间:2014-02-13 12:57:11

标签: python serialization matplotlib serial-port arduino

标题是我正在使用一个沿串行端口输出数据的Arduino。它输出如下:

120 1.23 170 2.54 210 2.32

左列是以毫秒为单位的时间,右列是0到5V之间的电压值。由空格隔开。编辑:看来stackoverflow不会让我以表格形式打印,所以要说清楚,我有120空间1.23 \换行170空格2.54等等。 我正在使用的Arduino草图:

#include <eHealth.h>


unsigned long time;
// The setup routine runs once when you press reset:
void setup() {
  Serial.begin(9600);  
}

// The loop routine runs over and over again forever:
void loop() {

  float ECG = eHealth.getECG();
  time = millis();
  Serial.print(time);
  Serial.print(" ");
  Serial.print(ECG, 3); 
  Serial.println(""); 


  delay(50);    // wait for 50 millisecond
}

现在在python的最后,我尝试了一些不同的脚本来使它工作,但到目前为止还没有成功。我想沿x轴(数据的左列)打印时间(以毫秒为单位)与电压值(右列)打印,并沿x轴更新时间,以便随输入数据一起变化。

我遇到的其中一段代码是这一段,但这似乎更适合在同一图表上绘制两段数据,这不是我想要的:

import sys, serial
import numpy as np
from time import sleep
from collections import deque
from matplotlib import pyplot as plt
import time


# class that holds analog data for N samples
class AnalogData:
  # constr
  def __init__(self, maxLen):
    self.ax = deque([0.0]*maxLen)       # maxLen = no. of samples?
    self.ay = deque([0.0]*maxLen)
    self.maxLen = maxLen

  # ring buffer
  def addToBuf(self, buf, val):
    if len(buf) < self.maxLen:
      buf.append(val)
    else:
      buf.pop()
      buf.appendleft(val)

  # add data
  def add(self, data):
    assert(len(data) == 2)
    self.addToBuf(self.ax, data[0])
    self.addToBuf(self.ay, data[1])

# plot class
class AnalogPlot:
  # constr
  def __init__(self, analogData):
    # set plot to animated
    plt.ion() 
    self.axline, = plt.plot(analogData.ax)
    self.ayline, = plt.plot(analogData.ay)
    plt.ylim([0,10])
   # update plot
  def update(self, analogData):
    self.axline.set_ydata(analogData.ax)
    self.ayline.set_ydata(analogData.ay)
    plt.draw()
def main():                           # main() function
  analogData = AnalogData(200)        # data range (maxLen)
  analogPlot = AnalogPlot(analogData)
  print 'plotting data...'
  # open serial port
  ser = serial.Serial('/dev/tty.usbmodem1411', 9600)
  blt = 0
  blot = []
  for i in range(5) : # total data points to plot
      line = ser.readline()
      data = [float(val) for val in line.split(" ")]
      blt = blt+1
      blot.append(float(val)) 
      #print blot
      print data
      if(len(data) == 2):
        analogData.add(data)
        analogPlot.update(analogData)     
  #close serial
  ser.flush()
  ser.close()
  time.sleep(1)
  plt.close("all")
  f=open("plot_store_1", "w")
  f.write("\n".join(str(x) for x in blot))
  plt.close("all")
# call main
if __name__ == '__main__':
  main()

理想情况下,我想要一个像这样的输出:

http://2.bp.blogspot.com/-IoeJ2QN-3Y0/UqeA2ZTTe9I/AAAAAAAADZg/PEOAZaCnYj0/s1600/VID_20131210_211336.mp4

1 个答案:

答案 0 :(得分:0)

这里有一个例子,说明你如何做你想做的事,但首先要做一些注意事项:

  1. 在注释行中,您可以找到如何从串口获取真实数据的线索(因为我没有测试它的串口,您必须自己尝试一下...... )
  2. 使用N,您可以控制最多要绘制的点数
  3. 使用refreshMillis控制绘图的刷新率
  4. 您可以按原样运行代码 并查看示例图
  5. 现在代码:

    from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
    import matplotlib.figure as mfig
    import PyQt4.QtGui as gui, PyQt4.QtCore as core
    import collections
    import time
    import random
    
    #import serial
    #ser = serial.Serial('/dev/tty.usbmodem1411', 9600)
    #def get_line():
    #    return ser.readline()
    
    def get_line():
        x = time.time()%10000
        y = random.random() * 5
        return "%d %.3f\n" % (x,y)
    
    refreshMillis = 300
    N = 10
    xs = collections.deque(maxlen=N)
    ys = collections.deque(maxlen=N)
    
    app = gui.QApplication([])
    
    fig = mfig.Figure()
    canvas = FigureCanvasQTAgg(fig)
    
    ax = fig.add_subplot(111)
    ax.set_ylim([0,5])
    line2D, = ax.plot(xs,ys)
    canvas.show()
    
    def process_line():
        line = get_line()
        data = map(float,line.split(' '))
        xs.append(data[0])
        ys.append(data[1])
        line2D.set_data(xs,ys)
        xmin, xmax = min(xs),max(xs)
        if xmin == xmax:
            ax.set_xlim([xmin,xmin+1])
        else:
            ax.set_xlim([xmin,xmax])
        canvas.draw()
    
    timer = core.QTimer()
    timer.timeout.connect(process_line)
    timer.start(refreshMillis)
    
    app.exec_()
    
    #ser.flush()
    #ser.close()