A few weeks ago, I was made aware of the Open Source Watch project while looking for some inspiration for projects to build. It looked really well done. But, there was room for improvement and I thought I would have a crack at building my own smart watch too.
For the most part, I only used the OS watch as a reference. While it would be fun to put an existing design together, I was after building my own from scratch.
Firstly, let’s have a look at the differences between my design and the OS Watch.
|The ‘tangrs Watch||OS Watch|
|Microcontroller||Arduino Pro Mini
Modified to run at 8MHz 3.3V
|Bluetooth||4.0 Low Energy||4.0 Low Energy|
There are some other subtle differences too.
- Mine used a metal link watchstrap
- Mine didn’t have LEDs
- Mine didn’t have a switch
- Vibration motor was wired differently
- Arguably a better, cleaner look ;)
We had very similar constraints in what the watch had to do:
- Battery had to last a whole day (10 hours bare minimum)
- Display had to remain on to display the watch face at all times
- As thin and as good looking as possible
- Containing open source or easily found parts
So with these constraints, I set out to design my smart watch.
N.B. due to limited computing resources on the watch, I actually delegate most of the controlling work to a mobile phone app. The smart watch just exposes a command interface over bluetooth.
I picked the Arduino Pro Mini for this project since it was small, cheap and had a built-in LDO voltage regulator for 3.3V operation.
I believe the OS Watch uses a step-up converter to get stable 3.3V operation on it. However, the drop-out voltage for the voltage regulator on my particular board was ~150mV, allowing perfect operation on input voltages as low as 3.45V. Because of that, I didn’t bother to add a step-up converter. Even at voltages lower than 3.45V, the ATmega can function within spec for 8MHz so it wasn’t a big deal. In fact, I could have just hooked up the unregulated voltage to the Arduino directly but I didn’t here.
I did have to desolder the reset button on the board though. It added 2mm to the thickness of the board and had the risk of being pressed. Instead, I wired the reset pin to an external interface in case the device had to be reseted.
The one thing that the OS Watch got right that I didn’t was the amount of SRAM. The OS Watch has 4K/16K depending on the microcontroller you use which is a lot more than the 2K that comes on ATmega328s. With a large framebuffer and bluetooth driver, I easily went over the 2K limit. In fact, I’m writing a driver for the OLED screen that doesn’t use a framebuffer and writes directly to the module for a saving of 1K.
I chose the nRF8001 bluetooth module from Adafruit because it was one of the few bluetooth 4.0 low energy modules available. I bought a few cheap bluetooth 4.0 UART chips off eBay but I couldn’t get them to work (and documentation was terrible).
The nRF8001 also has an interrupt pin so we can put the watch to a deep sleep mode and wake up when there is data to be read. Waking up on UART activity is impossible on the more power saving sleep modes since the UART module is powered down. I even tried tying the UART to an interrupt pin like some people suggested but there was still considerable data loss.
Unfortunately, I underestimated how large the driver would be. The Adafruit UART driver for this module takes up 1.2K of my precious SRAM! It was impossible to fit both the graphics driver and the UART driver.
For the OLED display, I used a module compatible with the Adafruit ones. I used the I2C module to reduce the amount of wires.
One thing to be careful about is that these displays suffer from screen burn in! This is especially a problem since it means that you have to take precautions when displaying a watch face constantly.
I somewhat mitigated this by inverting the display every minute (i.e. switch from black on white to white on black). It does take more power but it’s better than seeing outlines of text. Also I added a timeout to switch the display back to a watch face if there is no interaction with the watch (in case the watch loses connection and the mobile app can’t tell it to switch to a watch face).
Also note that the power consumption of the display is proportional to the number of white pixels displayed. There is also a dim mode that cuts power consumption to about one half. I used a timeout to switch to dim mode.
Buttons were wired to the interrupt pins. I had to kind of multiplex the use of one of the interrupt pins since there were 3 peripherals for 2 interrupt pins. I just threw a resistor onto the interrupt line from the bluetooth module and hooked both onto the same pin. The idea is either one of the button or the bluetooth module can pull the line low. We process bluetooth first, then check if the pin is still low. If it is still low, we know the button has been pressed.
The Arduino is programmed to deep sleep until something needs attention. It follows a event loop pattern.
The idea is the device goes to sleep at the end of an event loop and waits for an interrupt to occur. The interrupts go to empty interrupt handlers (with the exception of the watchdog) which only serves to wake the processor up. At this point, the event loop runs again and checks what has changed.
The watchdog is programmed to tick every second to increment the time. The watchdog is used instead of the more accurate timers because its interrupt can wake the processor from deep sleep. The lost accuracy can be made up by having the mobile app synchronise the time every half hour or so.
Lastly, total power draw cannot exceed continuously exceed 40mA or we won’t be able to run it for 10+ hours.
I used a vibration motor from an old mobile phone with an impedance of 55 Ohms. I wired a 10uF capacitor in parallel with the motor to smooth out most of the ripple caused by it. Then I chucked a transistor on with a 1K resistor on the emitter and wired it to a MCU pin. The motor will draw ~60mA peak.
I wired it straight to the battery since the motor needs a bit of oomph to get it to start.
I didn’t bother to throw in a flyback diode since there didn’t seem to be any large negative voltages when I measured it with an oscilloscope. Most of the occasional spikes disappeared if I put a small resistor in series with the motor. The diode would also take up too much physical space.
Although the software side of my watch isn’t completely finished, I can say that there is still a lot to improve in my watch. It certainly doesn’t have the polish of the OS Watch yet.
Some things that need improving include:
- Add an off switch
- Print case in black, higher quality ABS
- Thinner display
I will cover my progress in follow up posts.