Somewhere along I had it go to sleep just fine, but it didn't wake up. Now it wakes up fine, but doesn't want to go to sleep. Seems like I don't have the millis stuff right anymore, I don't get to where the comment "// HOW DO I GET HERE?" is. Too tired to see it, gonna go to bed.
#include <avr/sleep.h>
boolean leds_on = true;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
const long interval = 1000;
ISR(INT0_vect) {
sleep_disable();
leds_on = true;
}
void setup() {
// put your setup code here, to run once:
PORTB |= (1 << PB1); // input
DDRB &= ~(1<<PB1);
shutdown_chip();
}
void loop() {
if (leds_on)
{
cli();
leds_on = false;
}
currentMillis = millis();
if ( !(PINB & (1 << PB1)) )
{
charlie(3);
if (currentMillis - previousMillis >= interval)
{
// HOW DO I GET HERE?
charlie(5);
delay(2000);
shutdown_chip();
}
else
{
charlie(2);
}
}
else
{
animate_leds();
previousMillis = currentMillis;
}
}
void shutdown_chip()
{
leds_off();
/* Clear WDRF in MCUSR */
MCUSR &= ~(1 << WDRF);
/* Write logical one to WDCE and WDE */
/* Keep old prescaler setting to prevent unintentional time-out */
WDTCR |= (1 << WDCE) | (1 << WDE);
/* Turn off WDT */
WDTCR = 0x00;
ADCSRA &= ~(1 << ADEN); // turn off adc
GIMSK |= (1 << INT0);
GIMSK |= (1 << PCIE);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sei(); // Enable global interrupts
sleep_cpu();
sleep_disable();
}
void animate_leds()
{
for (int i = 0; i < 12; i++) {
charlie(i);
delay(50);
}
for (int i = 0; i < 12; i++) {
charlie(11 - i);
delay(50);
}
}
void leds_off()
{
DDRB &= ~(
(1 << PB0) |
(1 << PB2) |
(1 << PB3) |
(1 << PB4)
);
PORTB &= ~(
(1 << PB0) |
(1 << PB2) |
(1 << PB3) |
(1 << PB4)
);
}
void charlie (int var) {
leds_off();
switch (var) {
case 0: // 1
DDRB |= (1 << PB0) | (1 << PB2); // output
PORTB |= (1 << PB0); // HIGH
PORTB &= ~(1 << PB2); // LOW
break;
case 1: // 2
DDRB |= (1 << PB0) | (1 << PB2); // output
PORTB |= (1 << PB2); // HIGH
PORTB &= ~(1 << PB0); // LOW
break;
case 2: // 3
DDRB |= (1 << PB2) | (1 << PB3); // output
PORTB |= (1 << PB2); // HIGH
PORTB &= ~(1 << PB3); // LOW
break;
case 3: // 4
DDRB |= (1 << PB2) | (1 << PB3); // output
PORTB |= (1 << PB3); // HIGH
PORTB &= ~(1 << PB2); // LOW
break;
case 4: // 5
DDRB |= (1 << PB3) | (1 << PB4); // output
PORTB |= (1 << PB3); // HIGH
PORTB &= ~(1 << PB4); // LOW
break;
case 5: // 6
DDRB |= (1 << PB3) | (1 << PB4); // output
PORTB |= (1 << PB4); // HIGH
PORTB &= ~(1 << PB3); // LOW
break;
case 6: // 7
DDRB |= (1 << PB0) | (1 << PB3); // output
PORTB |= (1 << PB0); // HIGH
PORTB &= ~(1 << PB3); // LOW
break;
case 7: // 8
DDRB |= (1 << PB0) | (1 << PB3); // output
PORTB |= (1 << PB3); // HIGH
PORTB &= ~(1 << PB0); // LOW
break;
case 8: // 9
DDRB |= (1 << PB2) | (1 << PB4); // output
PORTB |= (1 << PB2); // HIGH
PORTB &= ~(1 << PB4); // LOW
break;
case 9: // 10
DDRB |= (1 << PB2) | (1 << PB4); // output
PORTB |= (1 << PB4); // HIGH
PORTB &= ~(1 << PB2); // LOW
break;
case 10: // 11
DDRB |= (1 << PB0) | (1 << PB4); // output
PORTB |= (1 << PB0); // HIGH
PORTB &= ~(1 << PB4); // LOW
break;
case 11: // 12
DDRB |= (1 << PB0) | (1 << PB4); // output
PORTB |= (1 << PB4); // HIGH
PORTB &= ~(1 << PB0); // LOW
break;
default:
;
}
}
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
The cli in your loop disables all interrupts, which are required to update the variable millis uses.
Are you sure? yes | no
but I only do cli once after wakeup? millis then get's updated in the loop
Are you sure? yes | no
I think "cli" is persistent when "loop" is left, so interrupts are then disabled permanently. I think the program flow was this: first you call "shutdown_chip", which enables interrupts with "sei", but in the interrupt, "leds_on" is set to true, and then "loop" is called from the Arduino framework, because the setup function is left after the chip is awake again, which then calls "cli", which is the reason why after this "millis" doesn't work anymore.
I didn't look into the details, but might be a good idea to never disable the interrupts, or just disable the external interrupt for the INT0_vect, if this is possible, or otherwise check in the interrupt handler if the loop is still running.
Are you sure? yes | no
okay, I currently fixed it with a counter and a small delay. Not the best way to do it, but it get's the job done :) first alpha version is working, nice
Are you sure? yes | no
Is the charlie(3); line being called?
Are you sure? yes | no
yes, also the charlie(2) in the else. Sad thing is I have no debug serial port or chance to check values of the time values..
Are you sure? yes | no
Are you getting in the if statement above where you mention? You are checking if PB1 is low, right? Half of my comment disappeared before, hope you get it now.
Are you sure? yes | no
yup. But it seems like the time stuff is broken, only charlie 2 & 3 are being called.
Are you sure? yes | no