Taking the Cytron Maker Pi Pico out for a spin with the Raspberry Pi Pico

Tony Goodhew has been in touch about some experiments he has run on the new, low-cost Maker Pi Pico from Cytron. TL;DR – here’s the Instructable.

In the UK, the Maker Pi Pico is available from The Pi Hut (also as a version without the Pico pre-soldered, but with header sockets). Other distributors around the world can be found at the bottom of this page. The board is very well thought-out and contains a whole raft of features:

  • Access to all Raspberry Pi Pico’s pins on two 20-way pin headers.
  • LED indicators on all GPIO pins.
  • 3x momentary push buttons
  • 1x RGB “NeoPixel-like” LED
  • 1x Piezo buzzer
  • 1x 3.5mm stereo audio jack
  • 1x microSD card slot
  • 1x ESP-01 socket
  • 6x Grove ports

Tony’s experiments are written in CircuitPython and cover using the GPIO pins, reading from the SD card, using a potentiometer on an analog input and using an SSD1306 display to show results from various inputs including a Pimoroni BME680 breakout board.

You can read the Instructable here and you can see one of his demo videos below:

The PicoPicorder – a work-in-progress prototype using a Raspberry Pi Pico and lots of components from Pimoroni and Adafruit!

During March, and for the past week as well, I’ve been working on the latest iteration of my Picorder project. This project, which has been my “go-to project” for the past 9 years (gulp!) is now running from a Raspberry Pi Pico and uses lots and lots of sensors and a touchscreen. You can read all about the project on this page which I will update as I develop and improve the project. Let me know what you think of it so far! All my code is open source and available on GitHub.

Trying out a Raspberry Pi Pico carrier and experimentation board – the Pico 360

It’s always nice when something new arrives in the post and it’s unexpected! Andrew Gale from PocketMoneyTronics has done great things in the past with his subscription-based soldering kits. This time, he has created a carrier board for the Raspberry Pi Pico which helps you to get going on coding with simple components. It is called the Pico 360 and it comes as a solder-it-together-yourself kit.

TL;DR – if you want one, it’s £3.60 (not a typo!) for the kit (not including the Pico itself) and it’s available over on Etsy.

Kit contents

The components are as follows:

  • The PCB
  • 6 red LEDs
  • 1 yellow LED
  • 1 green LED
  • Resistors for all those LEDs
  • 2 momentary buttons/switches
  • 1 piezo buzzer
  • 1 trim potentiometer
  • 2 sets of female header pins (for the Pico to plug into)
  • 1 set of male header pins (to breakout some extra pins)
  • 3 sticky nubs to go on the bottom

The genius move in this case is to include 5 pads which can be attached to with crocodile clips, making this excellent for education where re-use is as important as anything else.

Putting it together

Soldering it together was simple and is best done, in my opinion, in the following order (from lowest height to highest height):

  • Resistors
  • Buttons
  • Potentiometer
  • Buzzer
  • LEDs
  • Male header
  • Female headers

The components are all through-hole, so it should be easy for someone with even “beginner” soldering skills. The only thing I did find was that some of the pads are quite close together. I only had one “oops” and needed a solder sucker. That’s about average for me, anyway!

Once soldered together, I plugged in a Raspberry Pi Pico (which I had already soldered male headers onto).

Example code and video

To my delight, I was able to get all of the included components working straight-off-the-bat by using CircuitPython (which happened to be loaded onto the Pico). My code is here on GitHub as a Gist and you can see the code in action in the video below. If you want a MicroPython demo program, you can find that on Andrew’s website.

Summary and recommendation

This is a great idea for education, especially, and for beginner hobbyists just getting started with the Pico. There are enough components to keep the ideas flowing, and it’s a breeze to solder together. The soldering might put off some educators, of course, but I daresay it will be popular anyway. Who knows? There could be enough demand to do a surface-mount pre-assembled version…

Either way, great job, Andrew! This comes highly recommended!

More information

Andrew has written about the kit over on his website.

Buying the kit

The kit is available for an impressive £3.60 over on Etsy.

Using Sublime Text 3 to code with your Raspberry Pi Pico

There are, of course, many options when it comes to editing files. Raspberry Pi’s suggested way of coding for the Raspberry Pi Pico is to use Visual Studio Code. I must admit, I struggled to get on with it. In order to make my life easier, I wanted to use Sublime Text 3, which is what I use for work. Familiarity with your IDE/editor helps a lot when you’re doing something new, so I looked at how I could use it. I’m on Windows, so expect those kind of file paths 🙂 I’m also using CircuitPython which means the Pico presents itself as a drive on your PC (like a Removable Disk).

