Skip to content

Blog

Introducing The CircuitPython Show

CircuitPython Show

I’ve decided to start a podcast! The very original show name is The CircuitPython Show, about - you guessed it - CircuitPython! More specifically, about the people and the cool things they're doing with CircuitPython.

The show will be a question and answer style interview podcast. I’m shooting for each episode to be about 30 minutes. I’ll interview a person in (or around) the CircuitPython community and it will give listeners an opportunity to learn more about that person.

I’m still a ways out from releasing episodes. I’m planning on six episodes for season one and I’ve been emailing invites out to potential guests. So far I have three confirmed guests so I still have a little work to do. If you have any guest recommendations or want to be on the show, please let me know! (Really, please!)

I’m brand new to all this and I’m sure it will take me a few episodes to find my “voice”. I’m recording a teaser trailer and already I’m learning how hard this is! But if you’ll stick with me, I’m guessing the episodes will get better as I go along. I've really enjoyed my time in the CircuitPython community, especially the Adafruit Discord channel, and thought there are enough interesting people to make a podcast about those people and their projects.

A special shout-out to Michael Kennedy, host of the Talk Python To Me podcast. When I was considering doing this he took time out of his schedule to answer some questions for me and make some introductions. (And we’re both using Boostrap Dark for our websites, the similarity is unintentional!)

You can find out more at the newly launched website (running FastAPI of course) or follow the show on Twitter, which I recommend as that’s my platform of choice. I’ll probably drop some spoilers and other info on Twitter first.

I’ll blog some more when the teaser trailer is out or I have other news. Until then, I have a lot of work to do…

CircuitPython 2022

How cool is this: for the last few years Adafruit asks their community to share their individual goals for the CircuitPython community on the internet. From blogs posts to Twitter to YouTube videos (and more!), community members are encouraged to share their thoughts on what they want to build, features, or around the ecosystem.

I’m still fairly new to the community and my goals are much more modest than some of the others, such as the core developers. But I’ve found the community to be so welcoming and patient I thought I’d share a few thoughts.

So here goes.

A look back at 2021

2021 was the year I got into microcontrollers, CircuitPython, and hardware in general. After having bought a Circuit Playground Express in 2020 and it just sitting in a drawer, I went got into it in a big way in 2021. I purchased a rp2040 Feather, MatrixPortal M4, and an AdaBox subscription, starting with the rp2040 MacroPad. More importantly, I used them!

I learned to solder and bought a 3D printer, which makes playing with microcontrollers even more fun.

I built my MacroPad and started the MacroPad Awesome List - because MacroPads are cool. I love seeing what macros the community has come up with and then borrowing those ideas for my own MacroPad. I also created macros for my CAD program of choice, OnShape. (I’d rather learn and use FreeCad, but I really need a color blind mode).

I tackled my biggest project to date with the Sound Reactive NeoPixels Speaker Stand. This was pretty challenging and I wasted dozens of hours trying to port some sound reactive code from a digital microphone to an analog mic before breaking down and buying a digital microphone, which I just should have done in the first place! I’m very proud of the project and it so cool to look at.

Sound Reactive NeoPixels Speaker Stand

2022 Goals

I have two major goals for 2022 centered around hardware and community.

Hardware

I want to finish my Album Art project. I love that I combine my love of the physical (my record collection) with software (CircuitPython, FastAPI), and hardware (LED matrices with a MatrixPortal). I’ve made significant progress in 2022 already and the next step is integrating MQTT into the project. This is a great way to continue building on my novice Python skills as I learn FastAPI for the website that powers this (and asyncio!) as well as CircuitPython.

I’m looking forward to whatever AdaBox brings. This was my Christmas gift from my partner and I’m excited to see whatever ships next and I’m going to commit to building it right away.

Community

The Adafruit community is wonderful, especially the Discord channel. They’re welcoming to everyone and I get most of my (dumb) questions answered. I want to stay engaged and help out others where I can, if possible.

I have a goal of going on Show & Tell again once my Album Art project is done.

Lastly, reading through some of the other folks posting their 2022 thoughts, I want to reach out to Jeff Epler who shared that there might be room for further improvement to ” Continue to help people grow into the roles of reviewer and contributor. Maybe I can put my former experience in writing both documentation and articles for GNOME to use.

That’s it! A lot to look forward to in 2022. I think it’s so cool that Adafruit invites community members to share their goals for the year.

LED Matrix Progress

Now Working in CircuitPython!

When we last left our hero, he was unable to get a 8k image to load over the internet and display an image on the MatrixPortal and 64x64 LED….

I decided to take a different tack and I ordered a Matrix Bonnet for the Raspberry Pi from Digikey (Adafruit was out of stock). Let's just say that didn't work at all and I have reason to believe it’s the Bonnet after trying it on two different Raspberry Pi 2s and a Pi Zero 2.

