This instructable show how to use an ATtiny85 to create a tiny watch core that can run over 1 year before recharge or replace battery.

The instruction to make the watch case may be in next instructable.

I have made a few Arduino watch before, but I found the watch using ATmega boards or ATmega chips are a little bit too big to wear. So I would like to make it with a smaller chips.

I have choose ATtiny85 just because I can easy to get one.

The challenges for using ATtiny85 are:

  1. It only have 8K flash memory
  2. It only have 5 IO pins (I would like to keep the 6th IO pin as reset for easy re-programming)
  3. Since the above 2 limitations, it is hard to find a complete source code for an ATtiny watch on the web

I design to develop a tailor-make code to complete these challenge, it include:

  1. Power control to make the watch can run over 1 year
  2. Revise a time library to utilize WDT for power saving purpose
  3. Trim down a display library to meet 8K binary limitation
  4. Customizable font type
  5. Basic UI for adjust time just like a normal digit watch

Step 1: Preparation


Today core subject, ATtiny85.


Any ISP that can program ATtiny85.


In general expectation, a watch should run over 1 year without charging or replace battery. For my simple measurement of power usage and the battery specification, CR1220 can only run about half an year, CR2016, CR2025 and CR2032 can run over 1 to 2 years representatively.


Since the number of IO pins of ATtiny85 is very limited, I design display and further modules should all run in I2C. Power consumption and source availability are also important factors. I choose an OLED screen drive with SSD1306. It can find in 3 different sizes, 64x32 is the smallest one. (another sizes are 128x64 and 128x32)

Other Parts

A battery holder, a small bread board, some bread board wires, two buttons and a power switch (optional).

