With my ATtiny84 successfully rescued, I set to work to rewriting my Pomodoro program (is it officially firmware if it’s software for an embedded chip?) to make use of timers, as I had intended to do way back when. The goal was to reduce the power consumption of the chip by having it mostly be in sleep mode, and only occassionally turn the chip on to update LEDs (essentially, every second). With everything set up on a breadboard, I went to programming it on my desktop, to see if I could easily translate my original program from Arduino to fully C.
It was an interesting endeavor that was easier to do than I had expected it to be. I guess I picked up enough from Assembly and some C programming material to be relatively comfortable with programming the chip. It also involved a lot of datasheet referencing, as I needed to make sure to find the right registers on the chip to set prescaling and enable interrupts. Basically, I need the chip to run at a specific frequency, so that one of its timers takes exactly one second to overflow (reach its maximum count and reset to 0). Once that’s done, I could have the chip asleep except for when a second had passed (when that timer overflowed), and then quickly have it update the LEDs. For the testing of it all, it was fine to have it count per second (in fact, I clocked the chip so that it would overflow every 250ms to make it easier to see each step of the program as a whole). In the end, I’ll use a variable to check whether 60 seconds have passed, and then update the LEDs.
Most of the translation from Arduino to C was pretty easy to accomplish. Essentially, Arduino is just C with some pre-defined libraries to make it much easier to program Arduino chips. As a result, translating it over just involves finding alternatives for what Arduino had predefined. However, I did run into an interesting issue that will have me redesign the hardware a little.
Originally, my intention was to use the watchdog timer (WDT) so track the time. The watchdog timer, apparently, is designed to be used pretty much exactly for this purposes: to regularly time certain things. It doesn’t have any compare features or settings, it just overflows and lets you know when that’s happened. The datasheet as well indicated a setting that would have it overflow at 1s intervals, so, that sounds perfect, right? As it turns out, watchdog timers are notoriously imprecise. For the ATtiny84, it runs on a separate 128kHz oscillator, and when I prescaled it to the right setting, it was about 1s per overflow. That’s fine and dandy if it doesn’t matter much, but with it running slow as it did, it would accrue quite some delay across a full pomodoro, to the point of several minutes. Apparently, while it’s used for regular actions, it’s not intended to be used as an actual clock source in the sense of precise time measurement.
So, I had to retool that idea, and switch to the timer interrupt. After some initial foibles in trying to get it to work correctly, I found it almost exactly timed to 1s intervals, with a negligable deviation – about as reasonably accurate as I would want. With that solved, the rest of the reprogramming was hardly any issue at all.
Until, at least, the pause button came into view. Here, I have two problems, one of which may force me to retool things quite a bit. Firstly, I ran into the issue that the button has quite some bounce to it. That is to say, when we press it, in the timescale of our awareness, we may press it just the once; however, given that the microchip works far, far swifter than human reaction speed, it actually notices that the button is pressed and depressed several times just by the vibration of us pressing it down – i.e., it bounces. While it’s possible to debounce a switch via hardware, it’s more common to do it via software these days. The thing is, the Arduino, apparently, did this for me already; or, at least, I didn’t notice this issue in the previous build. So, I’ll have to figure out how to properly do this.
My second issue is somewhat related to the first. The interrupt I used was for pin PA6, on which I had the button there. It was a pin change interrupt, meaning that any time the pin changed from any state, the interrupt would trigger. So, pressing the button actually caused two interrupts to happen: pressing as well as depressing. That, of course, defeats the purpose of a pause button – it’d only pause while I was holding down the pin! I discovered that there is a dedicated pin for the kind of hardware interrupt I wanted (external), PB2 for the ATtiny84, but then I’d have to move quite a few things around (PORTB is where I had the three pomodoro LEDs). Nevertheless, pin PB2 allowed for a configurable hardware interrupt: either change, falling, rising, or low-level. That would at least allow me to reduce the problem of getting two interrupts for one press.
I’m not too sure yet if switching that around is the best solution, however. A quick glance online to solve my bouncing issue also showed me that most people recommend against using an external interrupt for a button press check. Firstly, for the bouncing issue, but secondly because triggering an interrupt also causes complications for registering what buttons do (apparently?). The recommended solution is what’s calling polling the button: regularly checking whether or not it’s pressed. It’s actually what I did in the original program as well, and may explain why I didn’t have the same issues there. I’m not sure how this will work out, though, as my intention was to have the microchip sleep most of the time and only activate about once per second. I’m concerned that if I poll the button only that once per second, I might end up making it non-responsive; after all, I could be pressing the button just inbetween two second counts.
I’m not too sure what to do about it yet, but it’s good that this is my major issue with the build so far, and that everything else has gone quite smoothly.