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

Python 使用pyserial解析int值并绘制直方图,python,matplotlib,arduino,serial-port,Python,Matplotlib,Arduino,Serial Port,我在这段代码上已经工作了几个小时,由于我缺乏python知识,所以我没有走多远。我有大量来自Arduino的数据。(下面是串行数据示例) 正如你所看到的,开头有“垃圾”。以下是我迄今为止的代码: import serial import matplotlib.pyplot as plt import numpy as np import time serialArduino = serial.Serial('/dev/ttyUSB0', 9600, timeout=3) plt.ion()

我在这段代码上已经工作了几个小时,由于我缺乏python知识,所以我没有走多远。我有大量来自Arduino的数据。(下面是串行数据示例)

正如你所看到的,开头有“垃圾”。以下是我迄今为止的代码:

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)
注意:我只关注从Arduino获取数据点列表的问题。我认为如何绘制这些数据应该是一个完全不同的问题,特别是如果你想在现场进行的话。(在这方面,关于StackOverflow,这里已经有几个问题涉及这个问题,例如,请参阅和)


这是我在现场发现的,没有任何测试:

#/usr/bin/env python2.7
导入序列号
将matplotlib.pyplot作为plt导入
将numpy作为np导入
导入时间
原始缓冲区=“”
ydata=[]
ydata_已更改=错误
ser=serial.serial('/dev/ttyUSB0',9600,超时=None)
#没有超时!
尽管如此:
#只读可用数据
waiting=ser.inWaiting()
如果等待>0:
#将新数据附加到传入缓冲区,删除“垃圾”
原始缓冲区=原始缓冲区+\
ser.read(waiting).replace('\x00','').replace('\n','')
#注意“部分”数字
#(例如,原始缓冲区='…,171,16',其中'16'
#应为“162”,但额外的“2”为
#仍在输入缓冲区中等待
idx=raw_buffer.rfind(','))
原始数据=原始缓冲区[0:idx]
原始缓冲区=原始缓冲区[idx+1:]
#获取新值列表并安全存储
原始列表=映射(λx:int(x)\
过滤器(λx:x!='',原始数据。拆分(','))
如果len(原始列表)>0:
扩展(原始列表)
ydata_已更改=真
如果ydata_发生变化:
ydata_已更改=错误
打印“新数据:”+str(ydata)
#用ydata做点什么
时间。睡眠(1)
代码有内联注释,否则应该是自解释的。请注意,此代码将永远运行,每次以某种方式扩展时,都会打印
ydata
的完整内容

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

  • 将任意阈值设置为
    len(ydata)
    ,然后中断循环并打印内容
  • 在两个不同但通信的线程上执行串行读取和打印
注意:我只关注从Arduino获取数据点列表的问题。我认为如何绘制这些数据应该是一个完全不同的问题,特别是如果您想实时绘制这些数据的话。(在这方面,在StackOverflow上已经有几个问题涉及到这个问题,例如,请参阅和)


这是我在现场发现的,没有任何测试:

!/usr/bin/env python2.7
导入序列号
将matplotlib.pyplot作为plt导入
将numpy作为np导入
导入时间
原始缓冲区=“”
ydata=[]
ydata_已更改=错误
ser=serial.serial('/dev/ttyUSB0',9600,超时=None)
#没有超时!
尽管如此:
#只读可用数据
waiting=ser.inWaiting()
如果等待>0:
#将新数据附加到传入缓冲区,删除“垃圾”
原始缓冲区=原始缓冲区+\
ser.read(waiting).replace('\x00','').replace('\n','')
#注意“部分”数字
#(例如,原始缓冲区='…,171,16',其中'16'
#应为“162”,但额外的“2”为
#仍在输入缓冲区中等待
idx=raw_buffer.rfind(','))
原始数据=原始缓冲区[0:idx]
原始缓冲区=原始缓冲区[idx+1:]
#获取新值列表并安全存储
原始列表=映射(λx:int(x)\
过滤器(λx:x!='',原始数据。拆分(','))
如果len(原始列表)>0:
扩展(原始列表)
ydata_已更改=真
如果ydata_发生变化:
ydata_已更改=错误
打印“新数据:”+str(ydata)
#用ydata做点什么
时间。睡眠(1)
代码有内联注释,否则应该是自解释的。请注意,此代码将永远运行,每次以某种方式扩展时,都会打印
ydata
的完整内容

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

  • 将任意阈值设置为
    len(ydata)
    ,然后中断循环并打印内容
  • 在两个不同但通信的线程上执行串行读取和打印

我会试一试。非常感谢您的帮助!我看到您更换了\x00。如果\x00更随机,有什么方法可以消除它吗?(\x44\x56\x22…等)对于消除总是从一开始就存在的“随机垃圾”,我是否还应该研究其他方法。(我注意到,有时它并不完美\x00…)我是python新手,所以我不知道有什么代码可以说“在“:”之后开始读取数据”(冒号).\x82\x9ab\x92\x82\x92b\x92\x82\x9ab\x92\x82\xa2b\x92\x82\x9ab\x92\x82\xa2b\x92\x82\x9ab\x92\x82\x92b\x92\x82\x9ab\x9@keakins13据我所知,Arduino不应该自己打印任何垃圾,尽管我可能错了。如果您能编辑您的问题并添加Arduino草图,以便我可以看一下,那将不胜感激。--是的,您可以
导入re
,然后使用
re.sub(“[^0-9a-zA-Z,]+”,'',raw_serial)
,其中
raw_serial=ser.read(waiting)
。然而,这有点残酷,因为我不知道发生了什么
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)
    /*
 * 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);  

}