First steps – direct editing

To start with, I created a Project and added the CIRCUITPY drive to the project. That way, I could see the files on the drive and just edit them.

I experimented for a while and tried to use the serial_monitor plugin to see the device and access the REPL. This plugin, though, doesn’t allow interaction at that level, so I’ve stuck with Putty for now. I have Sublime Text open on one screen and Putty on the other, but if you’ve only got one screen, just split it using Windows’ in-built facility.

Version control using Git / File synchronisation with the Pico

Of course, eventually you’re going to want to keep your code version controlled and backed up on GitHub… right? I mean, you wouldn’t want to just keep it on your Pico and then accidentally lose it? And version control is good, correct? Say “Yes, Mike”. 🙂

Having your repository keyed to be on the Pico itself is pretty bad form, in my opinion. Instead, you need a place for your code off of the Pico. This makes sense – that way if you want to do Git commits and pushes, you can do it from your hard drive, rather than direct from the Pico. But how to keep that “local” code in step with the Pico? That’s where file synchronisation comes in.

I looked at a few options, but what I really wanted was for the file system to be monitored for changes and then the code file(s) that had been changed to be automatically copied onto the Pico. I came across the FSync plugin. It is pretty bare bones, but it does what I want. You’ll need Package Control installed (see here for instructions). First of all, add a repository to Package Control and enter https://github.com/weverss/FSync into the text box. This links your ST3 installation to the specific GitHub for the plugin. Then, install the package by searching for FSync. Restart Sublime Text 3 and the package will be installed and ready.

In your menu, go to Preferences->Package Settings->FSync->Settings – User.

This will open up a blank file.

Now, go to Preferences->Package Settings->FSync->Settings – Default. Copy the whole thing and paste it into your User file and save it.

Now, edit the local_workspace and remote_workspace settings. Set them according to the location of your local folder and your Pico drive. Use / as the path delimited and do not add a trailing /.

Here’s mine:

{
    // File extensions list to ignore during sync
    "ignore_extensions": [".FSync", ".svn-base", "wc.db"] ,

    // WARNING: In both settings below, don't finish directories with '/'

    // Local directory to work...
    "local_workspace": "D:/Projects/Raspberry Pi/Pico/Pico Picorder/PicoPicorder (code)",

    // Remote directory to sync files from local directory ('local_workspace' setting above)
    "remote_workspace": "E:" // Don't finish it with '/'
}

Save it.

Now, what you should find is that each time you save a file in your LOCAL folder, it copies it to the CIRCUITPY drive.

And, because you have now moved your code to a local folder, you can now add it in the usual way to a GitHub repository.

Indentation

Don’t forget to change your Sublime Text 3 indents to “Spaces: 4”. This is at the bottom right of the screen in the grey strip. This is important as all the Adafruit libraries (and, indeed your code!) should use 4 spaces, not a tab character, otherwise you get indentation errors when it runs on the Pico.

Create a low-res thermal camera with a Raspberry Pi Pico, an AMG8833 sensor and an ILI9341 screen with CircuitPython

As part of an ongoing Raspberry Pi Pico-based project, I wanted to create a thermal camera. To do this, I first of all went shopping to find what I needed. Here are the two components for this mini project:

They’re not cheap components, but they’re what you need. You can get a better thermal sensor. This one is only 8×8, so quite low-resolution, but you get some nice results out of it (see the video below).

I chose CircuitPython for the project, because I’ve learned by now that CP has an enormous number libraries.

As always, Adafruit have provided great guides to both products. The screen tutorial is available here and deals with both wiring up and programming it. The tutorial for the AMG8833 thermal camera (there are two types of breakout boards for the sensor) is available here.

How to combine them, though, that’s the trick. I found this tutorial which uses an Adafruit Pygamer board and the Featherwing version of the AMG8833 breakout. This was enough to get me going with translating the array of pixel values returned from the camera denoting sensed temperatures into colour blocks. I had to strip out a lot of functionality relating to the Pygamer board, which was a bit of a pain if I’m honest, but what I was left with should fit nicely into the project I’m working on.

Here’s the wiring that I used:

and you can find my stripped-down code on GitHub. You will need to save the code onto your Pico as code.py to make it run automatically on power-up. You will also need to copy over some libraries to your Pico, so just take a look at the imports at the top of the code for those. You can find the library bundle here.

Here’s the result of the mini-project:

Playing sounds from the Raspberry Pi Pico using CircuitPython – a journey of discovery

