Pomodoro r2 Working Prototype

Yesterday, I managed to solve the pause button issue that I was facing. My main problem was running two timers at the same time so that I could use one to poll the button at a much shorter interval than the second timer for the lights. It took quite some fiddling, after I first tried to use the B timers to do this. However, I couldn’t get the compare timer working on the B timer, despite it having a compare register. I’m not too sure how it works yet, but I figured that the B timer compare register is actually for other purposes (such as using it to generate output), rather than an internal timer.

After quite some fiddling, I realized a much simpler solution to my issue than trying to get a B timer working on Timer 0: I just use the A timer on Timer 1. Now, Timer 0 is 8-bit and Timer 1 is 16-bit, so at first I thought it seemed a little wasteful but, then again, what else am I using that timer for anyway? So, I rewrote the program to have an A timer poll at a very high frequency (not even using a prescaler, if I recall), and found a little script online to debounce the button. Essentially, it just involves checking if the button is pressed, waiting for 25ms, and seeing if it’s still pressed. It seems to make use of the fact that a human being physically will not be able to push and release a button in that short a timeframe, and waiting to process it will also skip over the bouncing inbetween.

That still left me with an unsolved problem: the original version of this had two options for the button: a short press was a pause, and a long press was a reset. Right now, I don’t have that implemented. It would take a greatly different approach to the problem, as I did that using Arduino’s millis() function, and I have nothing similar on this firmware. However, the way I figured it, I have an ISP interface on there anyway, so I can get to that later if that’s still so important to me. ISP is awesome!

Next up came the soldering. Now, my first designs were for a PCB, so that I could make it in a nice little package that looked cool. However, that would have involved having that made in China, waiting a few weeks, and then possibly finding out that the footprints weren’t good because I changed this or that. So, I just figured to cut some perfboard and use my newly-learned solder bridge skills to make it. It was a good thing I did too, because I found out that some things were absolutely wrong. The button I was using for pause/reset, for instance, had two pins spaced two spaces apart, though by PCB design had it as one space apart. Similarly, the buzzer was slightly different than the footprint. On top of that, the ISP pin header I’d chosen was bigger than the header pin on the PCB. So, if I had ordered the PCB, it would not have worked for me in all likelihood!

Below you can see some pictures of the finished product. You’ll notice some of the adjustments I had to make in the side-by-side of the prototype and the design. The final picture shows a working model of the Pomodoro Timer r2. I have to tell you: I am so damned proud of myself for this one. There’s things to improve, like always, but this has got to be the cleanest, most complex working product I’ve made to date. Most of all, I built this up from scratch and learned so much from doing it.

Figure 3: The topside of the finished prototype

Pause Button Problem Solving

As I posted before, I’m working on trying to get the pause button working on the pomodoro device. There were two issues: firstly, the button needed debouncing, and I had to decide whether I wanted that in hardware or software; and, secondly, I was using a interrupt for the pause button that didn’t work correctly. Specifically, the hardware interrupt I was using activated on a pin state change, resulting in two activations per press (pressing down as well as letting go). Now, there was a potential to use another hardware interrupt, but that involved some rewiring.

As far as the debouncing goes, I found out that the usual solution involves an RC network (a resistor-capacitor network), which essentially provides a bit of a buffer by smoothing out the signal. It works, but as I mentioned before, isn’t done much anymore. In a previous post, I mentioned that reducing cost was a main consideration, but a more important reason turns out to be that there is no point in doing it in hardware when you already have a microcontroller with enough space to do it in software. Or, in other words: why do it the hard way when you already have everything you need in the microcontroller? So, I’ll have to see about implementing a software solution.

As for the other issue – how to handle the button press – I’m considering not using a hardware interrupt. One problem is that the hardware interrupt would require a hardware debounce, because debouncing it in software requires a degree of waiting for it to settle, which you can’t do if your interrupt is getting interrupted because the button keeps bouncing (very Catch-22, right?). What I’m considering now is using Timer B to regularly poll the button and debounce it in software when needed. The microcontroller is running at 250kHz to begin with, to that’s plenty of time to check for a button press. With the /1024 prescaler, that still ends up at 244.140625Hz. That’s plenty of time to check for a button press, though I will need to implement around a 50ms delay to hold off the debouncing (according to my reading).

