My goal was to make a pomodoro timer using a few basic parts and write the code for it using CircuitPython.
My requirements were pretty simple:
- write the code in CircuitPython,
- have an audible alert to indicate transition between the work/break phases,
- have a display of some sort to show progress through each phase, and
- have a way to set the length of each phase.
To satisfy requirement 1, I needed to use an Adafruit M0 or M4 microcontroller based board. I decided to see if I could make it work with an M0. These boards are great for simple CircuitPython projects, but if you have much code it's easy to run into memory limitations.
For very simple projects, a Trinket M0 does a great job, but I eventually decided to use a rotary encoder and wanted to try out the new
rotaryio support in the latest 3.0 release of CircuitPython. That ruled the Trinket out.
So that left the M0 Express versions of the Feather or ItsyBitsy. Either would work, but I decided to use the ItsyBitsy: it's smaller, so it would give me a bit more flexibility when it came time to designing a case. It would provide a bit more of a challenge, as well, due to the lack of mounting holes that the Feather has.
For requirement 2, I used the same piezo buzzer I used in my Humidity monitor guide. It's loud enough, small, and works nicely with the CircuitPython
When I thought about requirement 3, I thought about my toaster's interface. It uses a continuous knob and a radial display for setting darkness.
What isn't obvious from the photo is that the highest valued segment of the dial blinks as it counts down. Also, as the count down proceeds, the number of segments lit decreases. When none remain lit, the toast is done.
This immediately reminded me of a Light Emitting Diode (LED) NeoPixel ring.
For the final requirement I was still thinking about my toaster and a rotary encoder as input made sense, especially since I'd decided to use a ring as a display.
Rotating the encoder could be used to set the times, while the push switch could be used to cycle through modes:
- timer -> set work time -> set break time -> timer
and so on.
I'd implemented rotary encoder handling in CircuitPython in a previous guide, but this was a good chance to try out the new bundled rotary encoder support.
All that was left was adding a LiPo backpack so that it could be battery powered. The backpack is required since the ItsyBitsy doesn't have on-board battery support. That's one of the tradeoffs compared to the Feather. The nice thing about the backpack is that it doesn't increase the footprint, but it does add to the thickness of the ItsyBitsy. That wouldn't be a problem since the case will have plenty of thickness to accommodate it.
That's it: an ItsyBitsy M0 Express with a NeoPixel ring, a rotary encoder, and a piezo buzzer. Add in a LiPo backpack, power switch, and battery for power, and that's it. Below is the wiring diagram. The only difference is that I'm using a 500mAh LiPo in my build. Making the case bigger will allow use of a bigger battery. That makes no difference to the wiring, though.
Wiring is pretty straight-forward and described in detail on the Assembly page.
The battery connects to the LiPo backpack. The slide switch does as well, allowing the device to be turned off when not in use. The backpack is connected to the power connections on the ItsyBitsy, typically (as I did) by using the included bit of long-pin header.
The buzzer connects to ground and D12.
The Neopixel ring has it's power connected to the ItsyBitsy's 3v output, and it's ground to the ItsyBitsy's. The ring has two ground connections, and the second can be used during construction to avoid having to connect everything directly to the ItsyBitsy's ground. The ring's Data In connects to D11.
The center of the encoder, and one side of its switch connects to ground. The other side of its switch connects to D10, while its encoder pins connect to D9 and D7. Done as shown, the code will work correctly with the rotation direction. If you reverse the encoder connections, rotation will be opposite what's expected. Reverse the connections or switch the encoder pins in the code to correct it.