2015-08-19 6 views
0

Это мой первый вопрос, и я относительно новичок в python, так что любезно несите меня. Ваше руководство с этой проблемой будет принята с благодарностью!Arduino, Python, Serial и Unpacking Ценности: «ValueError: требуется больше, чем 1 значение для распаковки»

У меня есть pulse oximeter, который используется с particular Arduino shield для получения 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 

Тогда почему нет ack, когда программе так просто поручено распаковать две переменные и назначить их массивам? Это проблема, которая возникает в другой моей программе, и я хотел бы разобраться в ней! Любая помощь очень ценится!

ответ

0

Проблема заключается в том, что код python может считываться из буфера, когда Arduino печатается частично. Вы используете 4 одиночных отпечатка для Arduino и while True: data_in = ser.readline() в коде python. Таким образом, следующее может произойти:

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); 
} 
+0

Действительно, моя интуиция говорит, что программа питон читает Arduino серийный на примере, в котором линия не полностью напечатанной. После внедрения кода и загрузки его в Arduino, я все равно получаю ту же ошибку на частой основе. Возможно, буфер недостаточно велик? – preacherperkins

+0

Возможно, это связано с реализацией 'Serial.print'. Также я не знаю подробных функций функции C 'printf'.Возможно, печатные сообщения помещаются один за другим в поток, но не освобождают поток после его завершения (чтобы его можно было прочитать до завершения печати). Попробуйте модифицировать свой код python таким образом, чтобы он читал из потока, пока не встретит '' \ 0''. Если требуется несколько чтений, вы можете присоединить части к верным кортежам. Я попытаюсь обновить свой андер в ближайшее время, чтобы проиллюстрировать, что я имею в виду. –

+0

Я вижу, что вы имеете в виду, и попытается изменить мой код на Python таким образом, чтобы он не выполнял значение unpack, пока функция readline() не вернет все три значения. Однако, обратите внимание, что я очень новичок в python, и любые предложения кода будут очень полезны. Я также извиняюсь за задержку - я был вне города на выходные. Благодаря! – preacherperkins

 Смежные вопросы

  • Нет связанных вопросов^_^