eapi
 Alle Klassen Funktionen
hw.py
1 # -*- coding: utf-8 -*-
2 
3 """Ein Modul für die Verwendung des Eingabe-Ausgabe-Moduls für den Raspberry
4 Pi.
5 
6 Es besteht aus der Hauptklasse EAModul, die für die Ansteuerung vorgesehen
7 ist. Hierfür existieren verschiedene Demos, die von der Kommandozeile aus
8 aufgerufen werden können:
9 
10  $ python3 -m eapi.hw
11 
12 Mit Hilfe der Klasse DimmbaresEAModul können die LEDs auf dem Board gedimmt
13 werden.
14 
15 Das folgende Beispiel zeigt eine mögliche Verwendung:
16 
17 >>> from eapi.hw import EAModul
18 >>> ea = EAModul()
19 
20 Nun können wir ein paar LEDs anschalten
21 
22 >>> ea.schalte_led(EAModul.LED_ROT, 1)
23 >>> ea.schalte_led(EAModul.LED_GELB, 1)
24 >>> ea.schalte_led(EAModul.LED_GRUEN, 1)
25 
26 und wieder ausschalten
27 
28 >>> ea.schalte_led(EAModul.LED_ROT, 0)
29 >>> ea.schalte_led(EAModul.LED_GELB, 0)
30 >>> ea.schalte_led(EAModul.LED_GRUEN, 0)
31 
32 Der Wert des Tasters kann auch abgefragt werden.
33 
34 >>> taster0_gedrueckt = ea.taster_gedrueckt(0)
35 >>> taster1_gedrueckt = ea.taster_gedrueckt(1)
36 
37 Zum Schluss fahren wir das Modul wieder herunter:
38 
39 >>> ea.cleanup()
40 
41 Schaue in die Dokumentation der anderen Methoden, um weitere
42 Quelltextbeispiele zu finden.
43 """
44 
45 # Versuche, die Bibliothek für GPIO-Pins zu laden. Wenn dies scheitert, wird
46 # ein Dummy verwendet.
47 try:
48  import RPi.GPIO as GPIO
49 except ImportError:
50  import eapi.GPIODummy as GPIO
51 
52 
53 class EAModul:
54  """Die Klasse EAModul hilft bei der Ansteuerung eines Eingabe-Ausgabe-Moduls
55  für den Raspberry Pi. Es besteht aus drei LED und zwei Tastern."""
56 
57  LED_ROT = 0
58  LED_GELB = 1
59  LED_GRUEN = 2
60 
61  def __init__(self, pin_taster0=29, pin_taster1=31,
62  pin_led_rot=33, pin_led_gelb=35, pin_led_gruen=37):
63  """
64  Das Modul wird mit den gegebenen Pins konfiguriert.
65 
66  Pins der LEDs werden als Ausgänge und Pins der Taster als Eingänge
67  konfiguriert. Wenn keine PINS angegeben werden, werden die PINs
68  oberhalb des GND Pins links unten verwendet.
69 
70  >>> from eapi.hw import EAModul
71 
72  Wenn keine Werte angegeben werden, werden die Standard-Pins verwendet.
73 
74  >>> ea1 = EAModul()
75  >>> ea1.cleanup()
76 
77  Bei einer abweichenden Verdrahtung können die Pins angegeben werden.
78 
79  >>> ea2 = EAModul(29, 31, 33, 35, 37)
80 
81  Um den Quelltext übersichtlicher zu gestalten, können die Pins
82  direkt bezeichnet werden.
83 
84  >>> ea2 = EAModul(pin_taster0=29, pin_taster1=31, pin_led_rot=33,
85  ... pin_led_gelb=35, pin_led_gruen=37)
86  >>> ea2.cleanup()
87  """
88  GPIO.setmode(GPIO.BOARD)
89 
90  self._taster = [pin_taster0, pin_taster1]
91  GPIO.setup(self._taster, GPIO.IN)
92 
93  self._leds = [pin_led_rot, pin_led_gelb, pin_led_gruen]
94  GPIO.setup(self._leds, GPIO.OUT)
95 
96  # Observer initialisieren
97  self.__observer_leds = dict()
98  self.__observer_leds[EAModul.LED_ROT] = []
99  self.__observer_leds[EAModul.LED_GELB] = []
100  self.__observer_leds[EAModul.LED_GRUEN] = []
101 
102  def led_event_registrieren(self, led_farbe, methode):
103  """Registriert eine Methode, die ausgeführt wird, sobald die
104  entsprechende LED ihren Wert ändert.
105 
106  Die Methode wird über alle Veränderungen an der LED informiert. Dazu
107  wird die übergebene Methode aufgerufen.
108 
109  >>> from eapi.hw import EAModul
110 
111  >>> def update_rote_led(neuer_wert):
112  ... print("update: Status der roten LED hat sich geändert.")
113  ... print("Neuer Wert:", neuer_wert)
114 
115  >>> ea = EAModul()
116  >>> ea.led_event_registrieren(EAModul.LED_ROT, update_rote_led)
117 
118  Nun wird die Update-Methode aufgerufen, sobald sich der Wert der LED
119  ändert.
120 
121  >>> ea.schalte_led(EAModul.LED_ROT, 1)
122  update: Status der roten LED hat sich geändert.
123  Neuer Wert: 1
124 
125  >>> ea.schalte_led(EAModul.LED_ROT, 0)
126  update: Status der roten LED hat sich geändert.
127  Neuer Wert: 0
128 
129  >>> ea.cleanup()
130  """
131  self.__observer_leds[led_farbe].append(methode)
132 
133  def _notify_leds(self, led_farbe, neuer_wert):
134  """Alle registrierten Beobachter werden über eine Änderung
135  informiert."""
136 
137  for methode in self.__observer_leds[led_farbe]:
138  methode(neuer_wert)
139 
140  def taster_gedrueckt(self, num=0):
141  """
142  Liest den Wert des Tasters mit der gegebenen Nummer aus und gibt den
143  Wert zurück. Eine einfache Verwendung könnte wie folgt aussehen:
144 
145  >>> from eapi.hw import EAModul
146  >>> import time
147 
148  >>> ea_modul = EAModul()
149  >>> while not ea_modul.taster_gedrueckt(1):
150  ... ea_modul.schalte_led(EAModul.LED_ROT, 1)
151  ... time.sleep(0.2)
152  ... ea_modul.schalte_led(EAModul.LED_ROT, 0)
153  >>> ea_modul.cleanup()
154  """
155  if 0 <= num < len(self._taster):
156  if GPIO.input(self._taster[num]):
157  return True
158  else:
159  return False
160  else:
161  raise ValueError(
162  "Falsche Tasternummer. Muss zwischen 0 und {ln} liegen.".format(
163  ln=len(self._taster) - 1))
164 
165  ''' TODO testen und Kommentar entfernen
166  def toggle_led(self, led_farbe):
167  """Wechselt den Zustand der angegebenen LED von an nach aus - oder umgekehrt.
168 
169  Schaltet die LED aus, wenn sie an war, oder an, wenn sie aus war.
170 
171  >>> from eapi.hw import EAModul
172  >>> ea = EAModul()
173  >>> ea.schalte_led(EAModul.LED_ROT, 1)
174 
175  Nun ist die rote LED an.
176 
177  >>> ea.toggle_led(EAModul.LED_ROT)
178 
179  Nun ist die LED wieder aus.
180 
181  >>> ea.toggle_led(EAModul.LED_ROT)
182 
183  Nun ist sie wieder an.
184  """
185  # TODO noch nicht getestet.
186  alter_wert = GPIO.input(self._leds[led_farbe])
187  self.schalte_led(led_farbe, 1 - alter_wert)
188  '''
189 
190  def schalte_led(self, led_farbe, an_aus):
191  """Schalte die LED mit der gegebenen Nummer ein (1) oder aus (0).
192 
193  Der Wert für led_farbe ist LED_ROT, LED_GELB oder LED_GRUEN.
194 
195  Eine einfache Verwendung könnte wie folgt aussehen:
196 
197  >>> from eapi.hw import EAModul
198 
199  >>> ea_modul = EAModul()
200  >>> ea_modul.schalte_led(EAModul.LED_ROT, 1)
201  >>> ea_modul.schalte_led(EAModul.LED_GELB, 0)
202  >>> ea_modul.schalte_led(EAModul.LED_GRUEN, 1)
203  >>> ea_modul.cleanup()
204  """
205 
206  if 0 <= led_farbe < len(self._leds):
207  if an_aus == 1 or an_aus == 0:
208  GPIO.output(self._leds[led_farbe], an_aus)
209  self._notify_leds(led_farbe, an_aus)
210  else:
211  raise ValueError("Wert für an_aus muss 0 oder 1 sein.")
212  else:
213  raise ValueError("Falsche LED-Farbe.")
214 
215  def schalte_leds(self, rot_anaus, gelb_anaus, gruen_anaus):
216  """Schalte alle drei LEDs zu gleichen Zeit an oder aus.
217 
218  >>> from eapi.hw import EAModul
219 
220  >>> ea_modul = EAModul()
221  >>> ea_modul.schalte_leds(True, False, True)
222  >>> ea_modul.cleanup()"""
223 
224  self.schalte_led(EAModul.LED_ROT, rot_anaus)
225  self.schalte_led(EAModul.LED_GELB, gelb_anaus)
226  self.schalte_led(EAModul.LED_GRUEN, gruen_anaus)
227 
228  def taster_event_registrieren(self, taster_nr, methode):
229  """Registriere eine Methode, die bei Betätigung eines Tasters
230  ausgeführt wird.
231 
232  Die übergebene Methode muss ein Argument haben und wird mit der
233  Pin-Nur des Tasters aufgerufen, sobald der Taster gedrückt
234  wird. Eine einfache Verwendung könnte wie folgt aussehen:
235 
236  >>> def taster0_gedrueckt(pin):
237  ... print("Taster 0 wurde gedrückt.")
238 
239  >>> ea_modul = EAModul()
240  >>> ea_modul.taster_event_registrieren(0, taster0_gedrueckt)
241  >>> ea_modul.cleanup()
242  """
243  # TODO vereinheitlichen mit led_event_reg.: Liste mit Methoden
244  # zusätzlich zwei Methoden, eine für jeden Taster, die bei Event
245  # aufgerugen werden.
246 
247  if taster_nr < 0 or taster_nr >= len(self._taster):
248  raise ValueError("Falsche Taster Nummer." + taster_nr)
249 
250  GPIO.add_event_detect(self._taster[taster_nr], GPIO.RISING,
251  callback=methode, bouncetime=200)
252 
253  def cleanup(self):
254  """Setzt alle Pins des Pi wieder in den Ausgangszustand.
255 
256  >>> from eapi.hw import EAModul
257  >>> ea = EAModul()
258  >>> ea.cleanup()
259  """
260  GPIO.cleanup()
261 
262 
264  """Ein Erweiterung der Klasse EAModul, die dimmbare LEDs unterstüzt.
265 
266  Im Unterschied zum EAModul können über die Klasse DimmbaresEAModul die LEDs
267  mit Hilfe von PWM in der Helligkeit reguliert werden. Hierbei wurde die
268  Methode schalte_led so angepasst, dass sie nun auch Werte zwischen 0.0 und
269  1.0 annehmen kann.
270 
271  >>> from eapi.hw import DimmbaresEAModul
272  >>> ea = DimmbaresEAModul()
273 
274  Nach dem Erstellen eines Moduls, können die LEDs auch mit Werten zwischen
275  0.0 und 1.0 geschaltet werden. Sie leuchten dann weniger hell.
276 
277  >>> ea.schalte_led(EAModul.LED_ROT, 0.5)
278  >>> ea.schalte_led(EAModul.LED_GELB, 0.8)
279  >>> ea.schalte_led(EAModul.LED_GRUEN, 0.2)
280  """
281 
282  def __init__(self, pin_taster0=29, pin_taster1=31,
283  pin_led_rot=33, pin_led_gelb=35, pin_led_gruen=37):
284  """
285  Die PINs des Moduls werden konfiguriert.
286 
287  Pins der LED werden als Ausgänge, und Pins der Taster als Eingänge
288  konfiguriert. Wenn keine PINS angegeben werden, werden die PINs
289  oberhalb des GND Pins links unten verwendet.
290 
291  >>> from eapi.hw import DimmbaresEAModul
292 
293  >>> ea = DimmbaresEAModul()
294  >>> ea.cleanup()
295  """
296  super().__init__(pin_taster0, pin_taster1,
297  pin_led_rot, pin_led_gelb, pin_led_gruen)
298 
299  # Für jede LED wird ein PWM bereitgestellt, ueber den die LED
300  # gedimmt werden kann
301  self.__pwms = [
302  GPIO.PWM(pin_led_rot, 50),
303  GPIO.PWM(pin_led_gelb, 50),
304  GPIO.PWM(pin_led_gruen, 50)
305  ]
306  for pwm in self.__pwms:
307  pwm.start(0)
308 
309  def schalte_led(self, led_farbe, helligkeit):
310  """Schalte die LED mit der gegebenen Nummer ein (1) oder aus (0).
311 
312  Der Wert für led_farbe ist LED_ROT, LED_GELB oder LED_GRUEN.
313 
314  Wenn für helligkeit eine Kommazahl zwischen 0 und 1 angegeben
315  wird, lässt sich die LED dimmen: ein Wert von 0.5 lässt die
316  LED nur mit halber Kraft leuchten.
317 
318  Eine einfache Verwendung könnte wie folgt aussehen:
319 
320  >>> from eapi.hw import DimmbaresEAModul
321 
322  >>> ea_modul = DimmbaresEAModul()
323  >>> ea_modul.schalte_led(EAModul.LED_ROT, 1)
324  >>> ea_modul.schalte_led(EAModul.LED_GELB, 0)
325  >>> ea_modul.schalte_led(EAModul.LED_GRUEN, 0.5)
326  >>> ea_modul.cleanup()
327  """
328 
329  if 0 <= led_farbe < len(self._leds):
330  if 0 <= helligkeit <= 1:
331  # LED dimmen
332  pwm = self.__pwms[led_farbe]
333  pwm.ChangeDutyCycle(helligkeit*100)
334  self._notify_leds(led_farbe, helligkeit)
335 
336  else:
337  raise ValueError("Wert für Helligkeit muss zwischen 0 und 1 liegen.")
338  else:
339  raise ValueError("Falsche LED-Farbe.")
340 
341 __ea_modul = None
342 def demo_led_taster():
343  """
344  Ein einfaches Demoprogramm, um die LED und Taster auf dem Board zu prüfen.
345  """
346  import time
347 
348  input(
349  """
350  Die rote und grüne LED blinken abwechselnd. Gleichzeitig kann über
351  den einen Taster die gelbe LED an- und ausgeschaltet werden. Der
352  andere Taster beendet das Programm, wenn er länger gedrückt wird.
353  (Enter)
354  """)
355 
356  global __ea_modul
357  __ea_modul = EAModul()
358 
359  def __taster0_gedrueckt(pin):
360  global __ea_modul
361  __ea_modul.schalte_led(EAModul.LED_GELB, __ea_modul.taster_gedrueckt(0))
362 
363  __ea_modul.taster_event_registrieren(0, __taster0_gedrueckt)
364 
365  try:
366  while not __ea_modul.taster_gedrueckt(1):
367  __ea_modul.schalte_led(EAModul.LED_ROT, 1)
368  time.sleep(0.2)
369  __ea_modul.schalte_led(EAModul.LED_ROT, 0)
370  time.sleep(0.2)
371 
372  __ea_modul.schalte_led(EAModul.LED_GRUEN, 1)
373  time.sleep(0.5)
374  __ea_modul.schalte_led(EAModul.LED_GRUEN, 0)
375  time.sleep(0.2)
376 
377  except KeyboardInterrupt:
378  __ea_modul.cleanup()
379  finally:
380  __ea_modul.cleanup()
381 
382 
383 def demo_dimmen():
384  """Demoprogramm, um die Dimmen-Funktionalität zu prüfen."""
385 
386  import time
387 
388  input(
389  "Alle LEDs werden 0.0 auf 1.0 gedimmt und dann von 1.0 auf 0.0 (Enter)")
390  dim_ea_modul = DimmbaresEAModul()
391  for i in range(100):
392  dim_ea_modul.schalte_led(EAModul.LED_ROT, i / 100)
393  dim_ea_modul.schalte_led(EAModul.LED_GELB, i / 100)
394  dim_ea_modul.schalte_led(EAModul.LED_GRUEN, i / 100)
395  time.sleep(0.05)
396  for i in range(100):
397  dim_ea_modul.schalte_led(EAModul.LED_ROT, 1 - i / 100)
398  dim_ea_modul.schalte_led(EAModul.LED_GELB, 1 - i / 100)
399  dim_ea_modul.schalte_led(EAModul.LED_GRUEN, 1 - i / 100)
400  time.sleep(0.05)
401 
402  dim_ea_modul.cleanup()
403 
404 
405 def main():
406  """Hauptprogramm, das beim Starten des Moduls ausgeführt wird.
407 
408  Hierüber können verschiedene Demoprogramme gestartet werden.
409  """
410  # TODO Democlient für das Debugging ergänzen: Taster0->rote LED,
411  # Taster1->gelbe LED, Taster01->grüne LED. LEDs werden über Konsole
412  # visualisiert. Oder: Verschiedene Modi können über einen curses-client
413  # ausgewählt werden.
414  #
415  # https://docs.python.org/3/howto/curses.html
416 
417  command = input("Befehl angeben: demo_led_taster demo_dimmen: ")
418  if command == "demo_dimmen":
419  demo_dimmen()
420 
421  elif command == "demo_led_taster":
422  demo_led_taster()
423 
424 
425 
426 if __name__ == "__main__":
427  main()
def led_event_registrieren
Definition: hw.py:102
def schalte_leds
Definition: hw.py:215
def taster_gedrueckt
Definition: hw.py:140
__observer_leds
Definition: hw.py:97
def __init__
Definition: hw.py:62
def _notify_leds
Definition: hw.py:133
def schalte_led
Definition: hw.py:190
def taster_event_registrieren
Definition: hw.py:228
def cleanup
Definition: hw.py:253