DIY Digital Wristwatch


The main incentive behind this project was to see how much I could cram, in terms of both hardware and software, into a wristwatch-like device that is no larger than the display itself. An OLED display was chosen for being only 1.5mm thick and not requiring a backlight (each pixel produces its own light), but mostly because they look cool. The watch was originally going to have a 0.96″ display, but this proved too difficult to get all the things I wanted underneath it. Going up a size to 1.3″ was perfect.



Wristwatch schematic

Wristwatch schematic

On the hardware side the watch contains an Atmel ATmega328P microcontroller, 2.5V regulator, Maxim DS3231M RTC, 1.3″ 128×64 monochrome OLED, 2 LEDs (red and green), a buzzer sounder, 3 way switch for navigation, powered by a 150mAh LiPo battery which can be charged via USB and 2 PCBs (though one PCB is just used as a raiser for the OLED).

The ATmega328P uses its internal 8MHz oscillator and runs on 2.5V from a linear regulator. Its current draw is around 1.5mA when active and 100nA in sleep mode.

The DS3231M RTC is an excellent chip, housed in a small 8 pin package which includes a built-in temperature compensated MEMS resonator with an accuracy of ±5ppm (± 2 minutes 40 seconds per year). Only a decoupling capacitor and a few extra pull-up resistors were required. The RTC is wired up so that instead of having power applied to the VCC pin, it’s applied to the Vbat pin which reduces its current draw from around 100uA down to 2.5uA.
Unfortunately this chip seems to be very hard to get hold of at a reasonable price if you’re not in the US. I had to get mine as samples.

The battery charging circuit uses a Microchip MCP73832 along with some additional components for load sharing, where the battery can charge without the rest of the watch interfering with it.

You might have noticed in the schematic that the LEDs are directly connected to the microcontroller without any resistors. The internal MOSFETs of the microcontroller have an on resistance of around 40Ω, so with a 2.5V supply voltage and LEDs with 2Vf, around 12.5mA ends up through the LEDs. I would have liked to have a blue LED, but the voltage drop for those are usually more than 3V which would have required some additional resistors and a MOSFET.

As the microcontroller is running on 2.5V the battery voltage needs to be brought down a bit to obtain an ADC reading. This is done by a simple voltage divider. However, with the voltage divider connected across the battery there would be a current of around 350uA constantly flowing through it, this is a huge waste of power. A P-MOSFET (and some voltage level conversion for it, which I forgot about in the first version so it was always stuck on) was added so the divider can be turned on only when needed.

The 2.5V regulator being used is a Torex XC6206, primarily chosen for its tiny quiescent current of just 1uA.
Why a linear regulator and not a switching regulator? The switching regulators I looked at had an efficiency of at least 80% with a 2mA load, but that efficiency quickly dropped off to less than 50% with loads of 100uA. Since the devices connected to the regulator draw 2-3uA in sleep mode, a switching regulator would have performed incredibly poor compared to a linear regulator. The 2.5V linear regulator efficiency is 60% with 4.2V input going up to 83% with 3V input.



Top side, under display

Top side, under display


So we’ve got a nice OLED display and 32KB of program space at our disposal, surely we can have more than just the time and date?

Almost everything is animated

A lot of time was spent optimizing the rendering code which, in short, involves copying bitmap images from flash to the frame buffer in RAM and sending the frame buffer over SPI to the OLED. The end result was being able to maintain 100+ FPS in almost all areas of the watch with an 8MHz AVR. However, since the animations are frame based instead of time based and to save power, the frame rate is limited to 60FPS.

Some of the main animated things:

  • CRT animation when entering and exiting sleep mode (similar to the CRT animation that some Android smartphones have).
  • Main time numbers have a ticker effect.
  • Menus have a scroll left/right animation and selecting an option will cause the current menu to fall off the screen and the next thing to fall on.


  • Set up to 10 alarm times.
    Number of alarm times is only limited by the amount of available EEPROM.
  • Each alarm has the hour, minute and which days of the week it should be active on.
Alarms menu

Alarms menu




Car dodge

Car dodge




Turns on all OLED pixels and LEDs, also has seizure strobe mode




Plenty of options

  • 3 Channel volume control
    • UI
    • Alarms
    • Hour beeps
  • Sleep timeout
  • Display brightness
  • Animations
    You’re not going to turn them off, right?
Volume settings

Volume settings

Power saving

In ‘active’ mode the microcontroller tries to go into idle sleep as much a possible. In idle sleep the controller is woken each millisecond to see if anything needs to be updated, if not then it goes back to idle sleep, this usually takes less than 100us if the display doesn’t need to be updated. In this mode the current draw can be anywhere between 0.8mA and 2mA, depending on how long it takes to draw frames (fast frame draw time = more time in idle sleep).

In ‘sleep’ mode the microcontroller turns the OLED off and goes into power-down sleep mode where it is only woken by either a button press, an RTC alarm or USB being plugged in. In this state the microcontroller draws ~100nA.

Power consumption

In sleep mode the overall current draw of the watch is around 6uA. In active mode the current draw can vary from 2mA to over 70mA, though 10mA is the typical current draw.

Battery life in various modes
Battery capacity: 150mAh

(sleep mode)
(main time display)
2.85 years
15 hours
2 hours, 20 minutes

If the watch is in active mode for an average of 1 minute per day (with a 5 second sleep timeout that would be checking the time 12 times a day) and all volume channels set to minimum the watch should last for around 1 year and 4 months on a single charge.

Current draw breakdown (typical)

Part Current
ATmega328P (sleep / active) 100nA / 1.5mA
OLED (sleep / active) 500nA / 8.5mA
DS3231M RTC 2.5uA
Schottky diode (D1) (reverse leakage) 1uA
Regulator (quiescent current) 1uA
Other (MOSFET and capacitor leakage etc) 1uA
Total (sleep / active) 6.1uA / 10mA

v1 to v1.1 changes

The first version had a few problems:

  • Added level conversion for the ADC P-MOSFET.
    Without level conversion the P-MOSFET was always stuck on. To turn of the P-MOSFET off the gate voltage needs to be at around the same level as its source voltage (which is connected to the battery), but the microcontroller was only providing 2.5V.
  • Added a gate pull-down resistor for the MOSFET driving the sounder.
    The MOSFET gate was floating when the microcontroller was being programmed which was causing the MOSFET to turn on and allow non-pulsed current to flow through the sounder, which probably wasn’t good for it.
  • Larger solder pads for MicroUSB connector.
    Normally SMD MicroUSB connectors have solder tabs at the sides and should have extra solder pads underneath, but since this is soldered by hand the underneath is unreachable. With out the extra solder pads the USB connector was wobbly so some of the connector pins eventually broke their solder joints. To fix this issue I enlarged the side solder pads so that the connector can be soldered all along its side instead of just the tab. No more wobbly connectors.


Other problems

Out of 3 OLED displays, 2 died after a few minutes of being attached to the watch. One from Ebay and the other from AliExpress. I’m still not sure why they died, maybe just China quality? The one that worked was also from Ebay.

Future improvements

  • Programming via USB.
    At the moment 4 wires need to be poked into the board (SPI programming) and then hope they don’t fall out while programming.
  • Add a fuel gauge IC.
    At the moment the battery level is determined by its voltage, this isn’t a very accurate method of getting the remaining battery charge.
  • Different microcontroller.
    The current firmware is using ~28KB out of the 32KB of available program space in the ATmega328P, a different microcontroller with more program space and probably more RAM would be needed to add more things like a calculator (floating point stuff eats up a lot of program space). However, the ATmega328P has the most program space for an AVR in a 32 pin TQFP package, to have more program space I would have to use a 44 pin AVR. The ATmega1284 looks interesting.
  • Switching regulator, charge pump regulator or maybe a hybrid solution?
    The linear regulator in use at the moment isn’t particularly efficient and switching regulators don’t seem to be very good with low current draw. Perhaps a charge pump regulator or a hybrid solution to swap between a linear regulator for sleep mode and a switching regulator for active mode?
  • A case of some sort?

Sources available at GitHub

Parts list

Schematic Part/value Description Quantity
U1 Atmel ATmega328P Microcontroller 1
U3 MCP73832 Lithium battery charger IC 1
U4 XC6206P252MR 2.5V LDO Regulator 1
U2 DS3231MZ+ RTC 1
Q1, Q2 DMP1045U P-MOSFET 2
Q3, Q4 DMG6968U N-MOSFET 2
D1 ZLLS410 Schottky diode 1
D2 TS4148 High speed diode 1
C5 4.7nF Capacitor 1
C4, C6, C7 100nF Capacitor 3
C3, C8, C9, C10 1uF Capacitor 4
C12 2.2uF Capacitor 1
C1, C2, C11 4.7uF Capacitor 3
R4, R8, R10 100R Resistor 3
R6 2.7K Resistor 1
R5 7.5K Resistor 1
R7 10K Resistor 1
R1 22K Resistor 1
R2, R3, R11 47K Resistor 3
R9 390K Resistor 1
RN1 10K network Resistor network (4x resistors) 1
LED1 LED (green) LED 1
LED2 LED (red) LED 1
LS1 Sounder Magnetic sounder 1
SW1 3 Way navigation switch 1
MicroUSB connector (Ebay) 1
OLED1 OLED (Ebay / AliExpress) 1
Battery (Ebay) 1
Main PCB 1
Display raiser PCB 1
Watch strap G10 NATO 22mm 1

Featured at
Atmel, HackADay, Electronics Lab, adafruit

Water proof down to 0m!


18 pings

Skip to comment form

  1. Hi Zak,

    I finally finished something like a case for your watch. It’s 3d printed in 2 parts and I tried to make it as minimalist as possible.
    If anyone is interested, on my website are some pictures and the .stl files (and everything in german).

    1. That looks really good, I like it! 😀

    • marcello on February 13, 2015 at 3:09 pm
    • Reply

    Could you send me a file of the pcb and code so i could make my own? At if posable.

    1. Everything is available at

  2. I cant find the gerber files for the pcb.

    1. Use EAGLE to open watch.brd/.sch (here) and use the CAM processor to create gerber files in the correct format for your PCB manufacturer.

        • mark on January 19, 2016 at 2:01 pm
        • Reply

        hi, how to open watch.brd using eagle? I can’t open it and all I get is just code and I can’t download the file too. what should I do?

        1. Go to the main page of the N|Watch repo and click the “Download ZIP” button on the right side.

            • mark on January 20, 2016 at 3:02 am

            okay got it, thanks mate..

    • Alexander on February 17, 2015 at 6:34 pm
    • Reply

    Hi Zak, I use display chip SH1106, runs a line from the top of the display, I can not fix the code that worked full Screen, please podskazhyte that must be corrected, thank you in advance.

    1. Hi, I don’t have a SH1106 display so I can’t do much at the moment, but I do plan on buying one and getting it to work sometime.

    • BitAbbas on February 23, 2015 at 6:16 pm
    • Reply

    Pcb & hex email for me?

    1. They can be found here –

    • Greg on March 10, 2015 at 3:12 pm
    • Reply

    You can also use flat/slim battery (1.5-2mm) which costs about 10$, (at the capacity 100-200mAh) 🙂

  3. Your oled died because his VBAT = 3.3V to 4.2V, but you put the USB voltage and it is 5V (pin 6 of oled).

    1. The absolute max for Vbat is 5V. There is also a schottky diode which drops the voltage by at least 0.2V.

    • Tuur on May 21, 2015 at 10:28 am
    • Reply

    Dude this is amazing! The only question i have is:
    Does it receive notifications? And if it does with what Android version?
    And would it be compatible with Android 4.2.2

    1. No, the watch doesn’t have any kind of connectivity.

    • Jack Harwood on July 3, 2015 at 9:20 pm
    • Reply

    i wish this would come back

    • Lewis on July 23, 2015 at 9:35 pm
    • Reply

    Awesome job! This is one of the best DIY projects I’ve seen. I’ve used a couple of these OLED displays for other projects and I was wondering if you ever had problems with horizontal bands of differing brightness?

    1. Thanks 🙂
      I’ve only had issues like that from bad power, things like a bad connection or supply voltage being too low.

    • Hare on July 26, 2015 at 11:55 am
    • Reply

    Hello Zak,I’m doing a watch like you.I want to know how to make it knows it is charging,and when in sleep, alarm clock does not work until I wake it up.What should I do?
    I use arduino,but I hope you can tell me something.
    Forgive me for my poor English.

    1. Battery charging can be detected by reading the STAT pin on the charging IC (or whatever pin has a charging state output). For alarm wakeup the RTC needs to have an alarm interrupt output connected to an interrupt input on the microcontroller (similar to how a button can wakeup the microcontroller).

        • Hare on August 16, 2015 at 5:43 am
        • Reply

        alarm interrupt output isSQW PIN? Do I need to start the alarm interrupt in code? Thank

        1. Yes (but check the datasheet for your RTC IC) and yes.

            • Hare on September 4, 2015 at 5:40 am

            Do you create a Arduino project? I saw you writing TODO

          1. The Arduino part is about making some kind of library for interacting with the rest of the hardware on the watch (RTC, detect USB, detect charging and battery voltage etc). I’ve not started working on it yet, though.

  4. Hi,

    I’m trying to make a watch like you but I want to add accelerometers and other sensors. However, you used the DS3231. On its datasheet it says it consumes 110uA standby plus a 575uA temperature conversion current. How is it possible to use it with just 2.5uA? Does its precision get compromised? Wasnt it suposed to waste a lot more power than that? Does it communicate correctly that way?

    Thanks in advance,
    Sorry for the bad english, I’m brazilian XD

    1. The 2.5uA figure is when the RTC is being powered by Vbat instead of VCC. According to the datasheet the only difference between the two is that the temperature compensation conversion is done every 10 seconds instead of every 1 second when on Vbat. Having a lower sampling rate might effect accuracy if the temperature changes a lot in those 10 seconds, but other than that there are no issues.

    • Surachai on October 6, 2015 at 2:59 am
    • Reply

    I compiled but it error.

    Build started.
    Project “optiboot.cproj” (default targets):
    Target “PreBuildEvent” skipped, due to false condition; (‘$(PreBuildEvent)’!=”) was evaluated as (”!=”).
    Target “CoreBuild” in file “C:\Program Files (x86)\Atmel\Atmel Studio 6.2\Vs\Compiler.targets” from project “C:\Users\tevada2010\Downloads\Compressed\NWatch-master\firmware\src\optiboot\optiboot.cproj” (target “Build” depends on it):
    Task “RunCompilerTask”
    Shell Utils Path C:\Program Files (x86)\Atmel\Atmel Studio 6.2\shellUtils
    C:\Program Files (x86)\Atmel\Atmel Studio 6.2\shellUtils\make.exe all
    Building file: .././optiboot.c
    Invoking: AVR/GNU C Compiler : 4.8.1
    “C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.1061\avr8-gnu-toolchain\bin\avr-gcc.exe” -x c -mcall-prologues -funsigned-char -funsigned-bitfields -DF_CPU=8000000L -DBAUD_RATE=57600 -DLED_START_FLASHES=3 -DDEBUG -DLED=D6 -DLED_DATA_FLASH=1 -Os -fno-inline-small-functions -fno-split-wide-types -fno-tree-scev-cprop -ffreestanding -fno-exceptions -maccumulate-args -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mshort-calls -mrelax -g2 -Wall -mmcu=atmega328p -c -std=gnu99 -Wstrict-prototypes -Wextra -MD -MP -MF “optiboot.d” -MT”optiboot.d” -MT”optiboot.o” -o “optiboot.o” “.././optiboot.c”
    avr-gcc.exe(0,0): error: unrecognized command line option ‘-mshort-calls’
    make: *** [optiboot.o] Error 1
    The command exited with code 2.
    Done executing task “RunCompilerTask” — FAILED.
    Done building target “CoreBuild” in project “optiboot.cproj” — FAILED.
    Done building project “optiboot.cproj” — FAILED.

    Build FAILED.
    ========== Build: 1 succeeded or up-to-date, 1 failed, 0 skipped ==========

    1. The compiler that comes with Atmel Studio doesn’t support ‘-mshort-calls’. I’ve been using AVR-GCC 4.7.2. Right click on optiboot in the top right side window > Properties > Toolchain tab > AVR/GNU C Compiler > Optimization > Untick ‘Use rjmp/rcall (limited range) on > 8K devices (-mshort-calls)’.

    • John S on November 5, 2015 at 5:43 pm
    • Reply

    Hi I really like your project. I’m thinking of doing something similar myself. Question: wouldn’t a two diode setup work for the load sharing instead of your switching mosfet? Sure you have a voltage drop, but you’re dropping the V from 3.7 or so down to 2.5 anyway. Just wondered if you thought about this or not. Your project seems very well thought out.

    1. Thanks 🙂 Yeah you could replace the MOSFET with a diode, though the OLED and buzzer run straight from the battery so they won’t be quite as bright or as loud. It’s personal preference I suppose, MOSFET method works better but adds a little more complexity.

    • andrew on December 29, 2015 at 1:25 pm
    • Reply

    good job. but for what did you need 2 nchannel mosfets? thx

    1. Q3 N-MOSFET is for level shifting, 2.5V from the microcontroller isn’t enough to turn off the P-MOSFET (which controls the voltage divider for measuring the battery voltage) so Q3 shifts it up to the supply voltage.
      Q4 N-MOSFET is for driving the sounder.

      In the latest version (on GitHub, v1.4) the N-MOSFETs have been replaced with cheaper BC817-40 BJTs and Q2 P-MOSFET replaced with a BC807-40.

    • Seb on January 10, 2016 at 3:31 am
    • Reply

    Good job and thanks for sharing.
    Just 2 questions :
    – Why it is the drain of Q1 connected to VBAT and not the source ?
    – Do you think it is possible to increase low power with a higher value for R4 ?


    1. Hi, thanks.
      – Because the 5V from USB will then be connected to the battery via 2 diodes, D1 and the internal diode of the MOSFET. This will destroy the battery. More info here.
      – No, the gate of a MOSFET is similar to a small capacitor, once it’s charged or discharged then no more current will flow. A larger resistor will just make it turn on and off slower.

    • Seb on January 11, 2016 at 3:19 am
    • Reply

    Thank you for your prompt and clear response.
    & long live Puppets and Open source !

    • Hayri Uygur on January 15, 2016 at 1:52 pm
    • Reply

    Hello Zak,

    This is really the nicest and most thought through OLED Watch I have seen. I signed up on your mailing list in the hopes to at least get a hold of the PCB’s. It would be a little overkill for me to have fabricated the minimum 5 pieces with a fabhouse.
    Anyway I would love to CNC machine a nice custom case for this watch, it really deserves it. I saw that someone created a 3D printed case but a case out of aluminum would be great I think.
    Oh I almost forgot to thank you for all your work and making it free for everybody.
    Wish you all the best.

    1. Thanks 😀
      It’s very unlikely that I’ll be accepting orders anytime soon. I get PCBs from, they come in sets of 3. The main PCB and raiser bit can be ordered for about $15 and free postage.

        • Hayri Uygur on January 19, 2016 at 8:09 pm
        • Reply

        Thanks for the reply Zak.

        I thought of OSHPark too since they do fewer PCB’s than Elecrow which I used till now, unless I want to make a bunch of watches. Now I have to make sure I can get all the components first before I order the PCB’s. Come to think I can just order the main PCB and cut the raiser bit on my CNC along with a case.
        Anyway thanks again for all your hard work.
        Take care,

        • AneoPsy on April 26, 2016 at 3:01 am
        • Reply

        Can you share your gerber files ( I don’t know how to do it.
        Thanks you.

        1. OSHPark supports uploading the EAGLE .brd file directly, so you don’t need to deal with gerbers. But if you really want to use gerbers then you can follow these instructions –

            • AneoPsy on April 28, 2016 at 8:00 pm

            Ok thanks you, i will upload the EAGLE.bdr file

    • Damian on January 19, 2016 at 2:01 pm
    • Reply

    Hi! Your smartwatch is really awesome! I’m trying to find out how this firmware works, but I have little problems with reading your code. Can you tell me how do you written animations? I will be so grateful 🙂
    Thank you in advance!

    1. Here’s a quick run-though:
      The main rendering function is in draw.c, called draw_bitmap(). You’ll see at the top that it applies the animation by offsetting the Y location of each thing it renders. animation_offsetY() is in animation.c. Each time a new frame is drawn the animation_update() function is called from display_update() in display.c which updates the offset variable so that everything is rendered slightly further down the screen.

    • Oriq on February 7, 2016 at 12:45 am
    • Reply

    Hi ! Your smartwatch is very cool ! I will make it one but in my city doesn’t have that components so can i make it use arduino mini? and what components that dont’ needed if i use arduino mini ?

    1. Using an Arduino Mini will remove the need for the 2.5V regulator and microcontroller. You’ll also need to add resistors (around 100R) between the LEDs and Mini output pin.

    • Peter on March 9, 2016 at 9:23 pm
    • Reply

    Hi Zak, great project. I really am impressed, but wonder if it’s a good idea for first project..
    Your advice? how would you rate it, regarding difficulty level?
    Thank you

    1. Hey Peter, for a beginner I’d have to rate it 8/10 for difficulty. It’s definitely not a good first project. Though, you could recreate it on breadboard using through-hole parts and pre-made modules from ebay. The bare minimum to get it working is a power source (around 3V – 5V), an ATmega328P microcontroller and OLED module (make sure it’s an SPI type, not I2C). To make it usable you’ll also need a DS3231 RTC module and 3 buttons.

        • Jeremy on February 15, 2017 at 11:12 am
        • Reply

        Why not use a I2C OLED?

        1. The watch firmware only contains code for an SPI OLED. You could add I2C support, but then the frame rate will be limited to around 48FPS because the max I2C bus speed on most AVRs is 400KHz, while SPI is half the main clock frequency (8MHz for this watch, so SPI can run up to 4MHz).

    • Peter on March 17, 2016 at 8:29 pm
    • Reply

    Thank you Zak, for honest reply. I appreciate it.
    I already crash n burned with another project, so that’s why I ‘m asking.
    I will seriously consider your advice, and hold back for a while.
    But, it’s so intriguing, don’t know how long I can stay away.. 🙂
    Best regards

    • Oriq on March 24, 2016 at 4:37 am
    • Reply

    I have buy 12C LCD 0.96″ module, can i use it for make this project ? If not why? If can any change with the code?

    1. An I2C OLED can be used, you will need to change the code in ‘devices/oled.c’ to use I2C instead of SPI. Things will also run a bit slow as the maximum framerate with I2C is 50FPS, but the watch is supposed to run at 60FPS. Most areas will probably run at about 30-40FPS.

    • Gena on April 4, 2016 at 12:54 pm
    • Reply

    Hello, Zak.
    Tell me, please, where I can find datasheet for this 30 pin OLED display. I found this –, but it’s a 31 pin display and pin location is not the same.
    Is it true that pcb has to be changed for using I2C?

    1. That’s the datasheet for the OLED IC which is embedded into the display. You need the datasheet for the actual finished display, like this
      If you want to use I2C for the display then yes, the PCB will need to be modified as well as the code.

        • Gena on May 31, 2016 at 8:56 am
        • Reply

        Zak, I have a truble with DS3231MZ+. Somehow it counts to 90 instead of 60 (secs, mins, hours). And after 31 minute goes 24 and then back to 32 🙂 . Did you have similar problems?

        1. Sounds like you’re interpreting the RTC registers as decimal values, but they’re not. They are BCD, so the lower first 4 bits are the units digit of the number and the upper 4 bits are the tens digit. Decimal 89 is 59 in BCD. The datasheet will have all the info about which bits mean what.

            • Gena on June 1, 2016 at 11:41 pm

            Thank you 🙂

    • simon on June 22, 2016 at 3:38 pm
    • Reply

    quick question how are you gouys getting pcb’s made like this i’m aware youre using software like EAGLE how and where and what the cost for procuing shut a pcb?

    1. I get my PCBs from OSHPark, they’re $5 per square inch and you get 3 copies. You can upload the .brd file from EAGLE and it will show a preview of the design. Takes about 3 weeks from ordering to arriving in the UK.

  5. Hello, Zak.
    I am making a watch like your. I have some problem about animations. I have to set the SPI Clock to DIV2,but the screen fresh not smooth. There is a afterimage when moving.I use u8glib to run screen. It is the library’s problem ?

    1. Oh I’m wrong.It isn’t a afterimage. Is the graphics deformation.(I use “x++” to let it move) I would appreciate it if you could help me.

    2. Hi Hare, u8glib is not fast enough for smooth animations. You’ll probably have to code the display driver stuff yourself to get it running at a decent speed (like I did with this wristwatch).

      1. All right, I’ll try.

      2. Thank you very much for your help last time.It is very useful.Please allow me to continue to ask you some questions.
        About this PSTR("%02hhu:%02hhu%c")
        Where can I find a detailed description of the formatted output?I’ve already found it online. But it didn’t seem the same.

        1. There’s a lot of info about printf formatting online, like here, what differences are you seeing?

          %02hhu will print a 1 byte unsigned value padded with zeros to a minimum width of 2 characters.
          0 = Pad with zeros (normally spaces are used)
          2 = Minimum number of characters to print, will pad with zeros (from above)
          hh = Datatype length of a char (usually 1 byte)
          u = Unsigned decimal integer

          %c will print a single character.

            • Hare on July 6, 2016 at 4:14 pm

            Thank you very much.

    • Pippo on October 6, 2016 at 5:25 pm
    • Reply

    VBAT is too high, check the SSD1306 datasheet:

    VBAT = 3.3V to 4.2V

    1. It only marginally exceeds 4.2V when USB is attached and the datasheet doesn’t seem define an absolute max. A lot of projects use these OLED displays with 5V without problems, so I guess the display can just about handle it.

    • deathiscertainlifeisnot on November 2, 2016 at 11:27 am
    • Reply

    Hello Zak,

    I really enjoyed your work you have done here. I need to ask a question about the animations. Above comments you mentioned that you are using offsetY for creating animations. But the ssd1306 has 8 pages only in Y direction. How could you give the offset values as a pixel values continuously?

    Have a nice day

    1. Hi, the offset is applied when the images are rendered to the frame buffer in RAM, which is what gives access to individual pixels. Only once everything has completed drawing is the frame buffer then transferred to the OLED.

    • R.Aditya on June 29, 2017 at 3:50 am
    • Reply

    Will an Arduino Nano suffice for this project? Or do I have to use Arduino Pro Mini? PS I don’t want any space issues…

    1. Heya, Arduino Nano and newer Pro Mini boards both use the same microcontroller (ATmega328), both of them will work with the watch code which uses around 85% of the available space. Older Pro Mini boards come with a smaller controller (ATmega168) which will not work.

    • Riya Abraham on October 6, 2017 at 11:27 am
    • Reply

    Woov this looks amazing. Great work dude

    • Dmutro on October 31, 2017 at 9:43 pm
    • Reply

    Hello Zak!
    I apologize in advance for my curve English, I write to you through an interpreter. I live in Ukraine.
    I’m delighted with your work! I really want to repeat this watch myself. I collect the details and ran into a problem, we do not have a DS3231M, there is only a DS3231SN, a little in a larger enclosure. By datasheets like everything is the same. I also want to ask you, like a knowledgeable person – is it possible to replace the DS3231M with the DS3231SN without changing the firmware of the MK?
    And one more question torments me – there are on the AliExpress OLED displays 0.96 “128×64, they are slightly cheaper than 1.3”, is it possible their application in this clock scheme, or 0.96 “has a different information display algorithm?

    1. Hi Dmutro, I think the DS3231SN will work without any firmware changes, and a 0.96″ OLED should also work without any changes. However, there are 2 different chips inside these OLEDs, if you get one with an SSD1306 chip then it will work, but if you get one with an SH1106 then you will need to open config.h and change the OLED_CONTROLLER option to OLED_CONTROLLER_SH1106 and recompile the firmware.

        • Dmutro on November 4, 2017 at 9:59 pm
        • Reply

        Zak, thanks for the answer!
        I will try.

    • Dmutro on November 15, 2017 at 11:50 am
    • Reply

    Zak, another question, in which compiler can I recompile your watch project? This is to make the firmware from the LCD on the base of SH1106 chip.

    1. Any AVR-GCC compiler should work (like from here, but it’s easiest to download Atmel Studio and open .atsln in firmware/src/ with it, then choose build. The .hex and .eep will appear in the watch/debug/ folder.

        • Dmutro on November 17, 2017 at 12:28 pm
        • Reply

        hank you! I’ll try, maybe something will happen.

    • erik on January 30, 2018 at 8:42 pm
    • Reply

    You could reduce the active Power consumption of the uC by reducing the clock frquency to the Ultra Low Power 32kHz internal clock. You probabilty dont need a faster clock for the timer, and if you need it for spi, then you can turn the frequency up again. If the atmega you use doesnt have such a low power clock then you should consider switching to a uC that does
    All in all still a great Project

    • Evangelos on April 14, 2018 at 1:17 pm
    • Reply

    Hi there. Can you please show the schematic for the new, corrected version 1.1 that includes the chabges you did.

    1. Check out the GitHub repo HERE for the latest versions.

    • Jaeil on September 22, 2018 at 1:46 am
    • Reply

    Is firmware available on board version 1.1?

    1. Hey Jaeil, yes, you will need to change HW_VERSION to 1 in includes/config.h when compiling the firmware.

        • Jaeil on October 4, 2018 at 10:35 am
        • Reply

        Thanks, but I do not know how to compile

        1. You need to install Atmel Studio, open the .atsln file from firmware/src/ and press F7 to compile. The hex file will then be firmware/src/watch/Debug/watch.hex. You will also need to upload watch.eep to the EEPROM too. (Also, your comment doesn’t appear until I’ve approved it)

    • yuri on October 9, 2018 at 10:19 am
    • Reply

    hello Zak, awesome project! I have some noob questions, is it possible to use this solution of voltage measuring circuit? I mean you can switch off divider by using high-impedance mode on ADC and control pin

    1. Hey yuri, that link isn’t working for me.

        • Yuri on October 9, 2018 at 11:35 am
        • Reply

        forgot that the server is local, try this link here

        1. Hah, I thought the circuit you were asking about would be like that 😛 No, it won’t work. When the control pin is set to high impedance it will then see the full battery voltage (same for the ADC pin), exceeding the max voltage at the pin (VCC + 0.5 = 3V), which will then cause the internal ESD protection diode to conduct and it’ll end up leaking current to the 2.5V power rail. In section 18 I/O-Ports of the ATmega328 datasheet there is a schematic showing the diode placements.

    • Firaz on October 31, 2018 at 7:51 pm
    • Reply

    Hey man ..y r u sharing wrong information to others ??? 7 and 8 pins for crystal …how can read ..PWE_SENS on crystal pin ??? And the output of the charging ic…is 3.3v how it should be 5v ????

    1. Hi Firaz, wrong information? You can clearly see it working in the video 😛 Using the internal 8MHz RC allows the crystal pins to be used as normal GPIOs. The charging IC does not output 3.3V, how will it charge a LiPo battery to 4.2V? The charger will first run in constant current mode, where the voltage will rise as the battery charges, then once it’s almost charged it switches to constant voltage mode, and finally turns off once fully charged.

    • Andrii on November 18, 2018 at 4:49 am
    • Reply

    Hey, just made a v1.1 for my self. Looks great and works, except for some reason the brightness adjustment in the settings doesn’t work. The screen brightness is just stuck at low. Any ideas as to why?
    Thanks for the awesome project and for keeping it open source!

    1. Thanks! Have you tested all of the OLED solder connections to make sure they’re all properly making contact with the PCB? It will likely be one of the first 5 pins on either side of the strip.

        • Andrii Vladyka on December 19, 2018 at 2:19 pm
        • Reply

        Yep, that was the issue. Thanks for the reply.
        I’m however running into another issue, the clock is running behind about a second per week. Any advice as to the cause?

        1. A second per week is excellent! The DS3231M is spec’d at ±5ppm, which is ±3 seconds per week, so it’s all within spec.

            • Andrii Vladyka on December 20, 2018 at 1:08 am

            I see. Thank you for the reply.
            Hope you don’t mind another question. Do you happen to have a case sketch for 3d printing? Specifically the 1.1 board version. And if so, would you share it with me by email? Thanks in advance!

          1. I don’t know of any case designs for 1.1, but heres some for 1.3 and 1.4 that you might be able to modifiy:

    • Mark42XLII on January 11, 2019 at 5:12 pm
    • Reply

    Hello. Great project!
    Bought the stuff and soldered it. However, when setting fuses, I couldn’t set efuse to 0x06. In the site you link on AVRDUDESS, it says that there are problems when verifying undeclared bits, so when I read the fuses after trying to set them, hfuse and lfuse match what I expected but efuse is 0xFE. Using the fuse calculator from AVRDUDESS, and setting BODLEVEL0 on, it gives me 0xFE, so I guess it’s right?

    Also, when I uploaded optiboot, the red LED onboard flashed. What does that mean? I used Arduino as ISP to do it.

    Last question: to upload the program, do I need to use an UART converter or can I do it with just the ISP? Also, I followed one of your answers to a forum post explaining the configuration necessary for uploading the code via UART, but the attached picture with the options for AVRDUDESS is only available for registered users, and the forum says the admin disabled registrations.

    Thanks in advance.

    1. Hey Mark,

      Thanks 😀
      Yeah the efuse should really be 0xFE. 0x06 gives the same effect but verification will fail as the upper unused bits are always read back as 1, resulting in 0xFE.

      Optiboot will flash the red LED when the bootloader is entered and when programming, so sounds like it’s working as it should 🙂

      The main program can be uploaded via ISP, but will overwrite the bootloader. The bootloader is optional so that you can use UART to upload the main firmwre. Using the bootloader will prevent you from accidentally messing up the fuses, which can be a real pain to fix and so you only need to connect 4 wires instead of 5.

      Forum guests should be able to view attachments now, registration has been disabled since it was just filling up with bots.

        • Mark42XLII on January 13, 2019 at 7:34 pm
        • Reply

        Thanks for the reply! I actually figured that out by myself and it’s working now. I tried using an Arduino as USB serial converter, but no luck, and I don’t own a proper one. Not even one of those CH340G based converters. I tried to make one out of a Nano clone with a dead mega328p, but even removing the chip didn’t seem to make it work. Only TX was working, though RX was blinking. I think it doesn’t have enough output current. In the end, I could only trust ArduinoISP, and uploaded it via ISP. My screen also ran into issues (only some icons appeared on the top line and heavily glitched) and I thought it was my soldering, because I wasn’t sure about the controller ( the eBay listing said that it was both SH1106 and SSD1306). After reading some comments, I could confirm it was the controller and after installing Atmel Studio 7.0, pretty much everything broke, and with a downgrade to 6.1 I finally built the right version. Phew! I’ll make a pull request to add some stuff to the wiki, this info scattered in the comments can be really useful. But most of the time I spent was trying to use ArduinoISP and setting the wrong baudrate, uploading the code to the wrong place *facepalm*. It works great now! Just bought the wrong tactile switches :/ Thanks for the help! Also, I soldered mine by hand, with a rotten iron, some homemade flux and a cheap wire from an old extension cord. You are probably going to be impressed, but the hardest part to solder is the capacitors, since I can’t use wick to do the work for me and it always gets tilted.

        1. Wow xd

          The nano clone might not have worked because the USB-UART converter on it is running at 5V, but the watch runs at 2.5V, too low for the RX pin on the nano to see. Looking forward to seeing your piece of art, though 😀

            • Mark42XLII on October 14, 2019 at 8:10 pm

            Well, I’m a few months late, but after some email juggling with my parts supplier (LCSC) the right switches arrived and it’s working like a charm:
            Lately, I’ve been designing a fork of this project starring a 128×128 RGB565 OLED display and the CC2640R2F as the brains, for extra speed and bluetooth capabilities. I’ll have to sacrifice some power though – I’m estimating something like a two week charge cycle. But that’s for a 200mAh battery, and with the extra area from the bigger display I’m sure I can find a bigger battery with a thinner profile.

          1. Awesome! 😀 Will be interesting to see how your fork turns out!

            • Mark42XLII on October 14, 2019 at 8:15 pm

            Also, why don’t you use resistors with larger values for the battery voltage divider instead of that transistor on-off thing? AFAIK the ADC input impedance for the ATMega328P is around 100Mohms, I bet you could use something like 2x1Mohm resistors.

          2. The recommended max source impedance for the ADC is 10k. Higher value resistors are more susceptible to noise and things. 1M resistors are often used in those Arduino touch sensor tutorials so having the watch on your wrist with 1M resistors will probably throw the readings way off!

          • Panogari on January 11, 2020 at 12:13 am
          • Reply

          Hello Zak and Mark42XLII,

          Can I see the BOM (Bill of material) that you use at @Mark42XLII, I have a little problem in finding components, especially switch and piezo components.

          Thanks for answering

            • Mark42XLII on November 23, 2020 at 4:15 pm

            Wow, sorry for the delay, I didn’t even see this. I also struggled to find the parts, and I had to look trough countless pages of piezo speakers and switches to compare their dimensions and datasheets. I’m probably too late, but I hope you can still make something out of it.

    • emre on January 31, 2019 at 9:31 pm
    • Reply

    how can i use the micro usb port for also programming. actually,can i do that

    1. Hey emre, no the USB port is only for charging. Programming is done using a USBasp (or some other ISP programmer) and poking wires through the holes near the switch. Or, if you’re using the newer version then you’d use a USB-serial converter and pogo adapter and use the pads between the 2 buttons on the right side.

        • emre on February 21, 2019 at 9:20 pm
        • Reply

        thanks for answer, you are great!

          • emre on March 7, 2019 at 5:25 pm
          • Reply

          another question , i don’t understand how works offsetY parameter in draw_bitmap function could you explain

          1. offsetY is used by the main watch face when the numbers do the ticker animation. It moves the starting Y position (up-down position) when rendering the bitmap, and will also cause it to cut off the bottom of the bitmap by whatever value offsetY is.

    • Andrii Vladyka on March 25, 2019 at 3:49 am
    • Reply

    Hey Zak, quick question. What CPU pin can I use to pull up to a 1/ to ground if I wanted to add a vibration switch to activate the display? Maybe even a gyro module through firmware?

    1. You can use any pin that isn’t being used, on the latest v1.4 hardware that would be PB6 and PB7 🙂

    • Soham on May 2, 2019 at 12:28 pm
    • Reply

    Hi zak,
    I’m trying to make a watch like yours using arduino. Can u tell me how did u change the contrast of your watch??

    1. Command 0x81 then the contract value will set the contrast. Have a look at oled.c source code in the GitHub repo.

    • Soham on May 5, 2019 at 7:51 am
    • Reply

    Hi zak,
    I’m using arduino and every feature is working properly except displaying time. In your video how have u coded that only the seconds seem to clear not the whole display?

    1. Hi Soham, the code uses a frame buffer which is cleared and everything is re-drawn 60 times per second. After each re-draw the new frame buffer is then sent to the OLED, which overwrites whatever is on it.

        • Soham on May 6, 2019 at 7:18 pm
        • Reply

        Hey zac,
        I tried your way but it is not working, I think I have done it the wrong way so can u send me the code to display text using arduino??

        1. Requests like this aren’t free, email me if you want (top corner under the search bar) 😛

    • emre on June 16, 2019 at 4:16 pm
    • Reply

    Hi zak, i have some problems with programming.
    firstly,i have ftdi ttl converter but dont have pogo programmer i will make mine . in your pogo programmer has 470r and 15k resistor ,are they neccessary or can i ignore them .

    another one ,i tried to burn bootloader but i wasnt to able it.can you explain how it is done.

    1. Heya emre, the 470R and 1k5 resistors form a voltage divider to knock the 3.3V UART TX from the converter down to 2.5V, but it’s not really needed. The bootloader is uploaded using an ISP like an USBasp. Connect up the MISO/MOSI/SCK/RST/GND pins to the MI/MO/CL/R/GND pads on the watch.

        • emre on June 19, 2019 at 7:07 am
        • Reply

        I tried many times what you said didnt work (avrdudess didnt see the atmega).finally i connect a 16mhz crystal from xtal then i was able to burn bootloader do you think what is problem of my device

        1. Sounds like the fueses have been set wrong. Make sure they’re set to:
          High: 0xDE
          Low: 0xE2
          Extended: 0x06

            • emre on June 20, 2019 at 8:48 am

            thanks zak the watch almost done.I think next step improving my soldering skills 🙂

          1. Nice! At least it works! 😀

    • Andrii Vladyka on August 7, 2019 at 8:26 pm
    • Reply

    Hey Zak! Sorry for bothering you again, but I have a couple of questions:
    Should the battery indicator be slightly lower than full after a full charge (the lightning bolt disappears)?
    Maybe it’s because I made the V1.1 which uses MOSFET’s instead of the bipolar transistors like in V1.4 for the voltage divider? Or should that not matter? Or is it because the battery doesn’t charge fully despite the indicator due to the 22k RPROG? The datasheet for the IC says it should have a roughly 13k RPROG for 150mA, unless I’m looking at it wrong.
    For my battery, 200mA, should I use a 10k RPROG according to the datasheet (should yield 100mA = 1/2 of the battery capacity)? Or does that have no noticeable effect?
    Sincerely appreciate your help and advice, waiting for your reply.

    1. Hey again, the battery indicator should show full whenever the battery voltage is over 4V. Using MOSFETs or BJTs won’t matter, but in v1.1 the resistor values are 7k5 + 2k7 and in v1.4 they’re 10k + 10k, so the output voltage of the divider will be different. You will need to either change the resistor values to the values expected by the firmware or compile the firmware for your hardware version (HW_VERSION in config.h). The RPROG value will just depend on how fast you want to charge the battery, usually no more than 0.5C for normal batteries (0.5C for a 200mAh batt would be 100mA, or 10k RPROG). Lower RPROG will result in a higher charging current.

  1. […] A lot of the inspiration for this project came from the excellent work done by Zak Kemble at his blog. […]

  2. […] couple of weeks ago i saw this project by Zak Kemble here: I emediately wanted to build one myself using off-the-shelf […]

  3. […] Оригинальный проект был случайно найден на просторах интернета несколько месяцев назад. Вот он: […]

Leave a Reply to Zak Kemble Cancel reply

Your email address will not be published.

Are you human? *