The ATmega microcontroller (MCU) spends most of its time in a very low-current power-down mode. The MCU pins to which the two buttons are connected were very carefully chosen — only these two pins support interrupt on change while asleep, which is used to revive the watch and enable the display.
To minimize components, the internal pullup resistors are used on these pins. The buttons then simply connect between the two pins and ground. When the switch is open (button not pressed), what would normally be an unstable “floating” input is instead “pulled up” to VCC, which the MCU reads as a high logic level. Pressing a button creates a much lower resistance connection to ground, which is read as a low logic level.
There are a couple of different ways this could be wired up. Given what we know from the pullup-vs-ground explanation above, we might be inclined to connect the watch input pin to one of the Arduino’s digital output pins, then call the digitalWrite() function, passing HIGH or LOW to simulate an open or closed button state…but this won’t work correctly! Most microcontrollers are opportunistic in finding usable voltage, and the watch will be perfectly happy to use power from the default HIGH logic state on that pin instead of the battery! This will skew the results horribly…it’s worse than useless.
The traditional way around this is to use an optocoupler such as a 4N35 to isolate the voltages. The digital output from the Arduino drives an infrared LED inside the 4N35, which activates a phototransistor on the opposite side — wired to the watch — effectively pressing the button without injecting additional current into that circuit. Cool.
- I had no optocouplers on-hand, and didn’t want to wait for an order to arrive.
- There’s a technique I’ve been wanting to use in a tutorial forever…
My naïve interpretation of HIGH and LOW pin states used to imagine HIGH as providing 5 Volts out, and LOW as being essentially an open circuit, passing no voltage. Such a model makes perfect sense when you’re blinking an LED (a favorite pastime!), but it’s not accurate. Rather, HIGH is a connection to VCC, LOW is a connection to ground…or, in jargon terms, they source and sink current, respectively. To block the flow of current, we have to set the pin as an INPUT. That’s the third state in “tri-state output.”
Or picture it this way: in school they made us watch dull fire safety films, where we learned not to throw doors open, but feel for heat first (indicating fire on the other side). That’s a fair model for voltage and MCU pins. As an INPUT — door closed — we can sense heat (or not) outside without letting fire pass through; the door impedes the fire’s progress. The high-impedance state. As an OUTPUT — door open — fire can now pass either way, whether flowing in (LOW) or out (HIGH). Three states. Tri-state.
So that’s how we control the watch. Setting and leaving the Arduino pin’s state LOW, then switching between INPUT (open circuit) and OUTPUT (closing the connection to ground), we’re performing the very same function as the button, without passing any voltage from the Arduino to the watch. Our battery measurements should be fairly accurate now.
Do keep that optocoupler technique in mind though…it’s still a valid approach, and there are many other situations where they can be quite handy!
Here’s the completed testing fixture. It’s not much to look at…an Arduino, a Data Logging Shield, and wires soldered to the watch circuit’s positive and negative connections, and one button: