Python 및 firmata를 사용하여 Arduino 포트에서 동적 Tkinter 위젯 스케일 업데이트


10

Arduino 디지털 포트 값을 가져 와서이 값을 Python Tkinter Widget Scale로 설정하는 데 문제가 있습니다.

Firmata와 함께 Python과 Arduino를 사용하고 있습니다. 파이썬 코드로 arduino 보드에 액세스 할 수 있습니다. 예를 들어 레이블 위젯에서 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는 다음과 같은 것을 보여줍니다.

아날로그 0에서 실시간 값을 읽는 Python Gui 인터페이스

그러나 내가하려고하고 얻는 것은 아닙니다 :

디지털 핀으로 스케일을 업데이트하려고하는 것

코드는 다음과 같습니다.

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 Scale Widget을 레이블로 업데이트하는 것이지만 얻지 못했습니다.

파이썬 코드에 내 문제를 해결할 수있는 트릭이 있습니까? 인터넷에서 많은 연구를 수행했지만 끝낼 수 없었으므로 두 번째 디지털 핀의 상태가 변경되고 레이블이 True로 변경되면 스케일 코드에서 값에 해당하는 이미지 2에서 볼 수 있듯이 100이지만 여전히 0 마크에 있습니다.

명령 사용법과 스케일 위젯의 변수 매개 변수에도 익숙하지 않습니다.

요컨대, firmata를 사용하여 arduino의 디지털 포트 값에 따라 실시간 파이썬 Tkinter 스케일 위젯을 업데이트하고 싶습니다.

파이썬 2.7을 사용하고 있습니다

PS : 완전성 :

이것은 firmata가없는 arduino 코드 (Sketch)이며 예상대로 작동합니다.

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

}

내가 여기서 할 수있는 일은 파이썬에서 직렬을 통해 이러한 값을 가져 와서이 방법으로 스케일을 업데이트하는 데 사용하지만이 방법으로 작동하는지 모르겠습니다!

그리고 파이썬에서 생각한 것 : 그러나 여전히 알고리즘과 데이터 구조에서 배울 것이 많습니다. 의사 코드 만 :

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 2016 년

코드가 실행될 때 중지 버튼을 클릭 할 수 있습니까?
Mert Gülsoy

답변:


-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 문을 적절히 조정해야 할 수도 있습니다.
posX에 영향을주는 2 줄로 수행중인 작업에 유의하십시오. 이는 스케일을 업데이트하기 전에 수행하고 싶지 않은 작업 일 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.