#circuitpython-dev
1 messages · Page 89 of 1
Here's a video demonstration of the above script: https://youtu.be/wA8iXEtn8OI
Thanks for hosting Liz! have a great week everyone 👋
Thank you @candid sun for hosting/reading.
Turn off codeop on the feather. Metro has it off already. I'd disable errno on metro and redboard.
Where do I file Open Installer issues?
Claude helped with initial prompt:
Refactor common_hal_epaperdisplay_epaperdisplay_construct so that the current arguments are struct fields and then the function only takes the struct. Also add a macro that initializes it to default values.
And one follow up prompt before minor manual cleanup and testing:
Clean up board files by removing settings that match the default. In particular bools that are false should be default, commands with NO_COMMAND and highlight color as 0.
Fo...
Here is the notes document for the next CircuitPython Weekly Meeting in two weeks on August 25, 2025. It is at the normal time of 11am Pacific / 2pm US Eastern here on Discord. Add your hug reports and status updates to the document before the meeting. If you are unable to attend but would still like to contribute, feel free to add your notes and we’ll read them off during the meeting. Hope to see you there! <@&356864093652516868>
https://docs.google.com/document/d/1YxMrgfSw5AcotMzRo8oWV4AOjsYhb9v2mWQmUSDRz9E/edit?tab=t.0
CircuitPython Weekly Meeting for MONTH DAY, YEAR Welcome to the CircuitPython Weekly meeting notes! Feel free to add your Hug Reports and Status Updates before the meeting, alphabetically by your username. During the meeting, we go through them in order. If you can’t make the meeting and would s...
it happens when running from fruit jam power on with thonny not running. doesn't happen every time but just did a set of 10 power on, see what happens, power off.... and 4 out of the 10 times errored with the code.py line 40 memory allocation failed error. this is with the font used in the irc client mentioned above with the code.py that i added the onDiskFont() and the fonts to
`# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
SPDX-License-Identifier: MIT
from os import ge...
Does anybody know if CircuitPython already uses some kind of compression on QSTR strings (e.g. Hamming Huffman coding, LZW, or whatever)?
As I begin looking into fixing USB host glitches, I'm getting the sense I'll need to find ways of offsetting code size increases from any error handling code I might add.
It seems like most the stuff that can be turned off for the SAMD21 M0 boards has already been turned off.
qstr aren't but error messages are
thanks
does it seem plausible that error string compression is totally bypassed for non-ASCII strings? I'm looking at check_non_ascii().
by my casual reading of makecompresseddata.py, it looks like there might be a significant opportunity for improving the coding of non-english text.
By my reading of py/makecompresseddata.py, it looks like error string compression only works for pure-ASCII strings. If that's true, builds for languages that give us trouble on SAMD21 M0 boards are probably using uncompressed strings.
Implementing better compression might an easy win for freeing up code space. A possible fix: 1) write a python script to generate a zlib preset ...
After more research, this looks a bit more complicated: 1) The full zlib API isn't available in CircuitPython core. Instead it has the more limited uzlib. 2) zlib and uzlib both use LZ77/DEFLATE with a sliding window (not LZ78 or LZW), so building a good shared dictionary to use with random access decompression of individual strings might be a little tricky. Plausibly doable, but tricky.
Disabled codeop for Feather M0 and errno for Metro M0 and Redboard. Also bumped the Pico-PIO-USB submodule version. Checks passed with all CI builds successful.
Github having problems with issues, actions, PRs again today https://www.githubstatus.com/
Welcome to GitHub's home for real-time and historical data on system performance.
This update allows the tempo of a synthio.MidiTrack object to be manipulated after it has been constructed.
In my use case, I wanted to gradually increase the speed of a song within a game as it progresses.
Here is a demonstration of this property written for the Fruit Jam:
import audiobusio
import audiomixer
import board
import synthio
import time
import adafruit_tlv320
# configure dac
i2c = board.I2C()
dac = adafruit_tlv320.TLV320DAC3100(i2c)
dac.configure...
@candid sun if the fruit jam schematic is up on Learn, can you point me at it .. and if not, can you send me a copy as png/pdf/whatever?
guide isn't live yet but can you see this link? https://learn.adafruit.com/admin/guides/4298/editor/30676
Accounts
@candid sun no, I can't see unpublished guides anymore either
here are PNG files
Thank you!
I don't think that is the right file for compression. (Sorry) I think that is what MicroPython uses and they only support English.
We use https://github.com/adafruit/circuitpython/blob/main/py/maketranslationdata.py which does handle Unicode. That was one of the main requirements of the compression.
So, in that case, it looks like everything is just Huffman coded? It seems plausible there might still be benefit in switching to LZ77/DEFLATE using uzlib with a shared preset dictionary? In theory, that might save more bytes for redundant substrings across error messages? Does that sound interesting? I'm worried that the USB error handling stuff I want to add may not fit if I end up needing to upstream stuff to TinyUSB rather than adding it to usb_host.
Where's the best place to ask about the MatrixPortal S3 and its behavior with CircuitPython?
I get flickering updates in circuitpython, but not in C++
Support forum to start.
I can verify this behavior. I was running my terminal text program with a CP437 font. First time the code runs it errors as above. If I reran the code it worked fine. I was using Mu. I would have reported sooner, I thought it was part of the memory allocation issue being worked on before.
CircuitPython version and board name
Any version
Code/REPL
example:
import adafruit_fruitjam
vs
from adafruit_fruitjam import peripherals
Behavior
I was asked to post this issue for CircuitPython core developers by @ladyada.
In the Adafruit Learning System Guide Memory-saving tips for CircuitPython
https://learn.adafruit.com/Memory-saving-tips-for-CircuitPython/optimizing-memory-use
By selectively importing only the functions you need, you m...
It doesn't save memory. Similar to CPython the whole module is loaded. The only thing it does is change the name that is imported into the global scope (the module name vs the thing in it).
Can you reproduce it without any wifi code? It's tricky to debug something that happens sometimes. wifi adds a lot of variability.
The memory fix I did recently is in beta.2 so I wouldn't expect absolute newest to be any different.
It's more complicated that you think. It isn't just huffman. I wouldn't spend time on it.
We can worry about fitting the USB stuff after you've added it. We can always put things behind #ifdef.
the code at the top of this issue by Anne Barela also does it. Sometimes works, sometimes errors with memory allocation error
If the RTOS is premptive, BusDisplay has a race condition that may caused faults on shared buses. displayio_display_bus_begin_transaction may return false indicating that the lock could not be acquired. As _refresh_area does not respect the return value of displayio_display_bus_begin_transaction, _send_pixels will try to write to the bus without a lock. A guard is present in the code, but it is implemented in a way that is not thread safe.
Further incorrect handling of displayio_display_bus_begin_transaction:
https://github.com/adafruit/circuitpython/blob/117b5d1ed9bab67f91f852777bf4cec8ee8b53e4/shared-module/epaperdisplay/EPaperDisplay.c#L165-L168
I finally figured out a serviceable workaround for this, at least for gamepads. Basic idea is to count the number of consecutive calls to Device.read() that rase a USBTimeoutError exception. I haven't encountered a gamepad that will return more than maybe one or two timeouts in a row unless it's been unplugged. Keyboards on the other hand will do many timeouts until you press a key, so timeout counting doesn't work as well. This is a working example of the consecutive timeout counting met...
A PR with fixes would be super helpful! You've done most of the hard work finding the incorrect uses.
For people who've worked on USB stuff:
Do you have any favorite books or other reference documentation for understanding the USB specs?
the usb spec itself is a good starting point
Anybody have experience with "USB Complete" or "USB Embedded Hosts", both by Jan Axelson?
usb complete is my goto reference
okay. thanks. I'll probably get a copy of that then.
did you get a sniffer?
yeah. talked to pt and ordered one today.
k, great!
Looks like audioio got disabled inadvertently due to some edits in mpconfigboard.mk. For instance, there was a change in from CIRCUITPY_AUDIOIO = 1 to CIRCUITPY_AUDIOIO ?= 1, and that appears not to be overriding the default CIRCUITPY_AUDIOIO ?= 0 earlier in the file.
I'd be happy to create a PR but I've spent a couple of hours trying to get a build environment working, but haven't succeeded as of yet. I'm reluctant to submit a PR without testing it first.
I'd be happy to create a PR but I've spent a couple of hours trying to get a build environment working, but haven't succeeded as of yet. I'm reluctant to submit a PR without testing it first.
Feel free to make a draft PR and let the CI build for you. You can download artifacts from the CI run to test on your boards.
When you circle back to running it locally, jump on Discord and we can help get you set up. https://adafru.it/discord
A second ?= in a makefile for the same variable is ignored, per https://www.gnu.org/software/make/manual/html_node/Setting.html
If you’d like a variable to be set to a value only if it’s not already set, then you can use the shorthand operator ‘?=’ instead of ‘=’. These two settings of the variable ‘FOO’ are identical (see The origin Function):
FOO ?= barand
ifeq ($(origin FOO), unde...
Also interested in this. Got an INMP441 mic that would like to read with CircuitPython.
I've spent a couple of hours trying to get a build environment working, but haven't succeeded
Have you tried using the build-system in the cloud? See https://github.com/adafruit/circuitpython/blob/main/.devcontainer/Readme.md for instructions.
Hi I'm also running into similar issue when trying to run KMK on Seeed XIAO ESP32C3. I can sometimes successfully connect and working, but it disconnects after a few seconds. I'm seeing this error message
File "adafruit_ble/__init__.py", line 212, in start_advertising
MemoryError: Nimble out of memory
Fixes #10569
I've tested on a m5stack_cores3 with no apparent regressions on display handling. This strangely does not resolve #10536 so some other issue must also be present, however I can see on an oscilloscope that the SPI bus is now being shared correctly between busdisplay and sdcardio. One thing to note is running spi = board.SPI(); spi.try_lock() will now prevent the screen from being updated until the lock is released - this is a limitation of the the hardware.
I have also appli...
Thanks for the PR! I'm not sure this is the way we want to do it though. (More inline)
I'm worried all of these deletes are going to break something due to changing chip select issues. I wonder if we should split out the bus locking from chip select.
@lone axle fruit jam volume discussed here: https://forums.adafruit.com/viewtopic.php?t=219717
I'll wait for more info.
Thank you
it was not carter -- I was mistaken
Ideally setting up NTP on a integrated AirLift enabled board like Fruit Jam, PyPortal or MatrixPortal M4 would be as easy as (which will also ready a few env vars from settings.toml).
import adafruit_airlift_ntp as ntp
ntp.sync() # done
It actually takes quite a bit of setup currently. Bruce pointed this out and we put together a little helper library. Would it make sense for me to test and submit an adafruit_airlift_ntp librar...
is there a requirement to keep use of float and int64_t to the port level? I don't see references to them in the shared-bindings layer.
micropython has typedefs for some of them. we use int64 for ticks so I think we do use it in the core
Ok, maybe should just throw a NotImplemented for Int64 message types like I do with Float64 then
I'd like to keep float, so I'll ask in my PR whether I need to reshuffle stuff down to the common-hal
int64 should be fine. the vm supports them. they just aren't small ints
not sure what it does for float64
For context, I'm storing values from Circuitpython variables to internal objects that will be passed to micro-ROS. My impression was that this would be port-agnostic so I haven't put it in the common-hal so far, but I could be wrong. I don't think Circuitpython floats support double precision, right? If circuitpython has no vm variable for a double precision integer, there's no point in me supporting that either
Unless I offered something kind of janky like a manual byte array. Doing that would depend on whether there's a use case for it. Could always revisit later.
right, no double support that I know of. MP might have it. I haven't looked. long ints should be on
Mikey, Thanks for all your help.
only on 192kB builds and a few larger builds (like CPX displayio, I think)
Based on preliminary printf debugging, TinyUSB may sometimes call tuh_umount_cb() later than it should, or not at all. Not confident about that yet though. The latency I saw could also be from buffering of mp_printf() before it made it out over the USB device interface.
This is a patch for the mp_printf() stuff I was using to check when the tuh_mount_cb() and tuh_umount_cb() callbacks were being called:
diff --git a/shared-module/usb/core/Device.c b/shared-module/usb/core/Devic...
This is starting to smell like some kind of weird interrupt thing deep in the guts of TinyUSB.
Has anyone on MacOS been seeing CIRCUITPY drives not being mounted (or even visible from df) after a few unplug/replug cycles? I've been getting it a lot these past few days, with nothing I can think of having changed on my Macbook. A reboot of the Mac will fix it for a while. Killing the Finder doesn't help. It's not a TinyUSB issue, even the RP2 ROM UF2 bootloader won't show up.
Edit: The board is still there: shows up in USB Prober, can connect to via USB CDC if CircuitPython, just no USB MSC
I didn't check with df, but I've sometimes needed to go into the Disk Utility GUI tool to manually re-mount the drive
I can't replicate when and why though
yeah not in Disk Utility or diskutil. Very weird. Well I just did the Apple Silicon versions of the "shake-a-chicken" incantations (SMC reset by powering down fully for 30+ seconds and NVRAM clear by booting w/ held power button to get into options to do nvram -c). Let's see if those make difference
and this isn’t a case where the USB port’s power is disabled?
nope. If the board is CircuitPython, I can connect to it via USB CDC and it shows up normally in System Information or USB Prober. Just not USB MSC
Ah, that's interesting.
Yeah super weird and frustrating
I'm confident now that TinyUSB is not calling tuh_umount_cb() when it should. This diff has pico-sdk gpio code to turn the Fruit Jam's red LED (pin 29) on when tuh_mount_cb() is called and off when tuh_umount_cb() is called:
diff --git a/shared-module/usb/core/Device.c b/shared-module/usb/core/Device.c
index c9df0cf738..f650ed318a 100644
--- a/shared-module/usb/core/Device.c
+++ b/shared-module/usb/core/Device.c
@@ -18,16 +18,35 @@
#include "supervisor/shared/tick.h"
#include "su...
Possibly related: ports/raspberrypi/supervisor/usb.c includes this comment about pico-sdk vs CircuitPython interrupt handling for background tasks:
void post_usb_init(void) {
irq_add_shared_handler(USBCTRL_IRQ, _usb_irq_wrapper,
PICO_SHARED_IRQ_HANDLER_LOWEST_ORDER_PRIORITY);
// There is a small window where the USB interrupt may be handled...
CircuitPython version and board name
* ✅ A: `CircuitPython 9.1.0-beta.3-6-gc2443f993f` → BLE File Transfer Service (UUID `0xFEBB`) **appears as expected**
* ❌ B: `CircuitPython 9.2.4-154-gbd572f86f9` → BLE File Transfer **does not appear**, despite identical board configuration and settings
Code/REPL
*Expected**: BLE service UUID `0xFEBB` should be visible on CircuitPython 9.2.4-154-gbd572f86f9 after preforming
1. Custom UF2 built with the following settin...
@lone axle re the TLV gain settings and the speaker: It appears that the power-up value for the speaker amp gain is 6dB (lowest), and for the attenuator, the power-up gain is -78dB. That is, it is as quiet as possible when first powered up. The CircuitPython driver does not mess with these values on instantiation. So I'm not sure there's anything to do except maybe add some warnings. If there is a volume setting API in a particular Fruit Jam library, it could do some range limiting (and there could be a boolean to override that, for instance). Not sure if that makes sense or not
I was thinking to add warning print outs to all of the different volume/gain property setters inside of the TLV320 driver directly. That way any code downstream that sets the volume to anything higher than default will result in warning being printed.
that will include Fruit Jam library and OS, and any other project code.
Are you saying there would be a new API that can set new ceilings on the various gains (volume control and speaker gain)? If you don't change the ceilings, it will limit the gain to the set ceilings and print a warning. I think that's what you mean?
the default ceilings would be safe for the included speaker
a ceiling on headphone volume would probably be good too, to save people's ears, though headphones have different characteristics.
I was imagining a warning only, no enforcement of the ceiling. But am open to the idea of enforcing it too.
Maybe a loud_volume_protection boolean or similar as an init argument that defaults to True and disallows setting the level over a threshold.
A printed warning is not going to be seen unless someone has the terminal open. And if they want to go above the ceiling (because they have a big speaker or whatever), then warnings you can't turn off would be annoying.
I was thinking of more quantitative limits instead of just a boolean. But the defaults would be appropriate for the supplied speaker. Could add .*_max setters/getters for each gain setting, or have a single call that sets them all (with optional arguments whose default values are the default ceilings)
There are a lot of volume and gain settings: https://docs.circuitpython.org/projects/tlv320/en/latest/api.html
Okay, yeah re-reading your comment and thinking more I was coming to the same conclusion about numeric values instead of boolean.
We'll need to check how dac_volume interplayes with speaker_volume and headphone_volume.
left/right, manual headphone, regular headpohone
yeah that makes it trickier to effectively limit / warn
does fruit jam os or the fruit jam library have a simplified volume/gain API?
The TLV library does not really need this API, I think.
It just needs warnings in the guides
Not currently. It just exposes fruit_jam.dac currently and user code can do whatever with it.
we are really talking about a particular speaker
So, that is the place to start maybe. A helper volume function in adafruit_fruit_jam(and maybe helpers for setting headphone / speaker while at it) that simplifies the volume API down to only 1 thing, and then put the warning and enforcement there.
a simple volume API for speaker and headphones (that does left/right together, etc.) might be welcome. And that API can do the limiting. This is off the top of my head. I haven't looked at the libraires at all
if the user wants finer control, it is up to them to use the .dac safely
what do all the non-Python ported games, etc., do?
did someone just choose appropriate volume ranges?
I think so. For all of mine I believe I just copied the code from the TLV320 guide which included setting the volume levels. I assume Liz chose those values when writing the guide but havn't discussed with her.
Some of the existing projects use TLV320 library directly, they were written before the fruit_jam library. Once this change is in we ought to probably change them to use adafruit_fruit_jam so that all of our projects come with the warning / cieling mechanism that we add.
CircuitPython version and board name
Adafruit CircuitPython 10.0.0-beta.2-7-g117b5d1ed9 on 2025-08-12; Adafruit Fruit Jam with rp2350b
Code/REPL
import audiobusio
import audiocore
import audiomixer
import board
import time
import adafruit_tlv320
# setup audio
i2c = board.I2C()
dac = adafruit_tlv320.TLV320DAC3100(i2c)
# load wave file
wave = audiocore.WaveFile("test16.wav")
# set sample rate & bit depth
dac.configure_clocks(
sample_rate=wave.sample_ra...
@wraith crow maybe hold off on further audio changes in your PRs for the moment. We are going to refactor the volume handling in Fruit Jam OS and existing apps to use a new simplified API in adafruit_fruitjam (see above conversation for details). I'm working on this now and it would be good to just do any changes to the apps afterward ideally.
I think an API for handling the sound would be welcome and provide a common codebase. The tvl320 is kinda tricky in some of its settings.
Both 9.1.0 and 9.2.4 are old. Please try it with main which is a 10.0.0 beta.
See https://github.com/adafruit/circuitpython/issues/10522#issuecomment-3132579164
As of https://github.com/adafruit/circuitpython/pull/9344 (included in 9.1.0-beta.4), we no longer always start the BLE workflow, including the file transfer service you mention. Read that PR and see https://docs.circuitpython.org/en/latest/docs/workflows.html#ble for information about how to enable the BLE workflow when booting.
Did you try pressing the reset button as described here? https://docs.circuitpython.org/en/latest/docs/workflows.html#ble
The BLE workflow is enabled for Nordic boards. By default, to prevent malicious access, it is disabled. To connect to the BLE workflow, press the reset button while the status led blinks blue quickly after the safe mode blinks.
This should resolve reported issues:
- https://github.com/adafruit/Adafruit_CircuitPython_PyPortal/issues/139
- https://github.com/adafruit/Adafruit_Learning_System_Guides/issues/3055
If we are intending to make any more releases in the 9.2.x line I can submit a PR for that branch too.
foamyguy & dan, re: discussion on DAC volume... FWIW, in my experience with doing a portable synth project for Fruit Jam, it was pretty useful to be able to directly access dac.speaker_mute, dac.dac_volume, and dac.headphone_volume. In my case I only cared about line level or headphone level output, but I can see how other projects might want to make more use of the built in speaker. I really like the idea of having the FruitJamOS API provide a simplified volume control interface with guard rails, but also letting people use adafruit_tlv320 directly if they want finer-grained control for synth projects.
I have submitted with some proposed changes. https://github.com/adafruit/Adafruit_CircuitPython_FruitJam/pull/13 This adds a new unified and simpler 1-20 volume scale on the adafruit_fruitjam.peripherals object with a limit argument to prevent it from going too loud without deliberate action from user code.
The dac remains accessible directly via fruit_jam.dac so all control that is possible with it can still be done too, but it will bypass the new simpler audio API and thus be a bit more "use at your own risk" with regards to damaging speakers.
Once the API is settled and merged I intend to go over the existing projects from Fruit Jam OS / learn and change any that access the dac directly to use this new API instead.
@lone axle Nice. After reading some of your and others' comments, I'm starting to suspect that the current adafruit_tlv320 library may include some AI hallucinated stuff, or maybe things with swapped endianness. For example, the Functional Block Diagram on page 19 of the datasheet shows that the left and right DAC blocks go to the speaker outputs by way of a 0 dB to -78 dB attenuation stage followed by a 6 dB to 24 dB class-D amplifier stage. That does not match the API documentation for dac.speaker_volume
similar problem with dac.headphone_volume: API docs say
The current headphone volume in dB. :return: The volume in dB (0 = max, -78.3 = min)
but the Functional Block Diagram shows a 0 dB to -78 dB attenuation stage followed by a 0 dB to 9 dB Class A/B amplifier stage
@tiny peak It's possible there are bugs in the driver. I don't have any real knowledge or experience with audio or DACs so all of the different ranges listed are a bit of a mystery to me. If you find parts that don't match the datasheet feel free to submit PRs if you end up finding changes that make it match the datasheet more closely.
I may look into this some more. The datasheet is a 111 page monster and this DAC has quite a lot of features. It's not exactly straightforward.
yeah, it's definitely got a lot going on inside of it. Docstrings and implementation details may have come from the Arduino version of the driver as well which the CircuitPython ones are typically ports of/from.
reading some more of the datasheet... there may actually be a third gain stage... sounds like maybe the chain is digital volume control for each of the left/right DAC, then analog attenuation, then analog amplification.
It kinda sounds like the designers' intended way for applications to control volume is to mainly adjust the digital left/right volume registers because those include a "soft-stepping" feature to spread the changes out over many samples to avoid clicks and pops. So, like, maybe you're supposed to dial the analog stuff in for your hardware in a semi-set-and-forget kinda way, then use the digital gain at runtime? Not sure yet.
Pull Request:
Change line 75 of the library to read return (tz, host, _ESP)
This will return _ESP to the calling program for further use
Bruce
@b-blake what else are you modifying? Did you update the code.py as well?
CircuitPython version and board name
Adafruit CircuitPython 9.2.8 on 2025-05-28; Raspberry Pi Pico with rp2040
Code/REPL
# boot.py for pm2be_emulator
import supervisor
import usb_hid
...
PM2BE_REPORT_DESCRIPTOR = bytes((
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
0x09, 0x00, # Usage (Undefined)
0xA1, 0x01, # Collection (Application)
0x05, 0x08, # Usage Page (LEDs)
0x09, 0x4B, # Usage (Generic Indicator)
0x15, 0x...
indeed usage is currently limited to the range 1-65535 from the code here: https://github.com/adafruit/circuitpython/blob/117b5d1ed9bab67f91f852777bf4cec8ee8b53e4/shared-bindings/usb_hid/Device.c#L101
Page 32 of https://www.usb.org/sites/default/files/hut1_4.pdf does seem to indicate that 00 is a valid usage value for undefined.
If you want to try it out and are able to build circuitpython you could try changing the 1 here to a 0 and see if it allows proper emulation of your USB devi...
It's early stages, but it builds
woah... what's that? do you have any plans for hooking it up to WebUSB, WebAudio, and such?
I've been working on a VS Code extension for over a year now and this is meant to be part of the 'shell'/backend of a custom terminal, rather like this, but CircuitPython: https://github.com/WebReflection/micro-repl
(The broad strokes are blocked in: the REPL terminal, serial port connection, data plotting, syntax highlighting, and workspace management. Now working on refining everything. I've playfully been calling it Mu 2)
Thanks! I almost always update libraries before a release, too.
Thanks. I usually also do this before a release.
Some boards were missing bootloader_id: fields, even though they did have bootloaders available from https://github.com/adafruit/tinyuf2/tree/master/ports/espressif/boards.
I think the JavaScript in download.js is not setting the OPEN INSTALLER buttons properly.
code is:
// update the links of the download buttons for the given langage menu item
function updateFileLinks(option, language) {
var files = option.value.split(',');
parentNode = option.parentNode.parentNode.parentNode;
files.forEach(function(file) {
var extension = file.substr(file.lastIndexOf('.') + 1);
parentNode.querySelector(".download-button." + extension).href = file;
if...
I looked at the datasheet to try to find the power-on reset values for the volume/gain registers. It was indeed pretty confusing: the diagram (repeated twice, I think), shows "attenuation" but that's not the name in the register descriptions, I think.
If we are intending to make any more releases in the 9.2.x line I can submit a PR for that branch too.
Since I am conservative I still use 9.2.8. So I would appreciate it if you also merge this to 9.2.x. Even if you don't make a new release, I can just update my 9.2.x branch and keep it in sync with upstream.
I spent all evening playing with this stuff, including datasheet spelunking and setting up an audio scope to check amplitude changes. One result of playing with volume properties is that it seems like perhaps dac.headphone_volume has no effect at all on the output level?!? That's kinda weird. I plan to keep looking at this. Notes so far are at https://github.com/samblenny/tlv320dac-stuff
Yes
On August 19, 2025, at 5:28 PM, Mikey Sklar @.***> wrote:
mikeysklar left a comment (adafruit/circuitpython#10572)
@b-blake what else are you modifying? Did you update the code.py as well?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: @.***>
[ { @.": "<a href="http://schema.org">http://schema.org</a>", @.": "EmailMessage", "potentialAction": { @.***": "ViewAction",...
I am slowly catching up on CPday video, and in the "What is new in 10.0" there was discussion about /sd and another partitions that would be visible (at least with the FruitJam) when you connect to your computer.
So I was wondering on the (new) meaning of storage.disable_usb_drive() would that hide all the USB partition, or do we need more granularity (like I want SD card to be visible but not CIRCUITPY drive).
Good point that you might want more granularity. storage.disable_usb_drive() turns off USB MSC entirely. Fine to open an issue.
Thanks, editing mp_arg_validate_int_range() is my interim plan B. That is the function that shows up when searching through the source code. I can confirm changing the range validator to start at 0 appears to work and that the py device driver created to pair with this HID descriptor appears, via hidapitester, to send data as intended for this one application.
That change is exactly what I was going to do. If you want to submit a PR, go ahead. Otherwise I can do it.
Please do, thank you. How would I know if the change is made?
Please do, thank you. How would I know if the change is made?
This issue will get closed when it's done. Then it will be in the "Absolute Newest" board builds, and eventually in the next 10.0.0-beta release.
Could you give a link to the actual USB device we are talking about? I found several "PM2BE" or "PM2BEL" but I'm not sure which one it is.
- Fixes #10576.
Allow an HID usage of zero, even though it is "Undefined" in the HID spec: https://www.usb.org/sites/default/files/hut1_4.pdf. At least one known device has a usage of zero.
Looks good to me, thank you.
I didn't test, but did confirm that 0 is valid in the datasheet and saw that the user who found this initially reported that they tried it and it worked for the USB device they are trying to work with.
I'm suggesting a simpler way that is more like other code we have.
If everything in EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS is all zeros, then we could get away with not having this macro and instead using standard designated initializer syntax like below. I think this is easier to read.
epaperdisplay_construct_args_t construct_args = {
.bus = display_bus,
.start_sequence = display_start_sequence.
.start_sequence_len = sizeof(display_start_sequence).
...
}
In C, if any fields are initialized, then the unmentioned fields in the i...
I'm going to close this since it will be fixed by some upstream code when we merge v1.26.
See also https://github.com/adafruit/Adafruit_CircuitPython_TLV320/pull/8#pullrequestreview-3137579378 for some other weirdness.
huh... that's weird
@slender iron did you want me to review this? https://github.com/hathach/tinyusb/pull/3217
you mentioned tinyusb when we talked
Yes please
I think I may try hooking the Saleae up to the SDA and SCL pins on the GPIO header to see if I can watch what the driver is actually doing for the volume setters and getters
ideally an ntp helper would be part of https://github.com/adafruit/Adafruit_CircuitPython_NTP as an example or extra class, rather than a separate library
have you instrumented the python getters and setters first?
no. probably won't get to looking at it until tomorrow
there might be some errors in the register numbers, etc.
also might try/look at the arduino library, which was probably the basis for the CPy code: https://github.com/adafruit/Adafruit_TLV320_I2S
@ladyada,
I have added an ntp folder to the adafruit_fruitjam library, and it works.
It will need some work to make it meet AdaFruit standards, but ir works
The end user would only need to add fruitjam.setup_ntp to their code.
All the setup parameters are in settings.toml.
Bruce
@tulip sleet skimming through Adafruit_CircuitPython_TLV320
/adafruit_tlv320.py, I see that def speaker_volume() calls self._page1._set_spk_volume(), which includes the line:
self._write_register(_SPK_VOL, value)
Then, _SPK_VOL is defined as _SPK_VOL = const(0x26) (page 1, register 38). On the Functional Block Diagram in section 1.4, Page 1 / Register 38 is "Analog Attenuation" for the left speaker channel (range 0 dB to -78 dB). That path also goes through the "Mono Class-D Speaker Driver" stage (Page 1 / Register 42=0x2A, range +6 dB to +24 dB). That register gets set by _configure_spk_pga(), which gets called by speaker_gain().
It's not clear to me why the registers for the right channel attenuation and speaker gain seem to be ignored.
but... it does seem at first glance that the bitfield shifting and masking for Page 1 / Register 42=0x2A are implemented correctly for the amplifier gain bits and mute bit
The most suspicious thing I see is this:
@speaker_volume.setter
def speaker_volume(self, db: float) -> None:
"""
:param db: Volume in dB (0 = max, -63.5 = min)
"""
if db > 0:
db = 0
gain = int(55 + (db * 1.14))
gain = max(0, min(gain, 127))
self._page1._set_spk_volume(route_enabled=True, gain=gain)
The comment says 0 dB to -63.5 dB, but that's the range for the digital volume control (Page 0 / Register 65=0x41 and Page 0 / Register 66=0x42). Also, the gain scaling and clipping does not seem appropriate. The correct range for Page 1 / Register 38=0x26 is 0 dB to -78 dB (table 6-106 in the datasheet)
So, it looks like the driver is conflating the digital volume adjustment stage (Page 0, registers 64..66) with the analog attenuation stage (Page 1, registers 38 and 37 for speakers plus maybe 36 for headphones)
@tulip sleet do you know if there is any support in CircuitPython for hmac? Ladyada mentioned it may have been added at some point in the crypto stuff for matter or something else perhaps.
The proper values for setting Page 1 / Register 38=0x26 are listed in Table 6-24
We have some hmac code for CircuitMatter. I might have gotten it to run on CPy, but I don’t remember. Scott was making CircuitMatter work in CPython, and the I started working on porting that to CPy. I’ll look more tomorrow.
I made a scatter plot of TLV320 datasheet table 6-24 for the speaker volume register value vs. analog gain dB. It turns out to be a non-linear piecewise function, so the linear formula in speaker_volume() can't be right.
@tulip sleet since it will be hard to keep track of the above dac volume research notes here in the chat log, I made an issue for it and copied all the stuff over: https://github.com/adafruit/Adafruit_CircuitPython_TLV320/issues/9
Sorry, I do not have any link. PM2BE is just a name made up for the need to have some file name that makes some DIY context sense. It corresponds to Python Micro To Be Button Emulator where the number 2 means both “To” and “Two”. I do not currently know what the buttons do in context with the device’s real use. My impression is it is a controller with buttons. Why it is not using something like a game controller USB usage is a question.
So is it an actual device that you have, or some theoretical device someone is coding, and you don't have the code?
from this explanation i didnt undersdtand what i need to do when build circuitpython image and inside ciircuitpy drive need add to enable frp ?
The BLE workflow is enabled for Nordic boards. By default, to prevent malicious access, it is disabled. To connect to the BLE workflow, press the reset button while the status led blinks blue quickly after the safe mode blinks. The board will restart and broadcast the file transfer service UUID (0xfebb) along with the board’s [Creation I...
You don't need to change anything in the build, or add anything special to settings.toml unless you want to change the advertised name. But now, what you do need to do is to press the reset button when your status LED blinks blue. If you don't have an RGB status LED, then I think the plain status LED blinks.
We changed this so you have to take an action to start using the BLE workflow, because it was otherwise a security issue. Once you're paired/bonded, then it should start up automatic...
Does CircuitPython make use of RTT (https://www.raspberrypi.com/documentation/pico-sdk/runtime.html#group_pico_stdio_rtt)? I think it would be a more effective alternative to https://adafruit-playground.com/u/SamBlenny/pages/circuitpython-core-dev-debug-tricks#fruit-jam-led-debugging-3205599. You don't even need the official Raspberry Pi Debug Probe. See the section labeled "Debug with a second Pico or Pico 2" under Appendix A of Getting started with Raspberry Pi
Pico-series and the comments on https://github.com/raspberrypi/debugprobe/issues/175.
woah... I didn't know about that! It sounds potentially really useful. Have you used that before with Pico-SDK on an RP2350? Do you have an impression of how much delay it adds? Does it work inside interrupt handlers? Do you need some special software to get the RTT messages? I actually have a pico debug probe, and the Fruit Jam board I'm using has a debug port. So, if that all works, it might be an interesting solution for me.
My tentative plan is to do some profiling in the USB stack using several GPIO pins and Saleae's Logic 2 software. If I set it up right, I'm expecting the resulting logic analyzer trace pulse waves will act kind of like a flame graph showing how much time gets spent in which function. Can RTT be used to do that sort of thing?
I haven't tried it with my Pico 2, but according to my understanding of the "Target implementation" section of https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/, it's just an in-MCU-memory ring buffer of log messages that's shared between the target and the debug software. Thus, I'd assume it'd work inside interrupts, but I don't know for sure.
You'd probably want to configure it to only use non-blocking mode, which according to that linked webpage:
In non-blocking mode only data which fits into the buffer, or none at all, will be written and the rest will be discarded.
Do you have software you like for viewing RTT messages?
This is specific to Rust, but I like the ecosystem around the defmt crate: https://defmt.ferrous-systems.com/. I don't have much experience coding in C/C++.
ah... okay. I just came across a mention of that in connection with probe-rs as I've been reading up on RTT tools. Sounds like Segger has a tool called J-Link RTT Viewer for Linux that might possibly work, but it's not clear to me if that is tied down to only support their own debug probes.
It looks like OpenOCD has support: https://openocd.org/doc/html/General-Commands.html#Real-Time-Transfer-_0028RTT_0029
General Commands (OpenOCD User’s Guide)
hmm... interesting. I used openocd with the Raspberry Pi debug probe and a Feather RP2350 when I was messing with Zephyr stuff a while back. That worked pretty well. Thanks for the tips!
Makes sense, I was unaware that some display drivers are fussy about when chip selects are toggled. I can change it back into individual bus transactions for now, and spin in any cmd sequences. This would eliminate the possibility of regressions.
I believe I now understand the root cause of this problem. It has to do with priority inheritance and mutexes on FreeRTOS, which is the RTOS used by ESP-IDF.
FreeRTOS has some protection against priority inversion problems caused by mutexes. This is explained in detail here:
https://en.freertos.org/Documentation/02-Kernel/02-Kernel-features/02-Queues-mutexes-and-semaphores/04-Mutexes
A task holding a mutex can have its priority raised temporarily to prevent priority inversion deadlocks. It "...
Making this a separate issue again, per https://github.com/adafruit/circuitpython/issues/10561#issuecomment-3211752395. This will be fixed when the DotStar library is fixed not to hold the lock forever.
I just checked, and TinyUSB has an option to use RTT for its debugging output. That could potentially be really useful.
Hello. I found a potential bug in the HX711 library of CircuitPython. I opened an issue 7 days ago : https://github.com/adafruit/Adafruit_CircuitPython_HX711/issues/7. Do I need to do something more ?
- Fixes #10570.
Use CIRCUITPY_AUDIOIO ?= 1 as the default, then turn it off for chips that don't have it with CIRCUITPY_AUDIOIO = 0. That way, it can also be turned off selectively as needed.
Also add some prominent comments to fence the choices for each chip type, to make it easier to find a particular chip's settings.
Also conditionalize CIRCUITPY_ALARM_TOUCH as being dependent on CIRCUITPY_ALARM on boards that support it.
Makes sense, and looks good to me.
Overheating problem is also noticed in my case. With a basic LVGL application with only a spinner, the part of screen near the USB connector is getting really hot. In fact, screen in this area is getting black, making the gadget unusable.
I do not have the device that is to be emulated. I am investigating the emulation feasibility using Circuitpython on an RP2040/2350 class device. Thanks to you all and Frank Zhao it is possible to create the usb event driver side of the task needed to match the usb descriptor. Feasibility is being investigated on a pico with a few button switches. If successful, then the next platform will be an Adafruit Macropad running Circuitpython.
On Aug 20, 2025, at 11:45 PM, Dan Halbert @.**...
This is a minor bug fix for the changes introduced in https://github.com/adafruit/circuitpython/pull/10567.
When adjusting the tempo on a MidiTrack source that is actively playing, the current note (or pause) is set to a duration defined by the previous tempo value until it runs out and a new note (or pause) is played and the duration is recalculated. This can cause de-synchronization if two MidiTrack sources are playing concurrently.
This update simply scales the remaining duration (wh...
The tm_isdst attribute is present in CircuitPython’s struct_time solely for compatibility reason and will always return -1.
https://github.com/adafruit/circuitpython/blob/c2021402cba585c5c13ef52d9b95e2020ac480cc/shared-bindings/time/__init__.c#L136
Recommended: Keep the system/RTC time in UTC and apply offset/DST when required.
@lone axle are you actively working on volume setting fixes in the Adafruit_CircuitPython_TLV320 driver? (asking to avoid duplicating work)
I am not. My primary aim is to get the simplified version in the Fruit Jam library in place and then update the rest of our existing code to use it. It seems to work as is for moving the volume up and down. And we had some folks get blown out speakers so having the limiter in place will be good I think.
Improvements to the base TLV driver are welcomed but not something I'm actively working on at the moment.
okay. I'll continue with what I'm doing. There appears to be at least one significant bug in calculating speaker_volume register values. Maybe other things.
Thank you for looking into it!
Yeah. This is fun stuff. Excited to see it all up and working and boards in stock in the shop.
Is there a guide somewhere that says how to do test builds for libraries to see if the .mpy and documentation builds will run without errors?
I found this: https://docs.circuitpython.org/en/latest/docs/design_guide.html, which looks helpful for making edits. But, I didn't see obvious mention there of how to do builds. Perhaps I overlooked something.
I don't think there is a guide. Whenever I need to build .mpy I end up following breadcrumbs from the actions to the build tool. I can get you the command that builds mpy versions for a library in a moment..
CircuitPython version and board name
LILYGO T-Display S3, ESP32S3
Code/REPL
async def _discover_services_task(self):
if hasattr(self._connection, "_bleio_connection"):
bleio_conn = self._connection._bleio_connection
if hasattr(bleio_conn, "discover_remote_services"):
# іноді треба трохи зачекати
await asyncio.sleep(1.0)
try:
await asyncio.sleep(1)
...
@tiny peak The code that does it inside of the actions task is here: https://github.com/adafruit/workflows-circuitpython-libs/blob/3413c80af1b610fba8d653deec5bd9014a16895d/build/action.yml#L106-L110. I'm not 100% certain what all of the arguments get used for in that context but I've not found them to be terribly important for local testing. I usually do something like:
circuitpython-build-bundles --filename_prefix adafruit_fruitjam --library_location .
with filename_prefix filled in for whatever library I'm working in. This command gets run in the root of the library repo and builds the 9.x and 10.x mpy bundles. It requires https://github.com/adafruit/circuitpython-build-tools
Could you show a complete simple example to reproduce?
Where are you getting HCI TIMEOUT from? ESP32-S3 has native BLE and does not use HCI. But there are multiple LILYGO Display boards, both ESP32 and ESP32-S3. What is the exact name of the .uf2 or .bin file you're loading onto the LILYGO? I want to confirm it is the S3 Lilygo.
Could you give an example that is not using your bleak layer, but just _bleio or adafruit_ble?
awesome. Thanks! I'll give that a try.
Could you give an example that is not using your bleak layer, but just
_bleiooradafruit_ble?
Yes, simply
from _bleio import UUID
from adafruit_ble import BLERadio
from adafruit_ble.advertising import Advertisement
from adafruit_ble.advertising.standard import (
ProvideServicesAdvertisement,
SolicitServicesAdvertisement,
)
radio = BLERadio()
scan_results = radio.start_scan(
Advertisement,
ProvideServicesAdvertisement,
SolicitServicesAdvertisement,
...
Could you show a complete simple example to reproduce?
Where are you getting
HCI TIMEOUTfrom? ESP32-S3 has native BLE and does not use HCI. But there are multiple LILYGO Display boards, both ESP32 and ESP32-S3. What is the exact name of the .uf2 or .bin file you're loading onto the LILYGO? I want to confirm it is the S3 Lilygo.
Possibly i'm wrong, but i found that: A Bluetooth error 0x07 indicates that a device is out of range or Memory Capacity Exceeded
Could you show a complete simple example to reproduce?
Where are you getting
HCI TIMEOUTfrom? ESP32-S3 has native BLE and does not use HCI. But there are multiple LILYGO Display boards, both ESP32 and ESP32-S3. What is the exact name of the .uf2 or .bin file you're loading onto the LILYGO? I want to confirm it is the S3 Lilygo.
The latest one from https://circuitpython.org/board/lilygo_tdisplay_s3/
v9.2.8
You can try it with bitchat app. I used it to simulate ble device with my iphone/android
awesome-circuitpython has some updates.
@dhalbert Apologies if my branch sync messed something up, but it looks like all checks are clear now. Thank you for your work on those boards. Let me know if there's anything else I can help with to get this over the finish line. :+1:
@relic-se Nothing wrong! I just shrunk some boards and will now merge.
@tulip sleet what's the proper procedure to fix stuff like this after pulling newly merged upstream PR's into a local fork feature branch:
$ git status
On branch usb-find-unplug
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: frozen/Adafruit_CircuitPython_DotStar (new commits)
There were initially a bunch of git status lines about modified: frozen/... stuff. When I ran make update-frozen-libraries, it fixed most of them. But, the dotstar one is still left over.
I have this alias for getting the submodules at the right commits:
alias gitsubupdate='git submodule sync --quiet --recursive && git submodule update --init --filter=blob:none'
does what I saw mean there needs to be a PR to update the DotStar version in the CircuitPython repo?
kinda looks like the submodule commit ref is one tag behind the latest in the DotStar repo?
When I did this, it got git status to stop complaining:
$ cd frozen/Adafruit_CircuitPython_DotStar/
$ git checkout 163f2f166aee11d82303492bb1e5af4937e57b62
latest Adafruit_CircuitPython_DotStar tag points to 4b0ba64, so make update-frozen-libraries was one tag ahead of the submodule ref.
looks like that was something about fixing SPI locking to fix a funhouse crash
busio.UART code shows
//| class Parity
(https://github.com/adafruit/circuitpython/blob/6ed41a0d2f7422c89410d53a3ef3156613384ae5/shared-bindings/busio/UART.c#L371)
readthedocs shows
class busio.Parity
(https://docs.circuitpython.org/en/latest/shared-bindings/busio/index.html#busio.Parity)
but it should be busio.UART.Parity?
Yes, I just made that change. We'll update all the frozen modules before the next 10.0.0 beta release. We always do.
Yes, it should be, I just checked in the REPL.
I checked it too, thought it would be a quick PR, but wasn't sure how to make it right
//| class UART.Parity and busio gets automagically pre-ended?
I think the indentation for Parity might be wrong
I'm not set up to build right now, but I could try that somewhat blindly... I don't suppose there's a way to test docs non-locally
#10529 caused some boards to overflow after merging, due to some intervening changes.
This one has jpegio and synthio repeated.
danh, thanks for all the work wrangling releases. makes my head hurt just watching from the sidelines.
so. many. dependencies.
exciting to get all the new synthio stuff though
busio.UART.Parity inline documentation was indented too shallowly, make it appear as busio.Parity, instead of the correct busio.UART.Parity.
Thanks @anecdata for noticing this.
a lot is in my head after 8 years of working on this 🙂
Looks good to me. Thank you!
Looks good to me, thanks for the fix.
I think the 3 failing boards are the ones resolved by #10581
I'm working on a new board (https://www.olimex.com/Products/RaspberryPi/PICO/RP2350pc/) and I've got an initial CP firmware working with the DVI display, but when I try to enable PS RAM using #define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO8) the only thing I get on the serial console is "Serial console setup", nothing comes up on the USB console. Assuming their documentation is correct and the CS line is indeed GPIO8 is there anything else needed to get SPI PSRAM working on an RP2350 board?
ah ha 😁 I was just cleaning up and not expecting any change but the serial console displayed "tlsf_add_pool: Memory size must be between 20 and 9 bytes." A lead to follow......
and with CIRCUITPY_DEGUG_TINYUSB 1.... This prints continually
Serial console setup
*** PANIC ***
HardwSerial console setup
I believe I'm crashing on this instruction:
// Try and read the PSRAM ID via direct_csr.
qmi_hw->direct_csr = 30 << QMI_DIRECT_CSR_CLKDIV_LSB |
QMI_DIRECT_CSR_EN_BITS;
in ports/raspberrypi/supervisor/port.c
This is deeper into the hardware than I was hoping to have to look :/
Have you confirmed that you actually need to do anything to the chip select pin? Comparing the Fruit Jam and Olimex schematics, they both have CS pullups. The Fruit Jam doesn't have anything else wired up to the CS pin.
perhaps I'm misreading it. not sure
oh... I did miss some other stuff on the PSRAM_CS net. Looks like the Fruit Jam has that going to GPIO47 on the RP2350. hmm
What are you basing the new board off of? Is your source build defining some serial console stuff for TinyUSB debug or ESP32 AirLift serial out?
maybe those are trying to use GPIO8? I say that because the Fruit Jam ESP32-C6 module uses that pin for serial debug
Looking at the two schematics it did look like psram should work fine, I think the Metro RP2350 even used GPIO8
for the PSRAM chip select
My first message was probably misleading, the Olimex board is the new board (new for me 😁)
yeah, I got that part, I'm just wondering if you copied an existing board def to create the olimex board that you're working on
like, maybe there's some lingering use of GPIO8 defined in a spot that you overlooked?
I think I started from the Metro RP2350 but it could have been the Fruit Jam, I definitely borrowed from both
I looked pretty carefully for any GPIO8 conflicts, but I'll give it another look
what serial pins is tinyusb set to use?
I get a bit confused about the differences between tinyusb/uart/usb resources. The serial UART is using 0 & 1
I see in ports/raspberrypi/boards/adafruit_fruit_jam/mpconfigboard.h that there's a #define DEFAULT_UART_BUS_TX (&pin_GPIO8)
#define DEFAULT_UART_BUS_RX (&pin_GPIO1)
#define DEFAULT_UART_BUS_TX (&pin_GPIO0)
I'm trying to remember where I found the uart pin config stuff for TinyUSB. I was just looking at that the other day. Might be off in lib/tinyusb somewhere.
I think there's a way to turn off USB serial, maybe I'll dig up the setting and give it a try just to make sure there's no conflict from there....
err, I'm thinking that was on ESP and you could use the esptools to flash the bin. I don't know if there's an easy option on the RP2350 to do the same....
When you saw the error messages after doing the CIRCUITPY_DEGUG_TINYUSB 1 thing that you mentioned, are you sure that was the same error as was happening without enabling tinyusb logging?
I'm wondering if there's some lurking thing that defaults to sending TinyUSB uart logging data to GPIO8.
I decided the tinyusb PANIC message was a red herring and didn't really think about it much more. GPIO8 is used on the Fruit Jam to communicate with the ESP network coprocessor though so I suspect that would have problems if there was a conflict with tinyusb.
how long after the board boots are you hitting these errors? As I mentally review things I've heard people mention in relation to weird low-level bugs with bringing up different boards, I remember sometimes there's talk of adjusting oscillator startup delays.
that's about the extent of my knowledge on such things. curious to hear what you come up with if you figure it out.
Maybe a second after power up, I am using the PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 setting from the Fruit Jam and the PSRAM is the same part number.
Thanks, I appreciate the brainstorming, if I get it figured out there will probably be a PR to add the board 😁
yeah. good luck. I'm very curious to learn more about weird ways things can go wrong as I'm presently trying to track down some odd behavior in the USB stack.
Breakthrough! Don't have the answer yet, but after talking I noticed that the feather_rp2350 uses the same psram chip and uses GPIO8 for the CS line and I just loaded up that firmware from circuitpython.org and it loads and sees the memory 😁
nice!
I suppose you could just do a recursive diff on the board directories for the feather and your new-board-in-progress
maybe something will jump out
rogue ifdef... who knows
Yep, but unfortunately one of the first things that jumps out is that the feather is an rp2350a and this board is the rp2350b so there's going to be differences in how the port does things even if the board files are exactly the same. But at least I know the chip works and can be seen by CP
Well that was a lot of wasted time and noise for nothing, it had something to do with my build environment. I now have the dvi and the psram working, on to the next peripheral 😁 but that's enough for tonight!
does the 2350B differ in other ways besides just more pins exposed?
Not sure, I was afraid it did before I discovered, my problem was in my build environment
For people interested in improved TLV320DAC volume controls
( 🔥 🔊 😱 🚒 ), I've got a draft PR in progress at https://github.com/adafruit/Adafruit_CircuitPython_TLV320/pull/10
It's pretty far along. I found a few issues with the headphone signal chain, which my PR has fixes for. That includes a lower default volume for safe use with earbuds. I've tested that part, and I'm reasonably confident it's good. I also revised the doc-comments so the html docs built by Sphinx will be more complete (include some constants that got left out, etc).
Speaker signal chain still needs testing.
I tested the speaker, fixed a bug, and now it's ready for review and testing. Could probably use several sets of eyes and ears reviewing the proposed changes. From looking at the driver code, it seems like the default speaker volume was actually increased at one point, so there may be a project guide somewhere that uses the TLV320DAC with a higher wattage speaker. These changes are aimed at the 8Ω 1W speaker for Fruit Jam, so I'm not sure what the effect on other projects might be.
As noted by a user on discord:
FYI, on the Circuitpython Downloads page for the Elecrow 3.5" touch LCD, https://circuitpython.org/board/elecrow_crowpanel_3.5/, the image is completely wrong - it's showing an epaper display iwth a case, not the 3.5" board with a touch LCD.
It turns out we did already have a crowpanel 3.5 photo, but the .md file had been pointing to the wrong image. But I did swap it to a new image that shows the LCD rather than the back of the board along with correcti...
@tulip sleet when you have a moment I'm curious about hmac from back on the Matter work. Is/was it ever usable from CircuitPython? or how big of a barrier would there be to enabling it? The interest arises now because it seems to be necessary for modern AWS auth. The AWS_IOT library uses an older one that is no longer supported I think. I am looking into using amazon polly TTS service for a project idea from Limor.
Oooh there is an implementation from micropython here: https://github.com/micropython/micropython-lib/blob/master/python-stdlib/hmac/hmac.py I'll see if this can be used under CircuitPython
Yeah, following up on this. Between the micropython hmac implementation and adafruit_hashlib I was able to successfully make a request to AWS 🎉 
that might also be useful for generating TOTP codes?
There are a few TOTP projects on learn I know: https://learn.adafruit.com/search?q=TOTP but I am unfamiliar with the crypto that underpins it.
can it do hmacsha1 and hmacsha256? IIRC, that should cover what most auth services need.
looks like this one has a bring your own HMAC function in the code: https://learn.adafruit.com/circuitpython-totp-otp-2fa-authy-authenticator-friend/software
I think it must be doing hmacsha256. This is the code I have https://gist.github.com/FoamyGuy/6375c15b8e5d67753d23017e63023e51 in _sign() it does hmac and passes sha256 function.
My version is here: https://github.com/adafruit/CircuitMatter/blob/circuitpython/cm_hmac.py
The unknown error here is "not connected". I'm not sure why you became disconnected. Can you try it with something other than the bitchat app, like some simple BLE peripheral?
Normally one wouldn't call connection._bleio_connection.discover_remote_services() directly, but instead use the adafruit_ble API. Some examples are in https://github.com/adafruit/Adafruit_CircuitPython_BLE/blob/main/examples. For instance ble_uart_echo_client.py does scanning, and ble_uart_echo_test.py acts as...
@mikeysklar Is this resolved now? I don't see it as a core issue, but as a library issue.
@tiny peak is dac_volume intended to control output from the speaker? In testing it seems like raising and lowering it does not change how loud the audio coming from the small JST speaker is.
speaker chain is dac_volume -> speaker_volume -> speaker_gain, and 1 dB of change to any of those should sound approximately the same as 1 dB of change to another (note that speaker_gain step size is 6 dB though)
What code are you using to test with?
if you're using my test code, the "q" for +1 dB and "z" for -1dB dac_volume adjustments are pretty subtle. You should be able to hear a definite change by the time you move ±6 dB though
Also, when you say "small JST speaker", do you mean the 8Ω 1W mini speaker from the Fruit Jam kit? That's what I calibrated to.
from adafruit_fruitjam import FruitJam
fj = FruitJam()
print(f"dac_vol: ", fj.peripherals.dac.dac_volume)
fj.peripherals.dac.dac_volume = -40
print(f"dac_vol: ", fj.peripherals.dac.dac_volume)
fj.peripherals.dac.headphone_output = False
fj.peripherals.dac.speaker_output = True
print(fj.peripherals.dac.speaker_volume)
# fj.peripherals.dac.speaker_volume = -1
print(fj.peripherals.dac.speaker_volume)
fj.peripherals.play_mp3_file("saves/awspollyoutput.mp3")
But play_mp3_file() is new and not in the released library. It is the mp3 version of play_file() which does wav files.
Yes I think it's the same one, though mine is older I think from PyGamer days but not certain.
dac.speaker_output is a magic change-lots-of-stuff-at-once property that will overwrite previous changes to dac_volume
I'd recommend having a go with the test code that I posted in the PR, or at least using the same order of property setting calls
the tester is set up with a continuous tone, then you can use keys above the QWERTY left hand home row to increase various volume / gain settings and keys below the home row to decrease them.
spacebar will toggle the speaker amp power, so you can compare headphone jack noise level with and without the speaker turned on
Okay, I commented over on the PR, I'd like to add that as an example in the repo if possible.
Sounds goood. I'll add that file to the examples folder and put a brief "Usage Examples" section at the top of the API reference page. That will explain how the easy way to use the API is to start with speaker_output = True or headphone_output = True, then read dac.dac_volume to get your initial volume setting, then provide a user control so people can changedac_volume
I actually have one of these WeDo 2.0 kits and can test this directly.
@dhalbert - Agreed. This is a library issue and can be closed.
It is nearing resolution with NTP code being integrated to the Fruit Jam network.py module.
https://github.com/adafruit/Adafruit_CircuitPython_FruitJam/pull/14
Thanks @lone axle !
Thanks everyone. Have a great week 👋
thanks @lone axle
@lone axle I'm working on example code for you for the TLV320 PR. Ruff absolutely despised my coding style for the existing example code, so I'm having to rework it a bit.
Ok sounds good. Feel free to use noqa comments if it is being overly difficult.
I tried that, but it didn't seem to work. do you have examples of known working noqa comments?
There is a line that disables one of the rules: https://github.com/adafruit/Adafruit_CircuitPython_Display_Text/blob/7d1f187aac8e899e791324cc78633bf4f32c984b/adafruit_display_text/text_box.py#L267 you can specify different or multiple rules by changing F841 to whatever rule you want it to ignore. Then by custom we put a "human readable" comma seperated list of the disabled rules at the end of the comment as well.
okay, thanks. I'll have another go at that. Might be I put the comment on the wrong line
Unfortunately NO_COMMAND is not zero and mp_const_none isn't either. Think it is worth changing internally?
That sounds like a good plan. Thanks!
Here is the notes document for the next CircuitPython Weekly Meeting. It is in two weeks on September 8, 2025 at the normal time of 11am Pacific / 2pm US Eastern here on Discord. Add your hug reports and status updates to the document before the meeting. If you are unable to attend but would still like to contribute, feel free to add your notes and we’ll read them off during the meeting. Hope to see you there! <@&356864093652516868> https://docs.google.com/document/d/10SvxnkxPP0HhgSv0_x4WXYV0ySvnUcm6KjmpRXEPlUQ/edit?usp=sharing
CircuitPython Weekly Meeting for September 8, 2025 Welcome to the CircuitPython Weekly meeting notes! Feel free to add your Hug Reports and Status Updates before the meeting, alphabetically by your username. During the meeting, we go through them in order. If you can’t make the meeting and would...
that worked. pushed the commit to the PR branch.
fruit jam back in stock 🎉 https://www.adafruit.com/product/6200
CircuitPython version and board name
Adafruit CircuitPython 9.2.8 on Pico W RP2040
Hard fault: memory access or instruction error.
Code/REPL
# This script supports the Raspberry Pi Pico board and the Lilygo ESP32-S2 board
# Raspberry Pi Pico: http://educ8s.tv/part/RaspberryPiPico
# ESP32-S2 Board: http://educ8s.tv/part/esp32s2
import board, busio, displayio, os, fourwire
import adafruit_ili9341
import time, rtc
import wifi
import socketpool
import microcont...
The unknown error 7 here is a Nimble "not connected" error. I'm not sure why you became disconnected. Can you try it with something other than the bitchat app, like some simple BLE peripheral?
Normally one wouldn't call
connection._bleio_connection.discover_remote_services()directly, but instead use theadafruit_bleAPI. Some examples are in https://github.com/adafruit/Adafruit_CircuitPython_BLE/blob/main/examples. For instanceble_uart_echo_client.pydoes scanning, and `ble_ua...
@dhalbert where can I get valid error codes description? Can't find it in docs
It's not in the docs, because the "unknoown" errors are unexpected, and there are a lot of them. So they would be looked up in the source code. In this case, it is ports/espressif/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_hs.h.
Thanks for the report. Could you try with 10.0.0-beta.2 also? https://circuitpython.org/board/raspberry_pi_pico_w/ . You will not need to update the libraries, assuming they are already up to date. The 10.x versions are the same right now as the 9.x versions.
After a few tests, we noticed that you can reduce the temperature by decreasing the LCD backlight to 30 or 40 instead of the maximum 100.
Hope this helps
We could change the default, power-on brightness for this board by changing this line: https://github.com/adafruit/circuitpython/blob/9238ee7d869d5fd1a2d209d1fd58ec59cf656ae5/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/board.c#L83
That sounds like it might be a good idea. Would you suggest 0.4 or 0.3 here? Would anyone else like to weigh in based on their experience with the board?
We could change the default, power-on brightness for this board by changing this line:
circuitpython/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/board.c
Line 83 in 9238ee7
1.0f, // brightness
That sounds like it might be a good...
@peterzhenghj @kylefmohr Could you set the brightness by board.DISPLAY.brightness = 0.4 and see if that helps the high temp you are seeing?
dhalbert, thank you for your quick reply. Version 10.x doesn't help, but finally found the problem. I put the rotary encoder on the wrong pin which caused this. Sorry for any inconvenience.
It should not hard crash, even if a rotary encoder is on the wrong pin. Which pins was the rotary encoder attached to? Did you turn or push the rotary encoder at all?
Only minor changes needed. Should hopefully fix things along with better support for newer hardware.
I was able to approximately reproduce this problem on 10.0.0-beta.2. The original test program has some extra complications that were unrelated problems. For instance, doing list(connection) fais in any case because a connection is more like a dictionary than a sequence. I will be adding some type-checking code to adafruit_ble to make that error more obvious.
The fundamental problem is that this particular device, the LEGO WeDo 2.0 BLE thing, causes a `MemoryError: Nimble out of memory...
Simpler reproducer:
import busio, board
i2c = busio.I2C(board.A3, board.USB_HOST_DATA_MINUS)
It was coded/programmed to pin GP5 and GP7. It crashed immediately at startup
Van: Dan Halbert @.>
Verzonden: dinsdag 26 augustus 2025 19:05
Aan: adafruit/circuitpython @.>
CC: marcelwijn @.>; State change @.>
Onderwerp: Re: [adafruit/circuitpython] Core code crashed (Issue #10583)
https://avatars.githubusercontent.com/u/2847802?s=20&v=4 dhalbert left a comment (adafruit/circuitpython#10583) <https://github.com/adafruit/circuit...
I'd love help testing https://github.com/adafruit/circuitpython/pull/10584 before I un-draft it
-- Fixes #10533
On Fruit Jam and Metro RP2350, a usb_host.Port object is always created on restart, using board.USB_HOST_DATA_MINUS and board.USB_HOST_DATA_PLUS. However, the pins were not claimed in common_hal_usb_host_port_construct(). This made them accidentally available for other uses, such as trying to create an I2C object, and could cause crashes.
This PR claims the pins so they can never be used for anything else, and prevents crashes. Perhaps it should be possible t...
So we eventually need to update to a newer API for Touch? Could you open an issue about this if so? Thanks.
Sorry to say:
Metro ESP32-S2 and ESP32-S3 UF2's load but don't come up. /dev/ttyACM0 appears but not responsive, and no MSC shown.
Feather ESP32 V2 does not come up. No response on serial.
Espressif C3 DevKit board bootloops
Espressif C6 DevKit board shows boot log and then stops.
CircuitPython version and board name
CircuitPython 9.2.8 on Pi Pico RP2040 with adafruit_irremote 5.0.5
same behaviour:
10 beta 2 on Feather RP2040
10 beta 2 on WeAct STM32F411CEU6
Code/REPL
print("code.py")
import board,time
import pulseio,adafruit_irremote
# Maxlen is set high to mitigate a separate hard fault issue encountered, Adafruit_CircuitPython_IRRemote issue #76
pulsein = pulseio.PulseIn(board.D4, maxlen=600, idle_state=True)
decoder = adafruit_...
I confirmed that this resolves the hard crash that was reported in the issue using the reproducer scripts also from the issue.
Thanks for the fix!
Would we want to bring the micropython implementation of hmac into the bundle as adafruit_hmac.py? Or if I am going to use it within a project should I just include hmac.py in with my project files?
Yes, I suspect we'll need to update a number of APIs for IDF 6.0 when the old ones are removed. I'm not sure we need an issue for that work though. We'll bump into it when we upgrade to 6.0.
Thanks for the testing! I saw similar issues on the C5 and assumed it was a C5 issue. So I moved on. I see similar issues on the C6 and ESP32 so I'm hunting it down. I'm hopeful it'll fix all of the different variants and the C5. They added support for picolibc instead of newlib and that may have messed up some of the linking. I'm not sure, and still looking into it. I'll undraft after I've smoke tested successfully on a number of chips.
I'm not sure whether it's possible to reverse the TinyUSB setup. There is an
hcd_deinit(), so maybe it is. Any comments on this welcome.
I don't think it is possible. I believe host is going forever after it is started.
@slender iron fyi I am working on updating pico-sdk and cyw43-driver because we are behind on these (your inlining of the critical section routines is now in pico-sdk)
thought it might fix some RP2 wifi issues but I am not optimistic
kk, always good to stay up to date on them. I don't really like debugging when we're behind
thach merged in the c5 and c61 defs so I can switch back to upstream tinyusb too
Status LED Blink Codes
I am sure I asked this before but can't find the prior answer and internet searches failed me.
What are the 'blink codes' for the non-neopixel LED?
I am working on a new M0 board (SAMD21G18).
- I put it in bootloader
- I drag/drop my CircuitPython build
- The upload finishes
- the board boots
- the status LED blinks 5 times
UPDATE: I just tested a similar board from last year - my COIN_M0 - and I get the same behavior.
Tested with 9.2.4, 9.2.8, and 10.0.0.b2
I don't see what "5 blinks" means. (also, I never get the mass storage device)
5 blinks at the start is probably the 1 second of safe mode blinking
OK. Any ideas for how to debug without the usual CircuitPython console (no serial device and no mass storage device)?
The plot thickens. I found my original test from the prior release. I didn't load new code.
I connect to a Windows 11 machine and I see CIRCUITPY. I use the same cable and PCB and connect it to MacOS 15.6.1 and no mass storage device.
When I run the same test with my new PCB version I get the mass storage under Windows and no mass storage with MacOS.
Update pico-sdk submodule to raspberrypi 2.2.0 and cyw43-driver to v1.1.0, to bring them up to date. I have a tiny hope this might help some wifi problems. But we should be up to date anyway.
I had to do -DUSE_SDIOIT for CYW43 to prevent a compiler warning. See https://github.com/georgerobotics/cyw43-driver/issues/140
Tested on Pico W and Pico 2 W. Both passed a simple wifi test.
Tested on Fruit Jam. HDMI output still works. Also did a small I2C test.
@FoamyGuy If you have a chanc...
I loaded the artifact up on my Fruit Jam and tested my Internet Weather Clock App which seems to work fine. The screen still blanks out occasionally during web requests but it just flashes off and then on again, not really a big deal.
I tested successfully with Fruit Jam OS, the boot animation, and a handful of the included apps as well as a new project that I am working on that uses HSTX, WIFI, and audio. All appear to work as expected. I do still see the display going black during WIFI requests but no worse than before.
I think there will be other cases later, not just e-paper, where the defaults are non-zero. Another example on regular displays is the default 1.0f brightness. So, oh well, let's merge as is.
I also did a quick test on a Pico 2W with a basic requests example all seems to work as expected there as well.
The learn guide here: https://learn.adafruit.com/circuitpython-essentials/circuitpython-mp3-audio mentions:
Because creating an MP3Decoder object takes a lot of memory, it's best to do this just once when your program starts, and then update the .file property of the MP3Decoder when you want to play a different file. Otherwise, you may encounter the dreaded MemoryError.
And the constructor of MP3Decoder notes about the file argument https://docs.circuitpython.org/en/latest/shared-bin...
A few boards are now overflowing by a tiny bit. Remove some modules, consistent with some other SAMD21 boards.
Also fix missing BOARD_HAS_CRYSTAL on one board.
CircuitPython version and board name
Adafruit CircuitPython 10.0.0-beta.2 on 2025-07-31; M5Stack Cardputer with ESP32S3
Board ID:m5stack_cardputer
Code/REPL
No code
Behavior
With Adafruit CircuitPython 9.2.0 on 2024-10-28; M5Stack Cardputer with ESP32S3 the cardputer v1.0 (S3) and v1.1 (S3A) work fine.
But when upgraded to 10.0.0-beta2, with Open Installer, the board bootloop with the screen blinking with just the boot message, never appeari...
More testing points to a MacOS issue (I am running 15.6.1 on Apple Silicon).
I have tested my new board, my old board, and an Itsy Bitsy M0.
They all exhibit the same issues: no mass storage device and no serial device.
Using system_profiler SPUSBDataType does show the board.
did you recently upgrade macOS? I have macOS 26 beta on a mini and haven't yet seen trouble
I am slowly catching up on CPday video, and in the "What is new in 10.0" there was discussion about /sd and another partitions that would be visible (at least with the FruitJam) when you connect to your computer.
So I was wondering on the (new) meaning of storage.disable_usb_drive() would that hide all the USB partition, or do we need more granularity (like I want SD card to be visible but not CIRCUITPY drive).
Sadly, "yes". Just before starting this project, I updated various software including MacOS 15.6.1
do you have any third-party antivirus or backup products running?
No 3rd party antivirus or backup. I do use Time Machine on the Mac.
and you did reboot already?
Yes. Once. I can do it again.
i am at a loss otherwise. I'll upgrade my macOS 26 and see if it's having troubles too. Other mac i have is stuck on Ventura (Intel)
There was a post about a week ago ...
#circuitpython-dev message
... that I just found. It sounds similar (but could be a red herring)
Are your issues on Apply Silicon and are you on 15.6.1?
I am having similar issues of "no mass storage device" and "no serial device" while still being able to locate the device using system_profiler.
Apple Silicon: Yep; 15.6.1: Yep
@empty salmon @devout jolt I just upgraded to the latest macOS 26 beta, beta 8. I tried an Itsy M0 running 8.2.10 and then upgraded it to 10.0.0-beta.2. I unplugged it and replugged it several times, with and without ejecting properly, and also then wrote some files to it and repeated unplugging and replugging it. It did not disappear, and I was able to see the BOOT drive to, to update it.
This is a Mac Mini m1
Summary
I added a port-specific module, RTC to ports/analog. Now the analog port can handle rtc.set_time_source(), rtc.RTC() and r.datetime(). Note that the RTC calibration functions (common_hal_rtc_get_calibration() and common_hal_rtc_set_calibration()) are not implemented and are planned for the near future.
The implementation in the RTC module also enables two functions in the time module, which are time.time() and time.localtime().
The following example prints the c...
Thanks. I was occasionally able to see the BOOT drive and never able to see the CIRCUITPY drive.
This would be the fourth or fifth time Apple has broken something about FAT filesystem access.
You could try doing a backup on some other machine and then doing storage.erase_filesystem() and see if that helps.
Yeah. Sadly.
I am assuming you mean to do the erase on the Itsy Bitsy ?
yes
OK. I will give that a try on my Windows machine. I will also do some testing from Linux.
if you and @devout jolt can file bugs via Feedback Assistant, that would help. You could cross-reference each other's
Thanks. I have the same configuration and the same problem(s).
I can try but it would need to be on a day when someone has slipped me happy pills. I have had so many bad experiences with Apple support mechanisms that I loath even the filing step.
I looked at the release notes for 15.6 and 15.6.1 and as usual they are useless. I think 15.6.1 was a hurry-up release for that zero-day re image files
Those were my conclusions.
Yep, I filed a Feedback several days ago on this. @empty salmon Feedback #FB19813868. I discovered when it gets in this state, it also prevents .DMG files from mounting. Hopefully Dan's experience with the beta means this will be addressed in a few months
Thanks. I included you feedback number in my submission.
As an entry for the record, here is the output from system_profiler which shows my M0 board is recognized as a removable media even though Finder does not show the mass storage device ...
ECCN M0:
Product ID: 0x5687
Vendor ID: 0x1209
Version: 42.01
Serial Number: F159672950304A46462E3120FF143327
Speed: Up to 12 Mb/s
Manufacturer: Bradán Lane STUDIO
Location ID: 0x02100000 / 1
Current Available (mA): 500
Current Required (mA): 100
Extra Operating Current (mA): 0
Media:
Capacity: 8.2 MB (8,192,000 bytes)
Removable Media: Yes
BSD Name: disk4
Logical Unit: 0
Partition Map Type: Unknown
S.M.A.R.T. status: Verified
USB Interface: 2
Important: There is an error in the report. The flash chip on the ECCN M0 is only 4MB. I do not know why it is reporting 8.2MB when in 'bootloader' mode. It does show 4.2MB is 'run' mode.
Coin M0:
Product ID: 0x5687
Vendor ID: 0x1209
Version: 1.00
Speed: Up to 12 Mb/s
Manufacturer: Bradán Lane STUDIO
Location ID: 0x02100000 / 1
Current Available (mA): 500
Current Required (mA): 100
Extra Operating Current (mA): 0
Media:
Coin M0:
Capacity: 4.2 MB (4,190,720 bytes)
Removable Media: Yes
BSD Name: disk4
Logical Unit: 0
Partition Map Type: MBR (Master Boot Record)
S.M.A.R.T. status: Verified
USB Interface: 2
Volumes:
disk4s1:
Capacity: 4.2 MB (4,190,208 bytes)
File System: MS-DOS FAT16
BSD Name: disk4s1
Content: DOS_FAT_16
10.0.0-alpha.8 is the first alpha that boot-loops.
10.0.0-alpha.7 comes up and show CIRCUITPY, but keyboard and serial input do not work.
10.0.0-alpha.2 is the last alpha that works as expected.
I will do some bisecting.
FYI @todbot
This fixes the MICROPY_HW_MCU_NAME for two Pimoroni boards. One was wrong, one used a capital 'A' instead of 'a' like the other boards.
Note that for all of the Waveshare-boards, the name is just 'rp2350'. If this is relevant, someone should look up the boards and fix it.
The 8MB vs 4MB when in bootloader mode may be because UF2 files are 2x the size of the flash they program, so the UF2 bootloader lies to the OS so it will allow the copy to happen
A bisect was infeasible because between alpha.7 and alpha.8 was a merge from MicroPython with hundreds of unbisectable commits. However, I found that commenting out this in mpconfigboard.mk:
SRC_C += boards/$(BOARD)/cardputer_keyboard.c
got rid of the boot-loop and allowed input to work again (at the expense of the on-board keyboard, of course). So I'll take a look at that code.
@lone axle there is an open method on mp3decoder that takes in a new filename
One thing to note is that disable_usb_drive() saves USB endpoints. If we make each drive configurable, then we'd still use the endpoints.
The problem is that common_hal_keypad_demux_demuxkeymatrix_construct() allocates heap objects, but cardputer_keyboard.c wants to allocate an object that lives longer than a VM. So the constructor needs to be aware of this, probably in the style of common_hal_lvfontio_ondiskfont_construct(), which as a use_gc_allocator argument. I may want to generalize the allocation/deallocation routines used by lvfontio, since this is pretty much the same thing.
Thank you, the fruit jam PR is updated updated to use open() now.
Ran this test and it did not improve the situation.
Right now the web workflow only works when the ESP32 joins an existing WiFi network.
It would be very useful if CircuitPython on ESP32 could start its own WiFi access point, so a computer/phone can connect directly to it.
This helps in cases where:
1] No router / internet is available (off-grid, field use).
2] User prefers not to connect through external WiFi.
The AP mode wouldn’t need extra features beyond what already exists — just the same web workflow but hosted on the ESP32’s own WiF...
In the past, we used cardputer without the keyboard support and keyboard was done with KeyMatrix in software/python.
The next cardputer (cardputer adv) will have an I2C keyboard with a TCA8418 (this is an adafruit supported chip available and with a CP driver)... free GPIO will be exposed for expansion module. So while current cardputer works on v1.0 and v1.1, it will not work the same on "ADV".
If you make the CP10 version of cardputer keyboard less, at least it will work, even if it will n...
See #6795 and #8405.
In the mean time, there are some partial solutions with varying complexity:
https://gist.github.com/anecdata/bddc29b0d21f03c339e8641794addeca?permalink_comment_id=5728402#gistcomment-5728402
yeah, I know it, actually I tried this but my board can't connect to my phones hotspot [ android 15] but works fine on actual wifi .
I've started looking into this but haven't found an obvious issue. I am able to reproduce it.
My theory about interrupts appears to be wrong. If I blink the LED for every interrupt, it appears to continue the same during the black period. I haven't confirmed with a logic analyzer though.
There is also no long SPI transfer. I'm seeing lots of little ones instead.
My next theory is that we're trying to push too much through the memory bus and throwing off the DVI timing. However, slowing the...
I have not tried the smaller resolution specifically with the reproducer script but I can tomorrow. I have definitely seen the same issue appear with other projects that use the 320x240 resolution though. The say and spelling project I'm working on now uses that and shows this same behavior when downloading MP3s.
The product overlay project that I've been working on with JP also uses 320x240 resolution and has the same blanking happen.
It's likely unrelated but ...
today, when testing both my COIN_M0 and the Itsy Bitsy M0 running both 9.2.8 and 9.2.1 under Windows 11 (with the most recent major pack?) I was having problems saving code.py - I would throw an error and if the device had disconnected. I would have to unplug / replug to sort it but "save" would cause the problem to occur again. I tested with multiple USB cables and different USB ports.
what editor were you using?
Thonny. ... I didn't think to try another method 🫣
Thonny does not write to CIRCUITPY directly. It sends invisible commands to the REPL (file.write(...)) etc.
it's not a good test of CIRCUITPY access
I thought a "file save" from thonny did an actual "file save".
I did not use "run".
it still uses REPL commands, I think. That way it runs smoothly on non-USB boards that can't support CIRCUITPY USB access.
I will test with a simple file copy then.
maybe not, though, because CIRCUITPY would be read-only to the REPL, on second thought. I may be making this up
IIRC, certain file editors have problems because they write to the filesystem differently.
https://learn.adafruit.com/welcome-to-circuitpython/recommended-editors
I remember Notepad++ had a lot of problems back in the day, but doesn't now.
I know thonny's "run" is done by streaming the Python into the REPL.
Interestingly, it recommends Thonny
I wrote that section 🙂
I have used Thonny extensively but to rule it out, I will just try "copy" from the file system.
That's me taught then :)
no, i appreciate it, and I didn't remember exactly how I recommended Thonny. It was a real problem earlier on with a lot of editors that they didn't flush to disk
Back when I was using Notepad++ on Windows I noticed the bad disk flushing, so I
- saved locally
- created a desktop shortcut to a script that copied files to the circuitpython device
- Gave a the desktop shortcut a keyboard shortcut
So all I had to do is save, then do something like "CTRL+ALT+S" or whatever to upload it.
I teach my CircuitPython workshops using thonny. For that, I use an RP2040 based design. It's been great.
I will focus on getting a reproducible flow on Windows and test with a couple different M0 boards.
Theoretically, they should all be stable.
Right now there is no standard hook mechanism to do some C initialization in a general way after the VM starts. That was how I was thinking of creating the cardputer keyboard object on each VM instantiation. I could add something.
MicroPython has a _boot.py file which is usually frozen in that runs startup code for the VM. Often this mounts the filesystem, etc. However, MicroPython runs boot.py, _boot.py and main.py all in the same VM (if I remember right).
We have no such mechanism...
hi friends what's a good font for small text on those 64x32 matrix leds? the default terminalio.FONT builtin is ok but if there were one only like 6 or 7px tall that was still legible i'm curious
i want to put 4 lines of text on the screen (or one large one on top and two small below) and i'm not sure how to begin with that. i'm novice to python but do have a little bit going so far just not sure how to properly address matrixportal (using the ESP32-S3 based matrixportal fwiw, the docs seem really towards the M4?)
there are few small fonts around, 5pt and up, not sure where I got them (maybe various learn guides), but if you search you may find them: l_10646, LEDBDREV, MartianMono, NotoSans, PressStart2P, roboto, RobotoMono, tahoma, verdana
THANK YOU! i appreciate you taking the time to distill a shortlist for me , i will search out!
i tried the roboto, tahoma, verdana 8pt and wasn't happy, didn't try smaller but lemme try the rest on that list and in diff sizes
there are verdana 5-7, tahoma 5-8, several roboto 5pt and up
ah, here it is... https://forums.adafruit.com/viewtopic.php?t=203655
ok yeah that's what i found too i just hadnt tried them all yet, and the first few i plucked out didn't seem to be as legible as the default terminalio.FONT builtin
ill play with some more and see... next then is to figure out how to address the screen right and i guess that's labels?
i'd like to have a simple way to address the rows of the screen and "paint" to them
displayio works the same whether it's M4 or S3
ok thanks, ill look there. maybe that's what ive been missing.
brand new to this ecosystem
my project is to make a SPL monitor to connect to my Smaart SPL logging system's websockets API... i figure'd there has to be some sort of portable asyncio out there right it's got wifi, could just have it live display in the front of house
an alternative to splitting the screen into labels is something like this (I haven't tried it with other than builtin terminalio font, but it should? work https://gist.github.com/anecdata/0e426cc9d150c078f7f0b276afa6ff57
there is asyncio, but you're at the mercy of the blocking granularity of each module or library
but it can still be a huge help to get things multitasking
which is sorta-ok cuz i dont really expect more than an update every second or three, faster refresh would be ideal but my tolerance is huge here
it's just going to be going the whole time at events as a audience display
yeah ust 3x values from a json blob from a websockets endpoint printed to the screen, that's basically it
we should probably take this over to #help-with-circuitpython , this channel is more for core firmware development
oh hahaha sorry yes indeed, ill post there - did not realise the distinction
My experience: none of my devices can connect for web-workflow. In normal operation, I always need multiple calls to wifi.radio.connect() to establish a connection. This is true for both the Espressif and the RP2xxx port. The web-workflow in contrast uses a single try. This could also explain why this works for your "normal wifi", but not for the hotspot which maybe just needs to try harder.
I analyzed the code (again for both ports) and I think it has a flaw: it bails out on the first err...
CircuitPython version and board name
CircuitPython 10.0.0-beta.2-20-gedc82ddfee-dirty on 2025-08-29; linux [GCC 14.3.0] version
Adafruit CircuitPython 9.2.8 on 2025-05-28; S2Mini with ESP32S2-S2FN4R2
Code/REPL
from collections import deque
class Deque(deque):
def __init__(self, values, maxlen):
super().__init__(values, maxlen)
def append(self, value):
super().append(value)
d = Deque([1, 2], 3)
d.append(3)
print(list(d))
Be...
I created a 5x7 font based on the HP100XL. It's already in the right format for use with CircuitPython. You can find it here and if you browse the parent project, you will find the CircuitPython code for using it
Just curious. The Library Bundle has not been updated since August 10. Is that expected? Several libraries have been updatded since then.
No, that seems like something is broken. Thanks for mentioning. I will look into it
That was due to Github disabling cron actions automatically when there are no commits in a repo for 60 days. These jobs are inside of the adabot repo currently. There is an open issue to move the reports task to a different repo to avoid the problem. Looks like some more tasks will benefit from that move too.
I re-activated just now with the button so the tasks should run correctly on their next scheduled attempt.
This resolves: https://github.com/adafruit/adabot/issues/373
If merged, should happen at the same time as merging: https://github.com/adafruit/adabot/pull/403 in order to avoid duplicated task runs from the different repos.
The only change made from the original workflow files was the addition of repository: 'adafruit/adabot' inside of the actions/checkout task in two of the workflows.
It seems like the rest should work to me, but it tough to say for sure without having it try t...
@solar whale we ran a bundle update manually so there is a new release now: https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/tag/20250829.
Longer term solution for the root cause is in the works.
@tulip sleet I think I have a fix for the blanking. wait on beta.3 for me please
(blanking during esp32spi request)
great - I am still working on release notes.
Thank you!
I think I missed something with my COIN_M0.
Two questions:
Question 1:
I have Adafruit_CircuitPython_NeoPixel frozen and I have CIRCUITPY_FULL_BUILD = 0.
It seems I need to explicitly add neopixel_write to my COIN_M0 board using CIRCUITPY_NEOPIXEL_WRITE = 1.
Is this correct?
Question 2:
I have not built in a while. I now get `Minimum GCC version 14" but I do not see where I get GCC version 14 for atmel-samd boards.
= 1?
(sorry, I am so used to Discord on mobile that on desktop, ENTER keeps submitting my post)
CIRCUITPY_NEOPIXEL_WRITE ?= 1 is in py/circuitpy_mpconfig.mk, so it should be on by default. However, neopixel is not frozen in by default.
I add FROZEN_MPY_DIRS += to add it to my board. after the build, when I use import neopixel I get the error from neopixel.py line 20 with is the neopixel_write.
if you just do an import neopixel_write in the REPL, does it fail?
SPI was using DMA to transfer to PSRAM. When a cache miss occurs, the DMA can't switch to another transfer and throws off DVI timing.
So, only use DMA with SPI when the buffers are in SRAM. This will slow down SPI transactions when the FIFOs are empty and the CPU is busy running a background task. It will still be correct though since we control the SPI clock.
Fixes #10557
could you upload your mpconfigboard.mk using the + to the left or point me to it?
I think I've fixed this for the RP2350. The issue was that DMAing to or from PSRAM can stall out the DMA peripheral during a cache miss and throw off the timing of other DMA transfers. My fix makes SPI transfers use the CPU when one of the buffers is in PSRAM (or flash). This will potentially slow SPI transactions but ensures DMA transfers aren't stalled.
@tulip sleet This is waiting your review: https://github.com/adafruit/circuitpython/pull/10499
this is the repository copy which does not have the explicit CIRCUITPY_NEOPIXEL_WRITE = 1
(and sorry for the slowness but me dev env is a mess because I build in a VM on Mac but mac currently can load CP so I have a remote into a Windows machine for uploads) BLECK!
you can do make print-CIRCUITPY_NEOPIXEL_WRITE BOARD=bradanlanestudio_coin_m0 to see what it thinks the value is
do a make clean before a build if you change the .mk files
i felt like I had to test this, but maybe not
I have done a make clean BOARD= ...
The setting is = 1
so do a rebuild an then try import neopixel_write
Is this the right place to ask about my struggles to get two pi pico cowbell can bus hats to communicate with each other? The write buffers just fill up like nothing is being sent out.
better to ask in #help-with-circuitpython
this is more for core development discussions
The support forum is a good place too: https://forums.adafruit.com/viewforum.php?f=60
@lone axle want to wait on the cron changes until next week when we can watch it to make sure it is working?
Yep sounds good to me.
I'm not working again until Wednesday but you can do it Tuesday if you like. I'll hold off to approve though so it doesn't get done over the long weekend. Thanks for doing it!
FYI we're waiting until after the long US weekend to switch this.
Similar mp_obj_cast_to_native_base() would probably need to be added to the other methods in the class.
sorry for all the bothering. ... I am feleing pretty dumb at the moment.
I now have the newer GCC for atmel. When I build I get an error OPT_OS_ZEPHYR is not defined. It's coming from .../supervisor/shared/usb/usb.c
your submodules may be out of sync: Run this:
alias gitsubupdate='git submodule sync --quiet --recursive && git submodule update --init --filter=blob:none'
i mean run what the alias does. You might find the alias useful
take out the --filter=blob:none. Sounds like your git is somewhat old
FYI: git is 2.34.1
that is pretty old. See https://learn.adafruit.com/building-circuitpython/build-circuitpython#using-a-version-of-git-that-can-do-partial-clones-3146710 about using a newer git
it will save time on git fetches
have you consider updating to macOS 26 beta or is that too dangerous?
can you back out 15.6.1? I know Apple makes that hard
i do remember that from previous attempts
serve me right for accepting the update in the first place
well, it was an important zero-day fix. were you updating from 15.6 or earlier?
this is all kinda why I use very standard linux for a dev machine
15.6.0 to 15.6.1
I may take an old windows laptop and nuke it for linux
I have a few that are more than good enough for CP development
as a matter of fact, I will add that to my to-do list
I am going to test the FruitJam on a usable monitor...
There was a branch of the loading that failed to set max_slots. This led to unpredicatable allocation failures.
Fixes #10560
I suspect #10564 is the same psram issue
I've tested with my Weather Clock and that no longer blinks while it's performing the web requests. I had also seen the blinking when playing MP3 files from the SD card and this seems to have resolved that as well.
Since port_malloc() allocates outside of the CircuitPython heap, I think you're going to have a storage leak here if the program stops and you restart the VM. But since PulseIn has a finaliser, you could add a port_free() for raw_symbols to common_hal_pulseio_pulsein_deinit() .
Sorry for the delay in the review.
I also tested with the OP test program and see no blanking on an HDTV. Great, thanks!
are you looking at #10564? I will merge the lvfontinfo after I re-run the failing job (which looks like a CI glitch).
ya, it is more complicated because PIO can't just wait for more bytes and work the same
Got a Cynthion capture working to see what's going on between the gamepad and the Fruit Jam as I run this test code. Looks like the USB transaction to check the device descriptor is working fine on the wire. So, I'm guessing that means that somewhere in TinyUSB or the CircuitPython USB stack, that data isn't getting copied as it should (hence the all zero buffer thing).
This is the Packetry capture:
<img width="986" height="704" alt="Image" src="https://github.com/user-attachments/assets/2e...
Turns out It makes a difference whether I use the Adafruit generic SNES gamepad (low speed USB) or an 8BitDo SN30 Pro wired gamepad (full speed USB). With the SN30 Pro, I get the behavior shown in the previous comment (immediate all zero descriptor reads after the first successful read). With the low speed Adafruit gamepad, the all zero descriptor reads don't begin until I unplug the gamepad.
This is the same DMA from PSRAM issue.
The DMA can get stalled by DMA to/from PSRAM. So, copy the data into SRAM when we need to. Fail if we can't.
Fixes #10564
w00t. yay for bug fixing
@slender iron ok, I will make a release unless you have anything else.
I did another capture for the low speed gamepad. On the Cynthion side, it looked pretty much the same with a long series of successful 18-byte device descriptor read requests happening at about 5ms intervals and lasting until I unplugged the gamepad.
On the serial console side, the descriptor reads were successful (no errors about all zero result) until I unplugged the gamepad. After I unplugged, I started getting all zero descriptor error messages. When I let that run, it lasted until `Cons...
If I change the reproducer code to have time.sleep(0.01) (10ms) before each attempt to read the device descriptor, then the SN30 Pro (full speed) acts like the Adafruit gamepad in that it's fine until I unplug the cable. But, if I increase the sleep to 20ms, then unplugging doesn't cause the all zero descriptor errors. Smells like there's some kind of queue getting backed up or transaction that takes a while to timeout.
Automated website update for release 10.0.0-beta.3 by Blinka.
@tannewt
I think someone else who is more familiar with the codebase (and C) should make a proper fix.
@dhalbert
Yes, the diff was never meant to be merged as is. I didn't try all the methods, but at least pop() has the same issue.
This pull request is to add the neopixel_write and pixelbuf modules to the build for the COIN_M0. This is to enable 'out of the box' support for neopixels ~(which is already a frozen library for the board)_.
A full new CircuitPython 10 build environment was used to build and deploy. The contents of boot_out.txt are provided for reference:
Adafruit CircuitPython 10.0.0-beta.2-23-g4b2624a27b on 2025-08-29; Bradán Lane STUDIO Coin M0 with samd21g18
Board ID:bradanlanestudio_coin_...
I build a new dev environment and have successfully build, deployed, and tested the COIN_M0 with 10.0.0-beta.2.
It goes without saying this is usually a rough step for me but I have submitted the PR.
(The usual thanks yet again to @tulip sleet and @slender iron for patiently working with me to get this fix working).
Just tried this with the new 10.0.0-beta.3 release and it acts the same as with beta.2
@bradanlane
This board has external flash, so it's more like Feather M0 Express than, say, Trinket M0. So there is a lot more room, and you don't need to turn off so many modules.
I would suggest using something like the feather_m0_express/mpconfigboard.mk. You can turn off modules that are useless, but I'd leave LONGINT_IMPL = MPZ so you can have longints. And don't set CIRCUITPY_FULL_BUILD = 0. Just remove it and it will default to CIRCUITPY_FULL_BUILD = 1. Then you can turn ...
The coin m0 was originally based off the Itsy Bitsy (about a year ago).
One reason so much is turned off is the coin m0 is a "feature" board and has no exposed IO pins. It really only has SAMD21 analog audio to an onboard piezo, 3 touch pads, and 9 neopixels.
I am reticent to make too many changes as it should then be fully tested again.
I will change CIRCUITPY_FULL_BUILD = 1
I've tested this in my application, and I can confirm that it works without any display glitches. 🔥
CircuitPython 10.0.0-beta.3 Released!
https://blog.adafruit.com/2025/08/29/circuitpython-10-0-0-beta-3-released/
Highlights of this release:
- Convert mono audio to stereo when going through a stereo
audiomixer.Mixer. - Add
audiomixer.MixerVoice.panning, withsynthio.BlockInputsupport. - Add
synthio.MidiTrack.tempo. - Restore missing
audioiomodule on ESP32 and ESP32-S2. - RP2xxx DVI now works on more monitors and has fewer glitches.
Thank you for the fonts.
PS: Maybe you should switch to settings.toml
This PR fixes the syntax used to specify Union type hints used in Radio. Unions can be declared as either Union[type1, type2] or type1 | type2 (after Python 3.10). This PR chooses the first option to stay consistent with the rest of the CircuitPython repo.
Thoughts?
Hey again team,
This PR fixes the type hints for struct_time and time.localtime().
struct_time type error
time.localtime() type error
⚠️ This requires a new import (Optional) and I'm not sure where to specify that or if it's autodetected when generating the timehints?
Thoughts?
Hey team, I've been working through some type issues with 2 minor PRs ^ and a question about BlockDevices over on CircuirPython_Typing. https://github.com/adafruit/Adafruit_CircuitPython_Typing/issues/51
Hey team, Trying to resolve some type errors I'm seeing with sdcardio.SDCard, [storage.VfsFat](https://docs.circuitpython.org/en/latest/shared-bindings/storage/index.html#storage.VfsFat, and th...
This is fine, and the consistency is appreciated. Thanks!.
Thanks!
There are no type imports in in the inline documentation. Optional is a standard import by the type checkers; I don't know exactly where.
I think the BlockDevice protocol description was swiped from MicroPython, and includes things that are not used in core CircuitPython and in libraries like Adafruit_CircuitPython_sd. For instance, ioctl() talks about littlefs, which we don't use at all. I think you can remove the ioctl method. As for start_block vs block_num, they mean the same thing but start_block is more descriptive. For ReadableBuffer / WriteableBuffer vs bytearray, the ...Buffer is more precise.
Thank you for this. I have put up a proposed resolution in https://github.com/adafruit/Adafruit_CircuitPython_Typing/pull/52
Images automagically compressed by Calibre's image-actions ✨
Compression reduced images by 64.2%, saving 17.2 MB.
| Filename | Before | After | Improvement |
|---|---|---|---|
| assets/images/raspberry_pi@3x.png | 2.2 MB | 548.3 KB | 76.0% |
| assets/images/microcontrollers@3x.png | 2.1 MB | 770.5 KB | 64.8% |
| assets/images/boards/original/lolin_c3_mini.png | 1.3 MB | 351.8 KB | 72.... |
Is there some magic to enabling CIRCUITPY_DEBUG_TINYUSB ? I tried uncommenting the #define lines in ports/raspberrypi/boards/adafruit_fruit_jam/mpconfigboard.h for CIRCUITPY_CONSOLE_UART_TX, CIRCUITPY_CONSOLE_UART_RX, and CIRCUITPY_DEBUG_TINYUSB. Tried it with the default ..._TINYUSB 0 and also with ..._TINYUSB 1. In both cases, I can get a copy of the normal console output on the A4 (GPIO44) pin with 115200 serial into a rpi debug probe. But, there's no sign of TinyUSB debug stuff.
i'd look at what that value really controls. There are further logging options in tusb_config.h, I think.
Thanks. Figured it out. The magic is that you have to do #define CIRCUITPY_DEBUG_TINYUSB 2 or perhaps #define CIRCUITPY_DEBUG_TINYUSB 3. The number you pick there selects the log level.
hmm... as I suspected, the USB glitch stuff is a Heisenbug. Turning on debugging appears to add enough delay that the glitch goes away.
My last long bug investigation was also a Heisenberg 😀
supposedly tinyusb debug over RTT is possible. might try that.
supposedly RTT is really fast
Ended up using this procedure: https://adafruit-playground.com/u/SamBlenny/pages/circuitpython-core-dev-debug-tricks#tinyusb-debug-log-3206041
Not exactly sure why, but looking at that made me slightly nostalgic for the old days where my "debug prints" went straight to text video memory, back when a "multiple monitors" meant you stuffed a CGA and a Hercules Mono card into the same case. Which I guess might be ever so tenuously relevant to debugging code on a FruitJam
From what I read of RTT, I think that's sorta how it works? Like, it just stuffs entries into some big circular buffer in RAM, where some hardware peripheral hooked up to the debug circuitry can get at them?
that's why I just write code without any bugs in it, so I don't need a debugger. Of course I'm mostly kidding, but not all kidding. When I got my first computer, it took a while (another six months or so?) before I could save up enough to by any external storage - so whatever I wrote was gone as soon as the pwer went off. And if my code got stuck end an endless loop or poked something it shouldn't have and froze things, oh well... I think this is partly responsible for my tendency to write in a more defensive style which does a lot of internal "sanity checking" as things move along. Those habits have proven particularly useful for embedded programming - I do make mistakes, but the surrounding code usually catches and identifies things fairly well.
yeah... there are times and places where it really pays off to think pretty hard about what your code is gonna do before you turn it loose to do those things.
OK, I want one.... what other CircuitPython options supports RTT? (besides the FruitJam)
trying to figure out how to say this, but in a way I think more about what my code is not going to do, or at least what it's not intended to do yet, and actually set traps to make sure it doesn't go there. Kinda like (and including) typical preconditions / postconditions / asserts, but more... ???
People also spend a lot of time thinking about such things in the realm of Ada / SPARK language
and cars. I think some of that grew out of investigations in to stuck Toyota accelerators or something like that? Might be totally mis-remembering the details though.
But, yeah, generally for times and places where stuff actually needs to work
Personally, for anything beyond moderate complexity I'd just say don't try to write it in C
wait, you mean my CircuitPython microcontroller hobby project isn't MISSION CRITICAL!?? 😉
C++ can be a much better environment for building high performance, high reliability code. Of course in can also lead to unmitigated disaster faster than you can say printf( "hello world" ); if you try and use all the options or constantly chase the shiny new things
maybe not your project. I don't write things any other way...
If you've never experimented with trying to write some stuff in Ada / SPARK, it might blow your mind. Forces you to consider all sorts of edge cases and specify what behavior you intend.
Rust is sorta that way too, but it aims in a bit of a different direction.
Thing about C++ is it can be pretty much anything and everything. Some of those things being safe, and others very much not
Trouble with all of it is that ultimately you have to link against C libraries if you want to get stuff done in a reasonable amount of time.
Actually I thought twice before saying that. I've thought about placing (and most likely some time soon will) a VERY prominent warning section and some extremely blatant clauses in whatever "license" I end up with for my current project stating that this is NOT a "safe" system, and you are strictly FORBIDDEN from using it in ANY project which is channeling enough power or force (i.e. motors, etc.) to cause injury.
I'm probably being paranoid, but I know a bit about building high risk systems and I also know that my current project isn't exactly playing by the rules.
Good luck with figuring out how to handle that. Always tricky to decide how much time and effort to put in and when to call it good and ship the thing.
I highly doubt anyone would even think of using it for anything like that anyway. Well, except for some guy building a life size 40K Space Marine Cosplay and wanting power assist for leg motion....
mmm... yeah, you never know what people will try.
But I really, really want to, just need to find some volunteers. Which is a bit challenging, considering that anyone who participates in discussions on most of the places I frequent (certainly anyone already lurking - much lest posting - in circuitpython channels) is already outside of the primary "non-programmer" target audience for my project. Still, I could always throw out some YouTube videos. (sadly, that's not a joke...)
Tried enabling TinyUSB UART debug logging, but it didn't help. The logging worked, but it stopped the bug from reproducing. So, there weren't any interesting error messages to see. I'm guessing the Heisenbug effect was caused either by additional printf-related delays or by an increase in the TinyUSB stack size (there are ifdefs to increase stack when debug is enabled).
Tried using #define USBH_STACK_SIZE (3*configMINIMAL_STACK_SIZE) to increase the stack size, but it didn't change anything (bug still happens). So, I'm guessing the reason enabling debug logging stopped the bug was that all the printf stuff slows everything down.
It's not in the docs, because the "unknoown" errors are unexpected, and there are a lot of them. So they would be looked up in the source code. In this case, it is
ports/espressif/esp-idf/components/bt/host/nimble/nimble/nimble/host/include/host/ble_hs.h.
I have no something like a beacon, but I have Mi Band 6 that advertise the generic heartbeat and battery sensor services. And there same thing happen when I try to connect to it from esp32-s3.
I have not same problem when connecti...
We seem to have fewer sockets available in CP 10 (espressif 10.0.0-beta.3)? In CP 9, I could use 8 TCP sockets. in CP 10, only 4```py
import time, wifi, socketpool
pool = socketpool.SocketPool(wifi.radio)
socks = []
while True:
socks.append(pool.socket(pool.AF_INET, pool.SOCK_STREAM))
print(f"{len(socks)}") # 8 in CP 9; 4 in CP 10
so I don't think you could have for example, an HTTPS client and an HTTPS server with a connected client (this would not be an unusual use case)
CONFIG_LWIP_MAX_SOCKETS=8 is still 8. The limit of 4 is reached at socket creation time, presumably before the CONFIG_LWIP_MAX_ACTIVE_TCP=4 and CONFIG_LWIP_MAX_LISTENING_TCP=4 limits kick in. (Those haven't changed in 2 years either, but probably at least `_MAX_ACTIVE_TCP should?)
Wow, that's unexpectedly tight. Even 8 seems restrictive.
yes, but many competing demands for esp-idf memory
sure, but that can usually be better handled by allocating on the heap with a smaller default but allowing more on demand
(I raised it to 8 from 4 in a PR years ago)
some esp-idf options have to be configured in at build time, like how many stations can connect to a wifi AP, and probably other wifi and ble things
looks like the main affected bit would be static uint8_t socket_fd_state[CONFIG_LWIP_MAX_SOCKETS]; and static socketpool_socket_obj_t *user_socket[CONFIG_LWIP_MAX_SOCKETS]; in socketpool/Sockets.c
but the config constant hasn't changed, so I'm at a loss why only 4 STREAM sockets can be created now
that's in "our" ports/espressif/common-hal, not an ESP-IDF config
right, something could have changed under the covers in esp-idf
that's kinda weird...
or some new default or config option we didn't tweak yet
I had to upgrade to CP 10 to fix that socket hard fault, but lost sockets in the process
I suppose that's possible - a "new" option seems plausible but if so it's really hard for me to imagine them setting the default that low. I can see it being unusual for CircuitPython apps to bump up against an 8 socket limit, but it would cause far more noticeable problems for C/C++ apps using ESP-IDF
Espressif defaults are quite a bit higher... 10 for LWIP_MAX_SOCKETS and 16 for the other two params above (which don't use memory if not used)
I can poke around a bit - the httpServer listen loop needs to come from that list, as would each active Websocket (although you're only supposed to have one at a time). Shouldn't be too hard to throw enough (near) simultaneous requests at it to see where it breaks on my system.
I think all it would take is 1 HTTPS client, then 1 HTTPS server which then tries to either open a websocket or accept a client connection
4 is painful, 8 is livable
I'm currently running a 10.0 beta-ish fork build for a Lolin S2 Mini. I can switch to 10.0.0-beta.3 (hopefully it won't break my code) - what board/build are you seeing these problems on?
S3, but any espressif board should have the same behavior
10.0.0-beta.3?
yes
(QT Py S3 N4R2, but I doubt flash config or PSRAM have anything to do with it)
OK, running with 10.0.0-beta.3 and it so far everything seems to be working (my fork provides support for __all__, so some from XYZ import *s might have gotten a little wonky with out it)
nothing is jumping out at me from the esp-idf release notes
if you run my code above, do you get 4?
Need to hack togeher a load test
realizing it's not quite that simple... I was going to hit it with multiple concurrent REST requests from Postman and my "proxy" request base wrappers in a Jupyter notebook, but I think the current (non-async) adafruit_httpserver.Server will just "serialize" those
SO guess it's time to finally break the rules and see what happens when I try to open a second Websocket without closing the first one..
or do an HTTP[S] request from within the server route
we should have taken this to a thread o_O
gotta step away for a while
Never too late for fancy threads, we can spin one up when you're ready
so.... multiple active Websocket connections is - at least for my current use case - working
we should have taken this to a thread o_
CircuitPython version and board name
Adafruit CircuitPython 10.0.0-beta.3 on 2025-08-29; Adafruit PyPortal Titano with samd51j20
Code/REPL
>>>
paste mode; Ctrl-C to cancel, Ctrl-D to finish
=== import board
=== import storage
=== import adafruit_sdcard
=== import os
=== import digitalio
=== import busio
=== spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
=== cs = digitalio.DigitalInOut(board.SD_CS)
=== sdcard = adafruit_sdcard.SDCard(spi, cs)
=...
Oh, that is odd, thanks. Could you give a product link to the card that did not work?
Did you try reformatting the card?
Note also that this board supports the builtin module: sdcardio: https://docs.circuitpython.org/en/latest/shared-bindings/sdcardio/, which is very similar but not quite the same as adafruit_sdcard, and is meant to replace it for most uses.
Testing:
1)Run pre-commit run --all-files, Result:
ruff.....................................................................Passed
ruff-format..............................................................Passed
pyproject-fmt............................................................Passed
2)Hardware tests:
- SD-card tested with 'adafruit_sdcard' based on this tutorial
- Ethernet tested with 'adafruit_wiznet5k' based on this ...
CircuitPython version and board name
Adafruit CircuitPython 9.2.8 on 2025-05-28; Adafruit QT Py ESP32-S3 4MB Flash 2MB PSRAM with ESP32S3
vs.
Adafruit CircuitPython 10.0.0-beta.3 on 2025-08-29; Adafruit QT Py ESP32-S3 4MB Flash 2MB PSRAM with ESP32S3
Code/REPL
import time
import wifi
import socketpool
time.sleep(3) # wait for serial after reset
pool = socketpool.SocketPool(wifi.radio)
socks = []
while True:
socks.append(pool.socket(pool.AF_INET, pool.S...
Is there a way to easily revert a [library] PR? Looks like there is a use case on the VEML7700 for using on-chip interrupt functions, including on-chip smoothing, by polling a register (there is no interrupt pin). https://github.com/adafruit/Adafruit_CircuitPython_VEML7700/pull/31#issuecomment-2963463113
OK, to restate this:
There is no way for the host to know that the SD card is "temporarily read-only" if CPy opens a file on the SD card for write. I think maybe we need these rules:
- If, in
boot.py, CircuitPython mounts the SD card as read-only, then the CPy automounter can present the card as read-write to the host computer. CPy cannot remount the card as read-write once it is presented to the host. - If, in
boot.py, CircuitPython mounts the SD card as read-write, then th...
I'm not aware of an easy button it the GitHub interface anywhere. But it should be fairly easy (depending on comfort with git) checkout the last commit before the PR and then submit that as a new PR that would undo whatever came from the PR commits
I can do that tomorrow if you don't get to it, or can't get git to cooperate.
there is a revert on the PR page:
Ooh, nice. Thank you!
It may need to have conflicts resolved in this case. It outputs this error
OK, thanks, I'll do a new PR and back out the changes (re-insert the deletions)
Finally made some progress! Commit 3a19418 of my experimental usb-debug-wip3 branch extends the error handling for common_hal_usb_core_device_ctrl_transfer(). Previously, it ignored some of the possible result code enum values. By adding a check to raise an exception in the case of XFER_RESULT_FAILED, I can get a USBError ins...
-Fixes #10590
Detailed changes:
- For
cardputer_keyboard.c, allocateDemuxKeyMatrixit creates and the objects it holds (all the way down) on the port heap, because it lives past VM's. - To do the above, add support for non-VM heap for
DemuxKeyMatrixand thekeypadallocations it needs by passing an arguse_gc_allocator, as is done inlvfontio. - Add
mp_obj_port_malloc(),mp_obj_port_malloc_var(),mp_obj_new_port_tuple(), all of which allocate on the port heap, not the...
Thank you very much. The artifact works for me Adafruit CircuitPython 10.0.0-beta.3-3-g50922c9a74 on 2025-09-03, but something when wrong in the git action: Build CI / windows (not sure what it is, but it was in error and does not seems related to your change).
I cherry-picked two commits from https://github.com/micropython/micropython/pull/17269/ to fix a gcc 15 build problem on Windows.
Thanks for testing!
@b-blake I am confused as to what is working and not working. Please tell me whether these are right or wrong.
? The Metro RP2040 displays a drive for the SD card and shows its contents on your Windows 10 machine without anything in boot.py.
? The RP2040W with an SD card breakout wired up and the code above in boot.pyshows a drive but there is nothing in it. Or are you putting the mount code incode.py`?
This changed between 10.0.0-alpha.2 and 10.0.0-alpha.3. I am testing with no settings.toml, so no workflow considerations.
Why are these commented out?
The board doesn't have these camera pins connected to the ESP32-S3. I was initially copying the setup from circuitart_zero_s3. They are commented out there as well, so I assumed they weren’t required for CircuitPython to drive the camera-which I later verified by experimenting with the espcamera library.
That's fine. I'll just remove them, since they aren't used.
Looks fine now!
After you make changes and they build, click the circular arrows next to my username so I'll get a request to re-review. Then I'll get a ping about. Thanks.
@dhalbert, @tannewt
The issue is that 10.0.0 creates a secondary SD card instance when there is no native SD Card reader present.
If the user creates an SD Card instance, there are then two. One useable (user), the other useless (10.0.0).
On boards with a native SPI card reader it creates a functional SD Card instance whether there is an SD Card inserted or not.
Or if the user wants it or not.
- I am hoping that 10.0.0 will not create an SD Card on boards that do not have a native SD Ca...
CircuitPython version and board name
Adafruit CircuitPython 10.0.0-beta.3 on 2025-08-29; Raspberry Pi Pico W with rp2040
Board ID:raspberry_pi_pico_w
UID:E6632C85930F4136
MAC:2C:CF:67:08:08:49
Code/REPL
import board
import busio
i2c1 = busio.I2C(board.GP15, board.GP14)
Behavior
Traceback (most recent call last):
File "", line 1, in
ValueError: GP15 in use
Description
If the code interrupted for any reason, be it a coding error, p...
- Fixes #10606
Remove some lower-valued LWIP settings in sdkconfig.defaults on espressif. In particular, removed:
CONFIG_LWIP_MAX_ACTIVE_TCP=4
CONFIG_LWIP_MAX_LISTENING_TCP=4
These settings restricted the number of usable sockets. It looks like LWIP might have started paying more attention to these when it was updated in in ESP-IDF 5.4.1.
These were all removed:
CONFIG_LWIP_MAX_ACTIVE_TCP=4
CONFIG_LWIP_MAX_LISTENING_TCP=4
CONFIG_LWIP_TCP_SYNMAXRTX=6
CONFIG_LWIP_...
@dhalbert were you able to reproduce the initial problem and then verify that this fixed it? If not, I could probably build & test this on a Lolin S2 or S3 mini
Yes, I reproduced the problem easily with the test program in #10606, and verified this fixes it.
Is that all of your code.py? Displays and the busses they use aren't released during a reload. Instead, you must do displayio.release_displays() to release the display and its bus.
I have been trying to reproduce this on a Pico W with a very simple local webserver, running in Python, and an even simpler version of your HTTP test program in https://github.com/adafruit/circuitpython/issues/10455#issuecomment-3166290627, doing 10 requests a second. I have seen cases where the wifi module code starts raising EINPROGRESS errors, but mostly it is works fine.
However (and this is a big "however"), I am consistently seeing a crash into safe mode when I attempt to edit `cod...
Tested with the minimal example, and with an async example with 2-3 servers and the remainder of the sockets as clients, and all of the connections get made. Thanks, Dan!
OK, all set!
Could you now make a PR to add this board to circuitpython.org? See https://learn.adafruit.com/how-to-add-a-new-board-to-the-circuitpython-org-website. Thanks.
I think someone else who is more familiar with the codebase (and C) should make a proper fix.
I am and that is the proper fix for that function. The others need it as well but that's fine. Better to fix it for you first.
There is no way for the host to know that the SD card is "temporarily read-only" if CPy opens a file on the SD card for write.
Correct. If the host enumeration happens while CP has a file open for writing, the host will see read-only until the mount is ejected.
CPy cannot remount the card as read-write once it is presented to the host.
CircuitPython doesn't really mount as r/o or r/w internally. I think the remount setting is only for USB. Instead it checks when trying to open a file f...
Do you actually need these? I'd love to move away from MP_WEAK since these can be used even when not expected. In other words, the compiler doesn't check for correctness here. A #define to enable the function would be compile checked.
The issue is that 10.0.0 creates a secondary SD card instance when there is no native SD Card reader present.
This is not true. It does present a drive to the USB Host by having a LUN designated for SDCard. It doesn't talk to a missing card or create a sdcardio object.
If the user creates an SD Card instance, there are then two. One useable (user), the other useless (10.0.0).
No, there should only be one and it should be available at the LUN created earlier during USB enumeration. This...
@tannewt,
When I plug my MagTag into a USP port on my Windows 10 PC I get two USB drives.
M: CIRCUITPY aka MagTag
S: When clicked "Please insert a disk into USB drive (S:)"
My MagTag does not have a USB/SD Card reader.
It is displaying "MagTag Daily Weather Forecast Display" which does not use an SD Card for data.
Thus my confusion. Why is drive S: created when there is no drive S: to access and it is asking for a disk to be inserted?
Is it a drive that is only accessible from within Cir...
I don't need them, so I'll just remove them. I just spent the time figuring out where to put them, but I can come back to the commit to find that.
I left port_gc_collect() because it was already there.
I'll open an issue about replacing MP_WEAK functions with some guards instead. Did you mean that one might accidentally replace a weak function by mistake?
@b-blake
I tested a MagTag, running CircuitPython 10.0.0-beta.3. I loaded the stock version of the "MagTag Daily Weather Forecast Display" from https://learn.adafruit.com/magtag-weather/project-code-2, after doing a storage.erase_filesystem(), and verified that the program was running.
I then plugged the MagTag into Ubuntu 24.04, a Windows 11 Pro 24H2 machine, and a Windows 10 Pro 22H2 machine. On all machines, I only saw the CIRCUITPY D: drive.
So I don't know where your S: drive is co...
Add support for W55RP20-EVB-Pico and WIZNET_PIO_SPI communication (#10440).
Additionally, add support for the W6300-EVB-Pico2 board with Quad SPI functionality.
Tested with example code and libraries below.
Upstream tinyusb just merged a Pico-PIO-USB submodule hash update to pick up the changes from this PR:
https://github.com/sekigon-gonnoc/Pico-PIO-USB/pull/186 ("optimize to reduce delay between received DATA and sending handshake")
From reading the PR description, it seems plausible it might have some effect on this issue.
Hello, we've created a circuitpython library (https://github.com/sensebox/CircuitPython_VL53LxCX) for VL53L5CX and VL53L8CX ToF sensors based on this: https://github.com/mp-extras/vl53l5cx We are able to bundle the library and also release it but these types of sensor need a firmware file which will be transfered to the sensor on startup. Is there any good way how we could integrate the firmware file to the CircuitPython Package release?
Great! I've just submitted pr to circuitpython-org: https://github.com/adafruit/circuitpython-org/pull/1680
havent read the code too closely, but couldn't you simply convert each of the .bin files to a Python bytes/bytearray object (perhaps each one still on its own file), and import them at runtime, instead of reading a file? effectively the same, but likely simpler to configure the packaging of those files
would need some refactor of the ConfigDataFile class, but shouldn't be too hard
I believe it's possible to bundle .bin files with CircuitPython libraries already. I'm not sure if there is anything "special" needed beyond just including them in the repo though. There is an examplere here: https://github.com/adafruit/Adafruit_CircuitPython_PyCamera/tree/main/adafruit_pycamera where this is done. You could check the code and actions in that repo to see how the bundling work and if it requires anything additional.
as in...
class ConfigDataFile:
def __init__(self, blob):
self.blob = blob
def _read_offset_data(self, offset, size):
return self.blob[offset:offset + size]
# not sure how fw_data would be adapted
# in VL53LxCX.__init
if self._id == VL53L5CX_ID:
from vl53l5cx import fw
else:
from vl53l8cx import fw
self.config_data = ConfigDataFile(fw)
@lone axle I can merge https://github.com/adafruit/adabot/pull/403 and https://github.com/adafruit/circuitpython/pull/10596, but should I do it in a particular order? These are your cron workflow migrations.
I think the order they are merged shouldn't matter so long as they are merged on the same day. It's a cron task so it will trigger only at the time specified, not based on merging if I understand correctly.
great, will do it now
thank you
i thought setuptools ignored non-py files, but that's apparently wrong based on this link 🤣
seems like it packages the whole folder's content, which should work just fine for the usecase above :)
I believe it may not have done that before and was only added when the PyCamera library was in the works.
Thanks! Merging the other PR also now.
(our bundling tools at least)
i'd still go with the "convert to python" approach, so that i can simply import things, relying on relative paths can always become a footgun. but it is more cumbersome
btw, i believe the hardcoded 0x15000 on line 185 was intended to be _FW_SIZE
okay cool! Thanks for pointing to the PyCamera Library, I was already looking for other libraries who might have the same problem but didn't found it.
Hmm, I don't understand why the check fails...
Annotaions section suggest that there is some problem with 'features', I also see 'could not find expected ':''. So I guess it couldn't find ':', but it's in place.
One handy trick to know for finding stuff in CircuitPython libraries is using git submodule foreach in the bundle repo https://github.com/adafruit/Adafruit_CircuitPython_Bundle All of the libraries are submodules so this allows you to use CLI tools like find, git grep etc to search all libraries at once. e.g. this command in the bundle will search for .bin files:
git submodule foreach "find . -name '*.bin'||true"
Though it does also spam "Entering ___" for each repo which makes the output harder to find without searching. So tacking on an extra grep to filter those out can be helpful too
git submodule foreach "find . -name '*.bin'||true" | grep -v Entering
On linux. Sorry, I'm unsure of other platform commands but something similar should be possible.
Wow, putting s space between the 'board_url:' and the actual link worked!
Tighten up gaps in usb.core.Device error handling:
- Instances where
0xff(not a valid enum value) was assigned to thestatic xfer_result_t _xfer_result;variable (an enum type) are converted to usingXFER_RESULT_INVALID(a valid enum value). Both values were used to indicate the condition of waiting for a callback to finish. This change makes usage in usb.core.Device consistent with usage in the TinyUSB implementation. - Callback result code checks are converted from partial cove...
Submitting this as a draft to get comments. Before leaving draft status, I'd like to extend this to set unique USBError.errno values for the different places in usb.core that raise USBError and USBTimeoutError. General idea here is to make sure that TinyUSB error conditions do not get hidden or ignored by the CircuitPython usb.core implementation.
Hello, Working with a BMP581 on CircutPython9.2.8.
The adafruit_BMP5xx library doesnt seem to be in the 9.x library bundle.
So I assumed that I could pull it from github, and compile the .mpy (never done that, docs maybe a little crusty, but mpy-cross generated a .mpy:
(base) mperino@Aku:~/CircutPython/BMP5x/Adafruit_CircuitPython_BMP5xx$ mv /home/mperino/Downloads/mpy-cross-linux-amd64-9.2.8.static /home/mperino/bin/mpy-cross-9.2.8
(base) mperino@Aku:~/CircutPython/BMP5x/Adafruit_CircuitPython_BMP5xx$ chmod 755 /home/mperino/bin/mpy-cross-9.2.8
(base) mperino@Aku:~/CircutPython/BMP5x/Adafruit_CircuitPython_BMP5xx$ mpy-cross-9.2.8 ./adafruit_bmp5xx.py
(base) mperino@Aku:~/CircutPython/BMP5x/Adafruit_CircuitPython_BMP5xx$ ls
adafruit_bmp5xx.mpy adafruit_bmp5xx.py CODE_OF_CONDUCT.md docs examples LICENSE LICENSES optional_requirements.txt pyproject.toml README.rst README.rst.license requirements.txt ruff.toml
however when I copy over adafruit_bmp5xx.mpy and try an import (Adafruit CircuitPython 9.2.8 on 2025-05-28; Raspberry Pi Pico 2 W with rp2350a) :
from adafruit_bmp5xx import BMP5XX
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./adafruit_bmp5xx.py", line 37, in <module>
ImportError: no module named 'adafruit_register'
You need to also install the adafruit_register library. You can find it in the library bundle or use circup.
There are also pre-compiled .mpy files on the github release pages: https://github.com/adafruit/Adafruit_CircuitPython_BMP5xx/releases/tag/1.0.0 though in this case I only just made the first release a few hours ago so this library is still brand new.
I copied yours over, 4byte difference, added adafruit_register, and it's at least importing:
import adafruit_bmp5xx
I opened an issue under: https://github.com/adafruit/Adafruit_CircuitPython_BMP5xx/issues
LMK if I should close it.
my best guess is maybe the difference is based on the version being filled in our not. But I am not sure, perhaps there are specific versions of mpy-cross used that differ slightly.
I'll respond over there and close it. That way it can potentially be helpful if anyone else happens upon it before it gets added to the bundle.
Also looks like there is a change which dropped the generic BMP5XX and is using the more specific and helpful BMP5XX_I2C
from adafruit_bmp5xx import BMP5XX_I2C (good)
from adafruit_bmp5xx import BMP5XX (depricated i asssume)
correct BMP5XX_I2C is the class name moving forward. If we end up adding SPI support there would be a BMP5XX_SPI that is used for that. Possibly at that time BMP5XX class might return as a super class, but that would be an implemenation detail that doesn't change the API. user code would still use BMP5XX_I2C or BMP5XX_SPI
Greatly prefer the new class makes more sense. Thank you for the speedy support!
@dhalbert,
I have a theory that the ESP32 is for some reason also enumerating the USB manager that is used to load CircuitPython.
I say this because COM48 enumerates during a normal run. COM40 enumerates during for a CP load.
Can two drives enumerate on one COM Port?
I do not get the phantom drive on my Fruit Jam with 10.beta-3. I do get a CPSAVES drive (read Only). I think of it as a scratch drive.
Running on: Windows 10 Pro, 22H2, 19045.6282, installed 5/28/2020.
Something in the his...
I do this kind of thing with find . -name '*.bin' at the top level of the bundle repo. I don't bother with the git submodule foreach, since the submodules are just directories anyway.
Ahhhh yeah that is way easier. I got honed in on submodule foreach using it with git grep. But now that you mention it I think that could work the same way with grep and without the submodule loop.
Thank you!
i know you are using submodule foreach All The Time 🙂 to do patches or whatever. Makes sense you would continue the idiom
@tulip sleet I'm going to push button to run the update bundles workflow manually. Having a new release will make it possible to get correct versions of the files screenshot picures used in the guides. I figure it will also be nice to know now if there is any reason it can't complete from it's new home.
Just a few extra things to consider - The b"initializer" in the python source could take up more space than the .bin file contents. However, if you distribute it in .mpy format, that overhead might be removed. And there's also the per-file "file-system", overhead so if an actual .bin file needs to exist somewhere on the CIRCUITPY drive, that will likely add overhead.
Just pushed another commit that sets unique errno values for each place in the usb.core.Device implementation that raises USBError or USBTimeoutError. The idea is to provide more visibility so CircuitPython code can understand what's gone wrong when TinyUSB complains about something.
Reviewers: The last commit deletes two USBError error strings (stalled pipe and no configuration set). Since everything now gets a unique errno code, it's still possible to distinguish those two USBError i...
Just converted this from draft to ready to review.
My apologies, I'm not sure how to post the code, but here it is.
And a fuller console output:
CO2: 2126 ppm ===========================> code running happily
Temp: 29.9/28.7 C
Humidity: 59/56 %
CO2: 2143 ppm
Temp: 29.7/28.7 C
Humidity: 60/56 %
CO2: 2224 ppm
Temp: 29.6/28.7 C
Humidity: 60/56 %
Code stopped by auto-reload. Reloading soon. =======>commenting out the i2c1 line and the display/draw part
soft reboot
Auto-reload is on. Simply save files ov...
On the other hand, displayio.release_displays() seems to work, thank you. Never would have imagined that it works without configuring any displays.
I would expect the 2 solutions to be equivalent in terms of speed and resources usage... But the main point of my suggestion (being easier to pack Python files than "other" files) seems to be wrong, at which point it would be best to just use the existing bin files
Partial diagnosis:
- In circuitpython/shared-module/usb/core/Device.c, the
common_hal_usb_core_device_get_idVendor()andcommon_hal_usb_core_device_get_idProduct()don't check the boolean return value from TinyUSB'stuh_vid_pid_get()function. The code looks like this:uint16_t common_hal_usb_core_device_get_idVendor(usb_core_device_obj_t *self) { ...
In shared-module/usb/core/Device.c, the functions that do endpoint and control transfers wait for their callbacks using a timeout loop that calls RUN_BACKGROUND_TASKS;. That in turn calls tud_task() and tuh_task() along with other CircuitPython background stuff. So, I suspect that whatever is going wrong is somewhere deeper in the TinyUSB implementation.
Possible explanation/fix for the bad descriptor data:
Might make sense to also include a fix for common_hal_usb_core_device_get_idVendor() and common_hal_usb_core_device_get_idProduct() ignoring the TinyUSB return value of tuh_vid_pid_get() as described at:
For an example of when the "No configuration set" message might be useful as a diagnostic, see the description of this issue:
But, in that case, the code is probably only making it to the point where that error message happens because usb.core.Device fails to check some earlier error return codes from TinyUSB (bad vid/pid).
This issue seems to overlap substantially with
which describes a reproducer using Adafruit_CircuitPython_USB_Host_MIDI and a Roland MIDI keyboard.
Latest commit (probably, hopefully) fixes all of these:
- https://github.com/adafruit/circuitpython/issues/10553
- https://github.com/adafruit/circuitpython/issues/10563
- https://github.com/adafruit/circuitpython/issues/9930
The trick was adding a 50 ms delay after the first time that TinyUSB returns a failure result code for tuh_vid_pid_get() or a transfer callback.
CAUTION: The delay thing is a kludge to work around weirdness with TinyUSB's behavior when one of its `TU_VERIF...
Thus my confusion. Why is drive S: created when there is no drive S: to access and it is asking for a disk to be inserted?
CircuitPython pretends there is an SD card drive whenever sdcardio is compiled into CircuitPython. Think of this as a floppy drive without the floppy.
Is it a drive that is only accessible from within CircuitPython? How do I access it?
To use it, you can do what bablokb did.
I thin...
Did you mean that one might accidentally replace a weak function by mistake?
Nope, you may think you are overriding one but don't actually. So, it'll compile and link but not run the implementation you expected. (Lots of IDF issues for us were this.)
Thank you for the PR!
Why do you need a native PIO_SPI object? It seems you are only using this from the Python driver. The PIOASM library has an example of implementing a busio-like UART via PIO all from Python here: https://github.com/adafruit/Adafruit_CircuitPython_PIOASM/blob/main/examples/pioasm_rxuart.py
Want to split out the board definitions from the wiznet module addition? I'm happy to take the new board defs as we sort out the PIO stuff.
I've been playing at getting CircuitPython working with all the peripherals of the Olimex RP2350pc but like the SolderParty RP2xxx Stamp Carrier XL the USB A ports/hub has been wired in parallel to the dedicated USB_DM/USB_DP RP2350 pins. I've mostly got a version of CircuitPython working that respects the CIRCUITPY_USB_DEVICE=0 parameter which allows the device to use the attached USB A ports for USB Host functions (keyboards, mice) at the expense of having to use something like an FTDI serial cable and something like Thonny to transfer files. While I would like to see boards like this supported on Circuitpython.org I know not having a CIRCUITPY drive has been a hard stop for boards in the past. Given that, I'm thinking if I make this firmware available on github for public use, my understanding was that Adafruit would prefer I didn't call it "CircuitPython". I was thinking of simply referring to it as something like RP2350pc Python but my question is, is there an obvious place in the core where the CircuitPython branding can be adjusted?
I am able to reproduce this fairly easily with repeated HTTP fetches (doesn't have to be POST). I think this may be due to PR #10027, which switched to dynamic storage allocation in LWIP. I was able to get a stack backtrace after a failure that reported a tlsf assertion failure and I see that LWIP is doing storage allocate/free during an interrupt context. The port_malloc() and port_free() calls it uses are not protected in a critical section, so there may well be some overlapping stora...
Last commit reduces the delay after a TinyUSB failure result. Previously, I used 50ms to have a big safety margin. But, that seems excessive. I tested unplug detection for many builds with delays between 0ms and 20ms using my pile of USB devices.
A 15ms delay worked fine with everything. Full Speed devices were marginal down to 13ms and failed at 12ms. Some Low Speed devices were okay down to 3ms, but the Adafruit generic SNES gamepad was marginal below 12ms. 15ms seems like enough.
6. Fix missing error handling for
usb.core.Device.idVendorandusb.core.Device.idProduct
I ended up loading these changes on a board I'm testing. Things mostly seemed to work for the narrow case I was testing but I did notice that the Adafruit_CircuitPython_USB_Host_Mouse library now fails when one of these fields fails to be retrieved. It's an simple fix to catch now that there's a specific error code but this will be a breaking change for at least some of the Fruit Jam apps as the...
as these fields seem to error on retrieval relatively frequently.
Interesting. It's definitely been my experience that USBTimeoutError is very common for keyboards, mice, and wireless gamepads connected by USB-C or a USB wireless adapter. I will often see some USBError during initial connections, depending on the device, but I haven't seen much of it during normal usage unless I unplug. Was it a wireless mouse? I haven't tried much of that.
Did you happen to experiment with hotpluggin...
All of the cron tasks seem to have run correctly from in the core repo 
CircuitPython version and board name
Adafruit CircuitPython 9.2.8 on 2025-05-28; Raspberry Pi Pico W with rp2040
Board ID:raspberry_pi_pico_w
UID:E6632C85930F4136
MAC:2C:CF:67:08:08:49
Code/REPL
import time
import board
import busio
import wifi
import sys
import gc
import supervisor
import traceback
import adafruit_scd4x
import adafruit_requests
import adafruit_connection_manager
from os import getenv
i2c0 = busio.I2C(board.GP17, board.GP16)
scd4x = adafrui...
Strangely, I also have similar problems with SCD4x-CO2-monitoring. But I only log the data locally, no wifi involved and it takes much longer until it crashes. It could be a coincidence though. I "solved" it by auto restarting the Pico every two hours. This is not my normal use-case anyhow and so I did not follow up on the error.
In 10.x it appears that os.uname().sysname for some devices changed. The Matrix Portal M4 is one I konw of for sure that changed from samd51 to samd51j19. Getting more specific about the chip type it looks like.
Is that change intentional and likely to stay? If so I found some libraries that use that mechanism that will need to get updated with the new version.
although I guess the library should account for it for some period of time even if it was untentional and going to change back since there are beta releases out with that value.
This was https://github.com/adafruit/circuitpython/pull/10145, I'm pretty sure. It was meant to make the names more consistent.
Does anyone know why most code using the TLV320DAC3100 sets the sample rate to 11030 rather than 11025? Is that a quirk of the dac? I've used 11025 in some projects and that seems to work fine.
I do not know. @lone axle e.g. this line https://github.com/adafruit/Adafruit_CircuitPython_FruitJam/blame/e67239b37b9c82fd3d2557cd3bec3ba5e812e8f7/adafruit_fruitjam/peripherals.py#L160 uses 11030, which is in your initial commit
Did you happen to experiment with hotplugging with and without the changes?
I didn't but I can do a little more playing tonight. My suspicion has been that there's some soft reset occurring to the USB host device and then a timeout has to occur before the IDs become available, but that's entirely based on observation and the fact that putting the "find_mouse" call in a short retry loop has been used as a work around.
I gave these changes a go because I'm very deep into the weeds of a ...
@fleet hollow it is the sample rate used by the boot animation audio file. I used that file a lot for early audio testing it's likely I copied it around to a few places.
maybe that 11.03 is just a rounded 11.025
Exactly what I was thinking
I don't really know much about sample rates though, perhaps 11.03 is rounded? If 11025 is more of a standard that is probably what it should be.
Could you open the file in Audacity and check the sample rate there? 11025 is the standard. 11025x2 = 22050x2 = 44100, standard cd audio
yeah, looks like it is 11025
I just wasn't sure if there was a strange quirk with that DAC that make it incapable of reproducing 11025, but my guess is that isn't the case.
I'm working on some other updates to the FruitJam library. I'll add that fix in there.
as far as I am aware no. I just chose that value based on the properties I think.
thank you
did you see 11030 anywhere else, in a guide example, etc.?
I only see it in that library in the bundle. looking in the fruit jam os...
nope not in fruit jam OS (there is a BASIC line number with that value 🙂 )
I don't see 11030 in learn.adafruit.com anywhere, based on a google site search
so maybe it's just that line
I think it was originally in Fruit Jam OS and got moved into the library. So, we're good! It's fixed in this PR: https://github.com/adafruit/Adafruit_CircuitPython_FruitJam/pull/20
CircuitPython version and board name
Adafruit CircuitPython 10.0.0-beta.3 on 2025-08-29; Adafruit-Qualia-S3-RGB666 with ESP32S3
Board ID:adafruit_qualia_s3_rgb666
Code/REPL
# Test Qualia ESP32-S3 with RGB-666 4" Square Display
# Combination of CircuitPython internet test and RGB-666 4" square display setup
import os
import ipaddress
import ssl
import wifi
import socketpool
import adafruit_requests
import time
import supervisor
import json
import microcontro...
I've just noticed that directories without python code in them seem to take precedent over python code files. i.e. I have:
CIRCUITPY/
boot_animation/
a_spritesheet.bmp
...
boot_animation.py
When I do import boot_animation in the terminal it seems to be trying to import the folder and doesn't execute the code inside of boot_animation.py
In the short term I plan to change the name of the assets folder to work around this. But I'm also curious if it is somehow to possible to make import use the python file instead of the directory that doesn't contain code?
hmm, maybe there is something else wrong in my situation. Having trouble re-creating that now.
There are many CircuitPython boards that don't have a CIRCUITPY drive now, mostly ESP32. I've been itching to try romkey's new circremote that uses a pure-serial workflow like Thonny, mpremote, or code.circuitpython.org
Tried import .filename? [Module name so No .py]
With these files in the root of CIRCUITPY
fake_lib/
a_spritesheet.bmp
fake_lib.py
When you do in the REPL:
import fake_lib
It seems to be trying to import the directory. The contents of fake_lib.py are just print("Hello fake_lib.py") and that value never gets printed.
If you change the name of fake_lib/ to something else then run the same import it will execute the code inside of fake_lib.py
In CPython testing the same scenario results in the opposite behavior, th...
looks like CircuitPython doesn't support that syntax
>>> import .fake_lib
Traceback (most recent call last):
File "<stdin>", line 1
SyntaxError: invalid syntax
Ah maybe that was it, I must have had to clear that up for sen5x base driver or something
Yes, that has given me some hope and I do plan on submitting the board once I work out the last of the issues but as far as I know the boards that don't have CIRCUITPY so far have all had the WiFi workflow available to them so It's possible Adafruit won't want to make this leap yet 😁
Thanks, @bablokb , I feel less ashamed then. With a gregarious application of microcontroller.on_next_reset() my stuff restart nicely now. The bug still remains, of course.
that's import logic. you can import a module from a directory or a single file. It looks for a directory first. In general, you shouldn't have a directory with the same name as a .py file. I'll bet CPython does the same thing
it doesn't, I tried it.
under CPython it will execute the code in the .py file even if there is a folder by the same name with bitmap file in it (same conditions tested on CircuitPython)
Under 3.12 at least.
(.py) halbert@cod:~$ mkdir foo
(.py) halbert@cod:~$ cat >foo.py
print("foo.py")
(.py) halbert@cod:~$ cat >foo/__init__.py
print("foo/__init__.py")
(.py) halbert@cod:~$ py
Python 3.12.3 (main, Aug 14 2025, 17:47:21) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
> import foo
foo/__init__.py
>>>
CPython looks for an __init__.py file and if present, will import the directory module
so MicroPython/CircuitPython probably don't bother to look for __init__.py
that was with python2, python3 doesn't need __init__.py anymore
though you can have it if you need code at the top level of the module
i was just trying to figure out how to indicate that the dir was being used first
@wraith crow In your github comment earlier, you mentioned wanting to discuss USB host stuff here. Sounds good to me. Let's start a thread for it.
but if I rename __init__.py to blah.py, then it indeed imports foo.py. So we could do better.
it may not be worth the overhead of additional logic to fix. I was surprised by the behavior at first and couldn't figure out why the script wasn't running. TBH I thought I had tested it this way before, but I guess I have not. In any case it turned out to only be the first rung of the ladder down the rabbit hole I started on 🙂
sounds good. I started a thread over in #circuitpython-dev
Now that I know it, I will try to avoid naming directories the same name as python files. I opened an issue so it's tracked somewhere but totally fine to close if it's not a priority to change the behavior.
- Fixes #10455
#10027 (added in 9.2.5) considerably improved network performance on Pi Pico by using dynamic storage allocation in LWIP. However, it turns out LWIP can do heap operations during interrupts. Thus the operations need to be guarded in critical sections. Otherwise there are storage-related crashes at random intervals, and I saw storage assertion violations in gdb when a crash happened.
Tested on a Pico W, with a simple test program that did an HTTP fetch from a local server...
Not having CIRCUITPY isn't an issue anymore.
Your product supports at least one standard "Workflow" for serial and file access:
With a user accessible USB plug which appears as a CIRCUITPY drive when plugged in. With file and serial access over Bluetooth Low Energy using the BLE Workflow. With file access over WiFi using the WiFi Workflow with serial access over USB and/or WebSocket.Boards that do not support the USB Workflow should be clearly marked.
Cool 😁
We should probably call out the serial workflow their explicitly. I'd want it to work with code.circuitpython.org
I'll make sure testing code.circuitpython.org is on my todo checklist....
Note we now have a safemode.py too: https://learn.adafruit.com/circuitpython-safe-mode You can then log and restart after the safe mode.
Thanks for looking into this. It is not simple stuff.
I'm mixed about these changes:
- The error checking in getting PID and VID is good.
- The magically fixes things delay is a fix I'd like to avoid. Instead, we can dig a bit deeper into why this is happening. Seems like there will be something tinyusb does during that delay that is important to do before we call more of its API. @hathach is back and can help with this.
- I don't mind exposing TinyUSB error codes back to CP code but do...
- The magically fixes things delay is a fix I'd like to avoid. Instead, we can dig a bit deeper into why this is happening. Seems like there will be something tinyusb does during that delay that is important to do before we call more of its API. @ hathach is back and can help with this.
Okay, I can just remove the delay workaround. If somebody who actually understands how to troubleshoot weird low-level USB glitches wants to tackle a fix for the root cause, that would be fabulous.
*...
I'm trying to get a espressif esp32-c3-lyra board working, and I've been stuck for a couple of days on getting the status led neopixel working. Is there anyone around who might be able to offer some advice?
If somebody who actually understands how to troubleshoot weird low-level USB glitches wants to tackle a fix for the root cause, that would be fabulous.
@hathach is paid by Adafruit to work on TinyUSB, so if you can characterize the problem in an issue either here or in TInyUSB, he can take a look.
This is a second attempt at
with a smaller set of changes to usb.core.Device error handling:
- Instances where
0xff(not a valid enum value) was assigned to thestatic xfer_result_t _xfer_result;variable (an enum type) are converted to usingXFER_RESULT_INVALID(a valid enum value). Both values were used to indicate the condition of waiting for a callback to finish. This change makes usage in usb.core.Device consistent with u...
@tannewt I took a guess at what you might like and made this new PR:
Has anyone tried using https://github.com/czietz/etm-trace-rp2350 ? I think it might be a less intrusive alternative to https://github.com/adafruit/circuitpython/issues/10563#issuecomment-3240829108.
woah... that sounds interesting
@bablokb would you be willing to do some stress testing on this
I backported this to 9.2.x and tested it with my admin-webinterface on my systems. The browser opens nine parallel sockets at the same time. No problems and I cannot see any additional delays.
This is a backport of the commit as stated in the title - in the hope there will be a 9.2.9 release.
Indeed, I read about that and created a safemode.py, thank you for making it part of the record. I have not seen running it yet, the on_next_reset seems to be enough yet. But the bug remains, and the little computer told me to file one, so here it is. I try to do the bidding of our evil robot overlord larvae.
I ran 10.0.0-beta.3 vs. PR artifacts on a mix of Pico W and Pico 2W, rapidly sending packets up to 1KB back and forth. The 10.0.0-beta.3 Pico W had an odd panic (below) after about an hour, but the PR artifacts have been running all night so I don't see any regressions.
Create TCP Client Socket
Connecting
*** PANIC ***
tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAI
[01:00:58.400] Disconnected
[01:00:59.410] Warning: Could not open tty device (No such file or directory)
[01:00...
How does SPIDevice end up getting write(), readinto() functions that are callable from python code? They aren't listed in https://github.com/adafruit/circuitpython/blob/main/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c, but the example code calls them. I assume it is something to do with the enter function, but don't quite understand what it is doing to "tack on" those functions to make them callable. I see the python implementation has a similar thing going on: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice/blob/main/adafruit_bus_device/spi_device.py
I believe calling with on a SPIDevice returns the busio.SPI instance
(handling the locking and unlocking via the context manager)
Ahhh. Thank you
What's the simplest way to generate a lot of interrupts into the circuitpython core (raspberrypi)?
I'm pretty sure the GPIO inputs on the Raspberry Pi are interrupt capable. You should be able to set up an interrupt handler triggered by state change a digital input, then drive it with a square wave generator to get all the interrupts you could want.
Unfortunately I'm not finding any simple API examples to actually do this - if you're running Linux/Raspbian on the Pi then the kernel tends to handle interrupts, and examples for direct hardware access without a linux kernel seem thin.
I'm not wanting to change the core code
just have a lot of background interrupts happening behind the CircuitPython code
Even the arduino bits I've found mention that it's only "faking" it on Raspberry Pis
I can set up various bus protocols or digital streams like PulseIn or countio, but hoping there was an easier way. Tried watchdog, but RAISE isn't implemented on raspberrypi
Just to be clear, you're running CircuitPython directly on Raspberry Pi hardware, not Blinka in Linux/Raspbian or on a Pi Pico, right?
Ah, well that's different ....
the port naming is confusing (Big RPis are broadcom port)
any particular kind of interrupts?
anything really, I just want to stress test some CircuitPython code by having interrupts happening in the background, was hoping for something with minimal setup
I think pio can trigger interrupts
that sounds like a half day research job 😉 I'll try some countio or something
I think that uses pio on the raspberry pi
some things. like keypad poll in the core, so that's no use
almost certainly at the hardware level, I think question is what you can do from CircuitPython to "exercise" something which will cause lots of interrupts
yes
create an spi peripheral and toggle the cs pin very fast?
or maybe I can PulseOut to a PulseIn
it's plausible - maybe probable - that the wifi stack on a Pi Pico uses interrupts, so websocket torture tests might help
thing is, if your interrupt-generating code is in Python, then it will be self-regulating, because a lot of interrupts will slow down python vm execution and result in generating fewer interrupts
I'm actually looking for non-wifi non-socket interrupts to stress test wifi/socket code 🙂
so you probably want to toggle that pin with another board
(well, a Pi Pico W anyhow...)
there is also a way to generate a lot of usb interrupts, I think, but I'm fuzzy on the details
I'm fuzzier
Can GDB be used to mitigate that? I was able to get GDB debugging working with my Adafruit Fruit Jam and Raspberry Pi Debug Probe. It involved compiling CircuitPython from source with the DEBUG=1 argument passed to make, and using the firmware.elf file with GDB in addition to the firmware.uf2 file for flashing.
Wouldn't be surprised if just doing a bunch of console over USB IO requires interrupts - although it could plausibly avoid the need for lots of interrupts with a bit of hardware buffering, DMA, etc... so it would be implementation dependent
no, but usb is polled by the host, and I think there is an interrupt every time the host does the poll, so you could probably poll very often?
thanks, I've got a few things to try now, and will verify before I get too far that the feature actually uses interrupts and not polling in the core
with somethinng like wireshark
@crimson ferry by the way, the wifi module is connected over spi on the pico w, so any "wifi" interrupts would be either spi or pin change interrupts anyways
on espressif I could use Monitor mode
and if the interrupt code ever does any GC managed allocations, it will be extra self-regulating 🤯
you can't do gc inside interrupts
ah, sorry, I misunderstood
sure
this arose because LWIP allocates within an isr, but it's protected now with a new pr
C level allocations can - with great care, sometimes be used safely within an interrupt. But even then it's seriously sketchy, and any simple malloc/free calls will usually (and I only say that to be complete - I have no counter examples...) blow things up.
it's a bit different in micropython/circuitpython, because even the C-level allocations are managed, malloc is replaced
there is a number of specialized malloc-like functions you can use in special cases
Are you able to use picodvi on your board? I think it uses interrupts to set up dma. Rate of interrupts might increase at higher video resolutions?
It does look like countio is actually using an interrupt rather than PIO: https://github.com/adafruit/circuitpython/blob/main/ports/raspberrypi/common-hal/countio/Counter.c#L45
pulseio.PulseOut looks like it also does interrutpts, so maybe you could do a PulseOut to a counter
I may have a board that can do DVI, but I haven't messed with that at all. I'm trying PulseOut now, no need for countio (maybe) since PulseOut is generating its own interrupts.
@tannewt, @dhalbert
#1 I apologize for continuing this conversation. @dhalbert asked me a question and I answered it.
To use it, you can do https://github.com/adafruit/circuitpython/issues/10454#issuecomment-3068049424.
This gives me a third drive. It works just fine. The S: drive is still there.
I believe this is a Windows related bug that will not be resolved. Neither of you can replicate it, so you can't resolve it.
Bruce
The PR seems like a rational fix, so maybe completely unrelated, but under atypically extreme duress (hammering on TCP socket, and hammering on interrupts ...assuming the code is doing what I think), a TCP client will get hardfaults somewhat regularly with PR artifacts on Pico W:
<details>
<summary>Client code (on a Pico W):</summary>
# Adafruit CircuitPython 10.0.0-beta.3 on 2025-08-29; Raspberry Pi Pico W with rp2040
# Adafruit CircuitPython 10.0.0-beta.3-8-g9e7a03cbc2 on 202...
In shared-module/usb/core/Device.c, the error handling for _get_langid(), common_hal_usb_core_device_get_serial_number(), common_hal_usb_core_device_get_product(), and common_hal_usb_core_device_get_manufacturer() is suspicious.
- Tracing call chains, they all end in a
tuh_control_xfer()with a_transfer_done_cbcallback argument. Before those calls, nothing sets the_xfer_resultglobal, so its initial value is undefined. That could cause_wait_for_callback()to end befo...
Also, it turns out the string fetching functions I mentioned in the previous comment don't check if the device descriptor provides strings (i.e. do iProduct, iManufacturer, or iSerialNumber have non-zero string index values). Instead of checking the descriptor to see if a string exists, they just call into TinyUSB and rely on it to return a failure code if the string does not exist.
This approach is potentially troublesome because it masks the possibility of other USB errors. It would ...
Just added a commit to fix missing error handling for product, manufacturer, and serial_number string getter properties. Details of missing error checks at:
- https://github.com/adafruit/circuitpython/issues/10553#issuecomment-3263268914
- https://github.com/adafruit/circuitpython/issues/10553#issuecomment-3263322028
I'm reasonably confident these changes should be enough to resolve issue #10553