Programming Interrupts

I'm going to take a survey by response (since I don't have a list of choices, whatever has the most same responses will be declared the most popular)

What is the best or most write way to program interrupts in the Arduino IDE? Where do I get the information to do so?

The Arduino website (here) has two ways, Mr. Gammon proposes a third, and I have two book and a magazine that add two more. For a total of five different programming methods.

All I need is to simply enable and disable the pin change interrupts. Where is the best (and clearest) programming method found?

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode); seems to be the recommended way

The Arduino website (here) has two ways,

I would be interested in links to the two methods.

UKHeliBob:
I would be interested in links to the two methods.

I suppose he meant

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);	([color=green]recommended[/color])

versus

attachInterrupt(interrupt, ISR, mode);	([color=red]not recommended[/color])

which is just 1 way to do it.

adwsystems:
Where is the best (and clearest) programming method found?

The best one is any one that works.

The clearest one is one that works and which you understand.

You have not said anything to guide us about why you are confused between the different options you have found.

If you tell us what you want your program to do we could give more useful advice. attachInterrupt() is used to activate the external interrupts but there are many other interrupts for other purposes.

...R

Robin2:
The best one is any one that works.

The clearest one is one that works and which you understand.

You have not said anything to guide us about why you are confused between the different options you have found.

If you tell us what you want your program to do we could give more useful advice. attachInterrupt() is used to activate the external interrupts but there are many other interrupts for other purposes.

...R

So attachInterrupt applies only to INT0 and INT1 (Uno pins D2 and D3)?

UKHeliBob:
I would be interested in links to the two methods.

(1) attachInterrupt() - Arduino Reference

(2) http://playground.arduino.cc/Main/PinChangeIntExample

adwsystems:
So attachInterrupt applies only to INT0 and INT1 (Uno pins D2 and D3)?

Yes.

The pin change interrupt arrangements are separate from external interrupts. I suggest you study the Atmega 328 datasheet to get the full details. And Nick Gammon's tutorial.

...R

Robin2:
The best one is any one that works.

The clearest one is one that works and which you understand.

You have not said anything to guide us about why you are confused between the different options you have found.

If you tell us what you want your program to do we could give more useful advice. attachInterrupt() is used to activate the external interrupts but there are many other interrupts for other purposes.

...R

None of the examples appear to be complete in their code, clear in their explanation, or appear to be applicable to what I'm trying to do. As stated, all I need is to simply enable and disable the pin interrupts. It would also appear that I could use an example on determining which pin triggered the interrupt if using the Pin Change Interrupt as vaguely outlined in the first post here Gammon Forum : Electronics : Microprocessors : Interrupts.

Robin2:
Yes.

The pin change interrupt arrangements are separate from external interrupts. I suggest you study the Atmega 328 datasheet to get the full details. And Nick Gammon's tutorial.

...R

Suggestion already executed to not much avail.

I haven't found any references on how to enable and process multiple inputs on the same PCMSKx register or setting PCIFR/PCICR when working with pin interrupts from multiple banks. Nor how to turn off the PCMSKx when I don't want a bit in the interrupt to register.

adwsystems:
As stated, all I need is to simply enable and disable the pin interrupts.

That description is not sufficient to enable me to assist.

What pin interrupts? (Or what pins do you want interrupts working on?)
What do you want to happen when a pin causes an interrupt? What is your project?
What is going to trigger the interrupts?

The external interrupts and the pinChange interrupts are disabled by default.

...R

Robin2:
That description is not sufficient to enable me to assist.

What pin interrupts? (Or what pins do you want interrupts working on?)
What do you want to happen when a pin causes an interrupt? What is your project?
What is going to trigger the interrupts?

The external interrupts and the pinChange interrupts are disabled by default.

...R

I'd rather have the information to program it myself but if you would like to do all the work then by all means.

There are 12 pairs of inputs. Half are RUN/STOP (D0-D5 PMCSK2) and the other half are boolean sensor inputs (D9-D13 PMCSK0). When an RUN/STOP pin goes high, it toggles the state RUN to STOP and STOP to RUN. When changing to run the count of the odd pin is cleared. When an input goes high, the count for the pin pair is incremented. Additionally, there is a time (HH:MM:SS.msec) associated with the run time for each pin pair.

Each input needs to be debounced and the rising edges are no less than 100msec apart (plenty of debounce/retrigger time available).

Rather than constantly checking each individual pin, I thought it would be best to use the 'bank' aspect of the interrupts which happens in the background. Then the program can figure out which input changed state.

That's the scope of the project involving the interrupts. I don't see how it helps locate a complete/clear explanation of programming the pin interrupts. I look for to seeing your code.

Along the same lines, can you have a millis() call inside a ISR (PCINT0_vect) subroutine?

adwsystems:
I haven't found any references on how to enable and process multiple inputs on the same PCMSKx register or setting PCIFR/PCICR when working with pin interrupts from multiple banks. Nor how to turn off the PCMSKx when I don't want a bit in the interrupt to register.

Take a look at chap 17 in the ATMega328p datasheet.

The interrupts are described as being either "external interrupts" or "pin change" interrupts, even though they are all really external.

