From 3e8a7abc5cbdb7e8ca3b5dad08dc8209ba26cdc8 Mon Sep 17 00:00:00 2001 From: johnnohj <166672127+johnnohj@users.noreply.github.com> Date: Tue, 4 Jun 2024 10:27:26 -0400 Subject: [PATCH 1/9] Add files via upload --- examples/asyncio_event_example.py | 112 ++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 examples/asyncio_event_example.py diff --git a/examples/asyncio_event_example.py b/examples/asyncio_event_example.py new file mode 100644 index 0000000..3de1116 --- /dev/null +++ b/examples/asyncio_event_example.py @@ -0,0 +1,112 @@ +# SIMPLE ASYNCIO EVENT EXAMPLE + +# Brief program that illustrates using Events to coordinate tasks +# within Asyncio programs. The present example involves only one led +# and one event, but Asyncio allows a high degree of scaling. Adding +# several copies of the functions 'blink', 'input_poll', or 'state' +# should be straightforward with changes to names and objects. + +import board +import time +import adafruit_ticks +import digitalio +from adafruit_debouncer import Debouncer +import neopixel +import asyncio + +# Import library modules, as is tradition + +pin = digitalio.DigitalInOut(board.BUTTON) +pin.direction = digitalio.Direction.INPUT +pin.pull = digitalio.Pull.UP +button = Debouncer(pin) + +# Instantiate the input, in this case, the 'BOOT' button on a +# QT Py 2040. The debouncer ensures a clean hit. + +BLANK = (0, 0, 0, 0) +RED = (255, 0, 0) +GREEN = (0, 255, 0) +BLUE = (0, 0, 255) + +COLORS = {0: BLANK, 1: RED, 2: GREEN, 3: BLUE} + +# Define the various colors according to preference and set them into +# a dictionary for later retrieval. (Blue is not used in this code.) + +class color: + def __init__(self, initial_value): + self.value = initial_value + +# Create a class to hold and track the color while code executes. + +async def blink(color): + with neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.1) as led: + while True: + led[0] = COLORS.get(0) + await asyncio.sleep(1) + led[0] = COLORS.get(color.value) + await asyncio.sleep(0) + +# Instantiate the led using 'with ... as' construction to keep this +# function from blocking. 'COLORS.get(0)' indicates the led should show +# no color (i.e., turn off), while 'COLORS.get(color.value)' instructs +# the led to show the color pulled from the dictionary via the color +# class' color.value. The line 'asyncio.sleep(1)' sets the blink rate; +# in this case, once per second. + +async def input_poll(swapper): + count = 0 + while True: + button.update() + if button.fell: + print('Press!') + if count == 0: + count += 1 + print('Event is set!') + swapper.set() + elif count == 1: + count -= 1 + print('Event is clear!') + swapper.clear() + await asyncio.sleep(0) + +# This function checks the button for activity and sets or clears the +# Event depending on the button activity reflected in the 'count' variable. +# The count begins set at 0 and is alternatingly incremented (count += 1) +# and decremented (count -= 1) with each press of the button. + +async def state(swapper, color): + while True: + if swapper.is_set(): + color.value = 2 + else: + color.value = 1 + await asyncio.sleep(0) + +async def main(): + + color.value = 1 + COLORS.get(color) + +# Sets the color the led will first show on start + + swapper = asyncio.Event() + +# Creates and names the Event that signals the led to change color + + blinky = asyncio.create_task(blink(color)) + poll = asyncio.create_task(input_poll(swapper)) + monitor = asyncio.create_task(state(swapper, color)) + +# Creates and names Tasks from the functions defined above + + await asyncio.gather(monitor, blinky, poll) + +# Don't forget the 'await'! The 'asyncio.gather()' command passes the +# listed tasks to the asynchronous scheduler, where processing resources +# are directed from one task to another depending upon whether said task +# has signalled its ability to 'give up' control by reaching the 'await +# asyncio.sleep()' line. + +asyncio.run(main()) From 8e3a77fecb130a9efe0ef3de8ab3fbc25d2e5e26 Mon Sep 17 00:00:00 2001 From: johnnohj <166672127+johnnohj@users.noreply.github.com> Date: Tue, 4 Jun 2024 10:39:19 -0400 Subject: [PATCH 2/9] Update asyncio_simpletest.py Simple copy/paste beginning from https://learn.adafruit.com/cooperative-multitasking-in-circuitpython-with-asyncio/concurrent-tasks#one-led-3106269 to correct an issue raised, of all places, in the Issues section. --- examples/asyncio_simpletest.py | 59 ++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/examples/asyncio_simpletest.py b/examples/asyncio_simpletest.py index 59fa942..4732bbb 100644 --- a/examples/asyncio_simpletest.py +++ b/examples/asyncio_simpletest.py @@ -1,4 +1,57 @@ -# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries -# SPDX-FileCopyrightText: Copyright (c) 2021 Dan Halbert for Adafruit Industries +# SPDX-FileCopyrightText: 2022 Dan Halbert for Adafruit Industries # -# SPDX-License-Identifier: Unlicense +# SPDX-License-Identifier: MIT + +### Example for one led: + +import asyncio +import board +import digitalio + + +async def blink(pin, interval, count): # Don't forget the async! + with digitalio.DigitalInOut(pin) as led: + led.switch_to_output(value=False) + for _ in range(count): + led.value = True + await asyncio.sleep(interval) # Don't forget the await! + led.value = False + await asyncio.sleep(interval) # Don't forget the await! + + +async def main(): # Don't forget the async! + led_task = asyncio.create_task(blink(board.D1, 0.25, 10)) + await asyncio.gather(led_task) # Don't forget the await! + print("done") + + +asyncio.run(main()) + + +### Example for two leds: + +import asyncio +import board +import digitalio + + +async def blink(pin, interval, count): + with digitalio.DigitalInOut(pin) as led: + led.switch_to_output(value=False) + for _ in range(count): + led.value = True + await asyncio.sleep(interval) # Don't forget the "await"! + led.value = False + await asyncio.sleep(interval) # Don't forget the "await"! + + +async def main(): + led1_task = asyncio.create_task(blink(board.D1, 0.25, 10)) + led2_task = asyncio.create_task(blink(board.D2, 0.1, 20)) + + await asyncio.gather(led1_task, led2_task) # Don't forget "await"! + print("done") + + +asyncio.run(main()) + From 96f3d9a5da2d6fbbda323444307a82432d4c8ac0 Mon Sep 17 00:00:00 2001 From: johnnohj <166672127+johnnohj@users.noreply.github.com> Date: Tue, 4 Jun 2024 20:25:29 -0400 Subject: [PATCH 3/9] Update asyncio_event_example.py Corrections to code made based on test results. --- examples/asyncio_event_example.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/asyncio_event_example.py b/examples/asyncio_event_example.py index 3de1116..60d1ef3 100644 --- a/examples/asyncio_event_example.py +++ b/examples/asyncio_event_example.py @@ -6,13 +6,13 @@ # several copies of the functions 'blink', 'input_poll', or 'state' # should be straightforward with changes to names and objects. +import asyncio import board -import time import adafruit_ticks import digitalio from adafruit_debouncer import Debouncer import neopixel -import asyncio + # Import library modules, as is tradition @@ -34,7 +34,7 @@ # Define the various colors according to preference and set them into # a dictionary for later retrieval. (Blue is not used in this code.) -class color: +class Color: def __init__(self, initial_value): self.value = initial_value @@ -86,7 +86,7 @@ async def state(swapper, color): async def main(): - color.value = 1 + color = Color(1) COLORS.get(color) # Sets the color the led will first show on start From b5380ec2e2cdfb6d30003813366678bed0be0b7e Mon Sep 17 00:00:00 2001 From: johnnohj <166672127+johnnohj@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:45:05 -0400 Subject: [PATCH 4/9] Update asyncio_event_example.py --- examples/asyncio_event_example.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/asyncio_event_example.py b/examples/asyncio_event_example.py index 60d1ef3..e0514b6 100644 --- a/examples/asyncio_event_example.py +++ b/examples/asyncio_event_example.py @@ -8,6 +8,7 @@ import asyncio import board +# pylint: disable=unused-import import adafruit_ticks import digitalio from adafruit_debouncer import Debouncer @@ -17,8 +18,8 @@ # Import library modules, as is tradition pin = digitalio.DigitalInOut(board.BUTTON) -pin.direction = digitalio.Direction.INPUT -pin.pull = digitalio.Pull.UP +pin.direction = Direction.INPUT +pin.pull = Pull.UP button = Debouncer(pin) # Instantiate the input, in this case, the 'BOOT' button on a @@ -35,6 +36,7 @@ # a dictionary for later retrieval. (Blue is not used in this code.) class Color: + # pylint: disable=too-few-public-methods def __init__(self, initial_value): self.value = initial_value From a1ca479843e66eaeb46031dcee9723117ebabf6c Mon Sep 17 00:00:00 2001 From: johnnohj <166672127+johnnohj@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:45:35 -0400 Subject: [PATCH 5/9] Update asyncio_event_example.py --- examples/asyncio_event_example.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/asyncio_event_example.py b/examples/asyncio_event_example.py index e0514b6..63cd590 100644 --- a/examples/asyncio_event_example.py +++ b/examples/asyncio_event_example.py @@ -8,8 +8,6 @@ import asyncio import board -# pylint: disable=unused-import -import adafruit_ticks import digitalio from adafruit_debouncer import Debouncer import neopixel From 28188a8c2fa46a789ba093eace9083fba7da6829 Mon Sep 17 00:00:00 2001 From: johnnohj <166672127+johnnohj@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:51:10 -0400 Subject: [PATCH 6/9] Update asyncio_simpletest.py --- examples/asyncio_simpletest.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/asyncio_simpletest.py b/examples/asyncio_simpletest.py index 4732bbb..160f2d1 100644 --- a/examples/asyncio_simpletest.py +++ b/examples/asyncio_simpletest.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: MIT -### Example for one led: +# -----[Example for one led]----------------------------- import asyncio import board @@ -28,14 +28,13 @@ async def main(): # Don't forget the async! asyncio.run(main()) -### Example for two leds: +# -----[Example for two leds]------------------------------- -import asyncio -import board -import digitalio +# Import modules as above async def blink(pin, interval, count): + # pylint: disable=function-redefined with digitalio.DigitalInOut(pin) as led: led.switch_to_output(value=False) for _ in range(count): @@ -46,6 +45,7 @@ async def blink(pin, interval, count): async def main(): + # pylint: disable=function-redefined led1_task = asyncio.create_task(blink(board.D1, 0.25, 10)) led2_task = asyncio.create_task(blink(board.D2, 0.1, 20)) From f307a66b74b65f513572435fb93f1d81e8f0eba5 Mon Sep 17 00:00:00 2001 From: johnnohj <166672127+johnnohj@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:55:05 -0400 Subject: [PATCH 7/9] Update asyncio_event_example.py --- examples/asyncio_event_example.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/asyncio_event_example.py b/examples/asyncio_event_example.py index 63cd590..d61ae03 100644 --- a/examples/asyncio_event_example.py +++ b/examples/asyncio_event_example.py @@ -16,8 +16,8 @@ # Import library modules, as is tradition pin = digitalio.DigitalInOut(board.BUTTON) -pin.direction = Direction.INPUT -pin.pull = Pull.UP +pin.direction = digitalio.Direction.INPUT +pin.pull = digitalio.Pull.UP button = Debouncer(pin) # Instantiate the input, in this case, the 'BOOT' button on a From 8e7f4a502bd490dc0f640c60c015c20f378fb9a3 Mon Sep 17 00:00:00 2001 From: johnnohj <166672127+johnnohj@users.noreply.github.com> Date: Thu, 6 Jun 2024 20:49:10 +0000 Subject: [PATCH 8/9] Pending changes exported from your codespace --- examples/asyncio_event_example.py | 26 +++++++++++++++++++------- examples/asyncio_simpletest.py | 1 - 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/examples/asyncio_event_example.py b/examples/asyncio_event_example.py index d61ae03..ff62259 100644 --- a/examples/asyncio_event_example.py +++ b/examples/asyncio_event_example.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2024 J Fletcher +# +# SPDX-License-Identifier: MIT + # SIMPLE ASYNCIO EVENT EXAMPLE # Brief program that illustrates using Events to coordinate tasks @@ -33,13 +37,16 @@ # Define the various colors according to preference and set them into # a dictionary for later retrieval. (Blue is not used in this code.) + class Color: # pylint: disable=too-few-public-methods def __init__(self, initial_value): self.value = initial_value + # Create a class to hold and track the color while code executes. + async def blink(color): with neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.1) as led: while True: @@ -48,6 +55,7 @@ async def blink(color): led[0] = COLORS.get(color.value) await asyncio.sleep(0) + # Instantiate the led using 'with ... as' construction to keep this # function from blocking. 'COLORS.get(0)' indicates the led should show # no color (i.e., turn off), while 'COLORS.get(color.value)' instructs @@ -55,27 +63,30 @@ async def blink(color): # class' color.value. The line 'asyncio.sleep(1)' sets the blink rate; # in this case, once per second. + async def input_poll(swapper): count = 0 while True: button.update() if button.fell: - print('Press!') + print("Press!") if count == 0: count += 1 - print('Event is set!') + print("Event is set!") swapper.set() elif count == 1: count -= 1 - print('Event is clear!') + print("Event is clear!") swapper.clear() await asyncio.sleep(0) + # This function checks the button for activity and sets or clears the # Event depending on the button activity reflected in the 'count' variable. # The count begins set at 0 and is alternatingly incremented (count += 1) # and decremented (count -= 1) with each press of the button. + async def state(swapper, color): while True: if swapper.is_set(): @@ -84,25 +95,26 @@ async def state(swapper, color): color.value = 1 await asyncio.sleep(0) -async def main(): +async def main(): color = Color(1) COLORS.get(color) -# Sets the color the led will first show on start + # Sets the color the led will first show on start swapper = asyncio.Event() -# Creates and names the Event that signals the led to change color + # Creates and names the Event that signals the led to change color blinky = asyncio.create_task(blink(color)) poll = asyncio.create_task(input_poll(swapper)) monitor = asyncio.create_task(state(swapper, color)) -# Creates and names Tasks from the functions defined above + # Creates and names Tasks from the functions defined above await asyncio.gather(monitor, blinky, poll) + # Don't forget the 'await'! The 'asyncio.gather()' command passes the # listed tasks to the asynchronous scheduler, where processing resources # are directed from one task to another depending upon whether said task diff --git a/examples/asyncio_simpletest.py b/examples/asyncio_simpletest.py index 160f2d1..693a13e 100644 --- a/examples/asyncio_simpletest.py +++ b/examples/asyncio_simpletest.py @@ -54,4 +54,3 @@ async def main(): asyncio.run(main()) - From dd8519f4f22ff6268da535c4b1426a5731689c93 Mon Sep 17 00:00:00 2001 From: johnnohj <166672127+johnnohj@users.noreply.github.com> Date: Thu, 6 Jun 2024 21:54:52 +0000 Subject: [PATCH 9/9] edits attempted --- examples/asyncio_event_example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/asyncio_event_example.py b/examples/asyncio_event_example.py index ff62259..9998909 100644 --- a/examples/asyncio_event_example.py +++ b/examples/asyncio_event_example.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2024 J Fletcher +# SPDX-FileCopyrightText: 2024 J Fletcher # # SPDX-License-Identifier: MIT