|
Fischertechnik AVR Raspberry Pi Elektronik Netzwerk Sonstiges Impressum |
Stromsparen mit ATtiny25
Diese Schaltung läuft mit einem alten 65mAh-LiPo aus einem alten Spielzeug mehr als sechs Monate und erzeugt unerwartet helle Lichtblitze. Der Trick ist die Nutzung der "sleep"-Funktion des ATtiny, die den Strombedarf drastisch reduziert. Das Programm erzeugt alle 15 Sekunden einen Lichtblitz mit einer Dauer von 3 Millisekunden. Die weiße LED wird ohne Vorwiderstand betrieben, überlebt das aber problemlos; sie hat ja genügend Zeit zum Abkühlen. Der Stromverbrauch im Sleep-Mode/Watchdog-Enabled liegt bei ca. 6μA. Mit dieser Technik habe ich auch einen Temperatur-Logger auf Basis ATmega328P aufgebaut, der alle drei Minuten die Temperatur misst und auf einer μSD-Karte abspeichert. Dieser Logger läuft mit einem 420mAh-LiPo mehr als 4 Wochen. Quelltext/* 2011 Februar CN
ATTINY 25/45/85 fuer Blinkschaltung
Stromversorgung: 1 Zelle LiPo
Beschaltung: Pin 1 offen (Reset)
Pin 2 Ausgang fuer LED Port B3
Pin 3
Pin 4 Ground, Masse
Pin 5
Pin 6
Pin 7
Pin 8 Vcc, +3,7V
*/
#define SET_B3 PORTB |= (1<< PB3) // LED
#define CLR_B3 PORTB &= ~(1<< PB3)
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
/* ------------------------------------------------------------------------- */
#include <inttypes.h>
#include <avr/io.h>
#include <stdlib.h>
#include <string.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
//-----------------------------------------------------------------------------
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(uint8_t ii) {
uint8_t bb;
if (ii > 9 ) ii=9; // begrenze auf erlaubte Werte
bb=(ii+0x18)&0x27; // schiebe bit3 in bit 5
bb|= (1<<WDCE); // ist ggf. ueber .... ?????
MCUSR &= ~(1<<WDRF);
WDTCR |= (1<<WDCE) | (1<<WDE); // nur so geht der Enable vom Watchdog!!
WDTCR = bb; // set new watchdog timeout value
WDTCR |= _BV(WDIE); // Watchdog Interrupt Enable
}
//-----------------------------------------------------------------------------
// set system into the sleep state; system wakes up when watchdog is timed out
void system_sleep() {
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode(); // gute nacht, schlaf schoen...
}
//-----------------------------------------------------------------------------
void delay_seconds_by_watchdog(uint16_t sec){
uint16_t t1;
uint8_t t2; //t2 ist die tatsaechliche Watchdog-Zeit in Sekunden
uint8_t t3; //t3 ist der zugehoerige Parameter hierzu
t1=sec;
while(t1>0){
if(t1>7){t3=9;t2=8;}
else if(t1>3){t3=8;t2=4;}
else if(t1>1){t3=7;t2=2;}
else {t3=6;t2=1;};
setup_watchdog(t3);
system_sleep();
t1-=t2;
};
}
/* ------------------------------------------------------------------------- */
void wait(uint16_t dauer){
uint16_t j;
uint8_t i;
for(j=0;j<dauer;j++){
for(i=100;i>0;i--)asm volatile ("nop\nnop\nnop\nnop\nnop\nnop\nnop");
};
}
/* ------------------------------------------------------------------------- */
// ISR fuer Watchdog muss selber nichts tun; wichtig ist, dass sleep endet
ISR(WDT_vect) {
}
/* ------------------------------------------------------------------------- */
void main(void) {
uint8_t minutes=0;
DDRB = (1<<PB3); // Setze LED-Anschluss als Ausgang
sei(); // erlaube prinzipiell Interrupts
for(;;){
SET_B3; // LED an
wait(3); // ca. 3 ms
CLR_B3; // LED aus
DDRB = 0; // LED Ausgang als Eingang definieren, spart Strom...
delay_seconds_by_watchdog(15);
DDRB = (1<<PB3); // LED-Ausgang wieder richtig als Ausgang
};
}
/* ------------------------------------------------------------------------- */
Makefileavrdude = avrdude -v -v DEVICE = attiny25 CLOCK = 1000000 PROGRAMMER = -c avrispmkII -P usb OBJECTS = blink25.o # Fuses: internal oscilator 8 MHz, 1:8 prescale, BOD 2.7V FUSES = -U hfuse:w:0xDD:m -U lfuse:w:0x62:m AVRDUDE = $(avrdude) $(PROGRAMMER) -p $(DEVICE) OBJDUMP = avr-objdump COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -mint8 # symbolic targets: all: blink25.hex blink25.lss .c.o: $(COMPILE) -c $< -o $@ .S.o: $(COMPILE) -x assembler-with-cpp -c $< -o $@ asm: $(COMPILE) -S -o blink25.asm blink25.c .c.s: $(COMPILE) -S $< -o $@ flash: all $(AVRDUDE) -U flash:w:blink25.hex:i fuse: $(AVRDUDE) $(FUSES) install: flash fuse clean: rm -f blink25.hex blink25.elf $(OBJECTS) blink25.elf: $(OBJECTS) $(COMPILE) -o blink25.elf $(OBJECTS) blink25.hex: blink25.elf rm -f blink25.hex avr-objcopy -j .text -j .data -O ihex blink25.elf blink25.hex disasm: blink25.elf avr-objdump -Z -d blink25.elf %.lss: %.elf @echo $(OBJDUMP) -h -S $< > $@ cpp: $(COMPILE) -E blink25.c |