Tengo problemas para intentar obtener los valores de los puertos digitales de Arduino y establecer estos valores en una Escala de widgets de Python Tkinter.
Estoy usando Python y Arduino con Firmata. Puedo acceder a mi placa arduino con código python. Por ejemplo, en un widget de etiqueta, obtengo y configuro el valor del puerto analógico de Arduino en tiempo real en una etiqueta como en el siguiente código sin ningún problema:
import Tkinter
import pyfirmata
def onStartButtonPress():
while True:
if flag.get():
analogReadLabel.config(text=str(a0.read()))
analogReadLabel.update_idletasks()
top.update()
else:
break
board.exit()
top.destroy()
def onExitButtonPress():
flag.set(False)
port = 'COM7'
board = pyfirmata.Arduino(port)
it = pyfirmata.util.Iterator(board)
it.start()
a0 = board.get_pin('a:0:i')
top = Tkinter.Tk()
top.title("Reading Analog pins")
descriptionLabel = Tkinter.Label(top, text="Potentiometer input:- ")
descriptionLabel.grid(column=1, row=1)
analogReadLabel = Tkinter.Label(top, text="Press Start..")
analogReadLabel.grid(column=2, row=1)
flag = Tkinter.BooleanVar(top)
flag.set(True)
startButton = Tkinter.Button(top, text="Start", command=onStartButtonPress)
startButton.grid(column=1, row=2)
exitButton = Tkinter.Button(top, text="Exit", command=onExitButtonPress)
exitButton.grid(column=2, row=2)
top.mainloop()
Hasta este punto está bien y la GUI me muestra algo como:
Pero lo que intento hacer y no obtener es:
Aquí está el código:
import Tkinter
import pyfirmata
import serial;
def onStartButtonPress():
while True:
if flag.get():
analogReadLabel.config(text=str(d8.read()))
analogReadLabel1.config(text=str(d9.read()))
analogReadLabel2.config(text=str(d10.read()))
analogReadLabel.update_idletasks()
pos1 = d8.read()
if pos1 == True:
pos1 = int(pos1)
pos1 = 0
brightnessScale.set(pos1)
pos2 = d9.read()
if pos2 == True:
pos2 = int(pos2)
pos2 = 100
brightnessScale.set(pos2)
''' and so on '''
brightnessScale.update_idletasks()
top.update()
else:
break
board.exit()
top.destroy()
def onExitButtonPress():
flag.set(False)
port = 'COM7'
board = pyfirmata.Arduino(port)
it = pyfirmata.util.Iterator(board)
it.start()
a0 = board.get_pin('a:0:i')
d4 = board.get_pin('d:4:i')
d5 = board.get_pin('d:5:i')
d6 = board.get_pin('d:6:i')
d7 = board.get_pin('d:7:i')
d8 = board.get_pin('d:8:i')
d9 = board.get_pin('d:9:i')
d10 = board.get_pin('d:10:i')
top = Tkinter.Tk()
top.geometry("800x600")
top.title("Reading Analog pins")
descriptionLabel = Tkinter.Label(top, text="Potentiometer input:- ")
descriptionLabel.grid(column=1, row=1)
analogReadLabel = Tkinter.Label(top, text="Level 1")
analogReadLabel.grid(column=2, row=1)
analogReadLabel1 = Tkinter.Label(top, text="Level 2")
analogReadLabel1.grid(column=3, row=1)
analogReadLabel2 = Tkinter.Label(top, text="Level 3")
analogReadLabel2.grid(column=4, row=1)
brightnessScale = Tkinter.Scale(top, from_ = 500,
to = 0,
length = 500,
width = "30",
tickinterval = 50,
bg = "lightskyblue",
highlightcolor = "darkblue",
highlightbackground = "royalblue",
troughcolor = "darkblue",
state = Tkinter.DISABLED,
sliderlength = 50,
relief = "sunken",
label = "Volume do Reservatorio em %",
orient = Tkinter.VERTICAL)
brightnessScale.grid(column=1, row=5)
Tkinter.Label(top,text="Volume da Caixa em (%)").grid(column=1, row=6)
flag = Tkinter.BooleanVar(top)
flag.set(True)
startButton = Tkinter.Button(top, text="Start", command=onStartButtonPress)
startButton.grid(column=1, row=2)
exitButton = Tkinter.Button(top, text="Exit", command=onExitButtonPress)
exitButton.grid(column=2, row=2)
top.mainloop()
Para resumir: tengo conmutadores de láminas en cada puerto digital declarado en el código. Estos interruptores de láminas están normalmente en estado abierto, cuando coloco un campo magnético cerca de ellos, se cierra y obtengo un cambio en ese valor, como falso a verdadero. Lo que intento hacer es actualizar el widget de escala de Tkinter en tiempo real como las etiquetas, pero no lo entiendo.
¿Hay algún truco en el código de Python que pueda resolver mi problema? Debido a que investigué mucho en Internet y no pude hacerlo, como puede ver en la imagen 2 cuando cambia el estado del segundo pin digital, una etiqueta cambia a Verdadero, y en el código de escala esto corresponde al valor 100, pero todavía está en la marca 0.
Tampoco me siento cómodo con el uso del comando y los parámetros variables del widget de escala.
En resumen, quiero actualizar en tiempo real el widget de escala de Python Tkinter según los valores de los puertos digitales de arduino usando firmata.
Estoy usando Python 2.7
PD: para completar:
Este es mi código arduino (Sketch) sin firmata, que funciona como se esperaba.
int level;
int position;
void setup() {
pinMode(8, INPUT);
pinMode(9, INPUT);
pinMode(10, INPUT);
pinMode(11, INPUT);
pinMode(12, INPUT);
Serial.begin(9600); // ativa a porta serial
void loop() {
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
position = digitalRead(8);
if ( position == HIGH) {level=0;}
position = digitalRead(9);
if ( position == HIGH) {Level=100;}
position = digitalRead(10);
if ( position == HIGH) {level=200;}
position = digitalRead(11);
if ( position == HIGH) {level=300;}
position = digitalRead(12);
if ( position == HIGH) {level=400;}
Serial.println(level);
delay(500);
}
Lo que podría hacer también aquí es obtener estos valores a través de serial en Python y usarlos para actualizar la escala de esta manera, ¡pero no sé si en este método también funcionará!
Y lo que pensé en Python: pero todavía tengo mucho que aprender sobre algoritmos y estructuras de datos. Solo el pseudocódigo:
def setScaleValue():
while True:
if flag.get():
pos1 = d4.read()
if pos1 == True: #or 1
#Here is the problem i don't know for sure what comes in my digital port
#If is a True bool or a 1 as HIGH value from arduino
#And probably i don't know if it's possible to change the values of a scale in this way !!!
#or if i'm mistaken the Cast stuff in Python
pos1 = int(pos1)
pos1 = 0
brightnessScale.set(pos1)
pos2 = d8.read()
if pos2 == True:
pos2 = int(pos2)
pos2 = 100
brightnessScale.set(pos2)
brightnessScale.update_idletasks()
top.update()
else:
break
board.exit()
top.destroy()
return
d4 = board.get_pin('d:4:i')
d5 = board.get_pin('d:5:i')
d6 = board.get_pin('d:6:i')
d7 = board.get_pin('d:7:i')
d8 = board.get_pin('d:8:i')
brightnessScale = Tkinter.Scale(top, from_ = 500,
to = 0,
length = 500,
width = "30",
tickinterval = 50,
bg = "lightskyblue",
highlightcolor = "darkblue",
highlightbackground = "royalblue",
troughcolor = "darkblue",
state = Tkinter.DISABLED,
sliderlength = 50,
relief = "sunken",
label = "Volume do Reservatorio em %",
orient = Tkinter.VERTICAL)
brightnessScale.grid(column=1, row=5)
Tkinter.Label(top,text="Volume da Caixa em (%)").grid(column=1, row=6)
fuente
Respuestas:
en tu código:
Al agregar la línea de impresión, puede garantizar el valor y el tipo de variable.
Entonces, puede que tenga que adaptar su declaración if en consecuencia.
Tenga cuidado con lo que está haciendo con esas 2 líneas que afectan a posX, esto probablemente no sea lo que desea hacer antes de actualizar la escala.
fuente