system
June 25, 2010, 8:48pm
1
Hi!
i've got an couple of buttons which i don't want to poll so i created an event with the pcint of pin change interrupt.
After that i want to let the arduino sleep... and it will sleep! it sleeps to long because when i push a button i won't wake up
anyone suggestions?
Martijn from the Netherlands
system
June 25, 2010, 8:55pm
3
Sleep code is at the bottom
#include <LiquidCrystal.h>
#include "pins_arduino.h"
#include <avr/sleep.h>
char strMenu1[] = "Accu 1";
char strMenu2[] = "Accu 2";
char strMenu3[] = "Water";
char strMenu4[] = "Afval";
char* strucMenu[] = { strMenu1,strMenu2,strMenu3,strMenu4 };
int menu;
// RS // Enable // D4,5,6,7
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
volatile uint8_t *port_to_pcmask[] = {
&PCMSK0,
&PCMSK1,
&PCMSK2
};
typedef void (*voidFuncPtr)(void);
volatile static voidFuncPtr PCintFunc[24] = {
NULL };
volatile static uint8_t PCintLast[3];
/*
* attach an interrupt to a specific pin using pin change interrupts.
* First version only supports CHANGE mode.
*/
void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) {
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
uint8_t slot;
volatile uint8_t *pcmask;
if (mode != CHANGE) {
return;
}
// map pin to PCIR register
if (port == NOT_A_PORT) {
return;
}
else {
port -= 2;
pcmask = port_to_pcmask[port];
}
slot = port * 8 + (pin % 8);
PCintFunc[slot] = userFunc;
// set the mask
*pcmask |= bit;
// enable the interrupt
PCICR |= 0x01 << port;
}
void PCdetachInterrupt(uint8_t pin) {
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *pcmask;
// map pin to PCIR register
if (port == NOT_A_PORT) {
return;
}
else {
port -= 2;
pcmask = port_to_pcmask[port];
}
// disable the mask.
*pcmask &= ~bit;
// if that's the last one, disable the interrupt.
if (*pcmask == 0) {
PCICR &= ~(0x01 << port);
}
}
// common code for isr handler. "port" is the PCINT number.
// there isn't really a good way to back-map ports and masks to pins.
static void PCint(uint8_t port) {
uint8_t bit;
uint8_t curr;
uint8_t mask;
uint8_t pin;
// get the pin states for the indicated port.
curr = *portInputRegister(port+2);
mask = curr ^ PCintLast[port];
PCintLast[port] = curr;
// mask is pins that have changed. screen out non pcint pins.
if ((mask &= *port_to_pcmask[port]) == 0) {
return;
}
// mask is pcint pins that have changed.
for (uint8_t i=0; i < 8; i++) {
bit = 0x01 << i;
if (bit & mask) {
pin = port * 8 + i;
if (PCintFunc[pin] != NULL) {
PCintFunc[pin]();
}
}
}
}
SIGNAL(PCINT0_vect) {
PCint(0);
}
SIGNAL(PCINT1_vect) {
PCint(1);
}
SIGNAL(PCINT2_vect) {
PCint(2);
}
void setup()
{
lcd.begin(8,2);
pinMode(11,INPUT);
pinMode(12,INPUT);
pinMode(13,INPUT);
digitalWrite(11,HIGH);
digitalWrite(12,HIGH);
digitalWrite(13,HIGH);
lcd.print("boot");
PCattachInterrupt(11, e, CHANGE);
PCattachInterrupt(12, t, CHANGE);
PCattachInterrupt(13, d, CHANGE);
}
void e()
{
if(digitalRead(11) == LOW)
{
menu--;
lcd.clear();
lcd.print(menu);
fnMenu();
}
}
void t()
{
if(digitalRead(12) == LOW)
{
menu++;
lcd.clear();
lcd.print(menu);
fnMenu();
}
}
void d()
{
if(digitalRead(13) == LOW)
{
lcd.clear();
lcd.print("Read...");
fnMenu();
}
}
void fnMenu()
{
if(menu <= 0)
{
menu = 0;
}
if(menu >= 4)
{
menu = 4;
}
lcd.clear();
lcd.print(strucMenu[menu]);
set_sleep_mode(SLEEP_MODE_STANDBY); // sleep mode is set here
sleep_enable();
sleep_mode(); // System sleeps here
sleep_disable();
}
void loop()
{
}
system
June 25, 2010, 8:58pm
4
That's not a very good start to debug a wake-up problem - there's too much stuff that has absolutely nothing to do with wake-up interrupts.
Cut down your program to the bare minimum to set up the switch inputs, wake up conditions, and use Serial debug prints.
system
June 25, 2010, 9:04pm
5
that's true idd...
but i was wondering IF the arduino can wakeup from this interrupt... the datasheet of the atmel chip is to !@#@$#%$#$@# :D:D:D
i'm cutting down the code... :
system
June 25, 2010, 9:06pm
6
a normal interrupt wakes the arduino up... pcint until now not...