Introduction: Using the ATtiny85 "Ghost" Inputs
Whenever I make an Arduino project that requires battery operation and/or needs to fit in a small space I look to the ATtiny85 and ATtiny84 as my go to options. Because of their similarities, I often make versions that will work with either chip. The primary difference in my choice is the required number of I/O pins. The ATtiny85 is an 8-pin chip and has only 5 fully usable I/O pins while the 14-pin ATtiny84 chip has 11 fully usable I/O pins. Recently I was working on a project that required two more inputs than the ATtiny85 has available so the natural choice was the ATtiny84. But the hacker in me wanted to see if there was a way to make the application work on the ATtiny85. I was already familiar with one “ghost” input pin hack but I still needed to figure out a second one. While these “ghost” inputs are only useful for detecting switch presses, they do free up regular I/O pins for other normal functions. I’m probably not the first person to “discover” these methods but they don’t seem to be common knowledge so I present them here as a (hopefully) interesting tutorial and useful application.
Step 1: The Secret Life of Resets
“Resets” are not something that a lot of hobbyists spend time wondering about. Most of what we need to know is that our application starts up when power is applied and can be made to restart from the beginning if we use the provided reset pin. The reset pin only requires a momentary connection to the circuit ground in order to do its thing. The crucial thing to understand, however, is that the microcontroller chip will NOT preserve its memory when the reset pin is activated even though power has not been removed. A caveat for that is detailed in the software section.
At this point you may be thinking that the reset pin is only useful if you want to restart your program without having to crawl behind the sofa to unplug and then plug back in the power cord. This is actually a useful feature in some cases and I’ve used this method for things like restarting a game. One of the “secrets” though, is that you can have the software detect the difference between a power on start up and a reset pin restart. This is possible because the microcontroller chip has an internal register with flags that distinguish between various types of resets. The flags are for power on, external reset, brown out, and watchdog timer. You can simply check at startup to see if any of the reset flags are set and then perform different functions. A power on will reset all of the other flags and an external reset will clear the power on flag. The watchdog timer reset is useful but is not covered here because it can’t be activated by an external input.
Step 2: Hardware
The basic hardware setup is shown above. A normally open momentary contact switch is connected between the reset pin and ground. The connection for the brown out reset is a little less straightforward. It requires a normally closed momentary contact switch connected between the power input pin of the chip and VCC. As can be seen, there are also two common 1 amp diodes connected in series between the power input pin and VCC. A press of the switch causes a voltage drop across the diodes which activates the brown out detector of the chip if it is properly configured.
The Arduino IDE allows for the setting of the brown out voltage as part of the fuse configuration. The nominal values are fixed at 1.8, 2.7, and 4.3 volts. It requires two diodes to ensure sufficient voltage drop to trigger the detector because the minimum values for the 4.3 volt and 2.7 volt settings are more than 0.7 volts below the typical 5 volt or 3.3 volt power supply inputs. After you select the desired trigger level in the IDE, make sure to click on the “Burn Bootloader” option to properly configure the fuse settings.
Step 3: Software
The provided software is just a framework for checking and using the reset inputs detailed here. As can be seen in the listing, the check for the external reset flag can be set up to use a counter variable so that it only activates after a specific number of reset pin triggers. The counter variable is designated to be part of a section of memory that is specifically not initialized in order to maintain it through the reset cycles. That also means that the initial value is unknown on power up so the software sets it to zero if the power up reset flag is detected.