Pomodoro r2 Timer/Counter Interrupt Figured Out

I was struggling a bit with getting the timer of the ATtiny84 working correctly. After having set it up, setting a prescaler for the microchip as well as a prescaler for the timer itself, it still wouldn’t quite time to 1 second intervals as I thought it should have. It certainly was timing something, as my countdown did display, and the prescalers were working, because changing those changed the timing of the countdown, but still it didn’t turn out to be 1 second per interval. It took a lot of reading through the datasheet to solve this issue.

So, specifically, my timer ran just a little slower than 1 second. I took a stopwatch app on my phone and timed out 20 intervals (i.e. LED changes), and found that it ended up being 17% slow. Not a staggering amount, but counting for that over 25 minutes it would end up being over a minute slow per pomodoro count. Given that my current firmware somewhat skips over the first count, it would still end up okay, but that’s just sloppy programming!

The solution to my problem lay in reviewing step-by-step the process of the timer as described in the datasheet. Reading though the Timer/Counter Interrupt Mask Register 1 section explained what the Timer/Counter1 Control Register A did, which helped me relate the Timer/Counter Register to the Output Compare Register A. As you can imagine, it was a lot of juggling of registers and bits. However, going through that step-by-step helped me track down my issue. As it turns out, the Compare Match A Interrupts (OCIE0A in register TIMSK0) was dependent on the bit setting of WGM01 in register TCCR0A. In other words, I had set everything up to compare the timer to the value I’d set, except for the actual register that tells the chip to make that comparison. No wonder it didn’t work!

Reading up on the datasheet also explained why I got the exact mistimed count that I did. Without setting WGM01 in TCCR0A, the timer is in “normal” mode, where it doesn’t compare but just checks to see if its in overflow. Overflow is defined as maxing out the register at oxFF in hexadecimal, or count 256 in decimal numbers. I’d set up the prescalers so that the timer was just over a second for a full count (so 256 cycles took 1.045 seconds), which is why I needed to compare it not to 255 but to 243 cycles: 8,000,000Mhz / 32 (prescaler) = 250,000 cycles/sec. 250,000/1024 (timer prescaler) = 244.14 cycles/sec. However, we start counting at 0, so it’s a count of 243 that’s almost exactly one second. As a result, waiting for the overflow rather than the compare made my timer slow.

This leaves me with one last thing to figure out: the pause button. Last time, I mentioned that buttons are, apparently, usually polled instead of checked via interrupt. Furthermore, they are usually debounced in firmware rather than hardware. After reading more, I now know the reason for the latter. Even though the components needed for debouncing are quite cheap (we’re literally talking a couple of cents here), production rules are usually made by large companies who produce tens of thousands of boards per product. So, an addition of even a few components of a couple of cents still add up to a hefty cost when multiplied by thousands to millions of components. On top of this, each component added adds a production step, as they will need to be mounted to the board, again leading to higher costs. Firmware, on the other hand, is programmed once (hence only paid for once), and can be copied indefinitely. In my case, this just doesn’t apply, so why not hardware debounce if that meets my needs?

The other problem lies with checking the functions. In my original design, a short press pauses, but a long press reset a timer. I did that using the millis() function in Arduino, which I now realize was just a timer used to count milliseconds. However, that also involves polling that at a regular interval, whereas my goal was to have the microchip sleep most of the time to save on energy. I’ll have to figure out how to approach this. I’ve read two completely opposite points of view on this: a chip can be set to work slowly, sleeping most of the time to save as much energy in sleep states; alternatively, the chip can be set at a high frequency, so when it is awake, it does whatever it needs to as quickly as it can, so it can return to sleep as quickly as it can. Right now, I don’t know what’s best, but it’ll be fun to figure that out.

Pomodoro r2 Progress

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.

Setbacks and new hurdles

I’d left the pomodoro project in the freezer for quite a while. Last week, I figured I’d pick up on it again, and make some time for that hobby. It’s been challenging to pick it up again, however. KiCad, apparently, has had an update, and currently does not work on my PC. However, the error message that I get does not seem to be a common enough experience to warrant many questions about it online. It might be that it’s too recent for it to become an issue (it was a few days ago); it might be that the problem is unique to my setup; or, alternatively, it might be that the problem is really so trivial that most people have just applied some solution that I do not know.

Regardless, I figured to just work directly on the programming of the new uC, as that is a thing I can experiment with on the go without needing KiCad. Everything works fine for a few iterations as I test the LEDs by blinking them all in order, and I test various waiting functions, and so on. As I was testing out interrupt states, I started getting an odd message – for some reason, Avrdude was setting new fuses. On the next flash, it mentions that fuses have changed, and asks whether I want to reset them. Naturally, I do. However, the fuse setting issue seems to repeat, and then I can’t seem to connect at all anymore.

So, I figure to test some alternatives. Can I upload something else to the chip? Can I use the USBTiny to upload something to my first prototype? Is it the connections on the breadboard, is it the USBTiny PCB itself? What’s going on? All tests fail. So, a new challenge presents itself. I need to figure out where the problem is, followed by what the problem is, and then whether or not this is something that I can fix.

Pomodoro r2 – Update 5

I figured that my design was pretty much as done as I could make it, so I posted it on /r/PrintedCircuitBoard to see about getting some feedback. As always, the electronics subreddits tend to be quite wholesome and education, and full of supportive people willing to help out. Thankfully, they gave me a lot of good feedback, as you can see below:

The Reddit thread where I got my advice

I was happy to learn that KiCAD automatically takes thermal relief for pads into account, as before this thread I had no idea what this was. The other major thing I learned was that there is no reason not to increase trace thickness if you can. And, finally, I learned that there was such a thing as a decoupling capacitor to smoothe out power delivery to a microcontroller, and so I added one (and after advice moved it closed to the microcontroller). That all resulted in a slightly changed design. Furthermore, I solved my issue with the footprints by simply taking a digikey footprint directly from a component I am intending to buy, so that the problem solves itself. I am very excited to come to a close to this project, and seeing it in action!

An update of the board based on feedback from Reddit.

FreeCAD Modelling

So, today, I made my first thing in FreeCAD. When I was testing out some footprints and components for the Pomodoro Timer PCB, I noticed that none were exactly the type of buzzer that I had. Seeing as how my buzzer is pretty much a simple cylinder, I figured it was the perfect object to try and model in FreeCAD. In the end, I’d end up both with a working 3D model to use in KiCAD, as well as some basic experience with FreeCAD.

After quite some fiddling to get things working, and some initial experiments, I finally produced the part in 3D with exact measurements:

A FreeCAD model of the buzzer that I use

Importing that into KiCAD was actually super easy. There was literally a button to just locate any type of .step file and import it as the 3D model for a part that I had selected. So, happily, I put that part on my board. And, to my surprise, it unveiled a hidden error:

The pins didn’t fit!

When I checked the fit of the part, I could see that the actual pins didn’t fit! That sure would have been an issue had I ordered the PCB! I measured twice, and then another time; I checked my measurements in FreeCAD, and everything worked out well. The only outcome could be that the footprint in KiCAD wasn’t correct. Good thing to catch at this stage.

Pomodoro r2 – Update 4

So, I’ve reworked the PCB into what I expect to be the final revision. I eventually decided to add the coin cell battery holder on the PCB itself after all, because it would be a little fiddly to add a holder for two AAs on the back. I’d have to either mess around with glueing it on the back (and making sure that the PCB matches the size), or figure out some kind of screw mounting. Since I don’t have a proper glue gun yet and project box making is something I still have to learn, I figured this was a decent enough solution after all on the level that I’m currently at.

The PCB with components added. Apparently, there’s still no buzzer 3D image, despite it just being a squat cylinder.

As you can see above, the result of adding the battery holder is that the entire PCB is now a little wider and less high, as I shuffled components around slightly. Another thing I noticed was that the pins of the ISP had no significant marking for orientation. I had a look at how it was marked on my USB programmer and noticed that this was done on the back (probably to save space), and that seemed like a good practice to follow. All in all, I’m quite pleased with this final design. Before I do go ahead and order it, I do want to test it out on a breadboard; after all, you never know when you’ve made some silly design error.

So, next step will be to order the components. While waiting for them to arrive, I can rewrite the code already to fit the ATtiny84, so that I can test it as soon as everything is in.

