Hello,
I have a very weired problem about waking up an arduino with an external interrupt.
I have an ADXL345 from Adafruit connected to the Arduino, with the 2 Interrupt pins of the ADXL connected to pin 2 and 3 of the Arduino.
Arduino Pin 2 and 3 are configurated as INPUT, SPI is working
The ADXL is confugurated to send a LOW-Level Interrupt to the arduino if it detects Inactivity. Then an Interrupt-Service routine is executed and put the Arduino to sleep and the Low-Level of the ADXL will go to High, therefore no new interrupt will be generated (Code will be on the Bottom of the Post).
Before the Arduino will go to sleep the ADXL is configurated to trigger the same ISR, but this time if it detects any Activity.
If the ISR is triggered, the Arduino will wake up and continues.
I use one ISR for both, the Sleeping and the Wakeup because the other ISR is reserved for getting the Data out of the ADXL's internal FiFo (any time it hits its Sample limit the ISR is triggered and download the Data from the ADXL). loop()-Funktion is empty.
this is the Code snippet for assigning the Interrupts:
noInterrupts();
attachInterrupt(0, ADXL_ISR_General, LOW); //0 entspricht pin2
attachInterrupt(1, ADXL_ISR_FiFo, LOW); //1 entspricht pin3
interrupts();
The Programm works 95% of the Times, but sometimes the Arduino will go to sleep and never wake up. I checked the Interrupt-cable in this situation and it is definately on LOW level.
I tried for about 2 Weeks now, but can't figure out what may be causing the instability.
I checked via 2 LEDs, and found out that the Arduino won't exit the "sleep_cpu()" it just stays in sleep mode...
Here is the code of the Sleep/Wakeup ISR:
void ADXL_ISR_General() {
noInterrupts(); //Interrupts Abschalten um die Ausführung des folgenden Codes nicht zu behindern --> Hier gehen messdaten verloren, angesichts der Hohen bandbreite und der Vielzahl an Daten Verschmerzbar
EIFR = 0x01;//Löschen des 0er Interrupts
SPI.setDataMode(SPI_MODE3); //Data_Mode3 für den ADXL
uint8_t interrupt = adxl.getInterruptSource(); //Interruptgrund erfragen
if (adxl.triggered(interrupt, ADXL345_INACTIVITY)) //Inactivität --> Hier wird der uC Heruntergefahren
{
Sleep();
}
//if (adxl.triggered(interrupt, ADXL345_SINGLE_TAP)) //Stoß --> Hier wird der uC Hochgefahren
if (adxl.triggered(interrupt, ADXL345_ACTIVITY))
{
//Wakeup(); //wird nach dem aufwachen direkt aufgerufen
adxl.ActivityINT(false); //Aktivity interrupt ausschalten
}
EIFR = 0x01;//Löschen des 0er Interrupts
interrupts(); // Interrupts wiedereinschalten
}
void Sleep()
{
RED_ON; //Rote LED an
#ifdef DEBUG
YELLOW_ON;
#endif
digitalWrite(4, LOW); //GPS aus
//adxl.singleTapINT(true); //Tap-Interrupt anschalten zum wieder aufwachen
adxl.ActivityINT(true);
adxl.setRegisterBit(ADXL345_INT_ENABLE, 1, 0); //disable Watermark interrupt
adxl.InactivityINT(false); //disable Inactivity-Interrupt
#ifndef DEBUG
RED_OFF;
digitalWrite(7, LOW);
#endif
file.write('#'); //Schreibe eine Notification in das Log das nun in den schlafmodus übergegenagen wird
file.write('S');
file.write(10); //LF
file.sync();
set_sleep_mode(SLEEP_MODE_STANDBY); //set the Sleep-Mode Bit (choose wich sleep mode we want)
//set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// Set sleep enable (SE) bit:
sleep_enable();
//Disable the Brown-Out-Detector
sleep_bod_disable();
//
//
interrupts(); // Interrupts wiedereinschalten damit der uC auch aufwacht
//
// Put the device to sleep:
sleep_cpu();
//
// ## Sleeping! ##
// ## <<< THIS CODE WILL NEVER BE REACHED SOMETIMES >>>
#ifdef DEBUG
YELLOW_OFF;
#endif
//
// Upon waking up, sketch continues from this point.
sleep_disable();
noInterrupts();
Wakeup();
}
void Wakeup()
{
SPI.setDataMode(SPI_MODE3); //Data_Mode3 für den ADXL
//sleep_disable();
RED_OFF;
GPS_ON;
adxl.InactivityINT(true); //enable Inactivity-Interrupt
//adxl.singleTapINT(false); //Tap-Interrupt ausschalten
//adxl.ActivityINT(false); //Aktivity interrupt ausschalten --> Wurde in den eigentlichen IRQ gelegt, um zu garantieren das der IRQ erst NACH dem auslesen der interrupt-source abgeschaltet wird
adxl.setRegisterBit(ADXL345_INT_ENABLE, 1, 1); //enable Watermark interrupt
interrupts();
}
These are the used makros:
//Schnellere Port-Zugriffe
#define RED_ON PORTD |= 128
#define RED_OFF PORTD &= ~128
#define RED_TOGGLE PORTD ^= 128
#define YELLOW_ON PORTD |= 64
#define YELLOW_OFF PORTD &= ~64
#define YELLOW_TOGGLE PORTD ^= 64
#define GPS_ON PORTD |= 16
#define GPS_OFF PORTD &= ~16
Arduino runs on 3,7 to 4V @ 16Mhz (Custom PCB, Powered by LiPo), voltage ripple on arduino Vcc pin is about +-50mV wich should be OK...
Thanks for your time,
cad435