|
| 1 | +import time |
| 2 | +import trio |
| 3 | +import trio_gpio as gpio |
| 4 | + |
| 5 | +""" |
| 6 | +This example is taken out of my furnace controller. |
| 7 | +It has been tested with Raspberry Pi Zero W and I assume it will work with any board supported by trio_gpio. |
| 8 | +Use at your own risk. |
| 9 | +
|
| 10 | +If you aren't sure about how to hook up a button and led to your board, there are a lot of examples online. |
| 11 | +
|
| 12 | +Thank you @smurfix, who wrote trio_gpio and @njsmith and other in glitter:python-trio/general room |
| 13 | +who helped me out. |
| 14 | +""" |
| 15 | + |
| 16 | + |
| 17 | +class Led: |
| 18 | + # This class turns on and off the power to a pin. |
| 19 | + # Two events are setup for turning off an on the pin. Both events need to be |
| 20 | + # called at the same time or trio might await at the wrong spot. |
| 21 | + def __init__(self, line): |
| 22 | + self.x = line |
| 23 | + self._on = trio.Event() |
| 24 | + self._off = trio.Event() |
| 25 | + |
| 26 | + async def liteon(self): |
| 27 | + with gpio.open_chip() as chip: |
| 28 | + with chip.line(self.x).open(direction=gpio.DIRECTION_OUTPUT) as line: |
| 29 | + self._on.clear() |
| 30 | + self._off.set() |
| 31 | + while True: |
| 32 | + if self._on.is_set(): |
| 33 | + line.value = 1 |
| 34 | + # print('lite on') |
| 35 | + await self._off.wait() |
| 36 | + self._on.clear() |
| 37 | + elif self._off.is_set(): |
| 38 | + line.value = 0 |
| 39 | + # print('lite off')d |
| 40 | + await self._on.wait() |
| 41 | + self._off.clear() |
| 42 | + else: |
| 43 | + # should never be reached. |
| 44 | + # if the code does reach here, |
| 45 | + # turn off the power to whatever is being powered |
| 46 | + print('error: both are off.') |
| 47 | + self._off.set() |
| 48 | + |
| 49 | + |
| 50 | +class Button: |
| 51 | + # Add the events tthe button is attached to and the on off event are passed into the class. |
| 52 | + # The class listens for the voltage to rise then reverses whatever the current settings are. |
| 53 | + def __init__(self, line, event_on, event_off): |
| 54 | + self.y = line |
| 55 | + self._on = event_on |
| 56 | + self._off = event_off |
| 57 | + |
| 58 | + async def push(self): |
| 59 | + with gpio.Chip(0) as c: |
| 60 | + in_ = c.line(self.y) |
| 61 | + with in_.monitor(gpio.REQUEST_EVENT_RISING_EDGE): |
| 62 | + last = 0 |
| 63 | + async for e in in_: |
| 64 | + # This section is for debouncing the button. |
| 65 | + # As a button is pushed and released the voltage can rapidly go up and down many times |
| 66 | + # when the user only meant one push. To limit this, a delay is add to ignore changes. |
| 67 | + # This can be adjusted depending on the button and the respose. |
| 68 | + secs, ns_secs = e.timestamp |
| 69 | + now = float(str(secs)+'.'+str(ns_secs)) |
| 70 | + if now >= last + .25: |
| 71 | + print('button', e.value, secs, ns_secs, now) |
| 72 | + self._off.set() if self._on.is_set() else self._on.set() |
| 73 | + last = now |
| 74 | + |
| 75 | +# Trio-gpio uses the BCM pin numbering. So, the led is on the pin 21 |
| 76 | +# and the button that controls the yellow is hooked to pin 23. |
| 77 | +yellow = Led(21) |
| 78 | +yellowbutton = Button(23, yellow._on, yellow._off) |
| 79 | + |
| 80 | + |
| 81 | +async def main(y): |
| 82 | + async with trio.open_nursery() as nursery: |
| 83 | + nursery.start_soon(yellowbutton.push) |
| 84 | + nursery.start_soon(yellow.liteon) |
| 85 | + |
| 86 | + |
| 87 | +if __name__ == "__main__": |
| 88 | + trio.run(main, 1) |
0 commit comments