BromicAcid
International Hazard
Posts: 3244
Registered: 13-7-2003
Location: Wisconsin
Member Is Offline
Mood: Rock n' Roll
|
|
Help with Python program to control pump via electronic eye feedback
About a month ago I saw a paper on a continuous separating unit for a biphasic mixture. The supporting information can be found here:
http://pubs.acs.org/doi/abs/10.1021/ol301930h
Continuous Multiple Liquid–Liquid Separation: Diazotization of Amino Acids in Flow
Org. Lett., 2012, 14 (16), pp 4246–4249
Granted, without a subscription you cannot read the paper, just the abstract, but clicking the Supporting Info link in the upper right area allows you
to watch a video if it in action (pretty cool) as well as downloading the document that includes the code in Python to run the thing (also attached to
this post).
Essentially the program uses a web camera to take a photo of a float that lingers at the interface of the phases. It creates a high-contrast image
and adjusts a pump speed in order to keep the float stable.
Anyway, I don't know Python but I have learned enough to fix the code. As written I could not get it to run, it defined objects in the wrong order,
indentation and formatting had been lost, and although these are simple fixes, they took me somewhere in the neighborhood of 10 hours to implement
just to get it to where it is now (attached).
Anyway, where I am stuck is now after entering setup information the program takes the photo and allows me to define the area where the float is
located, after that however it tries to run the bit of code where it would try to control the float and I get this error:
TypeError: a float is required
I am doing all of this on my personal laptop as an extra curricular and unfortunately cannot reproduce it at home since the program does not let me
get past setup without something connected to a COM port but the error occurs following one of the calculations in the code below for NEWSPEED =.
<code>def adjustspeed(RATIO, PUMPIDENTITY): #method adjusts flow rate based on deviation of floater from intended area; can probably simplify
code with a generated list for pump identifiers
if int(config_dict[PUMPIDENTITY]) == 1:
ERROR = RATIO - 0.5
print "Bead %s\'s Relative Deviation from Interface = "%PUMPIDENTITY + str(ERROR)
NEWSPEED = min_max_speed((spd_dict[PUMPIDENTITY]+(spd_dict[PUMPIDENTITY]*ERROR*10)))
print 'Corrected pump %s\'s new speed to ='%PUMPIDENTITY + str(NEWSPEED)
ser_dict[PUMPIDENTITY].write('FLOW:%s \x0d'%str(round(NEWSPEED, 100)))
print 'Communication with pump %s was successful.'%PUMPIDENTITY
spd_dict[PUMPIDENTITY] = NEWSPEED
pass
if int(config_dict[PUMPIDENTITY]) == 2:
ERROR = 0.5 - RATIO
print "Bead %s\'s Relative Deviation from Interface = "%PUMPIDENTITY + str(ERROR)
NEWSPEED = min_max_speed((spd_dict[PUMPIDENTITY]+(spd_dict[PUMPIDENTITY]*ERROR*10)))
print 'Corrected pump %s\'s new speed to ='%PUMPIDENTITY + str(NEWSPEED)
ser_dict[PUMPIDENTITY].write('FLOW:%s \x0d'%str(round(NEWSPEED, 100)))
print 'Communication with pump %s was successful.'%PUMPIDENTITY
spd_dict[PUMPIDENTITY] = NEWSPEED
pass
if int(config_dict[PUMPIDENTITY]) != 1 and int(config_dict[PUMPIDENTITY]) != 2:
print "Error! Configuration not defined!"
pass
else:
pass
def poscalc(refpt1, refpt2, scanpt): #method defines a percentage based on deviation from scanpoint from set reference points
PERCENT = (float(1)-(float(scanpt[1])-float(refpt2))/(float(refpt1)-float(refpt2)))
return PERCENT</code>
I do not know enough about python to actually know what I am doing so I have just been putting random float(x) = ... type things there but I know it's
not right. Hopefully someone can see this and give me some suggestions to try. I know that work related subjects are frowned upon but this is not
strictly work related so much as using work resources and if I do get a working copy of the code it will be up on SM for anyone to use from that
point.
Edit: Amusingly enough, when I started getting this error today I had no clue that a float error was something built into the program. Since the
actual program itself controls the position of a physical float between the phases I spent about 45 minutes trying to find something in the code
itself where float was not defined or where the text had been hidden and was displaying it to tell me that it could not find the 'float' that I had to
define during the setup steps.
Attachment: ol301930h_si_001.pdf (8.6MB) This file has been downloaded 808 times
Attachment: EDIT phases revised.py (19kB) This file has been downloaded 673 times
[Edited on 6/9/2015 by BromicAcid]
|
|
smaerd
International Hazard
Posts: 1262
Registered: 23-1-2010
Member Is Offline
Mood: hmm...
|
|
BromicAcid - It sounds like there is some kind of casting error. Hehehe, no floats are a data type which store decimal places. It's defintiely
confusing that you are using a float (physical mechanism) and have an error involving a float though.
So the line NEWSPEED = has the error. I wish I had a webcam and everything set up to actually debug this. Something tells me its an error that arose
by using a different version of python then the authors used.
The line has 1 function call. It's not clear where exactly the type error is popping up,
did you try,
NEWSPEED = float(min_max_speed((spd_dict[PUMPIDENTITY]+(spd_dict[PUMPIDENTITY]*ERROR*10))))
or
NEWSPEED = min_max_speed((float(spd_dict[PUMPIDENTITY])+float((spd_dict[PUMPIDENTITY])*ERROR*10))))
or it would really be a kicker if it was this
NEWSPEED = min_max_speed(float(spd_dict[PUMPIDENTITY])+float(spd_dict[PUMPIDENTITY])*ERROR*10.0))))
I might install python to debug this if either of those does not solve the issue. Everything else looks essentially sound.
[Edited on 9-6-2015 by smaerd]
|
|
mayko
International Hazard
Posts: 1218
Registered: 17-1-2013
Location: Carrboro, NC
Member Is Offline
Mood: anomalous (Euclid class)
|
|
So, when I parse this:
NEWSPEED = min_max_speed(
(spd_dict[PUMPIDENTITY]+(spd_dict[PUMPIDENTITY]*ERROR*10))
)
That is to say, the function min_max_speed is expecting a floating point decimal but is in fact receiving a tuple containing a single number. (Tuples
are a sort of specialized list which are denoted in python with parentheses.)
Try this instead:
NEWSPEED = min_max_speed(
float(spd_dict[PUMPIDENTITY]+(spd_dict[PUMPIDENTITY]*ERROR*10))
)
The variables multiplied inside are likely to output a floating point anyway, but the float() function will guarantee that the type matches, which can
be important.
ED: on doublechecking, min_max_speed() 's return command is only called in the else branch. if SPEEDINPUT > 100, the function returns None, which
is not a float!
[Edited on 9-6-2015 by mayko]
al-khemie is not a terrorist organization
"Chemicals, chemicals... I need chemicals!" - George Hayduke
"Wubbalubba dub-dub!" - Rick Sanchez
|
|
mayko
International Hazard
Posts: 1218
Registered: 17-1-2013
Location: Carrboro, NC
Member Is Offline
Mood: anomalous (Euclid class)
|
|
try this:
Code: |
def min_max_speed(SPEEDINPUT):
if SPEEDINPUT > 1500:
SPEEDINPUT = 1500
elif SPEEDINPUT < 100:
SPEEDINPUT = 100
return SPEEDINPUT
|
[Edited on 9-6-2015 by mayko]
al-khemie is not a terrorist organization
"Chemicals, chemicals... I need chemicals!" - George Hayduke
"Wubbalubba dub-dub!" - Rick Sanchez
|
|
BromicAcid
International Hazard
Posts: 3244
Registered: 13-7-2003
Location: Wisconsin
Member Is Offline
Mood: Rock n' Roll
|
|
Thank you both for your suggestions, I will give them a try tomorrow or the next day and let you know how they work.
|
|
BromicAcid
International Hazard
Posts: 3244
Registered: 13-7-2003
Location: Wisconsin
Member Is Offline
Mood: Rock n' Roll
|
|
Mayko, I think you got it. My issue was that I was using a tack on the wall to mimic the location of a float, since it never moved it caused the
issue you pointed out where the output was not a number causing the error. Once I changed the code as you suggested it seems to be working fine.
Weather or not it controls a pump at this point is another story, I have it hooked to my GPS right now since it uses a serial connection and allows me
to get the program up and running by thinking it is talking to a pump. Will upload the complete code it it works, here is a picture of the thing
running. I am using a highlighter to mimic the float, image on the left is the highlighter and on the right is the high-contrast image that it
generates, the program is running in the background and is adjusting the pump up and down as I move it. Pretty slick.
|
|
mayko
International Hazard
Posts: 1218
Registered: 17-1-2013
Location: Carrboro, NC
Member Is Offline
Mood: anomalous (Euclid class)
|
|
Glad I could help! The authors appear to have made some... interesting coding decisions.
al-khemie is not a terrorist organization
"Chemicals, chemicals... I need chemicals!" - George Hayduke
"Wubbalubba dub-dub!" - Rick Sanchez
|
|
BromicAcid
International Hazard
Posts: 3244
Registered: 13-7-2003
Location: Wisconsin
Member Is Offline
Mood: Rock n' Roll
|
|
So, as promised the completed script is attached to this file as it currently stands. When it is running it will first check for a web cam, if there
is none attached it will shut down without warning. Then it will ask for the number of pumps that you want to control. After that it asks for the
COM port of the pump, if you put in a number where there is not a serial device connected it will exit without any warnings. For my development work
I connected my portable GPS which talks in old serial. After that you have to select the area where your float is and then the area of the tank.
After that it's off to the races. There are prompts for most of this but I thought I would provide an overview. There are quite a few modules that
need to be downloaded for Python to get it to work but I do not have a comprehensive list.
Don't worry, it will let you know what you're missing each time with a warning saying what it cannot find and it will not let you go forward.
I am also attaching a screen shot of the output generated from the program while it is trying to control the pump. And that gets me to where I am
right now and the next post of this project:
Using a computer to control a pump/motor using a Digital Potentiometer
Now that the digital tracking side is down, I cannot control the pump that I have
Hopefully I'll continue to have luck moving this project along but no matter what a workable version of this program has at least been produced.
Attachment: Serial Edit phases revised.py (19kB) This file has been downloaded 683 times
|
|
Texium
|
Thread Moved 22-11-2023 at 20:03 |