使用pyserial解析int值并绘制直方图

时间:2017-02-09 18:27:17

标签: python matplotlib arduino serial-port

我一直在研究这段代码几个小时,而且由于我缺乏python知识,我没有走得太远。我有大量来自Arduino的数据。 (下面的样本序列数据)

'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00171,170,171,171,171,172,171,171,172,171,170,168,169,170,170,170,168,170,171,170,170,170,170,170,171,170,170,170,169,169,169,170,169,168,168,167,168,168,169,167,168,168,168,168,168,167,167,168,169,168,169,169,168,169,167,167,167,167,167,166,167,167,167,167,166,167,167,166,166,167,167,167,167,167,166,166,167,166,166,166,166,166,166,165,166,166,166,165,166,165,166,166,165,166,166,166,165,165,166,165,165,165,165,165,166,166,165,165,165,165,166,165,165,165,165,165,165,165,165,166,166,165,165,165,162,167,165,166,166,165,164,167,166,165,165,165,164,166,165,164,164,164,165,165,164,165,164,164,164,164,164,164,165,164,164,164,164,164,164,163,164,164,164,163,164,164,164,164,164,164,164,163,164,164,164,164,163,164,164,164,163,164,164,163,163,163,163,163,163,164,163,163,163,163,163,163,163,163,163,164,163,163,163,163,163,163,162,163,163,163,163,162,163,163,163,163,163,163,163,163,163,163,163,163,163,162,163,162,162,163,162,163,162,162,162,162,163,163,162,162,162,162,162,163,162,163,163,162,163,162,162,162,162,162,163,162,162,160,162,162,163,162,162,162,165,163,162,162,162,162,162,162,162,162,162,161,162,161,162,162,162,161,161,162,161,161,161,161,\n'

正如你所看到的,有"垃圾"在一开始的时候。这是我到目前为止的代码:

import serial
import matplotlib.pyplot as plt
import numpy as np
import time

serialArduino = serial.Serial('/dev/ttyUSB0', 9600, timeout=3)

plt.ion()
cnt=0

ydata = [0] * 290
line, = plt.plot(ydata)
plt.ylim([0,1000])

while True:
  bytesToRead = serialArduino.inWaiting()
  valueRead = serialArduino.readline().rstrip()
  try:
     list = int(valueRead)
  except ValueError as e:
     list = 0 # ????
 #   mylist = list.partition("\n")[0]
  if list <=1000:
    ydata.append(list)
    del ydata[0]
    line.set_xdata(np.arange(len(ydata)))
    line.set_ydata(ydata)
    plt.axis([ 0, 288 , 0, 1000])
    binBoundaries = np.linspace(0, 288, 1.77)
    plt.show()
    time.sleep(1)

我最大的问题是摆脱&#34;垃圾&#34;分裂好的数字&#34;从逗号中可以将它们解释为单独的数字(我甚至需要这样做吗?)。我认为\n得到了照顾。我感谢您给我的任何帮助或建议或链接。

编辑:当我粘贴时,有些缩进搞砸了。还修改了一些代码。

Arduino代码(Pro Trinket 5V / 16MHz(FTDI))

    /*
 * Macro Definitions
 */
#define SPEC_TRG         A0
#define SPEC_ST          A1
#define SPEC_CLK         A2
#define SPEC_VIDEO       A3

#define SPEC_CHANNELS    288 // New Spec Channel
uint16_t data[SPEC_CHANNELS];

void setup(){

  //Set desired pins to OUTPUT
  pinMode(SPEC_CLK, OUTPUT);
  pinMode(SPEC_ST, OUTPUT);

  digitalWrite(SPEC_CLK, HIGH); // Set SPEC_CLK High
  digitalWrite(SPEC_ST, LOW); // Set SPEC_ST Low

  Serial.begin(9600); // Baud Rate set to 9600

}

/*
 * This functions reads spectrometer data from SPEC_VIDEO
 * Look at the Timing Chart in the Datasheet for more info
 */
