当前位置: 代码迷 >> python >> 使用pyserial解析int值并绘制直方图
  详细解决方案

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

热度:90   发布时间:2023-06-13 14:24:52.0

我已经在这个代码上工作了几个小时,而且由于我缺乏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)

我最大的问题是摆脱“垃圾”并从逗号中分离出“好数字”,以便将它们解释为单独的数字(我甚至需要这样做吗?)。 我认为\\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);  

}

注意:我只关注从Arduino获取数据点列表的问题。 我认为如何绘制这些数据应该是一个完全不同的问题,特别是如果你想现场直播 (在这方面,StackOverflow上已经有几个问题涉及这个问题,例如看到和 )


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

#!/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保持运行,每次以某种方式扩展时都会打印ydata的完整内容。

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

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