I have an arduino micro that I'm using as responsebox to catch reaction times.
Attached to the pin 2,3,7 and used as interrupts I have two buttons and a photodiode. The latter has to detect any possible change of light and start a millis() while the other two buttons must be "listening" for an answer and catch the time when are pressed. Then another void() does the calculations.
Now, everything works beautifully but if no response occurs, which means no button pressed, the millis() activated by the photodiode runs forever, which means that there is no way to end that interrupt.
I need a timer inside that function that tells to the photodiode's interrupt: after 2 seconds, ends the interrupt and go on with the last void(), which means don't wait anymore for the button pressed. I was looking for an example of "timer inside an interrupt " on google but honestly I don't have so much experience with arduino, can someone give me an example really, really, easy about how should I use this timer? My problem is that I don't know how to count 2 seconds inside that interrupt to put a flag and end the interrupt.
Any comment, suggestion or other possible solutions are appreciated.
Do I understand you correctly and you are performing processing within an Interrupt Service Routine?
If so, that is not a good idea. I don't think timers work within Interrupt Service routines because timers themselves require Interrupts. Best practice is to only use timers to do really quick processes, like set flags so that the processing OUTSIDE of the Interrupts is affected.
It would help to see the entire code (using code tags prevents getting complaints about not doing so).
So anyone using the words void() to describe a function is somewhat of a beginner.
I would agree you do not need to use interrupts at all. Your timing resolution is down to only 1mS and in that time you can do many hundreds of iterations of the loop function. So you thinking that using an interrupt is more accurate is totally unfounded.
You just want to use a state machine with a time out function added into it.
Thank you for all of your suggestions, and comments.
I appreciate your contributions, however for experimental reasons I still need an interrupt.
And my question is about how to use a timer inside of it.
I paste my code below:
N.B: everything related to the "serial" is because of a python script that is reading the output of Arduino.
#define button1Bit 2 //button Yes
#define button2Bit 3 //button No
#define fotoTrigger 7 //photodiode
#define ledPin 13 //Led for tries
volatile boolean started,userResponded;
volatile unsigned long start_time,stop_time;
int val = 0;
float response_time;
void setup() {
//setup the inputs
pinMode(button1Bit,INPUT);
pinMode(button2Bit,INPUT);
pinMode(fotoTrigger, INPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
started=false;
userResponded=false;
//start the serial port with velocity of 9600 bits per second.
Serial.begin(115200); // 9600
attachInterrupt(digitalPinToInterrupt(fotoTrigger), beginTrial, RISING);
attachInterrupt(digitalPinToInterrupt(button1Bit), response, RISING);
attachInterrupt(digitalPinToInterrupt(button2Bit), response2, RISING);
}
void beginTrial() {
if (started == false){
digitalWrite(ledPin, HIGH);
start_time = millis();
started = true;
}
}
void response() {
if (started == true) {
stop_time = millis();
userResponded = true;
val = 1;
}
}
void response2() {
if (started == true) {
stop_time = millis();
userResponded = true;
val = 2;
}
}
void finishTrial() {
response_time = (float)(stop_time - start_time);
started=false;
userResponded = false;
digitalWrite(ledPin, LOW);
}
void printresult() {
Serial.println(response_time);
Serial.println(val);
Serial.flush();
}
void loop() {
if (userResponded==true) {
finishTrial();
printresult();
//start_time = millis(); //to reset the clock
}
}
I hope that you can help me to get through the problem, that is the following:
how to end beginTrial() after 2 seconds and jump to printresult() without pressing buttons?
Ok, if I understand correctly, you wish to detect that one of your functions was called and the other one was not called within a pre-set amount of time.
While I agree with the others that this could be done without Interrupts, you could fix the program to work without a total redesign.
In the startTrial, you have the variable start_time. You also have start = true.
To stop your Trial, you call the function finish_trial.
JaBa:
Ok, if I understand correctly, you wish to detect that one of your functions was called and the other one was not called within a pre-set amount of time.
While I agree with the others that this could be done without Interrupts, you could fix the program to work without a total redesign.
In the startTrial, you have the variable start_time. You also have start = true.
To stop your Trial, you call the function finish_trial.
Thanks Jaba, I tried to use your solution but probably I didn't understand very well because it didn't work. I leave this comment to end the post, in this way I can also trace back to this solution in the future.
I managed to add another interrupt, which is called Timer1: Arduino Playground - HomePage and what I did is start the interrupt with beginTrial and set a flag in response() and response2() to end the timer.
However I'm a 'newbie', and I'm very curious about why it's not recommended to use an interrupt.
When I will find another solution, I will post it.
However I'm a 'newbie', and I'm very curious about why it's not recommended to use an interrupt.
Many a 'newbie' goes wrong when using interrupts, and if they are not needed (like to read, using "polling" in a tight loop, a button pressed by a human) the normal advice is to stay away from interrupts.
In your case, there was a somewhat confusing initial post without code, and you got the standard advice. Your focus on putting a timer within an interrupt also raised concerns, because the millis() function does not advance within an interrupt.
I think that interrupts can be appropriate for a reaction time device, and when you did post your code, and the nature of ISR's became clear some of the concerns with using interrupts were lessened.
JaBa's solution using the millis() based time out should have worked.
An ISR should return ASAP, not wait (loop) for some time. A flag can be set, indicating that the interrupt has occured, and the code in loop() will check that flag and proceed accordingly.
Inside an ISR you can take the time, using micros() or millis(). While micros() will track the current time, millis() is not incremented while an ISR is active. Thus you can implement (very) short delays inside an ISR, using micros() or delayMicroseconds(), if really required.
'void' is a data type, a special type indicating that a function does not return a value. A void function is not a function in the mathematical sense, other programming languages distinguish between functions, returning a value, and procedures not returning a result. In C speech all subroutines are commonly called functions.