I’ve been banging my head against this one for a day or so now. I have kludge that works, but I’d like to know what is wrong with the original code. Unfortunately, I can’t post a test case, for reasons that will become clear.
Background:
The system is started in
SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);
Part 1:
I have a working program that attaches 8 interrupts to 8 pins, 7 external and the RI_UC pin from the modem.
A timer handler loop runs a state machine every 500mS, that responds to the pins to manage a diesel engine. It all works fine electrically and logically. The typical setup looks like this (all seven external pin interrupts are the same):
#define FSDET C0
#define STDET C1
... define others... and double checked no accidental re-use of the particle Cn labels...
struct InputStruct{
bool state;
bool raw;
unsigned short hist;
};
// digital Input variables (set aynchronously by interrupts)
volatile InputStruct fuelSense;
volatile InputStruct startSense;
... repeat for other inputs...
void setup() {
//Configure Sensing
pinMode(FSDET,INPUT);
pinMode(STDET,INPUT);
...repeat for other inputs ...
// Set up interrupt driven inputs. no preferred priority, so leave default (13)
attachInterrupt(FSDET, _fuelInterrupt, CHANGE);
attachInterrupt(STDET, _starterInterrupt, CHANGE);
.... repeat for other input handlers...
}
loop(){
... stuff...
}
// Fuel Solenoid Sense input capture
void _fuelInterrupt(){
fuelSense.raw = (LOW == digitalRead(FSDET));
}
// Starter Solenoid Sense input capture
void _starterInterrupt(){
startSense.raw = (LOW == digitalRead(STDET));
}
.. rinse and repeat...
The .raw boolean state of each input variable is counted by a timer handler based debounce function (10mS interval), where .hist stores the hysteresis count, and eventually sets the stable .state true or false.
This works perfectly well. Each interrupt handler is fired on CHANGE and updates its respective variable.
Part 2:
Separately, I have a working program that reads/sends SMS via the cellular.command calls. It uses the RI_UC pin to detect incoming SMS, via an interrupt. It works fine.
However, when I combine these two programs, so the SMS can control the engine, one of the interrupts, responding to CHANGE on pin STDET / C1 simply stops being fired.
After checking everything twice for stupid syntax errors, name/label collisions, re-ordering the attachInterrupt() calls, in case of some undocumented internal limit on interrupt handlers, etc, my work-around was to copy the
attachInterrupt(STDET, _starterInterrupt, CHANGE);
from setup() to being called again in loop(). The loop() is used for the SMS state machine, running independently of the engine state machine. The attachInterrupt() is called (again) once during an initialisation state.
Voila, the interrupt is again fired on CHANGE and updates the startSense variable.
My question is this - it seems the only explanation is that the interrupt handler function attached to STDET / C1 is being detached/re-assigned between setup() and loop(). What would do this? Is there some secondary function of the C1 pin that would detach the interrupt when Cellular.command is called? Only the one interrupt is affected - all the others remain working after the initial attachInterrupt() call.
I know this is incomplete, but I don’t want to post 1000 lines of code. Any clues welcome.
I hate the work-around but will live with it until I find the cause.
Cheers,
AT