What they usually call the "external" interrupts are the two dedicated interrupts INT0 and INT1, whose functionality can be programmed to be any of either level (low) sensitive or rising or falling, or change activated.

What they call "pin change" interrupts are the external interrupts that only respond to pin change. There is one of these for each available port pin, and they are grouped by port, with just one vector for the entire port. So for example PCINT0 through to PCINT7 all share the one vector named "PCINT0_vect".

PortB: PCINT0 ... PCINT7: PCINT0_vect
PortC: PCINT8 ... PCINT14 :PCINT1_vect
PortD: PCINT16 .. PCINT23 :PCINT2_vect

The pin change interrupts have three separate levels of masking/enabling.

  1. Globally, like all other interrupts, with the I bit in the flags register, and controlled by cli() and sei().
  2. At the individual port level where the three vectors can be individually enabled.
  3. At the pin level where all 23 pins can be separately masked.

The Pin Change Interrupt Control Register (PCICR) enables each of the three interrupts at the port level, and the Pin Change Interrupt Flag Register (PCIFR) holds the corresponding requests for pending interrupts from these three sources.

The pin change interrupts are masked individually (all 23 of them) in a set of three registers, PCMSK0, PCMSK1 and PCMSK2.

The pin change interrupt code is programmed using the ISR() macro, as in

ISR(PCINT0_vect) {
  // do whatever
}

and...?

I would have to say that is the most straightforward explanation of that aspect I have read so far. but that's also the problem. Like all the other notes, its explaining how an engine runs without explaining how to install it or drive the car.

adwsystems:
and...?

I would have to say that is the most straightforward explanation of that aspect I have read so far. but that's also the problem. Like all the other notes, its explaining how an engine runs without explaining how to install it or drive the car.

To use the interrupts you just have to set the various registers described above. These can be accessed in C by name, for example:

PCMSK0 |= 0x20;       // enable individual PCINT5 pin
PCIFR = 01;           // strobe flag bit to clear any pending PCINT0_vect
PCICR |= 0x01;        // enable the PCINT0_vect
sei();                // global interrupt enable (if not already enabled)
// The system is now ready to respond with an interrupt to any change on the PORTB5 (PB5) pin.

In the end you just have to spend some time reading the data sheet to get comfortable with this stuff.

Got that too. I even found the 0x40 is a constant called PCINT6. Is there a function that relates the pin numbers to the PCINT6 values by any chance? It would make moving pins around a lot easier...

How do you enable multiple pins of the same PCMSKx mask?

How do you tell which pin triggered the interrupt? (a big blank left out of all examples I have found)

How do you disable one pin in the PCMSKx mask after you have enabled it (without losing all the others)?

adwsystems:
I'd rather have the information to program it myself but if you would like to do all the work then by all means.

I have no intention of depriving you of the work. But it would be a waste of my time and yours if I was advising about the wrong thing. Prior to your Reply #11 there was no indication that you were even interested in interrupts on more than 1 pin.

Rather than constantly checking each individual pin,

There is no intrinsic difficulty with checking each pin if there is plenty of time to do so. Interrupts are principally required to detect short lived events that might otherwise be missed, or events that happen too frequently for polling to be practical.

There are 12 pairs of inputs. Half are RUN/STOP (D0-D5 PMCSK2) and the other half are boolean sensor inputs (D9-D13 PMCSK0). When an RUN/STOP pin goes high, it toggles the state RUN to STOP and STOP to RUN. When changing to run the count of the odd pin is cleared. When an input goes high, the count for the pin pair is incremented. Additionally, there is a time (HH:MM:SS.msec) associated with the run time for each pin pair.

While this certainly points in the direction of pinChange interrupts you have not provided any information about the duration or frequency of the events other than to say (elsewhere) that there is at least 100msecs between successive events on the same pin. 100msecs is a long time for an Arduino.

And 12 pairs implies 24 pins so I think you will need a Mega rather than an Uno.

...R

Robin2:
I have no intention of depriving you of the work. But it would be a waste of my time and yours if I was advising about the wrong thing. Prior to your Reply #11 there was no indication that you were even interested in interrupts on more than 1 pin.
There is no intrinsic difficulty with checking each pin if there is plenty of time to do so. Interrupts are principally required to detect short lived events that might otherwise be missed, or events that happen too frequently for polling to be practical.
While this certainly points in the direction of pinChange interrupts you have not provided any information about the duration or frequency of the events other than to say (elsewhere) that there is at least 100msecs between successive events on the same pin. 100msecs is a long time for an Arduino.

And 12 pairs implies 24 pins so I think you will need a Mega rather than an Uno.

…R

Oops. My bad. 6 pairs of inputs (note the details in the post of the pin numbers).

I have no idea the duration other than they will not be closer than 100 msec and I have no idea the period or frequency of them. I don’t know when someone will push the start/run button nor do I (or anyone else) know when the input will trigger. This is for a real world application, this level of minutiae is impossible to define.

I suspect this is what you want…

If the inputs are the result of a human pushing buttons you can be quite certain that will be so slow that there is no need for interrupts.

That is why I have asked you (this is the third time) to tell us what the project is.

...R