Оновіть динамічно шкала віджетів Tkinter від Arduino Ports за допомогою python та firmata


10

У мене виникають проблеми при спробі отримати значення цифрових портів Arduino і встановити ці значення в масштаб віджетів Python Tkinter.

Я використовую Python та Arduino з Firmata. Я можу отримати доступ до своєї ардуїнської дошки з кодом python. Наприклад, у віджеті етикетки я отримую і встановлюю значення аналогового порту 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()

До цього моменту це нормально, і GUI показує мені щось на кшталт:

Інтерфейс Python Gui зчитування значення в реальному часі з аналога 0

Але те, що я намагаюся зробити, а не отримую:

Що я намагаюся оновити масштаб цифровими штифтами

Ось код:

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 to True. Що я намагаюся зробити, це оновити віджет масштабу Tkinter в режимі реального часу як мітки, але я його не отримую.

Чи є якийсь трюк у python-коді, який може вирішити мою проблему? Оскільки я провів багато досліджень в Інтернеті і мені не вдалося зробити це, як ви бачите на зображенні 2, коли стан другого цифрового штифта змінюється, мітка змінюється на True, а в коді шкали це відповідає значенню 100, але це все ще на позначці 0.

Мені не комфортно також використання команди та змінних параметрів віджету масштабу.

Коротше кажучи, я хочу оновити віджет масштабу пітона Tkinter в режимі реального часу відповідно до значень цифрових портів від arduino за допомогою firmata.

Я використовую Python 2.7

PS: для повноти:

Це мій ардуїно-код (ескіз) без фірматів, який працює як слід.

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 
        #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)

ваш третій файл неправильно сформований, def setScaleValue (): неправильно визначений, вам потрібно змінити рівень відступу після визначення функції.
esoterik

Коли ваш код працює, чи зможете ви натиснути кнопку зупинки?
Мерт Гюлсой

Відповіді:


-1

у вашому коді:

pos2 = d8.read()
print("pos2 is {} type {}".format(pos2, type(pos2)))  # This way, you'll know the var type you're getting on the console
    if posX == True:
        posX = int(posX)          # You then cast to an integer
        posX = 100                # You discard pos2 value by setting it to 100
        brightnessScale.set(posX) # You set the scale always to value 100

Додавши лінію друку, ви можете забезпечити значення та тип змінної.
Тоді вам, можливо, доведеться адаптувати свою заяву if відповідно.
Остерігайтеся того, що ви робите тоді, коли ті 2 рядки, що впливають на posX, це, мабуть, не те, що ви хочете зробити перед оновленням шкали.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.