void readSpectrometer(){

  int delayTime = 1; // delay time

  // Start clock cycle and set start pulse to signal start
  digitalWrite(SPEC_CLK, LOW);
  delayMicroseconds(delayTime);
  digitalWrite(SPEC_CLK, HIGH);
  delayMicroseconds(delayTime);
  digitalWrite(SPEC_CLK, LOW);
  digitalWrite(SPEC_ST, HIGH);
  delayMicroseconds(delayTime);

  //Sample for a period of time
  for(int i = 0; i < 3000; i++){

      digitalWrite(SPEC_CLK, HIGH);
      delayMicroseconds(delayTime);
      digitalWrite(SPEC_CLK, LOW);
      delayMicroseconds(delayTime); 

  }

  //Set SPEC_ST to low
  digitalWrite(SPEC_ST, LOW);

  //Sample for a period of time
  for(int i = 0; i < 85; i++){

      digitalWrite(SPEC_CLK, HIGH);
      delayMicroseconds(delayTime);
      digitalWrite(SPEC_CLK, LOW);
      delayMicroseconds(delayTime); 

  }

  //One more clock pulse before the actual read
  digitalWrite(SPEC_CLK, HIGH);
  delayMicroseconds(delayTime);
  digitalWrite(SPEC_CLK, LOW);
  delayMicroseconds(delayTime);

  //Read from SPEC_VIDEO
  for(int i = 0; i < SPEC_CHANNELS; i++){

      data[i] = analogRead(SPEC_VIDEO);

      digitalWrite(SPEC_CLK, HIGH);
      delayMicroseconds(delayTime);
      digitalWrite(SPEC_CLK, LOW);
      delayMicroseconds(delayTime);

  }

  //Set SPEC_ST to high
  //digitalWrite(SPEC_ST, HIGH);

  //Sample for a small amount of time
  for(int i = 0; i < 7; i++){

      digitalWrite(SPEC_CLK, HIGH);
      delayMicroseconds(delayTime);
      digitalWrite(SPEC_CLK, LOW);
      delayMicroseconds(delayTime);

  }

  digitalWrite(SPEC_CLK, HIGH);
  delayMicroseconds(delayTime);

}

/*
 * The function below prints out data to the terminal or 
 * processing plot
 */
void printData(){

  for (int i = 0; i < SPEC_CHANNELS; i++){
    Serial.print(data[i]);
    Serial.print(',');

  }

  Serial.print("\n");
}

void loop(){

  readSpectrometer();
  printData();
  delay(1000);  

}

1 个答案:

答案 0 :(得分:0)

注意:我只关注从 Arduino 获取数据点列表的问题。我认为如何绘制这些数据应该是一个完全不同的问题,特别是如果你想这样做 live (在这方面,StackOverflow上已经有几个问题涉及此问题,例如,请参阅thisthis

这就是我当场提出的,没有任何测试:

#!/usr/bin/env python2.7

import serial
import matplotlib.pyplot as plt
import numpy as np
import time

raw_buffer = ''
ydata = []
ydata_changed = False
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=None)
                                          # no timeout!

while True:

    # read only available data
    waiting = ser.inWaiting()
    if waiting > 0:

        # append new data to incoming buffer, remove 'junk'
        raw_buffer = raw_buffer + \
                     ser.read(waiting).replace('\x00', '').replace('\n', '')

        # Take care of 'partial' numbers
        # (e.g. raw_buffer='...,171,16' where '16'
        # should be '162' but the extra '2' is
        # still waiting in the input buffer
        idx = raw_buffer.rfind(',')
        raw_data = raw_buffer[0:idx]
        raw_buffer = raw_buffer[idx + 1:]

        # get list of new values and store them safely
        raw_list = map(lambda x: int(x), \
                   filter(lambda x: x != '', raw_data.split(',')))

        if len(raw_list) > 0:
            ydata.extend(raw_list)
            ydata_changed = True

    if ydata_changed:
        ydata_changed = False
        print "New Data: " + str(ydata)

        # do something with ydata

    time.sleep(1)

代码具有内联注释,应该否则不言自明。请注意,此代码将永久运行,每次以某种方式扩展时都会打印ydata的完整内容。

最后,让我添加一个观察结果:plt.show()是一个阻塞调用,因此如果在循环中插入该指令,则在关闭数字之前,您将无法解析新数据。您可能想要:

  • 将任意阈值设置为len(ydata),之后您将从循环中断并绘制内容
  • 在两个不同的,但正在沟通的线程
  • 上执行串行读取绘图