Arduino, Python, Serial and Unpacking Values: "ValueError: need more than 1 value to unpack" -
this first question , relatively new python, kindly bear me. guidance problem appreciated!
i have pulse oximeter used particular arduino shield produce 2 simple signals: pulse rate , oxygen saturation content. see arduino code:
#include <pinchangeint.h> #include <ehealth.h> int cont = 0; void setup() { serial.begin(115200); ehealth.initpulsioximeter(); //attach inttruptions using 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 of 1 50 measures reduce latency ehealth.readpulsioximeter(); cont = 0; } }
so output serial monitor, in other words when pyserial readline() called, comma-delimited lines looks like:
65,95 67,96 67,95 70,94
simple, right?
well, use python program in combination pyserial read these values, assign them vector, print them on graph in real time , save .csv file.
for reference, here program:
import serial import time import matplotlib.pyplot plt import numpy 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 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 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 open(full_path, 'w') f: writer = csv.writer(f) t, b, s in zip(array_data[0], array_data[1], array_data[2]): writer.writerow([t, b, s])
25% of time works fine. other 75% of time, randomly, program return following error:
traceback (most recent call last)l file "pulseox.py", line 74, in <module> bpm, sp02 = data_in.split(",") valueerror: need more 1 value unpack
so ignore rest of program except following lines:
data_in = ser.readline() spm,sp02 = data_in.split(",")
if, in fact, serial monitor outputting 2 comma-separated values such as:
67, 95 71, 95
then why there unpack error when program instructed unpack 2 variables , assign them arrays? problem occurring in program of mine , bottom of it! appreciated!
the problem python code might read buffer when arduino has printed partially. using 4 single prints arduino , while true: data_in = ser.readline()
in python code. following may happen:
void loop() { //bpm serial.print(ehealth.getbpm()); serial.print(","); // *** @ point python code may read has been written far, i.e. receives invalid data set , valueerror. *** //sp02 serial.print(ehealth.getoxygensaturation()); //new line serial.print('\n'); delay(500); }
you should first construct string of form x,y\n
, print string using single print. python part either reads data tuple or doesn't won't read incomplete tuples leading unpacking failure.
so following do:
void loop() { char buffer[32]; // make sure buffer large enough; sprintf(buffer, "%d,%d\n", ehealth.getbpm(), ehealth.getoxygensaturation()); serial.print(buffer); delay(500); }
Comments
Post a Comment