Значения Arduino, Python, Serial и Unpacking: "ValueError: для распаковки нужно более 1 значения"
Это мой первый вопрос, и я относительно новичок в python, так что будьте добры со мной. Ваше руководство по этой проблеме будет с благодарностью!
У меня есть пульсоксиметр, который используется с конкретным экраном Arduino для получения 2 простых сигналов: частоты пульса и содержания насыщения кислородом. Смотрите код Arduino:
#include <PinChangeInt.h>
#include <eHealth.h>
int cont = 0;
void setup() {
Serial.begin(115200);
eHealth.initPulsioximeter();
//Attach the inttruptions for using the pulsioximeter.
PCintPort::attachInterrupt(6, readPulsioximeter, RISING);
}
void loop() {
//BPM
Serial.print(eHealth.getBPM());
Serial.print(",");
//SP02
Serial.print(eHealth.getOxygenSaturation());
//NEW LINE
Serial.print('\n');
delay(500);
}
//=========================================================================
void readPulsioximeter(){
cont ++;
if (cont == 50) { //Get only of one 50 measures to reduce the latency
eHealth.readPulsioximeter();
cont = 0;
}
}
Таким образом, вывод в последовательный монитор, другими словами, когда вызывается pySerial readline(), разделенные запятыми строки выглядят так:
65,95
67,96
67,95
70,94
Просто, правда?
Что ж, я использую программу на python в сочетании с pySerial для чтения этих значений, назначения их вектору, печати их на графике в реальном времени и сохранения их в файле.csv.
Для справки, вот программа:
import serial
import time
import matplotlib.pyplot as plt
import numpy as np
import sys
import os
import csv
#time load
timestr = time.strftime("%Y_%m_%d")
#spacer
spacer = "_"
#user inputs name
name = raw_input('Enter full name: ')
file_name = name + spacer + timestr
file_name_str = file_name+'.csv'
#change directory
path = '/home/pi/Desktop/pulseox/data'
os.chdir(path)
text_file = open(file_name, "w")
full_path = path + "/" + file_name_str
#check
print full_path
#establish serial connection with ACM0
ser = serial.Serial('/dev/ttyACM0', 115200)
#establish vectors
thymeL = [ ]
bpmL = [ ]
sp02L = [ ]
array_data = thymeL, bpmL, sp02L
#declare time
thyme = 1
#establish plot values
#plt.axis([0,50,0,120])
plt.ion()
plt.title("Pulse [BPM] & SPo2 [%] v. Time [s]", fontsize = "16")
plt.xlabel("Time [s]", fontsize = "14")
plt.ylabel("Pulse (red) [BPM] & SPo2 (blue) [%]", fontsize = "14")
#print data to terminal, define time
while True:
data_in = ser.readline()
bpm, sp02 = data_in.split(",")
thyme = float(thyme)
bpm = float(bpm)
sp02 = float(sp02)
print "Time [s]: %s" % (thyme)
print "HR [BPM]: %s" % (bpm)
print "SPO2 [%%]: %s" % (sp02)
print
thymeL.append(thyme)
bpmL.append(bpm)
sp02L.append(sp02)
plt.scatter(thyme,bpm,color="red")
plt.scatter(thyme,sp02,color="blue")
plt.pause(0.1)
time.sleep(0.05)
thyme = thyme + 1
with open(full_path, 'w') as f:
writer = csv.writer(f)
for t, b, s in zip(array_data[0], array_data[1], array_data[2]):
writer.writerow([t, b, s])
25% времени все работает нормально. Но остальные 75% времени случайным образом программа выдаст следующую ошибку:
Traceback (most recent call last)L
File "pulseox.py", line 74, in <module>
bpm, sp02 = data_in.split(",")
ValueError: need more than 1 value to unpack
Поэтому игнорируйте остальную часть программы, за исключением следующих строк:
data_in = ser.readline()
spm,sp02 = data_in.split(",")
Если на самом деле последовательный монитор просто выводит 2 значения через запятую, такие как:
67, 95
71, 95
Тогда почему возникает ошибка распаковки, когда программе так просто распаковывают две переменные и присваивают их массивам? Это проблема, которая встречается в другой моей программе, и я хотел бы разобраться с ней! Любая помощь очень ценится!
1 ответ
Проблема в том, что код Python может читать из буфера, когда Arduino печатал только частично. Вы используете 4 отдельных отпечатка для Arduino и while True: data_in = ser.readline()
в коде питона. Таким образом, может произойти следующее:
void loop() {
//BPM
Serial.print(eHealth.getBPM());
Serial.print(",");
// *** At this point the python code may read what has been written so far, i.e. it receives an invalid data set and thus the ValueError. ***
//SP02
Serial.print(eHealth.getOxygenSaturation());
//NEW LINE
Serial.print('\n');
delay(500);
}
Вы должны сначала построить строку в форме x,y\n
а затем распечатать эту строку, используя одну печать. Затем часть Python либо читает кортеж данных, либо не читает, но не читает неполные кортежи, что приводит к ошибке распаковки.
Так что-то вроде следующего сделало бы:
void loop() {
char buffer[32]; // make sure buffer is large enough;
sprintf(buffer, "%d,%d\n", eHealth.getBPM(), eHealth.getOxygenSaturation());
Serial.print(buffer);
delay(500);
}