As you probably know by now, I’m not a microcontroller expert. However, with the advent of microcontrollers that use MicroPython and CircuitPython, I am a lot more comfortable using them now than I used to be! However, because the Raspberry Pi Pico is new, there aren’t a lot of practical examples of how to do things out there. There is excellent documentation, of course, but when you’re trying to do something specific, or something that hasn’t been thought of, it can be a voyage of discovery.

TL;DR

Scroll down to “Playing a WAV file” for the code that works and “Finding the Hardware” for a wiring diagram.

The project

I am currently working on a new version of my long-running Picorder project, my version of the classic Star Trek prop, the Tricorder. Whereas in the past I’ve used exclusively regular Raspberry Pi (with an occasional foray into Arduino to get analog inputs) as the brains, this time I am choosing to use the Pico. A PicoPicorder, if you will. One thing I’ve never done before is to reproduce the sounds made when the device is opened and scanning.

Finding the sound effect

My first job was to find the sound that I wanted to play. This was easy. TrekCore has a whole host of sound effects from the Star Trek series. I picked the one I wanted (this one) and downloaded it. I knew straight away that the full file was too long (and large), so I converted it, using Audacity, into a WAV file, squashed it into a mono sample and chopped most of it away, leaving me with a self-contained, much shorter, loopable sound effect.

How to play it

Now… how to play it. To start with, I looked at creating my own circuit and using PWM Audio. This post from Greg Chadwick indicated that I could do just that. However, it was, excuse me, a bit beyond me. It also used C/C++ as a programming language. I had already decided that, for this project, I would use Adafruit’s CircuitPython derivative of MicroPython. There were a lot of libraries, it is, basically, Python (which I can already use to a certain extent, thanks to the CamJam EduKits and all the other tutorials that are available), and it is extensively documented.

However, that blog post, and some previously-read Pico documentation, pointed me to needing to use I2S audio, which is how audio (DAC) boards work with the Raspberry Pi. This would give me high enough quality audio to play my sound effect and give me a bit of familiarity (which I always think is key to understanding how to do something).

The Raspberry Pi Pico and I2S

However (again), from my past reading I knew that the Pico does not have I2S pins in the same way that the regular Pi does. Some microcontrollers do have that built-in, but the Pico does not. I also knew that, in order to give functionality to the Pico that it does not have, you use PIO (Programmable Input/Output). (If you want to know about how to understand PIO even more, there’s this excellent article). It’s actually quite difficult to find “how to’s” on the Raspberry Pi website for PIO… in fact, I completely failed, so you will have to root around a bit.

First of all, I discovered this example from the Raspberry Pi GitHub repository that showed what PIO code you needed in order to accomplish that. However, because it’s written in C/C++ and is targeted at the SDK method of programming the Pico, rather than CircuitPython, it rather blew my mind. This is the important part, the PIO code:

.program audio_i2s
.side_set 2

    ; /--- LRCLK
    ; |/-- BCLK
bitloop1: ; ||
    out pins, 1 side 0b10
    jmp x-- bitloop1 side 0b11
    out pins, 1 side 0b00
    set x, 14 side 0b01

bitloop0:
    out pins, 1 side 0b00
    jmp x-- bitloop0 side 0b01
    out pins, 1 side 0b10
public entry_point:
    set x, 14 side 0b11

Complete gibberish, am I right? It was at this point that I almost gave up. 0b10? jmp? It’s assembly language, I thought, for the particular implementation on the Pico. Fair enough, but I have no idea what it all means. However, did that mean that I couldn’t use it? I had seen an example in MicroPython for using PIO inside Python (thanks Alister!) itself, but not CircuitPython.

I thought I’d step back and approach things a different way.

Finding the hardware

I weighed up the amount of problem-solving skills I had and, rather stupidly, assumed that I would be able to get I2S working, somehow.

If I could get I2S working, then I knew I would need a DAC and an amplifier to output the sound from the Pico. I came across this tutorial over on the Adafruit site for using the MAX98357 I2S mono amp which combined an I2S amp and a DAC on the same board. Ideal. It only outputs to one speaker but, for this project, one small speaker is all I need. I found the breakout on The Pi Hut’s site and they were kind enough to send it to me with some other bits for review purposes.

Looking more at the tutorial on Adafruit, I came across the CircuitPython wiring test. This shows how to hook up the MAX board to a microcontroller with I2S pins. To my dismay, the code example did not cover the PIO part. Okay, I thought, we can smash that bit and the other bit together somehow.

