Hello forums!
For my current project, I am trying to build a sort of 'easy button' that plays a short sound, then goes to sleep when a button is pressed. I have the sound playing properly, and the attiny85 does go to sleep at the end, but I'm having some trouble getting the chip to wake properly. Here is my code:
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#define adc_disable() (ADCSRA &= ~(1<<ADEN))
#define adc_enable() (ADCSRA |= (1<<ADEN))
// Audio encoded as unsigned 8-bit, 8kHz sampling rate
const unsigned char sound[] PROGMEM = {
0x7f, 0x80, 0x83, ... 0x30, 0x34, 0x00
};
unsigned int soundLen = 3347;
volatile unsigned int nextByte = 0;
void sleep() {
//Shuts everything down
sleep_enable();
sleep_cpu();
//Starts everything back up
sleep_disable();
}
void setup() {
//Set up registers for pin change interrupt on Pin 3
GIMSK |= (1 << PCIE); //Enable pin change interrupts
PCMSK |= (1 << PCINT3); //Enable interrupt on Pin 3
// Enable 64 MHz PLL and use as source for Timer1
PLLCSR = 1<<PCKE | 1<<PLLE;
// Set up Timer/Counter1 for PWM output
TIMSK = 0; // Timer interrupts OFF
TCCR1 = 1<<PWM1A | 2<<COM1A0 | 1<<CS10; // Enables PWM on OC1A, mode 2, and 1:1 prescaling.
OCR1A = 128; // 50% duty cycle initially
// Set up Timer/Counter0 for 8kHz interrupt to output samples.
TCCR0A = 3<<WGM00; // Fast PWM
TCCR0B = 1<<WGM02 | 2<<CS00; // 1/8 prescale
TIMSK = 1<<OCIE0A; // Enable compare match
OCR0A = 124; // Divide by 1000
pinMode(3, INPUT); //Configure pin as an input
digitalWrite(3, HIGH); //Enable internal pullup resistor
pinMode(1, OUTPUT);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}
void loop() {
}
ISR(PCINT0_vect) {
if(PINB & (1<<PB3)){
} else {
nextByte = 0;
}
}
// Sample interrupt
ISR(TIMER0_COMPA_vect) {
sei();
nextByte++;
if(nextByte >= soundLen){
sleep();
}
char sample = pgm_read_byte(&sound[nextByte]);
OCR1A = sample;
}
(Most of the code is based on an excellent tutorial here)
My schematic is very simple: A speaker connected from pin 1 to ground through a 220uF capacitor, and a button connecting ground to pin 3.
In my ISR on pin 3, I am attempting to check whether the button has been pressed or released. I only set nextByte back to 0 when I detect that the button has been pressed. If the button has been released, the code should go back to sleep on the next call of the clock ISR.
The problem is that the sound is playing both when the button is pressed and released. I don't think it's a button-bounce or electrical error, and I've verified that the attiny85 isn't resetting, so I spelled the ISR name correctly. What am I doing wrong?