Sciencemadness Discussion Board
Not logged in [Login ]
Go To Bottom

Printable Version  
Author: Subject: Help with Python program to control pump via electronic eye feedback
BromicAcid
International Hazard
*****




Posts: 3244
Registered: 13-7-2003
Location: Wisconsin
Member Is Offline

Mood: Rock n' Roll

[*] posted on 9-6-2015 at 13:40
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]




Shamelessly plugging my attempts at writing fiction: http://www.robvincent.org
View user's profile Visit user's homepage View All Posts By User
smaerd
International Hazard
*****




Posts: 1262
Registered: 23-1-2010
Member Is Offline

Mood: hmm...

[*] posted on 9-6-2015 at 14:25


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]




View user's profile View All Posts By User
mayko
International Hazard
*****




Posts: 1218
Registered: 17-1-2013
Location: Carrboro, NC
Member Is Offline

Mood: anomalous (Euclid class)

[*] posted on 9-6-2015 at 14:25


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
View user's profile Visit user's homepage View All Posts By User
mayko
International Hazard
*****




Posts: 1218
Registered: 17-1-2013
Location: Carrboro, NC
Member Is Offline

Mood: anomalous (Euclid class)

[*] posted on 9-6-2015 at 14:46


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
View user's profile Visit user's homepage View All Posts By User
BromicAcid
International Hazard
*****




Posts: 3244
Registered: 13-7-2003
Location: Wisconsin
Member Is Offline

Mood: Rock n' Roll

[*] posted on 9-6-2015 at 14:54


Thank you both for your suggestions, I will give them a try tomorrow or the next day and let you know how they work.



Shamelessly plugging my attempts at writing fiction: http://www.robvincent.org
View user's profile Visit user's homepage View All Posts By User
BromicAcid
International Hazard
*****




Posts: 3244
Registered: 13-7-2003
Location: Wisconsin
Member Is Offline

Mood: Rock n' Roll

[*] posted on 9-6-2015 at 19:19


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.

programrunning.JPG - 256kB




Shamelessly plugging my attempts at writing fiction: http://www.robvincent.org
View user's profile Visit user's homepage View All Posts By User
mayko
International Hazard
*****




Posts: 1218
Registered: 17-1-2013
Location: Carrboro, NC
Member Is Offline

Mood: anomalous (Euclid class)

[*] posted on 10-6-2015 at 11:33


Glad I could help! The authors appear to have made some... interesting coding decisions. :P



al-khemie is not a terrorist organization
"Chemicals, chemicals... I need chemicals!" - George Hayduke
"Wubbalubba dub-dub!" - Rick Sanchez
View user's profile Visit user's homepage View All Posts By User
BromicAcid
International Hazard
*****




Posts: 3244
Registered: 13-7-2003
Location: Wisconsin
Member Is Offline

Mood: Rock n' Roll

[*] posted on 8-2-2016 at 16:30


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.

DSC01349.JPG - 301kB

Attachment: Serial Edit phases revised.py (19kB)
This file has been downloaded 683 times




Shamelessly plugging my attempts at writing fiction: http://www.robvincent.org
View user's profile Visit user's homepage View All Posts By User
Texium
Administrator
Thread Moved
22-11-2023 at 20:03

  Go To Top