The MAX board arrived the next day and I wired it up. Here’s my wiring (thank you Adafruit and Fritzing for the software and parts library!):

Now that was done, PIO was the next step. Or so I thought.

Using PIO in CircuitPython and the Adafruit Discord server

By this point, I knew I was going to need some extra help. Adafruit has, amazingly, created a Discord channel for discussion of their products and, Hallelujah, CircuitPython. There was even a special channel for PIO. I joined and then realised how active the channels all were – awesome, so much expertise and experience.

From suggestions received there, I came across this tutorial on the Adafruit site for using PIO in CircuitPython, so I finally knew that what I was trying to do was possible. Somebody then pointed this example out to me that uses PIOASM (PIO assembler) to create audio on the Pico using CircuitPython.

Wanting to know how things work

At this point, I lost several hours trying to combine things together before realising that I ought to start from first principles.

Returning to the example from earlier which shows the PIOASM example to create audio in CircuitPython. All the example does is to create the necessary PIO code, assemble it, and then use it to play a sine wave.

To my surprise, once I’d got the pins sorted out, it crashed. I got the following error which others might get, so here it is:

Traceback (most recent call last):
File "code.py", line 40, in <module> File "adafruit_pioasm.py",
line 65, in assemble IndexError: list index out of range

Hmmm. Vexing, that.

I had come across this video, a “Deep Dive” with Scott, who works on CircuitPython for Adafruit:

And I wondered… was the functionality so new that I was using a too-old version of CircuitPython and its libraries? I downloaded the latest stable build of the CircuitPython UF2 from this page which was 6.2.0-beta.4 at the time. I also downloaded the latest version of the Libraries and updated the PIOASM Python file from there onto my Pico. I ran it again and… it worked! It worked! Awesome! That wasn’t the end of the adventure, though… I wanted to play a WAV file.

Playing a WAV file

I returned to the CircuitPython wiring and test page for the MAX board. This contains the following code:

import audiocore
import board
import audiobusio

wave_file = open("StreetChicken.wav", "rb")
wave = audiocore.WaveFile(wave_file)

audio = audiobusio.I2SOut(board.D1, board.D0, board.D9)

while True:
    audio.play(wave)

while audio.playing:
    pass

This simply creates an object containing a sample WAV file (StreetChicken), sets up an I2S device and then plays it until it’s finished.

I changed the D1, D0 and D9 references to my own pins and added the argument names for clarity:

audio = audiobusio.I2SOut(bit_clock=board.GP10, word_select=board.GP11, data=board.GP9)

This matches the wiring diagram above. At this point, I knew I was blundering about in the dark and I knew it wouldn’t work. No PIO stuff evident there, after all. The Pico wouldn’t know what to do with itself. Right?

Wrong.

The sample, which I had copied to the root of the Pico’s CIRCUITPY drive, came out of the speakers. It was distorted and repeated over the top of itself, but it was playing! What the heck?

Rolling with it

I decided to roll with it. I changed the code to simply play the WAV file once and then sleep. This resulted in the following (you might need to turn the volume up):

 

It was quite distorted, as you can hear, but it did match what I could play on my laptop. A piece of electronic hip-hoppy music. But why did it work?

I asked on Twitter, I asked on the Adafruit Discord channel and Peter Onion asked me whether I knew what the I2SOut code did. I did not. I received a pointer to the audiobusio/I2SOut code on the Discord channel and took a look. To my surprise, it had all the PIO code in it! That means… That means that someone else has done all the hard work with the PIOASM stuff… That’s amazing!

Clearing up the sound

I spoke to David Glaude on the Discord channel about the problem I was experiencing with the glitchy sound (see video above). He let me see his test script (which was adapted from the previous examples I noted above). I tried it out. It loops the StreetChicken music 10 times. It showed that the glitching problem was still there and also pointed to a problem with the while i2s.playing part – there might be a bug (which David has reported). David also suggested that there was an issue with the Pico being connected to the laptop – i.e. the reading of the flash memory was interfering with the I2S playback. I tried it with a wall PSU and, indeed, this cleared the issue up.

I then altered the code to play back my sound sample of the tricorder in a loop, based on David’s code. To my delight, it works perfectly (if connected to a non-reading power source). You might need to turn your audio volume up a bit, but this is what it now does!

In conclusion

You can get sound, quite easily, out of a Raspberry Pi Pico using CircuitPython. Use audiocore to open and play your WAV files over I2S with the CircuitPython audiobusio library from Adafruit doing the heavy lifting with regards to PIO. And get on the Adafruit Discord channel – there’s a lot of help available out there! 🙂