I don’t remember what I was doing this morning, but I was back to playing with the matrices and the MatrixPortal. Danh in the Adafruit Discord, who had already helped me previously by recommending ImageMagick for my project, helped me out again. He shared a code sample making it easy to switch the MatrixPortal from read / write to read only, as only it or a computer should write to it at a time. I accidentally reset my MatrixPortal this morning and wiped it. I had some regular Python code to write the image to disk, so I tried it out on the MatrixPortal and what do you know - it worked!

I was able to initialize the network, connect to my web server, download the 64x64 image, write it to disk, and display it on the matrix.

That was a pleasant surprise, so now I’m on to the next step: converting the JPEG image from Discogs to a tiny bitmap that can be displayed in CircuitPython.

I wasn’t sure if I could use ImageMagick in Python and a couple search engine queries later I was using the Pillow library.

It’s this easy:

from PIL import Image


img = Image.open("cash2.jpg")

new_img = img.resize((64, 64))
rgb_img = new_img.convert('P')

rgb_img.save('cash2.bmp')

It takes the image, in this example the cover art to one of Johnny Cash’s American Recordings albums that I had saved as cash2.jpg locally and converted it to a tiny bitmap. I transferred it up to my web server and it works! Here is the Man in Black himself in his 8 bit glory:

Johnny Cash Album Cover

It’s exciting to have solid progress. Now I need to integrate the Pillow code into FastAPI. After that is a big chunk of work in figuring out how to get MQTT to work, but more on that later.

The Right Tool for the Right Job

With silversaucer.com now up and running with about half the functionality, I’ve turned my attention to try and displaying a bitmap on the Adafruit matrices.

I have two 32x64 matrices and have soldered my Adafruit Matrix Portal so it can display a 64x64 image. The first thing I learned was that the bitmap’s size correlates directly to the matrix. Thanks to Dan in Adafruit’s Discord server, I discovered the ImageMagick library can handle turning any image into a bitmap with a couple command line arguments. I ran through some random albums, downloaded the artwork and converted about half a dozen of them to bitmaps. They’re so cute and tiny!

64X64 bitmap of the album Beautiful Garbage by Garbage

And it looks like this:

Beautiful Garbage on the 64 x 64 Matrix

I’ve spent most of the week trying to do this. I can display a 64x64 bitmap from the filesystem, I can do a slideshow and display multiple bitmaps, but the one thing I can’t do: download and display over the internet. I’m not even able to download it, save it to disk, and then display it. One of the challenges of working with CircuitPython is staying within the memory limits as it’s a microcontroller, not a full blown computer like a Raspberry Pi is.

I’m trying to do the following:

  1. Parse the Discogs JSON to get the URL to the album’s cover art. (You must be authenticated to get a link to artwork).
  2. Take the image and convert it to a bitmap. ImageMagick can do this, so I need to save the jpg to the filesystem and then convert it and save it again (or display it in memory).
  3. Send a link to the image or bitmap to my local network to the device powering the LED Matrix.
  4. Display the bitmap on the LED Matrix

Even with almost 40k free, I run out of memory trying to download and display an 8k bitmap. I’ve tried to stream it without any luck. None of the CircuitPython libraries (image load seem to work no matter how I call it over the network. A few folks helped me out in Discord with some pointers, especially around showing how much memory is available which was super helpful, but no luck.

If there is one lesson I have learned since trying to port the sound reactive code for my speaker stand in trying to go analog instead of digital, is use the right tool for the right job. I spent dozens of hours tearing apart CircuityPython code and was never able to make it work. After spending a few days on this, I’m not going to make that mistake again.

If CircuitPython can’t display the image easily, let’s try a Raspberry Pi. I still have a bunch of them just lying around and the Matrix Bonnet is only $15, so I put in an order to Digikey yesterday. (Both of us being in Minnesota, their products get to me quickly).

Now I have a couple more design decisions to make. What kind of MQTT message do I want to send to my Pi locally? The image link? Convert the image to a bitmap and save on my DigitalOcean droplet or on my local Pi?

Longer term I’m leaning towards storing all this data in a database. The Discogs API seems a touch slow when returning a random album, and this would speed it up considerably, especially when loading and displaying an image. More updates next week after the Pi bonnet comes.

December 2021 update and next steps

Now that I’ve semi deployed Silver Saucer, with working SSL, it’s time to think about what’s next as the year comes to an end.

I can either start working on the “Choose an album” functionality or I can start working on the IOT / image piece.

The “Choose” uses similar methods to the random functionality, but first it must return a bunch of lists and then display them in a drop down box. The user chooses what they want to play, hits submit, and that artwork appears. I need to build the methods to return the various lists and decide how many choices and what happens with each one on POST.

I don’t have Javascript installed, so one option is to take the HTMX course offered by Talk Python for interactive drop down menus.

Either way, some research and some work to do.

The second option I thought was going to be a lot easier than it turned out to be. I know the image URL location from the Discogs API, now I need to pass that to the MatrixPortal and 64x64 LED Matrix display and draw it.

I’ve spent most of the last two days trying to wrap my head around displayio and other drawing libraries. First, the LEDs only support bitmaps, and those have strict rules. ImageMagick has a convert tool built in to help with converting images at the command line. I can convert them, and display part of them, but I haven’t figured out how to display them at 64x64x yet, and that’s been most of the last two days.

But even before I know which image to draw, I need to send a message from the SilverSaucer.com server to the MatrixPortal. I’ve successfully installed MQTT using SSL (which also took a good chunk of all day Sunday) to do that. Now I just need to code the subscriber portion in the MatrixPortal and add the push in the web app. “Just”.

So that’s where I’m at. I need to pick one and stay with it as I’ve been kind of jumping around as I get stuck. And I’m very stuck, but writing things down does bring a greater clarity for what needs to be done.

The Right Tool for the Right Job

With silversaucer.com now up and running with about half the functionality, I’ve turned my attention to try and displaying a bitmap on the Adafruit matrices.

I have two 32x64 matrices and have soldered my Adafruit Matrix Portal so it can display a 64x64 image. The first thing I learned was that the bitmap’s size correlates directly to the matrix. Thanks to Dan in Adafruit’s Discord server, I discovered the ImageMagick library can handle turning any image into a bitmap with a couple command line arguments. I ran through some random albums, downloaded the artwork and converted about half a dozen of them to bitmaps. They’re so cute and tiny!

I’ve spent most of the week trying to do this. I can display a 64x64 bitmap from the filesystem, I can do a slideshow and display multiple bitmaps, but the one thing I can’t do: download and display over the internet. I’m not even able to download it, save it to disk, and then display it. One of the challenges of working with CircuitPython is staying within the memory limits as it’s a microcontroller, not a full blown computer like a Raspberry Pi is.

I’m trying to do the following: 1. Parse the Discogs JSON to get the URL to the album’s cover art. (You must be authenticated to get a link to artwork). 2. Take the image and convert it to a bitmap. ImageMagick can do this, so I need to save the jpg to the filesystem and then convert it and save it again (or display it in memory). 3. Send a link to the image or bitmap to my local network to the device powering the LED Matrix. 4. Display the bitmap on the LED Matrix

Even with almost 40k free, I run out of memory trying to download and display an 8k bitmap. I’ve tried to stream it without any luck. None of the CircuitPython libraries (image load seem to work no matter how I call it over the network. A few folks helped me out in Discord with some pointers, especially around showing how much memory is available which was super helpful, but no luck.

If there is one lesson I have learned since trying to port the sound reactive code for my speaker stand in trying to go analog instead of digital, is use the right tool for the right job. I spent dozens of hours tearing apart CircuityPython code and was never able to make it work. After spending a few days on this, I’m not going to make that mistake again.

If CircuitPython can’t display the image easily, let’s try a Raspberry Pi. I still have a bunch of them just lying around and the Matrix Bonnet is only $15, so I put in an order to Digikey yesterday. (Both of us being in Minnesota, their products get to me quickly).

Now I have a couple more design decisions to make. What kind of MQTT message do I want to send to my Pi locally? The image link? Convert the image to a bitmap and save on my DigitalOcean droplet or on my local Pi?

Longer term I’m leaning towards storing all this data in a database. The Discogs API seems a touch slow when returning a random album, and this would speed it up considerably, especially when loading and displaying an image. More updates next week after the Pi bonnet comes.

blog/silversaucer

The python3-discogs Library

In June 2020 Discogs announced they were going to discontinue support for the Python library they maintained. Shortly after, a few members of the community picked up where Discogs left off and announced a community version of the library.

I remember Discogs’ announcement but I forgot about the community. I had starred their repository at some point but randomly came across it again late last week.

I started to refactor my project on Friday to use the API to see if it would be easier than using requests to parse all the JSON. And it was. In one method I think I went from about 40 lines of code to 5. Yay APIs!

I didn’t understand the API thoroughly and got stuck on a few parts. The documentation is pretty good and has examples using the Python REPL but I still had a couple problems trying to put it together.

It turns out that the community members are very responsive and helpful to questions. I quickly received some pointers and help on the right way to do things and by the end of the weekend I not only had re-written the code to get a random album, but it was trivial to use the same code to get a random EP or single. In fact, I bet my code is way more Pythonic now as I’m only using one method for both.

This is another example of the beauty of open source. One group discontinues support but another is able to pick it up and keep it going.

With all the help I received, I wrote up a lot of the functions to use the API that would appear in a Python program and started a discussion and submitted a pull requestto update the documentation. The community has been welcoming and it’s the least I can do to give back.

Silver Saucer Discogs Integration

The progress continues in moving Silver Saucer to FastAPI. I've spent almost all of my free time learning FastAPI from the Talk Python course. It would probably have gone faster if I was directly following the training course, but of course I'm doing my own thing.

I'm trying to do two things at the same time. First, build this in FastAPI, but use my own content, including CSS, page structure, and integrating the Discogs API instead of using a database. Second, I'm re-using some code (mostly the services that call the Discogs API) from the old Silver Saucer Pyramid site. I haven't touched that code in almost a year (for shame!) so I have to review that as I go.

Yesterday was a good day as I was able to wire up the Discogs integration using 90% of that old services code. It turns out when I create the class to manage the call, it's pretty specific as the first time I got it to work, I thought I was pulling in the record title, but instead it was the image URL, which I quickly converted to an image since I had something working:

Discogs returning an album image of Liz Phair's Exile in Guyville

From there, I was quickly able to call the rest of the data I wanted from the API and display it on the page. My memory of how the release date works must be off or requires more research. I thought I could pull both the release date of the specific album. For example, if it's re-issued like Garbage's BeautifulGarbage was last month, it would show a November 2021 date. But there was a main release date that should show 2001, but I can't seem to find it in the API. Oh well.

I was also able to update the HTML for the Genres and display that better than I did on the last site, parsing the list and showing it as sub-bullets. Another obligatory screenshot of everything working when clicking a random album:

Discogs returning an album image of Japandroids last album

I need to start coding the 7" / EP random function and then start on manually choosing a record. I have a couple questions on the training and thankfully Talk Python offers office hours, which are today!

Lots to do and I'm having fun doing it.

SilverSaucer and FastAPI Progress Update

I’ve made significant progress this weekend in taking the Building Full Web Apps with Fast API training from Talk Python.

I’m enjoying the course and it’s cool to learn how async works in a web application. My site will be far less complex than the training and I’ll probably skip the database part, though I might want to wire that up later depending on how fast the Discogs API really is.

One of my favorite things about taking courses from Michael Kennedy and Talk Python is that the design patterns are consistent across courses. While my knowledge of Python is sill limited, I was able to pick this up quickly as I move from a pattern of controllers in Pyramid to doing most of the same work, just now in the viewmodel itself in FlasAPI. At one point I was pretty confused, because I had the knowledge of where we were going in the training, it just wasn’t there yet. As I stuck with it, it made more and more sense. (Nice work, Mr. Kennedy!)

Obligatory work in progress screenshot, with a new logo coming soon:

Silver Saucer homepage running on FastAPI

After I finish up coding the login piece, I’m going to start work on the Discogs integration. Hopefully it won’t be too hard to move that over as I did have it working in Pyramid. I spent way too much time yesterday working on Bootstrap and CSS to tweak the site. It was a bit frustrating as I really don’t know Bootstrap (or CSS for that matter). In the end it’s close to what I want, but I never was able to get horizontal lines working. I would never make it as a frontend developer.

I also had an aha moment for phase 2. In phase 2, when I select a record to play (or from random), I want it to display the album art on my LED matrix. I wasn’t sure how that was going to work if I did it on a public website. I was playing around with the idea of hosting it in the house on a Raspberry Pi for local access only, but doing the login chapter gave me an idea.

I’m going to disable the ability to register logins on the site and not link to the login page. I’ll be the only one who can login, and with the stored cookie, it will know it’s me. If it’s me, the site will send a MQTT message back to the MatrixPortal controlling the LED to display the art. I just finished setting up my MQTT Mosquitto broker, so hopefully I can get this to work. MQTT is new to me, but I know CircuitPython already integrates with it. But that’s why that is phase two. Let’s not put the cart before the house because I already have so many projects….

Adafruit Macropad Awesome List

Inspired by the CircuitPython Awesome List, I've created an Awesome List for the Adafruit Macropad.

I finally found some time to set mine up after I received mine this past summer in the Adafruit AdaBox subscription. I've 3D printed a couple of cases for it already and also programmed mine to work with the Onshape CAD software.

It's pretty cool and I was curious to see what others had programmed for macros for their applications and I figured why not create a list for everyone!

If you have any suggestions for what to add, please let me know or feel free to fork and send a pull request. Contributing guidelines are in the list and if you have any questions, you can find me on Twitter or on the Adafruit Discord (link in the list).