pho ramen soba

Wednesday, 27 September 2023

[New post] circuitpython 8.2.6 observations

Site logo image whbeebe posted: " Let's talk about CircuitPython 8.2.6 running on the Raspberry Pi Pico W. The latest versions of both CircuitPython and MicroPython (from which CircuitPython is derived) has implemented Python's async/await concurrent support. The code has a lot of "id" Arcane Science Lab

circuitpython 8.2.6 observations

whbeebe

Sep 27

Let's talk about CircuitPython 8.2.6 running on the Raspberry Pi Pico W. The latest versions of both CircuitPython and MicroPython (from which CircuitPython is derived) has implemented Python's async/await concurrent support. The code has a lot of "identifying" code that tells me what some of it's resources are. You don't need them for the async portions, but it comes in handy when I'm trying to debug or create new CircuitPython applications, and I believe you'll find them as useful as I have. One other little feature is the use of Python 'f' strings to print formatted strings with data. It's a feature that's been in regular Python for a few years now, and it's been copied over to MicroPython and CircuitPython for nearly as long. What follows is the code listing, after which I describe various section functionalities.

  import board  import digitalio  import gc  import microcontroller as mc  import os  import sys  import time    # Introduce yourself  #  print(f"\n{os.uname().machine}")  print(f"{sys.implementation.name} v{'.'.join(map(str,sys.implementation.version))}")  print(f"CPU clock: {mc.cpu.frequency:,} Hz")  print("-------------------------------\n")    # Show available memory  #  print("Memory Stats - gc.mem_free()")  print(f"Free: {gc.mem_free():,} Bytes")  print("----------------------------\n")    # Show flash size  #  flash = os.statvfs('/')  flash_size = flash[0] * flash[2]  flash_free = flash[0] * flash[3]  print("Flash Stats- os.statvfs('/')")  print(f"Size: {flash_size:,} Bytes\nFree: {flash_free:,} Bytes")  print("----------------------------\n")    # Check local WiFi network  #  import wifi  networks = {}  for network in wifi.radio.start_scanning_networks():      if len(network.ssid) > 0 and network.ssid[0] != '\x00':          networks[network.ssid] = network  wifi.radio.stop_scanning_networks()  print("WIFI: SCAN, SORTED BY SSID")  for ssid in sorted(networks):      print(f"SSID: {ssid:<24}- RSSI: {networks[ssid].rssi}")    import binascii as ba  NAME = os.uname().sysname.upper()  UNIQUE_ID = ba.hexlify(mc.cpu.uid).decode('ascii').upper()  HOST_NAME = NAME + "-" + UNIQUE_ID[-4:]  print()  print(f"Board SSID: {HOST_NAME}")  print("----------------------------\n")    # Check for any I2C devices  #  import busio  import displayio  import adafruit_displayio_ssd1306 as ssd1306    displayio.release_displays()  i2c = busio.I2C(board.GP9, board.GP8)  i2c.try_lock()  i2c.scan()  i2c.unlock()    display_bus = displayio.I2CDisplay(i2c, device_address=60)  display = ssd1306.SSD1306(display_bus, width=128, height=32)    import asyncio    interval_addition = 0.0    async def blink(pin, interval):      with digitalio.DigitalInOut(pin) as led:          led.switch_to_output(value=False)            while True:              led.value = True              await asyncio.sleep(interval)              led.value = False              await asyncio.sleep(interval + interval_addition)    import rotaryio    # SW - GP18 - push button  # DT - GP19 - direction  # CLK - GP20 - pulse out  #  async def rotary_encoder():      global interval_addition      encoder = rotaryio.IncrementalEncoder(board.GP20, board.GP19, 4)      last_position = 0.0      while True:          position = encoder.position          if position != last_position and position >= 0:              print(f"Off delay: + {position/10} sec")              if position > last_position:                  interval_addition += 0.1              else:                  interval_addition -= 0.1              last_position = position          await asyncio.sleep(0)    import keypad    async def rotary_encoder_push(pin):      with keypad.Keys((pin,), value_when_pressed = False) as keys:          while True:              event = keys.events.get()              if event:                  if event.pressed:                      print("Rotary encoder pushed")                  elif event.released:                      print("Rotary encoder released")              await asyncio.sleep(0)    async def main():      led1_task = asyncio.create_task(blink(board.GP16, 0.2))      led2_task = asyncio.create_task(blink(board.GP17, 0.1))      roto_task = asyncio.create_task(rotary_encoder())      push_task = asyncio.create_task(rotary_encoder_push(board.GP18))      await asyncio.gather(led1_task, led2_task, roto_task, push_task)    asyncio.run(main())  

Preamble

Lines 9 through 49 document the Pico W's environment, which is how much memory and flash storage, and the WiFi environment. It's the WiFi environment check I want to draw attention to. It's more robust than just about every other example on the web. It turned out that for whatever reason the call to wifi.radio.start_scanning_networks()  returns duplicates and entries in which the SSID is full of nulls. That's why I used a Python dictionary to eliminate duplicates and to test to see if the first character of the SSID isn't a null. I then sort the resultant dictionary on the keys (SSID) and print out a sorted list, which makes it easier to read.

