For some years I have wanted to create a low powered Arduino compatible system. The Arduinos themselves do not seem to be suited to this as they do not have the low power features implemented into the Arduino IDE. So, after looking around at alternatives that I could still programme from within the Arduino IDE I settled on the ATtiny85. I have pottered about for several years looking to get a programmer for this chip but never managed to get around to either making one or purchasing one, plus they seemed quite complicated (at least to me) to programme as well. Recently I discovered the DigiSpark ATtiny85 board and this seemed to be mostly what I wanted. Additionally, it is suitably low cost.
It has a built-in USB connection which is used for programming, has low power library already implemented and can be programmed directly (almost) from the Arduino IDE. Once the board is added to the Arduino IDE and the Windows drivers manually installed (the automatic method didn't work for me) the only real difference is that within the Arduino IDE the compile and programme button is selected without the DigiSpark PCB plugged in. Once the compiling is completed you then have 60 seconds to insert the ATtiny85 PCB and then it programmes (most times), very quickly. I'm sure many readers are well familiar with this approach but it was new to me and it took me most of a day trying to get it to actually work. Things are only difficult when you don't know how to do them.
I used the ideas outlined in (Low power projects digispark ATtiny85 modification - Arduino - WIKI (liutyi.info)) to see how to reduce the power consumption to the lowest I could achieve. The standard Digispark ATtiny85 consumes approximately 8 mA when executing a programme with no external peripherals connected which is much too much current for my use as I want to run the board from a CR2032 battery. Most of this is due to the 7805 regulator contained within the PCB. I didn't want to run the board from a supply of more than 5V so this regulator was not needed. I did not really want to start de-soldering this regulator so I just snipped the input and output connections and if I want I can always add a solder blob to remake the connections. This reduces the current requirement to approximately 3 mA with about 1.5 mA of that being due to the permanent power LED indicator. The only way to get rid of this is to remove the LED or resistor. I couldn't identify the resistor so I de-soldered (very badly) the LED. I think this is my first surface mount LED removeable and it was a bit of a botch. Still, I removed the LED and the PCB still worked and programmed. The current reduced to approximately 1.5 mA. The amended DigiSpark PCB is shown below. You can just see the snipped legs of the 7805. It is possible to further reduce the current requirement of the DigiSpark hardware but that requires changes that might affect it's capability to be reprogrammed so I have not done any of them.
Now it was time to try the software low power options available to the ATtiny85. I used the programme provided on the website listed above and this reduced the current to approximately 0.4 mA. My adapted programme that flashes an LED for one second every 48 seconds is listed below. It isn't very pretty as I was having a problem getting the WDT to restart after an 8 second sleep and tried all sorts of things before working out that everything has to be reset and interrupts re-enabled every time. At least I think you do. Anyway, it works if you do and it doesn't if you don't.
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // disable ADC (before power-off)
#define adc_enable() (ADCSRA |= (1<<ADEN)) // re-enable ADC
void setup()
{
// Power Saving setup
for (byte i = 0; i < 6; i++) {
pinMode(i, INPUT); // Set all ports as INPUT to save energy
digitalWrite (i, LOW); //
}
adc_disable(); // Disable Analog-to-Digital Converter
wdt_reset(); // Watchdog reset
wdt_enable(WDTO_1S); // Watchdog enable Options: 15MS, 30MS, 60MS, 120MS, 250MS, 500MS, 1S, 2S, 4S, 8S
WDTCR |= _BV(WDIE); // Interrupts watchdog enable
sei(); // enable interrupts
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Sleep Mode: max
}
void loop()
{
int timeindex;
timeindex = 0;
//
setupwdt();
pinMode(0, OUTPUT);
digitalWrite(0, HIGH);
sleep_enable();
sleep_cpu();
//Set the LED pins to LOW. This turns it off
pinMode(0, OUTPUT);
digitalWrite(0, LOW);
//
wdt_reset(); // Watchdog reset
wdt_enable(WDTO_8S); // Watchdog enable Options: 15MS, 30MS, 60MS, 120MS, 250MS, 500MS, 1S, 2S, 4S, 8S
WDTCR |= _BV(WDIE); // Interrupts watchdog enable
sei(); // enable interrupts
for (timeindex = 0; timeindex < 6; timeindex++)
{
sleep_enable();
sleep_cpu();
} /* sleep */
}
ISR (WDT_vect) {
WDTCR |= _BV(WDIE);
}
void setupwdt(void)
{
wdt_reset(); // Watchdog reset
wdt_enable(WDTO_1S); // Watchdog enable Options: 15MS, 30MS, 60MS, 120MS, 250MS, 500MS, 1S, 2S, 4S, 8S
WDTCR |= _BV(WDIE); // Interrupts watchdog enable
sei(); // enable interrupts
} /* setupwdt */
I have added a blue LED to P0 in series with 118 Ohm resistor (actually four 470 Ohm resistors in parallel as these were the smallest resistors I could find). The resistor is on for 1 second and then off for 48 seconds (6 x 8 second sleeps using the watch dog timer). The on current is about 2 mA and the off current is about 0.3 mA so the average current is (1 x 2 + (48 x 0.3))/49 = 0.33 mA. The system diagram is shown below (the four parallel resistors are 470 Ohms each).
I am using 'approximately' when referring to measurements as the current is dependent on the voltage of the power supply and when I changed from a 3.2V power supply to an allegedly 3.2V CR2032, the current dropped to around 0.3 mA. I am using a lithium CR2032 from GP Batteries (BQS1304 GPCR2032 TDS Rev10.doc (cellpacksolutions.co.uk)). The datasheet does show that the voltage of a new battery drops quite quickly from the nominal 3.2V to a more realistic 2.8V. The ATtiny85 does work at this reduced voltage of 2.8V but once the voltage drops to about 2.6V or so it does have problems restarting if power is disconnected. This is a bit more sensitive than I wanted but I am aiming to make a system that once turned on is not turned off again so this sensitivity to the supply voltage should be OK. The datasheet shows a capacity of 220 mAh at a load of 15 kOhms leading to about 1100 hours of continuous operation. The amended Digispark has the equivalent load of about 9-10 kOhms at 2.8V so will be less than this 1100 hour maximum, probably nearer to 600-700 hours. This is still plenty and means a CR2023 powered amended DigiSpark should work continuously for at least 25 days. Good enough for a Christmas decoration.
A video showing the LED very excitingly flashing is given below.
For some reason I do not seem to be getting the battery life that I have calculated above. After a few days the LED was noticeably dimmer. When I tried to measure the battery voltage I accidentally disconnected the battery and then the system would not restart from the used battery. I am not sure why as the battery voltage still shows as 2.7V.
While I was trying to work out what the problem was I did notice that every 8 seconds there was a current surge. This is to be expected as the ATtiny85 wakes up to check if anything needs to be done. With a digital multimeter it was not possible to measure what that current surge is. So I added a low value resistor (12 Ohms) into the ground connection so that I could use my DSO to measure the current. The 12 Ohm resistor will slightly reduce the voltage supplied to the ATtiny85 it should only be a few mV and not too much of a problem. If a higher current load is used then this resistor would need to be removed. The image below shows the current consumption when the LED is turned on. The scales are 10 mV per vertical division and 250 ms per horizontal division.
The quiescent voltage is 4 mV and with the 12 Ohm resistor this equates to 0.33 mA which is as expected. There is then a step up to 16 mV as the ATtiny85 wakes up and gets ready to turn on the LED, equating to a current of 1.3 mA. This period lasts for about 75 ms and then the LED turns on. showing a voltage of 21 mV which equates to 1.75 mA which is the power needed by the ATtiny85 and the LED. The ATtiny85 goes back into sleep mode while the LED is on ( a very clever arrangement) so needs to wake up for another 75 ms to turn off the LED, needing a small additional burst of current. This is pretty much as expected.
The image below shows the current needed when the ATTtiny85 wakes up from an 8 second sleep, resets the WDT and then goes back to sleep again. This period lasts for about 60 ms and requires the same 1.3 mA as above. The scales are 10 mV vertical and 100 ms horizontal.
This does indicate that the DigiSpark ATtiny85 board is doing pretty much what I anticipated so I am uncertain why the battery did not seem to last the full 25 days. It could be that the battery had lost some power capacity (I had used it before!) so I will try another brand new battery. I have had these batteries for a couple of years but the use by date is 2028 so they should be OK. I'll see how long this new battery lasts.
Dubbie