21 June 2021

CircuitPython Stuff

I think it was back in 2015 when I happened on MicroPython while seeing if it was possible to run Python on microcontrollers, but I think there were some limitations at the time? It might've just been that I wouldn't've been able to use it on the Teensy boards that I have. Anyway, I pretty much just brushed it aside back then.

Don't remember how or when I originally found CircuitPython, but I had designed a test board with the ATSAMD21E18A-A microcontroller, some tactiles, and a USB mini-B jack; the board ended up sitting for a while since it was kinda meant to answer questions (mainly if I didn't need pullup resistors for the tactiles), but I wasn't interested enough to fully go forth with it.

Earlier this year, I ended up getting a lot more interested in CircuitPython (maybe because I was visiting Adafruit's site more often than not?) because of a custom game controller idea (which will be written about in a separate post), and started the deep dive.

Eventually I learned that I need pins PA30 and PA31 for programming the bootloader (so it was a very good thing that I didn't make that test board because I would've had to solder directly to those pins), that I would need a programmer (SEGGER's J-Link series) and some sort of way to interface the programmer to the project board. I planned on using some probe pins (same ones from the Raspberry Pi clock and controller converter projects, and also some taller ones if I happened to need a little more clearance) on the adapter board between the programmer and the project board, and some circular contact pads on the project board for the four signals I would need to connect to the programmer (3.3 volts, ground, SWCLK, SWDIO).

With at least that, I was able to at least designed the boards for the projects I had while worrying about the other questions later. At this point, I think I was just going to use the generic bootloader and wasn't sure if I was going to have to build a custom version of CircuitPython. When I got to the point of looking into the configuration files for CircuitPython, I did find that I would need to build CircuitPython myself for each project (really each MCU at the very least), and I forgot how I ended up poking at the configuration files for the bootloader, but I found that the generic one wouldn't've worked for my uses because it looks for some sort of status LED.

I had gotten Adafruit's Trinket M0 for answering the question of needing a crystal and for just tinkering with stuff like the DS3231 and ADS1115 (yeah, I know the Trinket has analogue inputs, but the ADS1115 was supposed to be used with the Raspberry Pi for testing... the Trinket ended up being more of a knee-jerk purchase).

I had ordered a whole slew of boards that I designed and ordered a bunch of stuff from Mouser (and a few things from Digi-Key) when I was ready for the first "wave" of projects. The two types of programming adapter boards (the aforementioned probe pin type and a custom one for the project I would be able to complete) were part of this order. The adapter with probe pins was a bit difficult to solder because the annular rings for the probe pins were too small, but I had gotten it soldered enough, and the custom adapter just had wires soldered to the board that would be soldered temporarily to the project board.

Cloning the git repositories and adding the project I was working on at that time (Griffin Powermate hack, more on it in another post), it wasn't too hard to get CircuitPython or the bootloader built, nor was it hard to programme the bootloader. The problem I ran into was that I ended up building an alpha version of CircuitPython 7 (which caused library issues) because I didn't fully read the CircuitPython building guide, so I had to fiddle around a bit before I got it to build CiruitPython 6.2.0, but everythign worked as expected after that.

I think while looking for a set of probe pins (like a header, but with probe pins instead) that would probably make it easy to solder, I found a dimension for the preferred annular ring size and I think I went and changed the vias for the probe pins I had, since I originally had nothing to go off of. (The preferred annular ring dimension was from the same company of the probe pins I have.) After getting the new set of adapter boards (and pins because I didn't want to bother with the old adapter boards at that point), I found that it was much easier to solder (especially the ground pin) and the pins ended up much more stable.

When it came time to do stuff with the dev boards I made (one with the ATSAMD21G18A-A and another with the ATSAMD51J19A-A, these will be in another post), I was ready with having CircuitPython and the bootloader ready for the boards. The problem I ran into was trying to programme the bootloader onto either board using the probe pin adapter, and I tried compressing the pins the entire way onto the pads, but that didn't seem to help, so I defaulted to using the custom adapter for getting the boards programmed.

I know I was running over the order of the contact pads when I thought to compare them to the pins, but I don't remember when it was besides that I already had programmed all the dev boards, and when I brought up the adapter board in EAGLE, I found that I botched the order of two of the pins. I decided to fix the board later, but I figured that the pins probably ended up in that order because I was using the contact pads for the bottom side of the board as reference instead of the top side. I ended up just using a via to run the trace for the 3.3-volt input on the bottom of the board, so that I could leave the SWDIO trace on top of the board and uninterrupted (it was also easier to do than revise the entire board). This time, I ended up salvaging the probe pins from the other adapter boards, which I honestly should've done in the first place because it was quite easy to do, but I still had to buy another set of the shrouded header because it's SMT and I don't have a hot air station. (I tried using the reflow oven at work with the boards upside-down to see if I could desolder them that way, but it didn't do anything, probably because they're too light.)

With the new adapter board revision, I soldered only one of the two boards (I haven't decided on a third pin length) for testing, and went to purposely brick one of my 21G boards by loading the bootloader meant for the 51J onto it via the boot drive that appears after double-clicking the reset button. After setting the programmer up, I ran the bootloader-writing process while holding the boards together with enough force, and it wrote the bootloader just fine. I tried to brick one of my 51J boards, but it wouldn't brick, even with trying to rewrite the bootloader or erase the flash space with the programmer. Both the ATSAMD21 and ATSAMD51 have a sort of write protection that's mentioned in the guide on how to use a programmer to write the bootloader (if you bricked a board or have a new MCU), but because I was following a much easier guide that didn't require me to boot to Windows (or have to pass the dev board through to my Windows VM), it was something that JLinkExe automatically took care of (or whatever). (It makes me kinda wonder how the one that wrote the guide for Linux was able to brick three or four Adafruit ATSAMD51 dev boards if I wasn't able to brick my dev board in a couple different ways.) Anyway, I did get the other adapter board soldered together after the successful test.

CircuitPython has a built-in library called board, which makes it easier to code with because you can have names assigned to a microcontroller pin (for example, "SDA" could be one of the names for pin PA08), but while I thought it was kinda inane to have to set up the pin names for board, I ended up setting the names up for one of the projects I was working on (the custom game controller). I later found microcontroller which has pin built into it, so instead of having to assign "SDA" to PA08 in the config file for building CirucuitPython, I could instead just call the pin directly with microcontroller.pin.PA08 (though I actually import microcontroller.pin as mcp and use mcp.PA08 instead). I went back into the config file and cleared it out since it'd be easier to keep track of the pins and make changes within the code instead of having to use notes to cross-reference everything.

Not really too much to say about CircuitPython itself, since it's really not too much different than Python (though it does have somewhat-reduced functionality), but it does require the programmer to think about available flash space (for large programmes or programmes with assets of some sort) and memory. Flash space can always be expanded with a 1-16MB (I think even 32MB?) flash chip over SPI and changing the specific CircuitPython config file to add the flash chip and the MCU pins that it's connected to, but memory is not expandable as far as I'm aware?

CircuitPython definitely is one of my favourite things that I've come along, since it allows me to really do things that I haven't been able to do with only discreet parts or having to rely on a Raspberry Pi of some sort, and though I'm somewhat limited to the libraries that Adafruit's written for certain devices, I still have a lot more freedom than I used to.