ATtiny85 - Using capacitor for backup power to persist clock time to EEPROM

As discussed in the initial design post, the idea is to connect a 0.47F capacitor to the VCC and GND pins of the ATtiny85. Then when we lose power, the capacitor will provide the ATtiny85 with enough juice to store the current clock time to its EEPROM. When we gain power again, the ATtiny85 will read the clock time back from the EEPROM and start over. In this way, we avoid killing the EEPROM of the ATtiny85 with too many write operations.

To that end, I purchased something like this over EBay (2 for $3, so works out to about $1.50 each).

The code to check for supply voltage drop looks like this:

voidloop() { // Execute loop() every secondif (!timer1) return; else timer1 =false; // Measure supply voltage// Source: adc_enable(); ADMUX = _BV(MUX3) | _BV(MUX2); // VCC as reference, band gap voltage (~1.1V) as input _delay_us(250); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversionwhile (bit_is_set(ADCSRA, ADSC)); //…

ESP-12E calling Google Timezone API

The ESP-12E module of the ESPCLOCK V2.0 project is done. All the clock control logic has been shifted to the ATtiny85 module, so the ESP-12E is only in-charged of periodically getting the NTP time, converting to local time, and sending it via I2C to the ATtiny85.

One of the unresolved problems in the original ESPCLOCK project is calling the Google Timezone API via HTTPS. Because Google's HTTPS cert is different for servers in different geographical locations, this presents a problem for the original code:

const String GOOGLE_API_URL ="[loc]&timestamp=[ts]"; constchar* GOOGLE_API_CERT ="AD:B8:13:99:64:F5:75:F5:78:5C:FA:43:19:EA:8F:AF:2B:AE:54:FE"; ... HTTPClient http; http.begin(url.c_str(), GOOGLE_API_CERT); int rc = http.GET();
The solution I used is the one outlined in this comment.

const String GOOGLE_API_URL ="[loc]&timestamp=[t…

ESP-12E I2C test communication with ATtiny85

I ran a little test to make sure the ESP-12E is able to communicate with the ATtiny85 via I2C.

These are the connections required:

ESP-12E ➜ ATtiny85

   D1       Pin 2
   D2       Pin 1

D1 and D2 are both connected to 3V3 on the ESP-12E with 10K resistors. The ESP-12E and the ATtiny85 are connected via different USB cables (ATtiny85 via the Arduino Uno) to the same USB hub.

The sketch for the ESP-12E (I2C master):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33#include <stdint.h>#include <Wire.h> byte tx =0; voiddebug(constchar*format, ...) { char buf[256]; va_list ap; va_start(ap, format); vsnprintf(buf, sizeof(buf), format, ap); va_end(ap); Serial.println(buf); } voidsetup() { Serial.begin(115200); Wire.begin(); } voidloop() { Wire.beginTransmission(0x26); Wire.write(++tx); Wire.endTransmission(); debug("tx = %d", tx); Wire.requestFrom(0x26, 1); if (Wire.available() >=1) { …

Attiny85 timer programming using Timer1

This Arduino sketch uses Timer1 to drive the LED blinker:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44#include <avr/io.h>#include <avr/wdt.h>#include <avr/sleep.h>#include <avr/interrupt.h>bool timer1 =false, led =true; // Interrupt service routine for timer1 ISR(TIMER1_COMPA_vect) { timer1 =true; } void setup() { // Setup output pins pinMode(1, OUTPUT); set_sleep_mode(SLEEP_MODE_IDLE); // Setup timer1 to interrupt every second TCCR1 =0; // Stop timer TCNT1 =0; // Zero timer GTCCR = _BV(PSR1); // Reset prescaler OCR1A =243; // T = prescaler / 1MHz = 0.004096s; OCR1A = (1s/T) - 1 = 243 OCR1C =243; // Set to same value to reset timer1 to 0 after a compare match TIMSK = _BV(OCIE1A); // Interrupt on compare match with OCR1A// Start timer in CTC mode; prescaler = 4096; TCCR1 = _BV(CTC1) | _BV(CS13) | _BV(CS12) | _BV(CS11); sei(); } void loop() { if…

ATtiny85 timer programming using the Watchdog Timer

This Arduino sketch uses the watchdog timer on the ATtiny85 to interrupt every second to pulse the LED:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31#include <avr/io.h>#include <avr/wdt.h>#include <avr/sleep.h>#include <avr/interrupt.h>bool led =true; voidsetup() { // Misc setup pinMode(1, OUTPUT); set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Setup watchdog timer to interrupt every second MCUSR &=~_BV(WDRF); WDTCR |= (_BV(WDCE) | _BV(WDE)); WDTCR = _BV(WDP1) | _BV(WDP2); WDTCR |= _BV(WDIE); sei(); } ISR(WDT_vect) { sleep_disable(); digitalWrite(1, led ? HIGH : LOW); led =!led; // Execution continues in loop() } void loop() { sleep_enable(); sleep_cpu(); // MCU goes to sleep here; wake up by watchdog timer interrupt }
The advantage of this approach is I can use the SLEEP_MODE_PWR_DOWN mode to put the MCU to sleep to save the maximum amount of power when there is nothing to be done. T…

Test programming the ATtiny85

Just got my ATtiny85 chip today from the postman and playing with it now.

There are quite a number of ways to program the ATtiny85, from the very cheap (USBasp, Tiny AVR Programmer, USBtinyISP) to the more expensive (AVRISP mkII). The Tiny AVR Programmer is probably the most convenient of the lot because it targets the ATtiny family specifically, so no cables are required. Just plug the chip into the provided socket.

Since I already have a spare Arduino Uno lying around, I am going the no-cost way, using the Uno to program the ATtiny85. You basically need to hook up the Uno to the ATtiny85 on a breadboard via 6 jumper wires. It's actually easier than it sounds, and took all of a couple of minutes to do.

Arduino Uno ➜ ATtiny85
   5V           Vcc
   Gnd          Gnd
   Pin 13       Pin 2
   Pin 12       Pin 1
   Pin 11       Pin 0
   Pin 10       Reset

The breadboard looks like this:

Configuring the Uno to become an ISP
The next step is crucial. You need to upload a sketch to the Uno so …

ESPCLOCK V2.0 - Design

I previously started a project to hack an analog clock to sync with NTP. I call the project ESPCLOCK, because it uses the ESP8266 chip (or more specifically, the ESP-12E development board for the ESP8266) to integrate with the analog clock.

From a usability viewpoint, I like the fact that there is no need to mess with timezones during setup. Basically when setting up the WiFi, the setup page grabs the timezone from your browser automatically. So setup is as simple as entering the WiFi credentials, and the clock will start keeping accurate time and handle daylight saving automagically.

However, in its current state, there are two issues with the clock:

1. The battery life is awful. Connected to a 2400mAh USB battery pack, it can only last for about 27 hours. A typical analog wall clock will run for at least a year on a single AA battery.

2. To deal with possible power loss, it writes the current clock time to EEPROM every second. Since the EEPROM has a limited number of write cycles, t…