Hi there,
Trying to call an interrupt to set a flag to sound an alarm buzzer.
I really dont know if I am doing this in the right way!
I read i cannot call delay from within an interrupt.
Any way to call an interrupt when a flag is active?
Do I really need a pin to use the interrupt?
please comment the sample code! thanks!
//// arduino interrupt using a flag
int buz_pin = 2;
int int_pin = 3;
int counter = 0;
volatile boolean intFlag = LOW;
void setup(void) {
Serial.begin(9600);
pinMode(buz_pin, OUTPUT);
pinMode(int_pin, OUTPUT);
attachInterrupt(digitalPinToInterrupt(int_pin), isrFun, CHANGE);
}
void loop() {
if(condition(8)) digitalWrite(int_pin, HIGH); // force interruption
if(intFlag) alarm(); // alarm every 8 iteraction
Serial.println(counter++);
delay(5000);
}
boolean condition(int div){ // any hypothetical condition returning a bool
return counter % div == 0 ? HIGH : LOW;
}
void alarm(){ // ring a bell :)
Serial.println("alarm");
int alen = 10;
while(alen--){
tone(buz_pin, 1000, 50);
//delay(100);
noTone(buz_pin);
}
}
void isrFun(){
digitalWrite(int_pin, LOW);
intFlag = !intFlag;
}
mvcorrea:
Trying to call an interrupt to set a flag to sound an alarm buzzer.
Why? Why not just sound an alarm buzzer? 
Loop sets pin_int to HIGH
ISR executed by LOW to HIGH change
ISR sets pin_int to LOW (triggering the next CHANGE interrupt), intFlag is set to HIGH
Immediately after return ISR will be entered again
ISR sets pin_int to LOW (but it is already LOW so no new interrupt is triggered), intFlag is set to LOW
Loop continues, but will never see a HIGH on intFlag.
I would use something like
//// arduino interrupt using a flag
int buz_pin = 2;
int int_pin = 3;
int counter = 0;
volatile boolean intFlag = LOW;
void setup(void) {
Serial.begin(9600);
pinMode(buz_pin, OUTPUT);
pinMode(int_pin, OUTPUT);
attachInterrupt(digitalPinToInterrupt(int_pin), isrFun, CHANGE);
}
void loop() {
if (condition(8)) {
digitalWrite(int_pin, !digitalRead(int_pin)); // force interruption
}
if (intFlag) {
intFlag = false;
alarm(); // alarm every 8 iteraction
}
Serial.println(counter++);
delay(5000);
}
boolean condition(int div) { // any hypothetical condition returning a bool
return counter % div == 0 ? HIGH : LOW;
}
void alarm() { // ring a bell :)
Serial.println("alarm");
int alen = 10;
while (alen--) {
tone(buz_pin, 1000, 50);
//delay(100);
noTone(buz_pin);
}
}
void isrFun() {
intFlag = !intFlag;
}
alarm
0
1
2
3
4
5
6
7
alarm
8
9
10
11
12
13
14
15
alarm
16
17
18
The first alarm starts with a counter value of 0, because 0 % 8 == 0.
Trying to call an interrupt to set a flag to sound an alarm buzzer.
Why do you think you need to do that ? What problem are you trying to solve ?
I think it is just bad wording.
He tried to trigger an interrupt from loop by software, but the flag never showed true,
because the two directly adjacent interrupts clear the flag before loop can test it.
Triggering interrupts by software is a good tool to debug ISR's in a controlled environment.
That gives at least one reasonable usage for the technique.
If the OP would specify exactly what he wants to achieve,
there would be a good chance of recommending a different way to go.
I think explaining why the current code does not work is more useful,
even if it leads to a suboptimal (but working) solution.
@mvcorrea: What do you really want to achieve?
Sorry for the late feedback, but yesterday I posted extremely late..
@aarg, yah, calling directly have the same behaviour, but using an interrupt we can just stop the program at any point.
@Whandall, thats exactly What I am trying... triggering the interrupt by software.
@UKHeliBob, Thats the way I found to manage a software trigger, please explain the other options?
Thats the right way to trigger an interrupt from software?
I tried here to use an alarm clock as an example as you don't need any external input to ring the buzzer when the time arrives.
After my research, I was not able to do it without attaching it to a physical pin.
yah, triggering from an external pin works fine.
I think I missed something here! I supposed We could break the normal program flow in 2 ways. from an external stimulus or from an software event (like an exception).
thanks to all,
@UKHeliBob, Thats the way I found to manage a software trigger, please explain the other options?
I still don't understand why you want or need to trigger an interrupt from software.
In order to do it the program will need to change state of a pin to cause the ISR to be called. So why not just call the ISR function at the point when the pin state would have been changed ?
UKHeliBob:
So why not just call the ISR function at the point when the pin state would have been changed ?
Did you ever try what you recommend?
Whandall:
Did you ever try what you recommend?
To be honest, no. Is there a flaw in what I am suggesting ?
If you use attachInterrupt you could call the 'ISR',
because it is not really an ISR but a standard void function that can be called in any context,
the Arduino core just happens to call it from the real ISR.
A pinchange interrupt handler or any other real ISR can not directly be called (rti / ret difference).
Both routines would assume disabled interrupts on entry, which a normal call does not guarantee.
For this trivial example just flipping the flag would be enough.
Ok, so let me rephrase my question.
So why not just call a function that does the same as the code in the ISR at the point when the pin state would have been changed ? Note that it would be preferable to disable interrupts in the function.
Simulating the net outcome (even by calling the one and only function that creates it)
is a little different to testing the call mechanism via interrupt.
The stimulated pin change checks in addition to the mere net outcome
- that the correct function will be called if the pin changes
- that you have set all masks to the correct values
For external interrupts attachInterrupt takes care of both (except global disable),
but in general I think its a good idea to test as much as possible.
The stimulated pinchange could be used to build a button-recorder and/or button-replay device
to test debouncing or any type of button processing with controlled and repeatable input.
Thanks for the full explanation.
I am still not convinced that the OP needs to use an interrupt as all it does is to set a flag that is checked and reacted to in loop() and that has a delay(5000) in it anyway.
What we don't know is if this is a complete project or just a test of part of a larger one.
UKHeliBob:
I am still not convinced that the OP needs to use an interrupt
I did not try to make you believe it has to be done this way, did I?
It can be done, in other contexts it's a useful technique,
I see no reason to insist in changing the strategy.
I did not try to make you believe it has to be done this way, did I?
Nor did I say that you had
It can be done, in other contexts it's a useful technique,
Yes, as your full explanation lays out and for which I thanked you.
I see no reason to insist in changing the strategy.
We still don't know the full context. In the program posted there is effectively a 40 second delay in loop(), so using an interrupt to sound a buzzer seems a little unnecessary.
Maybe the OP will enlighten us as to the full context in which this technique is to be used.
@UKHeliBob there is no context in this code.
regarding in not calling the function directly, when calling directly you just loose all the benefits of using the interrupt (that can suspend the code at any point, call the function and return to the place where it was previously).
in this simple example could not be the case (due lack of complexibility) but its a very handy way of programming.
As I mentioned, using hardware interrupts (using like a button to suspend the program flow "at any line", do whatever you want and return to it) works just ok.
But there are events that are created from software. in my example I am just counting on the main loop. if any exception occurs I want to run it, then resume the main loop.
I also found a related topic on the forum: Software interrupts - Programming Questions - Arduino Forum
regards,
when calling directly you just loose all the benefits of using the interrupt (that can suspend the code at any point, call the function and return to the place where it was previously).
But if you are going to trigger the interrupt by having the program itself change the state of the interrupt pin then you gain none of those benefits, so why use an interrupt ?
@UKHeliBob please enlighten me.
could you please help me with a sample from how you trigger an interrupt from a value I get via i2c?
lets say from a bmp280, when temperature goes over a threshold?
regards,