Pomodoro r2 – Update 3

I had a quick look at the schematic I made, and spotted a quick mistake there. I had tied the buzzer to the reset line, as I figured that pin would only be used when reprogramming the ATtiny84. However, I neglected to notice that the pin is an active-low pin, meaning that it resets when the signal is low; as a result, the pin has to be tied high – i.e. the buzzer would be on a constant high line. Whoops! So, that was an easy fix, fortunately.

A circuit schematic for the Pomodoro timer, showing an ATtiny84 linked to a number of LEDs, an ISP programmer, and a buzzer. The schematic indicates the whole set is powered by a 3-volt battery.
Figure 1: A slight adjustment to the schematic

I don’t have an ATtiny84 yet, but I’ve been testing the interrupts with an ATtiny13. It turns out that there’s a Watchdog function, which is quite easy to implement. I read through a good post on low-power mode for the ATtiny13 which explained it quite well. That post is the third in a series of three, of which the second one also nicely explains timers in general. As it turns out, trying to program it in low-power mode won’t really matter that much for my project.

The basic idea is that the timer is a separate structure within the microchip, that keeps timing regardless of whether the code runs. That’s why it can interrupt the code at any point, freeze it, do its Interrupt Service Routine, and get back to the code. It’s a great way to have a microchip respond to a button input no matter what it’s going, or to have a chip go into low-power sleep mode until it has to do its job (for example, taking a temperature measurement once per hour). The timers work on a microprocessor-level of speed, so we’re talking mHz here; consequently, most interrupts I’ve seen are in the order of seconds. Though my circuit only cares about minutes, I’m going to have to default to waking the chip up every second for a countdown. Still, though, that must save some power, right? Well, yes and no. It saves some energy on that low-power state microchip. And in the meantime, there will be a handful of LEDs on almost constantly – the power usage of the microchip pales in comparison.

Nevertheless, I’m going to reprogram the code to use the timers, and downclock the microchip. Not particularly because it will generate a massive powersave, but because I want to learn and this is quite a simple project to test this out on. Plus, any little bit helps, right? While at this point I could reconsider my choice of LEDs over an LCD screen (considering the LEDs are a big power drain anyway), I don’t think I will. I want to finish the project, and if I keep revising it, it may end up never being done. So, with that in mind, I started testing KiCAD’s PCB builder.

While the interface is somewhat arcane – there’s many options, shortcuts, jargon-filled terms, and so on – the process is actually quite simple. Mostly just a case of dragging a component from place to place, and then clicking along a path to put connections in. After some fiddling, I was easily done. On top of that, I saw that there was a 3D viewer built-in – score! So, this is my current version:

You can see that there was no 3D image for the buzzer, but otherwise I’m quite pleased. I took pin headers as a placeholder for the small putton and switch that I’ll be using in the bottom right. On the left, there’s two pin headers that I used as a placeholder for the battery. My main problem is still that I want a rechargeable solution for power – I just don’t feel like throwing away coin cell after coin cell. So, I figured, this way, for now, I can at least hook up whatever battery solution I end up with. If I don’t install it on the board directly, I might actually just include two notches on the sides of the board for me to slide in a rubber band and hook some battery back on the back.

Pomodoro r2 – Update 2

I’ve reworked the schematic to include the ATtiny84, and decided to just put a switch in there for the audio. After all, it either needs to attract your attention, or it doesn’t. There’s little sense in dimming it. If needed, I can always finagle a resistor in there during prototyping to check.

A circuit diagram showing the schematic for the second revision of the Pomodoro timer. It is a tangle of wires and components.
Figure 1: Pomodoro Timer, Rev 2.

I’m not particularly happy with how many lines cross in this schematic, but overall I still think it’s fairly legible. This time, I made sure to include a good footprint for each component in KiCad as well. I hope that’ll help me construct a good PCB later on, if I choose to do so. The one component I was struggling with a bit was the battery. I want to include it on the back somehow, but I’m not sure how. I’m pretty sure I can’t just glue it to the back (I mean, can’t I?), so I’m still thinking what to do about that.

Either way, it’ll be time to order some components soon for this build. In the meantime, I can look to adjusting the programming.