I am trying to synchronize two Leds controlled by two Arduino Unos. They both blink at the same frequency but have a phase shift which should get compensated over time throughout reacting to each others blinking.
I do this via external interrupts that trigger on a Low Signal on Pin 2. The respective ISR called 'raisePhase' increments a variable called 'phaseValue'. As soon as phaseValue reaches a critical level (I defined it as 5.0) the LED blinks and promptly sends a LOW Signal to the other Arduinos Pin 2 thus incrementing his phaseValue and so on. I am also constantly incrementing phaseValue via a Timer interrupt using the TimerOne library to make sure every LED is able to blink at all.
My problem is that as soon as my code enters the ISR 'raisePhase' it gets stuck there and executes it for about 70 times before going back to normal (I am only setting Pin 2 on LOW for 1 microsecond). My Timer triggered ISR seems not to work anymore whereas void loop() mus somehow still be working since it resets phaseValue to zero and makes the LED blink.
I attached three Screenshots of my serial monitor leaving out the ~70 'phase raised' for better reading. Note that phaseValue gets reset at a value of 3.76 instead of 5.0
I am aware that external interrupts are stronger than timer interrupts which again have priority over the loop function. Anyway I don't understand why the external interrupt ISR gets executed so many times and how I can avoid this. For my algorithm to work I should apparently also include a delaytime in which one Arduino is not listening to the other right after blinking. Is there a good way to do this without using delay within my ISRs?
I am very grateful for any ideas on how to fix this.
void raisePhase()
{
phaseValue = phaseValue + epsilon;
Serial.println("phase raised");
void increase_phaseValue() {
phaseValue = (1 / slope) * log(1 + (pow(e, slope) - 1) * timeScale); // This is basically modelling an RC Circuit Voltage Curve. TimeScale only represents a fixed step since the actual time does not matter and I don't want to work with millis()
timeScale=timeScale+0.5;
Serial.println(phaseValue);
as it appears to define a function within another function. It appears to be missing two curly brackets.
(2) Serial.print(...) and Serial.println(...) should not be used inside an ISR.
(3) If you post your code piecemeal, you are likely to get pieces of an answer. Context is important but is lost when you post this way.
To post code and/or error messages:
Use CTRL-T in the Arduino IDE to autoformat your complete code.
Paste the complete autoformatted code between code tags (the </> button)
so that we can easily see and deal with your code.
Paste the complete error message between code tags (the </> button)
so that we can easily see and deal with your messages.
If you already posted without code tags, you may add the code tags by
editing your post. Do not change your existing posts in any other way.
You may make additional posts as needed.
Before posting again, you should read the three locked topics at the top of the Programming Questions forum, and any links to which these posts point.
If your project involves wiring, please provide a schematic and/or a wiring diagram and/or a clear photograph of the wiring.
Thanks for the answer so far. I edited my code example.
I did read the forum instructions before posting but I apparently misunderstood this point here:
'With coding problems, if possible post a "minimal" sketch that demonstrates the problem - not hundreds of lines of code.'
void increase_phaseValue() {
phaseValue = (1 / slope) * log(1 + (pow(e, slope) - 1) * timeScale); // This is basically modelling an RC Circuit Voltage Curve. TimeScale only represents a fixed step since the actual time does not matter and I don't want to work with millis()
timeScale=timeScale+0.5;
Serial.println(phaseValue);
as it appears to define a function within another function. It appears to be missing two curly brackets.
That's right I messed it up when copying my code.
If I can't use Serial.println within ISRs, is there a good way to find out whether they have just run or not?
Bionic6:
Thanks for the answer so far. I edited my code example.
I did read the forum instructions before posting but I apparently misunderstood this point here:
'With coding problems, if possible post a "minimal" sketch that demonstrates the problem - not hundreds of lines of code.'
You should read that as meaning a minimal complete compilable sketch
If I can't use Serial.println within ISRs, is there a good way to find out whether they have just run or not?
In you ISR just use a variable as a flag - something like
interruptTriggered = true;
and then the regular code can watch out for that and set the variable back to false when it has noticed the ISR.
If you really are getting too many interrupts it is perfectly normal to use the first interrupt to switch off interrupts on that I/O pin. Then some other code can switch them on again when appropriate.
Thanks for the good tips! I used FALLING now which worked just fine. My interrupts now use flags instead of Serial.println as well. Sometimes I just can't think of the simple way to do it