If you’ve been reading this blog for a long time, you’ll know that my first Raspberry Pi project was a version of a Star Trek Tricorder. The first version was made out of LEGO and used a Pi in combination with an Arduino Leonardo clone.
It was rather large, it didn’t do a LOT but I liked it and it taught me so much. It also started my unhealthy obsession with sensors!
Flash forward nine years from the original conception (!). I have since moved on with the project to using more sensors, better enclosures and exploring battery power.
The arrival of the Pico
This year, the Raspberry Pi Pico was launched. This was the first Raspberry Pi microcontroller (featuring their own silicon, no less!) and it immediately made me think of my old project. Could this be the low-power device I was looking for? Could this device which didn’t have the boot-up time of the regular Raspberry Pi and with no SD card to corrupt, be the thing that I had been looking for?
Getting the kit together
I wanted to just check that I could use everything that I wanted to use in the latest iteration of the Picorder. In nine years, sensors have become more widely available, more complex and there were a lot more types to choose from. I settled on the following components:
- 1 x Raspberry Pi Pico (this one from The Pi Hut)
- 1 x piece of 160x100mm stripboard
- Various male and female pin headers (anywhere I could find them)
- Lots of female-to-female jumper cables (anywhere I could find them)
- 1 x BME680 air quality sensor (Pimoroni Breakout Garden)
- 1 x VEML6075 UVA/UVB sensor (Pimoroni Breakout Garden)
- 1 x 11×7 Matrix (Pimoroni Breakout Garden)
- 1 x BMP280 atmospheric sensor (cheap Chinese version from AliExpress)
- 1 x AMG8833 thermal sensor (Adafruit, but from Pimoroni)
- 1 x Ultimate GPS Breakout v3 (Adafruit, but from Pimoroni)
- 1 x MAX98357A I2S mono amp (Adafruit, but from The Pi Hut)
- 1 x small 3W speaker (Pimoroni)
- 1 x 2.8″ TFT LCD Breakout with resistive touchscreen (Adafruit, but from The Pi Hut)
- 1 x STMPE610 Resistive Touchscreen Controller (Adafruit, but from The Pi Hut)
Why these components? In one word: quality.
Both Adafruit and Pimoroni products are very high quality (and they’re not cheap!) and they have a lot of support available in terms of tutorials and libraries. For the Adafruit products, there is one trade-off – you need to use their fork of MicroPython (called CircuitPython) in order to get the most out of their support material. More on this decision later! For the Pimoroni products, I just had to make sure that there were Adafruit CircuitPython libraries available for the bare components – which there are!
For some of the sensors (as you can see), I chose to use components from the Pimoroni Breakout Garden series. I already had some of them, but mostly I chose them as they offer the smallest form-factors out there for sensors of those particular types. For the GPS, I did consider the Breakout Garden PA1010D sensor, but as I already had the Adafruit Ultimate GPS board, I thought I’d save some pennies! First time for everything… 😉
Where to start?
First of all, I started to solder-up all the components. I really wanted to just solder wires directly to the boards (to make it more ‘solid’) but I realised that I wasn’t completely stupid, so decided to go for headers on everything. Much digging around for headers ensued…
11×7 matrix screen
You know what makes a good project? Blinkies! 🙂
One of my components was the 11×7 matrix screen from Pimoroni’s Breakout Garden range.
Getting this working was a bit of a trial (see this blog post) and involved hacking one of the Adafruit CircuitPython libraries to include the module. I received lots of help on this one from David Gaunt (who worked out the translation maths).
When we eventually got the pixels up the right way (the display in the video above was rendering upside down, but I didn’t know that to start with!), I was able to display text and other things on it. It was a small step to the final project, but it was a start! I’ve since pushed a change to the Adafruit GitHub repository (which was then superseded, but heigh ho!). It was an interesting experience, contributing to an open source library…!
One of the things I’d never quite managed with other versions of the Picorder is to make it play the appropriate sounds when controls are pressed and when sensors are having readings taken. You can read all about getting sound to work on the Pico in this blog post. Here’s what it sounded like eventually:
As I’ve said in the blog post, sound works best when you’re not using the USB connection to read the CircuitPython ‘flash drive’. You can make some truly horrific sounds, and I’m still not quite sure about the settings I need to produce the best sound from the little Pico, but that’s for later investigation. I found the sounds I wanted on TrekCore, by the way.
Screen and thermal sensor module
The next thing to get working was the 2.8″ touch screen. I hadn’t totally settled on using the “touch” capabilities of the screen yet, but to save myself time later, I soldered all the pins on the SPI side of the screen plus the three “jumper points” to enable that side. Fortunately, Adafruit has this great guide for wiring up the module and using CircuitPython to display stuff on it.
I wanted the thermal sensor to be one of the “stars of the show” in the PicoPicorder, so I decided to get that working first of all. You can read all about that on my blog post here. Here’s the video of it in action at a basic, no-additional-UI level:
Sensors, sensors and more sensors
I dug into the Adafruit CircuitPython libraries a bit more and was delighted to find library modules for the BME680 air quality sensor, the good-old BMP280 atmosphere sensor and the VEML6075 UVA/UVB sensor. These are easy to install for a CircuitPython program – you just drop them in the lib folder on your Pico’s ‘flash drive’. The same went for the Adafruit Ultimate GPS v3 breakout – there was a tutorial for this last module as well, detailing all the information you could get back.
Getting the touchscreen working
At this point, I decided that I did want to use the touchscreen of the 2.8″ screen. At first, I thought I could simply hookup the outputs of the touchscreen from the breakout to the analog inputs of the Pico. This didn’t work, but I have no real idea why, but I then looked at the description of the screen on The Pi Hut site which mentioned the need for a touchscreen controller. Sighing heavily at yet another lot of postage, I ordered the controller board from The Pi Hut. In the meantime, I looked up the software options. I found the Arduino example and eventually (after many an hour) found that there was a CircuitPython equivalent. Hurrah. The component arrived, I hooked it up (again using headers and jumpers) and attached it to the I2C area on my stripboard. A quick I2C scan showed that it had appeared immediately and I integrated the Adafruit library.
Designing the user interface
The project was inspired by Star Trek, so to Star Trek I would go again for the user interface. LCARS was what I’d always wanted, which was the style used on Star Trek: The Next Generation. Big thanks to Mike Okuda and the Star Trek: The Next Generation Team for the LCARS design in the first place (no copyright infringement intended!) I found some LCARS Photoshop shapes and a colour palette from Retoucher07030 on DeviantArt. I also found the Okuda font on dafont.com so I had everything I needed. The screen is 320x240px, so I knew that was my footprint. The following is what I came up with (you’ll notice there’s plenty of space for expansion!):
Onto this, I would add the labels and values from the sensors on-the-fly.
Note to self: I could create two “pages” for the interface and then just add the labels in the bitmap file. That way, I’d only need to render the values on-the-fly. This is something to think about – with each library and bitmap and wave file, I am using up the memory on the Pico and it isn’t infinite!
I found I also needed to load the Okuda font onto the Pico (obviously) so the look of the coded labels and values would match the other labels on the bitmap.
The next thing to do was to code the system so that the touch “areas” correctly triggered the relevant actions (more on this later).
Current status of the PicoPicorder project
Close-up of the main “atmosphere” screen:
Close-up of the GPS screen (I’m inside at this point, but I do know the module works as I did manage to get a fix at one point):
Close up of the thermal camera screen:
The code for the project is all available on GitHub. Not all of the files are used – some are just prototyping code. The key ones, in addition to the CircuitPython library files under lib are:
- code.py – the main routine that instantiates the PicoPicorder class and then works out what mode you are in at any given time.
- PicoPicorder.py – the main object class, mostly controlling the display and the various things displayed on it.
- ThermalCamera.py – the object class that deals with the thermal sensor and displaying the 8×8 grid.
- Colours.py – the object class that deals with the colours available to the PicoPicorder – this is useful for both the ThermalCamera and the main object.
- The img folder contains the bitmap for the main UI.
- The fonts folder, obviously, contains the Okuda font.
- The snd folder contains the sound effects as they currently are (such as they are!)
Video demonstration of the system as it currently is
This is the situation as it was on 3rd April 2021. It’s… okay… See below for some notes on what I need to do next!
Future of the project
I’ve noticed a few flaws with the PicoPicorder, and these need to be fixed:
- The initial render of the labels onto the bitmap is a bit slow. (This may be an un-fixable issue, who knows?).
- The touchscreen (and this is the main flaw!) is extremely sluggish to register the touches. Now, to explain: CircuitPython does not have “interrupts”. So, I cannot just say “when there’s a touch, do something”, I have to keep on checking to see if there’s a touch each time around the main control loop. The trouble is, when the sensors are being interrogated, I can’t see the state of the touchscreen! So, for instance, on the first screen, you end up with:
- Check touchscreen.
- Check a sensor and output the sensor reading (x5)
- Check touchscreen.
- This means that I’m only checking the touchscreen once every half-to-three-quarter seconds. Unfortunately, the touchscreen chip also buffers the touches, so I’m checking the coordinates of the touch on the screen as it was when I touched it… that number of seconds ago. In the meantime, it’s buffered a good dozen or more readings. This could mean that I’m touching the bottom-right of the screen, but the code thinks I’m still touching top-left, like I was X seconds ago. Talk about frustrating!
- Due to these factors, I might have to rewrite completely using MicroPython which does have interrupts! ARGH!
Oh, yes. I also need to come up with a 3D printable design for the case. I’m not very good at 3D modelling, so this will be a stretch! I want something with a hinge so the screen is protected, too!
I’ve also decided that I will create my own circuit board. I’ve used Fritzing to do the first version (I know, it’s not brilliant, but it’s what I can cope with at the moment!) and am expecting the boards sometime next week or the week after.
Plenty to do, then, but at least I’ve got a prototype! 🙂