Checking for I2C Devices

Lines 51 through 61 dig deeper into the Pico W's environment, in this case any devices attached via the I2C bus.

Asyncio

The last section of the code, lines 66 to 140, are the interesting parts. Line 66 imports the asyncio library, which we'll use throughout the remaining code listing. Lines 70, 86, and 103 use the async keyword before the function definition to mark these functions as using concurrency, instead of threads, for multitasking. All the sleep(..) functions are now written as await asyncio.sleep(...) to work with the concurrency framework. Failure to use regular sleep instead of asyncio's sleep will cause only the first function called to execute. Behind the scenes, asyncio's sleep yields to allow any other scheduled concurrent threads to execute. Even a call with '0' will yield, and return almost immediately after.

Lines 114 to 121 set up the running of the tasks. The way the tasks are written, none of them actually return, which means everything works as it's intended to, which is all the time.

Oddball Problem

I have a small 128 character by two line display attached via I2C. For the longest time the could would fault at 58, saying that the pin was already being used, which was perplexing as hell. I finally found, in another forum post about another problem, the line at 57, which temporarily releases the display and thus the pin to be defined at line 58. Even more bazaar is that the I2C device scan returns nothing.

Finally, the print line at 93 shows up on the LCD display even though I don't explicitly do that. The LCD display is echoing what goes out on the REPL all on its own. It's as if CircuitPython, behind the scenes, is scanning and finding that LCD display and then using it without me setting it up that way. I have never encountered this kind of behavior before, either with earlier CircuitPython releases or anything from MicroPython, either.

Comment
Like
Tip icon image You can also reply to this email to leave a comment.

Unsubscribe to no longer receive posts from Arcane Science Lab.
Change your email settings at manage subscriptions.

Trouble clicking? Copy and paste this URL into your browser:
https://arcanesciencelab.wordpress.com/2023/09/27/circuitpython-8-2-6-observations/

WordPress.com and Jetpack Logos

Get the Jetpack app to use Reader anywhere, anytime

Follow your favorite sites, save posts to read later, and get real-time notifications for likes and comments.

Download Jetpack on Google Play Download Jetpack from the App Store
WordPress.com on Twitter WordPress.com on Facebook WordPress.com on Instagram WordPress.com on YouTube
WordPress.com Logo and Wordmark title=

Automattic, Inc. - 60 29th St. #343, San Francisco, CA 94110  

at September 27, 2023
Email ThisBlogThis!Share to XShare to FacebookShare to Pinterest

No comments:

Post a Comment

Newer Post Older Post Home
Subscribe to: Post Comments (Atom)

NEW! Weekly Menu Inspo ⭐️

Simple, delicious recipes to add to your menu this week: pumpkin cranberry oats, quinoa veggie bowls, 1-pot soup, ...

  • [New post] This tried-and-true Irish pub-inspired soup is creamy and thick with chunks of potatoes and leeks throughout.
    Emily Morgan posted: "This tried-and-true Irish pub-inspired soup is creamy and thick with chunks of potatoes and leeks thr...
  • LA COURONNE LYONNAISE, TWO WAYS
    This bread originates in Lyon, and is shaped as a crown, therefore the name ...
  • Keto Chicken Pot Pie Casserole (Gluten-Free)
    INGREDIENTS US CustomaryMetric▢4 cups cooked chicken breast (roasted, rotisserie...

Search This Blog

  • Home

About Me

phoo, ramen, soba
View my complete profile

Report Abuse

Blog Archive

  • November 2025 (18)
  • October 2025 (21)
  • September 2025 (19)
  • August 2025 (28)
  • July 2025 (25)
  • June 2025 (28)
  • May 2025 (34)
  • April 2025 (36)
  • March 2025 (39)
  • February 2025 (36)
  • January 2025 (43)
  • December 2024 (46)
  • November 2024 (51)
  • October 2024 (44)
  • September 2024 (1172)
  • August 2024 (1572)
  • July 2024 (1413)
  • June 2024 (1289)
  • May 2024 (1362)
  • April 2024 (1472)
  • March 2024 (1827)
  • February 2024 (2413)
  • January 2024 (2936)
  • December 2023 (2135)
  • November 2023 (1639)
  • October 2023 (1285)
  • September 2023 (918)
  • August 2023 (864)
  • July 2023 (795)
  • June 2023 (800)
  • May 2023 (796)
  • April 2023 (754)
  • March 2023 (649)
  • February 2023 (736)
  • January 2023 (1159)
  • December 2022 (968)
  • November 2022 (921)
  • October 2022 (852)
  • September 2022 (708)
  • August 2022 (766)
  • July 2022 (877)
  • June 2022 (684)
  • May 2022 (716)
  • April 2022 (698)
  • March 2022 (781)
  • February 2022 (734)
  • January 2022 (955)
  • December 2021 (1387)
  • November 2021 (3002)
  • October 2021 (3213)
  • September 2021 (3188)
  • August 2021 (3232)
  • July 2021 (1697)
Powered by Blogger.