Динамически обновить масштаб виджета Tkinter из портов Arduino с помощью python и firmata
У меня возникли проблемы с получением значений цифровых портов Arduino и установкой этих значений в шкалу виджетов Python Tkinter.
Я использую Python и Arduino с Firmata. Я могу получить доступ к своей плате arduino с помощью кода python. Например, в виджете label я получаю и устанавливаю значение аналогового порта Arduino в режиме реального времени на метку, как в следующем коде, без каких-либо проблем:
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()
До этого момента все было в порядке, и графический интерфейс показывал мне что-то вроде:
Но то, что я пытаюсь сделать и не получаю:
Вот код:
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()
Подводя итог: у меня есть герконы в каждом цифровом порту, объявленном в коде. Эти герконы обычно находятся в разомкнутом состоянии, когда я помещаю рядом с ними магнитное поле, оно замыкается, и я получаю изменение этого значения от False до True. То, что я пытаюсь сделать, это обновить виджет шкалы Tkinter в режиме реального времени в качестве меток, но я его не получаю.
Есть ли какой-нибудь трюк в коде python, который может решить мою проблему? Поскольку я провел много исследований в Интернете и не смог этого сделать, как вы можете видеть на рисунке 2, когда состояние второго цифрового контакта изменяется, метка меняется на True, а в коде шкалы это соответствует значению 100, но оно все еще находится на отметке 0.
Мне также не нравится использование команд и переменных параметров виджета scale.
Короче говоря, я хочу обновить в реальном времени виджет шкалы python Tkinter в соответствии со значениями цифровых портов от arduino с помощью firmata.
Я использую Python 2.7
PS: для полноты картины:
Это мой код arduino (скетч) без firmata, который работает так, как ожидалось.
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);
}
Что я мог бы сделать также здесь , так это получить эти значения через serial в python и использовать их для обновления шкалы таким образом, но я не знаю, будет ли этот метод работать!
И что я думал в Python: Но мне еще многое предстоит узнать об алгоритмах и структурах данных. Просто Псевдокод:
def setScaleValue():
while True:
if flag.get():
pos1 = d4.read()
if pos1 == True: #or 1
# Вот в чем проблема: я не знаю точно, что входит в мой цифровой порт.
#If - это True bool или 1 как ВЫСОКОЕ значение от arduino
#И, вероятно, я не знаю, можно ли изменить значения шкалы таким образом!!!
#или, если я ошибаюсь, материал Cast в 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)
@Vinicius Biscolla, 👍12
Обсуждение1 ответ
в вашем коде:
pos2 = d8.read()
print("pos2 is {} type {}".format(pos2, type(pos2))) # Таким образом, вы будете знать тип var, который вы получаете на консоли
if posX == True:
posX = int(posX) # Затем вы приводите к целому числу
posX = 100 # Вы отбрасываете значение pos2, устанавливая его равным 100
brightnessScale.set(posX) # Вы всегда устанавливаете шкалу на значение 100
Добавив строку печати, вы можете обеспечить значение и тип переменной.
Затем вам, возможно, придется соответствующим образом адаптировать свое утверждение if.
Остерегайтесь того, что вы делаете с этими 2 линиями, влияющими на PosX, это, вероятно, не то, что вы хотите сделать перед обновлением шкалы.
- Как работать с аналоговыми показаниями с помощью RPi и Firmata?
- Отправка значения с одного Arduino на другой
- Последовательная связь Arduino с Python: отправка массива
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- Отправьте несколько значений int из Python в Arduino, используя pySerial
- Сброс последовательного порта Arduino в последовательном мониторе и Python
- Колебания показаний датчика температуры LM35 (+- 5°C) с Arduino UNO
- Защита вашего компьютера от глупых (arduino) ошибок
ваш третий файл имеет неправильную форму, def setScaleValue(): не определен должным образом, вам нужно изменить уровень отступа после определения функции., @esoterik
Когда ваш код будет запущен, сможете ли вы нажать на кнопку "Стоп"?, @Mert Gülsoy