Skip to content

Instantly share code, notes, and snippets.

@jscrane
Created June 17, 2012 14:49
Show Gist options
  • Save jscrane/2944741 to your computer and use it in GitHub Desktop.
Save jscrane/2944741 to your computer and use it in GitHub Desktop.
Sketch demonstrating software PWM and putting ATtiny85 into deep sleep
#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