PCIFR question

Hi,

I've done my homework reading the datasheet, but I am to stupid to be 100% sure that I understand it right, thus I seek help from those kind enough to bare with my yawning.

To back up a bit... I have an application where I want to count events that have a much slower repetition rate than my loop function. Plus, they are burdoned with the so called debouncing effect - I use a mechanical switch.

With that conditions I decided I might check the PCIF2 bit of the PCIFR register every time I enter the loop. In principle if it is set to 1 it means that I had an "interrupt requsest" which I assume means that the input pin has changed it state...physically. I'll just copy - paste the relevant text for refeence. This is from the ATmega328 & friends manual.

Bit 2 – PCIF2: Pin Change Interrupt Flag 2 When a logic change on any PCINT[23:16] pin triggers an interrupt request, PCIF2 becomes set (one). If the I-bit in SREG and the PCIE2 bit in PCICR are set (one), the MCU will jump to the corresponding Interrupt Vector. The flag is cleared when the interrupt routine is executed. Alter- natively, the flag can be cleared by writing a logical one to it

OK, reading on it sayt that MCU will jump to the corresponding interrupt vector... but what is the condition for the jump?? Innitialy I thought it was a defined interrupt routine , plus ofcourse appropriate SREG and PCICR bits, but it seems only the latter two conditions suffice. So to use the Flag register to measure my switch..ehm switching I actuall have to disable the PCIE2 in the PCICR register and only set the appropriate bit in the PCIMSK to 1.??? Because otherwise "The flag is cleared when the interrupt routine is executed. " and I miss it when I check it in the main loop.

OK, that kind of works, I would just like a confirmation of someone more knowledgable.

One other question: I rely on newsoft serial which uses pins on the same pin change interrupt bank (but of course different pin). Will that interfere with my pin...I don't know what newsoft serial will do with my mask settings!?!

Why all the faffing around with interrupts ? Poll the switch each time through loop() and debounce the input in software. There is even an example in the IDE.

Thanks for the answer!

The switch is at LOW level only for a few 10 ms, otherwise it's HIGH. I am catching the whole DOWN/UP transiton. Sorry I forgot to mention this. Besides, at this point, I would like to understand the issue regardles the underlying physical problem.

Polling PCIFR is not the way to use interrupts. The whole point of them is to have an ISR called. If you are going to poll a flag you may as well poll the actual event.

http://www.gammon.com.au/interrupts

Thanks for your answer Nick.

I find the isr clumsy in my applicaton as it gets triggered many times at each event. The switch is mechanical (tipping bucket actually) and I am just interesten in counting the actual tipping not the 20 or so connections and disconections made as it tips. Filtering would also help but I'm playing with a 100% software solution at this point.

Of course I could have a special variable that is incremented every ISR call and then a special check in the loop that would only increment my final counter once, but I find this unnecessary overhead. The PCFIR has only two states and it will tell me exactly what I need, of course if it is not cleared by the ISR.

Thanks again.

peter_: I find the isr clumsy in my applicaton as it gets triggered many times at each event. The switch is mechanical (tipping bucket actually) and I am just interesten in counting the actual tipping not the 20 or so connections and disconections made as it tips.

So, add one in the ISR, turn that interrupt off, and re-enable it at some suitable interval later.

Or, do what you normally do for debouncing, and only add one to the count if a suitable time has elapsed.

One other question: I rely on newsoft serial which uses pins on the same pin change interrupt bank (but of course different pin). Will that interfere with my pin...I don't know what newsoft serial will do with my mask settings!?!

Yes, software serial (I'm not sure about the "old" newsoftwareserial) uses pin change interrupts. Can you use an external interrupt instead?

Your idea basically isn't going to fly. If you are testing the PCIF2 flag, and an interrupt occurs due to software serial, then that ISR will fire and clear the PCIF2 flag.

peter_: Thanks for the answer!

The switch is at LOW level only for a few 10 ms, otherwise it's HIGH. I am catching the whole DOWN/UP transiton. Sorry I forgot to mention this. Besides, at this point, I would like to understand the issue regardles the underlying physical problem.

Is that milliSeconds or microSeconds ? The former I suspect if the switch is activated by a tipping bucket.

start of loop
  read the input
  if the input is LOW and was HIGH last time
    if the input has been LOW for some time
      perform actions
    end if
   end if
end of loop

Thank you both.

UKHeliBob: working within the loop is not working for me, because my loop takes about 20 seconds to "go arround", which by my calculation means that there is no way that I can have two events durring one loop. Durring that 20 seconds I have a lot of things to do , and I can not afford to look at the input manuall.

Nick:

So, add one in the ISR, turn that interrupt off, and re-enable it at some suitable interval later.[\quote] Yes, true, I can do that, because I know when to expect something on NSS port and turn on the interrupt before the communication

Can you use an external interrupt instead?[\quote] Yes , the cleanest way. I'll prbably go with that in the end.

Your idea basically isn't going to fly. If you are testing the PCIF2 flag, and an interrupt occurs due to software serial, then that ISR will fire and clear the PCIF2 flag.

Hmm, I think it's still going to fly. Since software serial uses interrupt routines, they will automatically clear the FLAG when they are performed. And I am only looking at the flag when there is no communication for sure...But I agree ...clumsy.

I greatly appreciate all your inputs. Peter

peter_: ... my loop takes about 20 seconds to "go arround", ...

Why?

Post some code or I'll have to move this to some other part of the forum. The part that deals with hypothetical questions.

Please use code tags.

Read this before posting a programming question

Hmm, I think it’s still going to fly. Since software serial uses interrupt routines, they will automatically clear the FLAG when they are performed. And I am only looking at the flag when there is no communication for sure…

How do you know this?

The fact that is takes 20s is ok. That is the worse case scenario if it has to do certain interfacing with humans.
It is not a problem of the code. It is a consequence of the application.

In any case the loop is never so long that I could expect to make and error of double tipping the bucket in one loop even if the preciptition is at a world record rate.

Anyway the code is several hundreds of lines , and I wrote most of it: noone would survive reading it :slight_smile:
Peter

The fact that is takes 20s is ok. That is the worse case scenario if it has to do certain interfacing with humans.
It is not a problem of the code. It is a consequence of the application.

It is more likely that it is a consequence of how you have written it.

How are you handling the interface with humans ? Normally you would do it by reading the input and, if it is not present or not complete, move on and execute the loop() function until it is present or complete. What sort of input is it ? Can you at least post an example of how you you are reading and dealing with it ?

peter_: Anyway the code is several hundreds of lines , and I wrote most of it: noone would survive reading it :-) Peter

Don't worry, we've seen longer code than that.

The fact is that this is starting to turn into something like a "how do I jump out of an interrupt?" question. This is a question that goes into a lot of low-level detail about something very specific, without much detail about why this is needed (and usually without any code).

If you post your code, we can probably help you. 20 seconds in the main loop just sounds wrong. Perhaps a state machine would help you.

http://www.gammon.com.au/statemachine

No, no the code is OK, Nick.

There are activities that just take that long. It does not need to be avoided and it's really not a problem for the application.

You have helped me a great deal. Thanks.

I am intrigued as to what activities take 20 seconds. Can you expand on that ?