wzschoche / arduino-pinchangeint

Automatically exported from code.google.com/p/arduino-pinchangeint
0 stars 0 forks source link

Interupt functions not getting called #18

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I have a 3 position keyswitch.

Position 1. Turn to the left. Arduino input pin 8 LOW when turned here
Position 2. Center common pin. Not a detectable position.
Position 3. Turn to the right. Adruino input pin 9 LOW when turned here

 pinMode(keySwitchState1,INPUT);      
 pinMode(keySwitchState2,INPUT);
 digitalWrite(keySwitchState1,HIGH);
 digitalWrite(keySwitchState2,HIGH);
 PCintPort::attachInterrupt(keySwitchState1,&keySwitch1Event,FALLING);
 PCintPort::attachInterrupt(keySwitchState2,&keySwitch2Event,FALLING);

I have 2 functions that are supposed to be called when keyswitch is turned and 
it is not happening:

void keySwitch1Event(){
      relaySet(POSITION_OPEN);
      digitalWrite(greenButtonLed,LOW);
      while (keySwitchState1 == LOW){
        digitalWrite(redButtonLed,HIGH);
        delay(200);
        digitalWrite(redButtonLed,LOW);
        delay(200);  
      }
      relaySet(POSITION_CLOSE);
      digitalWrite(redButtonLed,LOW);
      digitalWrite(greenButtonLed,HIGH);

  }

 void keySwitch2Event(){
      relaySet(POSITION_CLOSE);
      digitalWrite(redButtonLed,LOW);

      while (keySwitchState2 == LOW){
        digitalWrite(greenButtonLed,HIGH);
        delay(200);
        digitalWrite(greenButtonLed,LOW);
        delay(200);
      }
      relaySet(POSITION_CLOSE);
      digitalWrite(redButtonLed,LOW);
      digitalWrite(greenButtonLed,HIGH);

 }

Anyone have any ideas?????????????? Thanks, Justin Filiault

Original issue reported on code.google.com by timothyf...@gmail.com on 10 Aug 2013 at 8:02

Attachments:

GoogleCodeExporter commented 9 years ago
This won't work because during the Interrupt handler (keySwitchEvent), 
interrupts are off. delay() works by counting timer interrupts. The timer never 
gets interrupted, therefore delay() will wait forever.

The primary principle in creating any interrupt handler routine is to be very, 
very short and return control back to the main program as soon as possible. 
"Short" means microseconds. If you keep that in mind, it will guide your code 
design and you'll stay out of trouble.

The way to handle this is to create a volatile variable that is set inside the 
interrupt handler. Check the value of the variable inside the main loop. If 
it's set, reset it and then go about your work.

Remember that switches bounce. You might want to use my tigger library 
(https://code.google.com/p/tigger/) to handle your switches. See the usage 
information there in the wiki.

Original comment by m...@schwager.com on 13 Aug 2013 at 11:18

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
To m...@schwager.com:

Thanks for the response... However, I have a few more questions and comments on 
interrupts. My code works now kind of as written... The problem I had above was 
not with delay but with the while condition. I forgot to use digitalRead():
while (keySwitchState1 == LOW) should be while (digitalRead(keySwitchState1) == 
LOW).
The delay didnt work but did not wait forever it just didn't delay at all. So I 
tried to increase it to 20000 instead of 2000 and it works!!! WEIRD HEY??? Any 
I a have a weirder problem. The function I wrote relaySet works fine when I 
call it in LOOP portion but not in setup. Nor does it work when I call it in 
the interrupt function keySwitch1Event. If I take the code out of the relaySet 
function and put it in the keySwitch1Event then the relay gets set. Can you not 
call other function from within an interrupt??? I do now understand its not a 
good practice because I should be doing something quick inside and interrupt 
and get out but this shouldn't be a limitation is it? What I am doing is using 
a keySwitch as an override to the normal functionality, when it is turned I 
want 2 lights to flash alternately so one knows it is in override mode. I could 
check in the loop function over and over to see if the key is turned but it is 
almost perfect to have and interrupt handle it maybe I should just set a flag 
and have my loop check for the flag and handle it? Again though why when I use 
interrupts does my relaySet function not work in setup portion of the program 
and when I remove the interrupt it works just fine? Thanks again for the 
advice!! SMART SMART :) -Justin

Original comment by timothyf...@gmail.com on 14 Aug 2013 at 12:16

GoogleCodeExporter commented 9 years ago
First of all, using delay() inside any function that's called from an interrupt 
is broken, so you shouldn't expect it to work at all inside an interrupt. If it 
seems to work in any fashion then ok, I can't tell you why it would work, but I 
can tell you that it should not and I would not trust the code that did so. The 
exception to this is if you set the I-bit inside your event function. But then 
you would have to be very deliberate about what you were doing.

The ATmega datasheet says, "When an interrupt occurs, the Global Interrupt 
Enable I-bit is cleared and all interrupts are disabled. The user software can 
write logic one to the I-bit to enable nested interrupts..." You are not 
writing to the I-bit hence your code does not have nested interrupts.

The delay(int) function calls the micros() function (see cores/arduino/wiring.c 
under the installed arduino code on your machine). micros() looks at the 
timer0_overflow_count variable, which is updated- via an interrupt handler- 
whenever TIMER0 overflows. TIMER0 is started during init(), which is loaded 
into your Arduino the same as setup() and loop(). init()'s source is also in 
wiring.c.

So fundamentally, you have an issue using delay(). Again, how/why it does 
anything is explainable I'm sure but I don't have the time to look at it.

You should be able to call a function from within an interrupt handler, but 
again you have delay()s in there so I don't know what is happening. 

Regarding relaySet() in setup(), I would do the Serial.begin() at the beginning 
of setup(), then start printing out the values of things that you expect to see 
inside relaySet(). The only way to figure out why it doesn't work within 
setup() is to check your expectations versus reality. What are the values of 
your variables inside the function? Which leg of the if command is run? Why?

Again, I don't expect anything with delay() to work inside an interrupt. Weird 
things will happen (if they happen at all), which is what you've found.

Original comment by m...@schwager.com on 15 Aug 2013 at 6:39