Created
June 17, 2012 14:49
-
-
Save jscrane/2944741 to your computer and use it in GitHub Desktop.
Sketch demonstrating software PWM and putting ATtiny85 into deep sleep
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define __STDC_LIMIT_MACROS 1 | |
#include <stdint.h> | |
#include <avr/sleep.h> | |
#include <avr/interrupt.h> | |
void setup() { | |
pinMode(0, OUTPUT); | |
pinMode(2, INPUT); | |
GIMSK |= _BV(INT0); // enable INT0 | |
MCUCR &= ~(_BV(ISC01) | _BV(ISC00)); // INT0 on low level | |
ACSR |= _BV(ACD); // disable the analog comparator | |
ADCSRA &= ~_BV(ADEN); // disable ADC | |
sei(); | |
} | |
// time before sleep in millis | |
#define IDLE_TIME 5 * 60000L | |
volatile int d = 15; | |
volatile uint32_t last = 0; | |
volatile boolean asleep = false; | |
ISR(INT0_vect) { | |
if (asleep) | |
asleep = false; | |
else { | |
uint32_t now = millis(); | |
if (now - last > 1000) { | |
d += 10; | |
if (d > 95) | |
d = 15; | |
} | |
last = now; | |
} | |
} | |
void spwm(int freq, int pin, int spd) { | |
digitalWrite(pin, HIGH); | |
delayMicroseconds(spd * freq); | |
digitalWrite(pin, LOW); | |
delayMicroseconds(spd * (255 - freq)); | |
} | |
// see http://arduino.cc/forum/index.php?topic=83826.0 | |
#define BODS 7 //BOD Sleep bit in MCUCR | |
#define BODSE 2 //BOD Sleep enable bit in MCUCR | |
void sleep() { | |
set_sleep_mode(SLEEP_MODE_PWR_DOWN); | |
sleep_enable(); | |
// turn off the brown-out detector. | |
// must have an ATtiny45 or ATtiny85 rev C or later for software to be able to disable the BOD. | |
// current while sleeping will be <0.5uA if BOD is disabled, <25uA if not. | |
cli(); | |
uint8_t mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector | |
uint8_t mcucr2 = mcucr1 & ~_BV(BODSE); | |
MCUCR = mcucr1; | |
MCUCR = mcucr2; | |
sei(); // ensure interrupts enabled so we can wake up again | |
asleep = true; | |
sleep_cpu(); // go to sleep | |
sleep_disable(); | |
} | |
void loop() { | |
for (int i = 20; i < 240; i++) | |
spwm(i, 0, d); | |
for (int i = 240; i > 18; i--) | |
spwm(i, 0, d); | |
uint32_t now = millis(), then = last, interval; | |
if (now < then) // handle overflow | |
interval = (UINT32_MAX - then) + now; | |
else | |
interval = now - then; | |
if (interval > IDLE_TIME) | |
sleep(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment