Power Management and Sleep Modes

Power Management and Sleep Modes
  1. Arduino UNO
#define BUTTON_PIN_INT0 2 void handle_int0(); void setup() { // 17mA to 13mA for (int i = 0; i < 20; i++) { if (i!=2) { pinMode(i, OUTPUT); } } // setup watchdog timer WDTCSR = (1<<WDCE) | (1<<WDE); // 24; // change enable and WDE - also resets WDTCSR = (1<<WDP3)|(1<<WDP0); //33; // prescalers only - get rid of the WDE and WDCE bit WDTCSR |= (1<<WDIE); // enable interrupt mode // 0.384mA to 0.058mA ADCSRA &= ~(1<<ADEN); // disable adc // 13mA to 0.381mA SMCR = (1<<SM1)|(1<<SM0)|(1<<SE); // enable power save mode attachInterrupt(digitalPinToInterrupt(BUTTON_PIN_INT0), handle_int0, FALLING); } void loop() { digitalWrite(LED_BUILTIN, HIGH); delay(1000); digitalWrite(LED_BUILTIN, LOW); for (int i = 0; i < 2; i++) // gives ~16sec { // 0.058mA to 0.328uA MCUCR = (1<<BODS)|(1<<BODSE); // set both BODS and BODSE at the same time MCUCR = (MCUCR & ~(1<<BODSE))|(1<<BODS); // then set the BODS bit and clear the BODSE bit at the same time __asm__ __volatile__("sleep"); } } void handle_int0() { } // watchdog interrupt ISR(WDT_vect) { }
#ifndef F_CPU #define F_CPU 1000000UL #endif #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <avr/sleep.h> #define BIT_IS_SET(byte, bit) (byte & (1 << bit)) #define BIT_IS_CLEAR(byte, bit) (!(byte & (1 << bit))) #define LED_PIN_INTO PB3 #define BUTTON_PIN_INT0 PD2 #define LED_PIN_INT1 PB4 #define BUTTON_PIN_INT1 PD3 #define LED_BLINK_PIN PB5 int main(void) { DDRD &= ~(1 << BUTTON_PIN_INT0); PORTD |= (1 << BUTTON_PIN_INT0); DDRD &= ~(1 << BUTTON_PIN_INT1); PORTD |= (1 << BUTTON_PIN_INT1); DDRB |= (1<<LED_BLINK_PIN)|(1<<PB4)|(1 << PB3); EIMSK = (1<<INT0)|(1<<INT1); EICRA = (1<<ISC00)|(1<<ISC10); // 0.384mA to 0.058mA ADCSRA &= ~(1<<ADEN); // disable adc // setup watchdog timer WDTCSR = (1<<WDCE) | (1<<WDE); // 24; // change enable and WDE - also resets WDTCSR = (1<<WDP3)|(1<<WDP0); //33; // prescalers only - get rid of the WDE and WDCE bit WDTCSR |= (1<<WDIE); // enable interrupt mode set_sleep_mode(SLEEP_MODE_PWR_SAVE); // replaces above statement sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT) sei(); while (1) { PORTB |= (1<<LED_BLINK_PIN); _delay_ms(1000); PORTB &= ~(1<<LED_BLINK_PIN); for (int i = 0; i < 2; i++) // gives ~16sec { // 0.058mA to 0.328uA MCUCR = (1<<BODS)|(1<<BODSE); // set both BODS and BODSE at the same time MCUCR = (MCUCR & ~(1<<BODSE))|(1<<BODS); // then set the BODS bit and clear the BODSE bit at the same time sleep_cpu(); } } return 0; } ISR(INT0_vect) { if(BIT_IS_CLEAR(PIND, BUTTON_PIN_INT0)) { PORTB |= (1 << LED_PIN_INTO); } else if(BIT_IS_SET(PIND, BUTTON_PIN_INT0)) { PORTB &= ~(1 << LED_PIN_INTO); } } ISR(INT1_vect) { if(BIT_IS_CLEAR(PIND, BUTTON_PIN_INT1)) { PORTB |= (1 << LED_PIN_INT1); } else if(BIT_IS_SET(PIND, BUTTON_PIN_INT1)) { PORTB &= ~(1 << LED_PIN_INT1); } }
.def temp = r16 .equ LED_PIN_INTO = 3 .equ BUTTON_PIN_INT0 = 2 .equ LED_PIN_INT1 = 4 .equ BUTTON_PIN_INT1 = 3 .equ LED_BLINK_PIN = 5 jmp start .org INT0addr ; INT0addr is the address of EXT_INT0 jmp handle_pb0 .org INT1addr ; INT1addr is the address of EXT_INT1 jmp handle_pb1 start: ldi r16, 0xff out DDRB, r16 out DDRC, r16 out DDRD, r16 sbi ddrb, LED_PIN_INTO sbi ddrb, LED_PIN_INT1 sbi ddrb, 5 sbi portd, BUTTON_PIN_INT0 // setup pullup resistor sbi portd, BUTTON_PIN_INT1 // setup pullup resistor lds temp, ADCSRA cbr temp, 0b10000000 //ADEN 7 bit // disable adc sts ADCSRA, temp ;; enable int0 and int1 ldi temp, (1 << ISC00) // The low level of INT0 generates an interrupt request. ori temp, (1 << ISC10) // The low level of INT1 generates an interrupt request. sts EICRA, temp ;; enable int0 and int1 in temp, EIMSK ori temp, (1<<INT0) // INT0 External Interrupt Request 0 Enable ; Arduino Pin 2 ori temp, (1<<INT1) // INT1 External Interrupt Request 1 Enable ; Arduino Pin 3 out EIMSK, temp // setup watchdog timer ldi temp, 0b00011000 sts WDTCSR, temp ldi temp, 0b00100001 sts WDTCSR, temp lds temp, WDTCSR ori temp, (1<<6) sts WDTCSR, temp in temp, SMCR ori temp, (1<<SM1) ori temp, (1<<SM0) ori temp, (1<<SE) //ldi temp, (1<<SM1)|(1<<SM0)|(1<<SE); // enable power save mode out SMCR, temp sei loop: sbi portb, LED_BLINK_PIN rcall delay_500ms cbi portb, LED_BLINK_PIN rcall delay_500ms in temp, MCUCR sbr temp, 0b0110_0000 out MCUCR, temp cbr temp, 0b00100000 out MCUCR, temp sleep rjmp loop handle_pb0: sbis pind, BUTTON_PIN_INT0 sbi portb, LED_PIN_INTO sbic pind, BUTTON_PIN_INT0 cbi portb, LED_PIN_INTO reti handle_pb1: sbis pind, BUTTON_PIN_INT1 sbi portb, LED_PIN_INT1 sbic pind, BUTTON_PIN_INT1 cbi portb, LED_PIN_INT1 reti delay_500ms: ; the subroutine: ldi r16, 31 ; load r16 with 31 OUTER_LOOP: ; outer loop label ldi r24, 0xfd ; load registers r24:r25 with 1021, our new ; init value ldi r25, 0x03 ; the loop label DELAY_LOOP: ; "add immediate to word": r24:r25 are ; incremented adiw r24, 1 ; if no overflow ("branch if not equal"), go ; back to "delay_loop" brne DELAY_LOOP dec r16 ; decrement r16 brne OUTER_LOOP ; and loop if outer loop not finished ret ; return from subroutine