<p>can we use this microcontroller instead http://www.amazon.in/VEEROBOT-CRUX-ATtiny85-Development-Board/dp/B0115IZ7XU?ie=UTF8&amp;keywords=attiny%2085&amp;qid=1466594287&amp;ref_=sr_1_3&amp;sr=8-3</p>
<p>no idea, never use it yet. but it have a USB socket, seems similar to Digispark. if true, the boot loader eat up around 2 KB memory, then may not have enough room to fit this program.</p>
<p>How do you modify the code for a 64x48 display?</p>
just guess it similar to 64x32, but have 2 more page.
<p>Works fine, but i have bigger OLED ( http://www.ebay.com/itm/351493950611?_trksid=p2057872.m2749.l2648&amp;ssPageName=STRK%3AMEBIDX%3AIT ) and cant seem to find where to edit so it fills my screen, also id like to be able to edit sleep so it can be on all the time, where to do these changes?</p>
I have made an ring watch base on this core, you may find more details here:<br>https://m.instructables.com/id/ATtiny85-Ring-Watch/
<p>You left one pin unused what a waste :-)<br>Seriously though: great project and looks good too</p>
<p>can you send me the download files i don't want to pay thank you email; klambie at enutil-energy.com</p>
<p>which download files? I have no idea what you are talking about</p>
<p>Not waste, I just reserve it for future development. Actually, in my latest code, I change to used only one pin to connect three or more buttons, and reserve remain more pin for further features, such as serial GPS or BLE.</p>
<p>good idea though the purist in me would then think....hmmm attiny10 ;-)<br>Great project, well done</p>
<p>wow, I think i'm going to base my Attiny85 pocket watch on this :)</p>
<p>Nice idea and 'ible! I wonder if this could be compacted even more, maybe an SMD attiny, SMD buttons, and like you mentioned, a smaller battery? I wonder just how tiny this could be made. Also, I wonder if there's green on black versions of this display? Then you could make the font look like an old terminal, so it'd look like an ancient computer. Anyways, neat idea and project, I might make it sometime.</p>
<p>coming soon</p>
<p>Cool! I noticed the buttons and the resistor are still through hole, though. If you're not too intimidated by SMD soldering, couldn't it be just a <em>bit</em> smaller? ;)</p>
<p>yes, I do not have SMD button and resistor in hand. And I design add one more button and use resistors for the button panel too late, so it is temporary solution.</p>
<p>Ah, ok. Well, I look forward to seeing it once you've finished with it!</p>
<p>Even thermal compensated RTC units drift over time. How stable is the ATTiny as it relates to time drift?</p>
<p>It needs time to measure, in my previous experience, use Lithium battery is better than rechargeable battery. It run a few days ago, and the variation still not over 1 minute.</p>
<p>How do you calibrate? Step by step please! My build of this loose minutes every hour. Suggestions please</p>
<p>Revised step 8 for the time calibration details</p>
<p>Thank your for revised Calibration Step. However, to help the &quot;clueless&quot; like myself, it could also specify the calibrated values are edited into WDT_Time.cpp at lines:</p><p>static uint16_t wdt_millis_per_interrupt = 1076; // calibrate value</p><p>and for readVcc()</p><p>result = 3094575L / result; // calibrated value </p>
<p>Good!</p><p>Sorry for the misleading, the code come from over 3 sources and I have substantially revised. I will try to move also calibrate value at the top in next instrucables. (ATtiny Ring Watch) </p>
<p>Sorry but I'm still doing something wrong. After I determine the ms and mv numbers I still loose too much time. So I think I am not computing the calibration numbers correctly. </p>
<p>can you show your calculation?</p>
<p>WDT_Time.cpp shows to compute measured voltage in mv:</p><p> // result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000</p><p> result = 3375900UL / result; // calibrated value</p><p> return result; // Vcc in millivolts</p><p>My measured voltage is 3.3V which is 3375900 by this formula - When I make results=3375900UL then debug shows 14806 This is confusing to me.</p>
<p>I have updated step 8 for voltage calibration.</p><p>Please be noted that:</p><p>wdt_millis_per_interrupt vale should be within +/- 10 of 1000 milliseconds</p><p>voltage reference value should be within +/- 100k(~0.1 v) of 1125300UL</p><p>auto tune wdt_millis_per_interrupt by voltage level not yet implement (i.e. voltage reference calibration not affect time accuracy)</p>
<p>This is not working for me. Using Atmel Attiny85 20PU - IDE 1.65 with settings Tiny85 at 1Mhz Internal</p><ol><br><li>Program chip with Attiny85_Watch_ino with WDT_Time.cpp with default or original entries </ol><p> static uint16_t wdt_millis_per_interrupt = 998; // calibrate value</p><p> result = 1089952UL / result; // calibrated value</p><ol><br><li>Note down current local time<li>Set time on Attiny chip<li>Measure and note actual Mv on Attiny chip<li>Wait 1 to 8 hours and note elapsed time in milliseconds<li>Note Debug values<li>Compute wdt_millis_per_interrupt as: 51300000 / x = y (x = debug value noted, y= calibrated value)<li>Enter value of y at &ldquo;static uint16_t wdt_millis_per_interrupt = 998; // calibrate value&rdquo; in WDT_Time.cpp replacing 998<li>Compute millivolts using x / debug value * 1125300 = y (x=measured millivolts, y= calibrated value)<li>Enter values of x and y at &ldquo;result = 1089952UL / result; // calibrated value&rdquo; replacing 1089952 in WDT_Time.cpp<li>Reprogram Attiny85 chip with the newly calibrated values.<li>Reset time of Attiny85 to current local time. </ol><p>I then recheck the Attiny clock but time is either gaining or losing after only a few minutes. Am I still doing something wrong?</p>
<p>I am writing a new version to help auto calibrate the value, it should release at these few days.</p>
<p>Thanks -- looking forward to it.</p>
<p>Try this:</p><p><a href="https://github.com/moononournation/ATtinyWatch" rel="nofollow">https://github.com/moononournation/ATtinyWatch</a></p><p>it will auto tune the interrupt value when you set the time, if this not the first time of time setting and the previous setting is over 1 hour.</p>
<p>Hello, this version works but with caveat. I must reset the unit when trying to set time for self calibration. The time will start rapidly changing by itself. Once I reset it, it behaves and keeps time accurately. Thanks for your work and sharing. Pete</p>
<p>This version works quite well. However, I have a question. How and where do I change where the text begins to display.? It displays low, towards the bottom of the display. Its a 128x64 0.96 inch display. Maybe your display is smaller and the text seems bigger because of that. Thanks again for all your help.</p>
<p>Sorry for late reply, I have just tested on 128x32 and 128x64 screen. You may uncomment the screen #define at the file ssd1306.h for change resolution setting.</p><p>Please find the updated at the same place:</p><p><a href="https://github.com/moononournation/ATtinyWatch.git" rel="nofollow">https://github.com/moononournation/ATtinyWatch.git</a></p>
Haven't tried with attiny, but the megas drift several seconds every hour. An experiment was off by about twenty minutes after roughly 8 hours at room temperature. My mechanical watch was more accurate.
<p>Hi,that ssd1306 looks verry small,it looks smaller than mine,my ssd1306 128x64 wont fit on half a small breadboard like this does,where did you buy it from?</p>
the resolution is 64x32
<p>Hi does the number on these batterys corraspond to mah cr2025 and cr2016 etc?</p>
<p>CR2016, CR2025 and CR2032, the first 2 digits if the battery diameter and the last 2 digits is thickness. Thicker battery should have more mAh.</p>
<p>these are the errors when i try to compile:</p><p> This report would have more information with</p><p> &quot;Show verbose output during compilation&quot;</p><p> enabled in File &gt; Preferences.</p><p>Arduino: 1.0.6 (Windows NT (unknown)), Board: &quot;ATtiny85 @ 8 MHz (internal oscillator; BOD disabled)&quot;</p><p>attiny85watch.ino: In function 'void setup()':</p><p>attiny85watch:17: error: 'INPUT_PULLUP' was not declared in this scope</p><p>attiny85watch:23: error: 'TinyWireM' was not declared in this scope</p><p>attiny85watch:24: error: 'class SSD1306' has no member named 'begin'</p><p>attiny85watch:25: error: 'class SSD1306' has no member named 'fill'</p><p>attiny85watch.ino: In function 'void enter_sleep()':</p><p>attiny85watch:42: error: 'class SSD1306' has no member named 'fill'</p><p>attiny85watch:43: error: 'class SSD1306' has no member named 'off'</p><p>attiny85watch.ino: In function 'void wake_up()':</p><p>attiny85watch:53: error: 'class SSD1306' has no member named 'on'</p><p>attiny85watch.ino: In function 'void draw_oled()':</p><p>attiny85watch:74: error: 'class SSD1306' has no member named 'fill'</p><p>attiny85watch:80: error: 'class SSD1306' has no member named 'print_digits'</p><p>attiny85watch:82: error: 'class SSD1306' has no member named 'draw_pattern'</p><p>attiny85watch:83: error: 'class SSD1306' has no member named 'print_digits'</p><p>attiny85watch:84: error: 'class SSD1306' has no member named 'draw_pattern'</p><p>attiny85watch:85: error: 'class SSD1306' has no member named 'print_digits'</p><p>attiny85watch:87: error: 'class SSD1306' has no member named 'print_digits'</p><p>attiny85watch:88: error: 'class SSD1306' has no member named 'draw_pattern'</p><p>attiny85watch:89: error: 'class SSD1306' has no member named 'print_digits'</p><p>attiny85watch:91: error: 'class SSD1306' has no member named 'print_digits'</p><p>attiny85watch:92: error: 'class SSD1306' has no member named 'print_digits'</p>
it require Arduino 1.6.5, ATtiny core source and TinyWireM library.
<p>thank you.</p>
<p>Hi i want to make an weather station with an dht22 sensor and this oled display and the attiny, everithing works grat with an 20x4 display lcd<br>i just need the code to print some text how i use the command oled.print_digits(&quot;some text&quot;); ?</p>
<p>Solved! i use this code:</p><p>#include &quot;SSD1306_minimal.h&quot;<br>#include &lt;avr/pgmspace.h&gt;<br><br>#define DEG &quot;\xa7&quot; &quot;C&quot;<br><br>SSD1306_Mini oled;<br><br>void setup(){ <br> oled.init(0x3c);<br> oled.clear();<br> delay(1000);<br>} <br><br> <br>void loop(){<br> oled.startScreen();<br> oled.cursorTo(15,1);<br> oled.printString( &quot;Oled_Attiny85&quot;); <br>} </p>
<p>Good!</p><p>In this program, it only contain digit bitmap font, so it cannot display any other character. I will implement it in the future if it still have enough room in the 8K flash.</p>
<p>Dear 陳亮</p><p>I'm upload error </p><blockquote>sketch\WDT_Time.cpp: In function 'void setup_watchdog(int)':<br><br>WDT_Time.cpp:323: error: 'WDTCR' was not declared in this scope<br><br> WDTCR |= (1 &lt;&lt; WDCE) | (1 &lt;&lt; WDE);</blockquote><p>How can i debug ?</p><p>Thanks</p>
<p>It depends on which ATtiny source you are using, sometimes WDTCR constant may be WDTCSR.</p><p>I am currently using this source:</p><p><a href="https://github.com/vprimachenko/ArduinoTiny" rel="nofollow">https://github.com/vprimachenko/ArduinoTiny</a></p>
<p>I had same error. Create folder WDT_Time in libraries folder. Put WDT_Time.cpp and WDT_Time.h inside that folder and re-compile. This worked for me under IDE 1.65</p>
<p>How can install Tiny correct</p><p>This is new error </p><blockquote>Arduino: 1.6.7 (Windows 10), Board: &quot;ATtiny85, 8 MHz (internal oscillator; BOD disabled)&quot;<br><br>Warning: platform.txt from core 'Arduino Tiny' contains deprecated recipe.ar.pattern=&quot;{compiler.path}{compiler.ar.cmd}&quot; {compiler.ar.flags} &quot;{build.path}/{archive_file}&quot; &quot;{object_file}&quot;, automatically converted to recipe.ar.pattern=&quot;{compiler.path}{compiler.ar.cmd}&quot; {compiler.ar.flags} &quot;{archive_file_path}&quot; &quot;{object_file}&quot;. Consider upgrading this core.<br>Warning: platform.txt from core 'Arduino Tiny' contains deprecated recipe.c.combine.pattern=&quot;{compiler.path}{compiler.c.elf.cmd}&quot; {compiler.c.elf.flags} -mmcu={build.mcu} -o &quot;{build.path}/{build.project_name}.elf&quot; {object_files} &quot;{build.path}/{archive_file}&quot; &quot;-L{build.path}&quot; -lm, automatically converted to recipe.c.combine.pattern=&quot;{compiler.path}{compiler.c.elf.cmd}&quot; {compiler.c.elf.flags} -mmcu={build.mcu} -o &quot;{build.path}/{build.project_name}.elf&quot; {object_files} &quot;{archive_file_path}&quot; &quot;-L{build.path}&quot; -lm. Consider upgrading this core.<br>exec: &quot;avr-g++&quot;: executable file not found in %PATH%<br>Error compiling.<br><br> Thanks<br></blockquote>
<p>it can compile again after reinstall Arduino 1.6.5</p>

About This Instructable




More by 陳亮:Photo Pop Up Card ESP8266 WiFi Analyzer IoT LED Sign 
Add instructable to: