Hallo zusammen,
ich versuche gerade meine ersten Schritte in Kivy, Python und PyFirmata.
Was geht: mit einem Button in der GUI eine LED am Arduino anzusteuern.
Was nicht geht: mit einem Button am Arduino den zustand eines Buttons in der GUI zu ändern.
Da ich mein eigentliches Projekt bereits mit main.py und main.kv begonnen habe, habe ich zum testen das rpi-kivy-screen-master runtergeladen. Dies besteht aber nur aus der main.py in der mit build die GUI direkt aufgebaut wird. Das meiste konnte ich umschreiben, nur beim abfragen des board.digital[23].read() Zustands und damit das ändern des Zustands von Button 'input' scheitere ich total...
Hier die main.py
[Codebox=python file=main.py]
import kivy
from kivy.app import App
from kivy import platform
from kivy.uix.button import Button
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import *
from kivy.uix.image import Image
from kivy.lang import Builder
from kivy.properties import ObjectProperty, StringProperty
from kivy.clock import Clock
from time import sleep
import serial
from pyfirmata import ArduinoMega, util
from pyfirmata.util import Iterator
from pyfirmata import SERVO
from pyfirmata import INPUT
from pyfirmata import OUTPUT
if platform == 'linux':
board = ArduinoMega('/dev/tty.usbserial-A6008rIF') # please check on wich serial port talks the Arduino
if platform == 'win':
board = ArduinoMega('COM5') # please check on wich serial port talks the Arduino
#for now, use a global for blink speed (better implementation TBD):
speed = 1.0
it = Iterator(board)
it.start()
# Set up GPIO:
board.digital[22].mode = OUTPUT
board.digital[23].mode = INPUT
board.digital[23].enable_reporting()
# Make the background violet:
Builder.load_string('''
<RootWidget>
canvas.before:
Color:
rgba: 1, .3, .8, .5
Rectangle:
pos: self.pos
size: self.size
''')
# Modify the Button Class to update according to board.digital input:
class InputButton(Button):
def update(self, dt):
if board.digital[23].read() == 1:
print ("button on")
self.state = 'normal'
else:
print ("button off")
self.state = 'down'
class RootWidget(FloatLayout):
'''This is the class representing your root widget.
By default it is inherited from FloatLayout,
you can use any other layout/widget depending on your usage.
'''
# debugging code to print out all my objects when I hit the switch
level = 1
def print_tree(self,my_obj):
print str(self.level) + " "*self.level + str(my_obj)
for child in (my_obj.children):
self.level += 1
self.print_tree(child)
self.level -= 1
# This callback will be bound to the LED toggle button:
def press(self):
print ("LED on")
board.digital[22].write(1)
def release(self):
print ("LED off")
board.digital[22].write(0)
pass
class MainApp(App):
def build(self):
## Original Code ##
## Instantiate the first UI object (the GPIO input indicator):
#>>> #inputDisplay = InputButton(text="Input")
## Schedule the update of the state of the GPIO input button:
#>>> #Clock.schedule_interval(inputDisplay.update, 1.0/10.0)
## Create the rest of the UI objects (and bind them to callbacks, if necessary):
#outputControl = ToggleButton(text="LED")
#outputControl.bind(on_press=press_callback)
## Add the UI elements to the layout:
#>>> #layout.add_widget(inputDisplay)
#layout.add_widget(outputControl)
print('build running')
return RootWidget()
if __name__ == '__main__':
MainApp().run()
[/Codebox]
Und hier die main.kv
[Codebox=python file=main.kv]
<RootWidget>:
# this is the rule for your root widget, defining it's look and feel.
height: 110.0
width: 190.0
Button: # outputControl
id: output
text: 'LED'
height: 50.0
width: 50.0
size_hint_x: 0.0
size_hint_y: 0.0
x: 30.0 # 0 = left to nn = right
y: 30.0 # 0 = bottom to nn = top
on_press: root.press()
on_release: root.release()
Button: # inputDisplay
id: input
text: 'Input'
height: 50.0
width: 50.0
size_hint_x: 0.0
size_hint_y: 0.0
x: 110.0
y: 30.0
[/Codebox]
Gruß
Thilo
Kivy PyFirmata Problem
Ich denke ich habe eine Lösung gefunden, allerdings weiß ich grad absolut nicht wie ich diese in meinen Code einbinden muß...
Hier der Link: Updating widget content from a items list
Gruß
Thilo
Hier der Link: Updating widget content from a items list
Gruß
Thilo
Da ich bei den unzähligen Versuchen immer wieder die Meldug "'float' object has no attribute 'ids'" bekomme, habe ich in der class RootWidget(FloatLayout) noch
eingebaut um mir die ids im RootWidget auflisten zu lassen.
Ergebnis:
Ich versteh momentan echt nicht wo und wie ich
und
im main.py einbauen muß, damit sich der Status des Buttons mit der ID in_button ändert wenn sich der Wert von board.digital[23].read() ändert???
Die Befehle
funktionieren...
hier nochmal die beiden Programmcodes, main.py:
und main.kv:
Gruß
Thilo
Code: Alles auswählen
...
class RootWidget(FloatLayout):
...
def __init__(self, *args, **kwargs):
super(RootWidget, self).__init__(*args, **kwargs)
print 'rootwidget ids:', self.ids
...
Ergebnis:
Code: Alles auswählen
rootwidget ids: {'output': <WeakProxy to <kivy.uix.button.Button object at 0x023C19D0>>, 'in_button': <WeakProxy to <kivy.uix.button.Button object at 0x029848B8>>}
Code: Alles auswählen
self.ids.in_button.state = 'down'
Code: Alles auswählen
self.ids.in_button.state = 'normal'
Die Befehle
Code: Alles auswählen
...
print ("button on")
... und ...
print ("button off")
...
hier nochmal die beiden Programmcodes, main.py:
Code: Alles auswählen
import kivy
from kivy.app import App
from kivy import platform
from kivy.uix.button import Button
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import *
from kivy.uix.image import Image
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.properties import ObjectProperty, StringProperty
from kivy.clock import Clock
from time import sleep
import serial
from pyfirmata import ArduinoMega, util
from pyfirmata.util import Iterator
from pyfirmata import SERVO
from pyfirmata import INPUT
from pyfirmata import OUTPUT
if platform == 'linux':
board = ArduinoMega('/dev/tty.usbserial-A6008rIF') # please check on wich serial port talks the Arduino
if platform == 'win':
board = ArduinoMega('COM5') # please check on wich serial port talks the Arduino
#for now, use a global for blink speed (better implementation TBD):
speed = 1.0
it = Iterator(board)
it.start()
# Set up GPIO:
board.digital[22].mode = OUTPUT
board.digital[23].mode = INPUT
board.digital[23].enable_reporting()
# Make the background violet:
Builder.load_string('''
<RootWidget>
canvas.before:
Color:
rgba: 1, .3, .8, .5
Rectangle:
pos: self.pos
size: self.size
''')
class RootWidget(FloatLayout):
'''This is the class representing your root widget.
By default it is inherited from FloatLayout,
you can use any other layout/widget depending on your usage.
'''
# debugging code to print out all my objects when I hit the switch
level = 1
def print_tree(self,my_obj):
print str(self.level) + " "*self.level + str(my_obj)
for child in (my_obj.children):
self.level += 1
self.print_tree(child)
self.level -= 1
def __init__(self, *args, **kwargs):
super(RootWidget, self).__init__(*args, **kwargs)
print 'rootwidget ids:', self.ids
# = rootwidget ids: {'output': <WeakProxy to <kivy.uix.button.Button object at 0x023C19D0>>,
# 'in_button': <WeakProxy to <kivy.uix.button.Button object at 0x029848B8>>}
# This callback will be bound to the LED toggle button:
def press(self):
print ("LED on")
board.digital[22].write(1)
def release(self):
print ("LED off")
board.digital[22].write(0)
def in_button(self):
if board.digital[23].read() == 1:
print ("button on")
#self.ids.in_button.state = 'down'
else:
print ("button off")
#self.ids.in_button.state = 'normal'
pass
class MainApp(App):
def build(self):
## Original Code ##
## Instantiate the first UI object (the GPIO input indicator):
#>>> #inputDisplay = InputButton(text="Input")
## Schedule the update of the state of the GPIO input button:
#>>> #Clock.schedule_interval(inputDisplay.update, 1.0/10.0)
## Create the rest of the UI objects (and bind them to callbacks, if necessary):
#outputControl = ToggleButton(text="LED")
#outputControl.bind(on_press=press_callback)
## Add the UI elements to the layout:
#>>> #layout.add_widget(inputDisplay)
#layout.add_widget(outputControl)
Clock.schedule_interval(RootWidget.in_button, 1.0/4.0)
print('build running')
return RootWidget()
if __name__ == '__main__':
MainApp().run()
Code: Alles auswählen
<RootWidget>:
# this is the rule for your root widget, defining it's look and feel.
height: 110.0
width: 190.0
#in_button: in_button
Button: # outputControl
id: output
text: 'LED'
height: 50.0
width: 50.0
size_hint_x: 0.0
size_hint_y: 0.0
x: 30.0 # 0 = left to nn = right
y: 30.0 # 0 = bottom to nn = top
on_press: root.press()
on_release: root.release()
Button: # inputDisplay
id: in_button
text: 'Input'
height: 50.0
width: 50.0
size_hint_x: 0.0
size_hint_y: 0.0
x: 110.0
y: 30.0
Thilo