I'm currently overhauling some working code to include a lot more power management at the valuable advice of people on these forums.
My code does a bit of general housekeeping, enables interrupts and puts the processor to sleep. My timer interrupts wake the system up as planned (at a rate of 125Hz), does its business and then the system goes back to sleep. This is all in a while loop which keeps going until a continue flag is set to zero - the plan is to use a pin change interrupt to "cancel" the current operation.
The code is a time lapse generator, so it delays for however long (say 4 seconds), takes a picture and then delays, etc. It does this forever unless one of the following two conditions are satisfied:
1. The shot count has hit a preset maximum, i.e. the user says "take 512 shots (that's all my memory card will hold)".
2. The shoot button is pressed whilst the time lapse is in progress.
I know interrupts work because besides the pin change interrupt, the timer does its job and keeps the timer going and the shots taking even though the LCD is turned off and the CPU is sleeping.
The buttons are on the following pins:
1. Shoot, port C, pin 3, PCINT11
2. The rest, port B pins 1-5, PCINT1-5
So during my i/o intialisation function i have this:
//Set interrupt pins //general buttons PCMSK0 |= (1 << PCINT1) | (1 << PCINT2) | (1 << PCINT3) | (1 << PCINT4) | (1 << PCINT5); //shoot button PCMSK1 |= (1 << PCINT11);
Then, i enable the interrupt in the time lapse code:
void start_interval_shoot(void) { //Initialise and start timer2, turn on pcint bit, enable sleep modes and set sleep mode to awake on timer compare or pin change, enable global interrupts sei(); PCICR |= (0 << PCIE0) | (0 << PCIE1); timer2_init(); sleep_enable(); set_sleep_mode(SLEEP_MODE_PWR_SAVE); interval_continue = 1; lcd_clrscr(); //display the shooting screen lcd_puts("Shot No.:0\n"); lcd_puts("Timer: 0"); for (uint8_t j=0; j < 20; j++) { //display remaining seconds lcd_gotoxy(9,1); itoa(timeremain, buffer, 10); lcd_puts(buffer); //display shot count lcd_gotoxy(9,0); itoa(shotcount, buffer, 10); lcd_puts(buffer); Delay_ms(500); } //Shooting functionality is done in interrupts while(interval_continue == 1) { lcd_command(LCD_DISP_OFF); sleep_mode(); } //Disable sleep, disable interrupts, disable the timer intervalstart = 0; sleep_disable(); cli(); timer2_deinit(); }
The vectors are:
ISR(PCINT1_vect) { lcd_command(LCD_DISP_ON); lcd_clrscr(); lcd_puts("Shoot"); Delay_ms(1000); } // Run when shoot is pressed ISR(PCINT0_vect) { lcd_command(LCD_DISP_ON); lcd_clrscr(); lcd_puts("Other"); Delay_ms(1000); }
So, what should happen is:
1. timer starts, interrupts on, etc
2. there's a status display and then the proc. sleeps to conserve power
3. every so often a shot is taken
4. if the shoot or any other button is pressed, the display is turned on and a message is written, then it turns off again.
The ports are connected to Vcc and the switch pulls them to ground. Certainly there IS a logic change on the pins when a button is pressed.
I get the feeling (again) that it's an obvious mistake, i've checked the vectors, the pins and the setup, interrupts are on and working...