Any way to do non hardware interrupts on the 328

Is there a way to duplicate the function of a hardware interrupt, pins int0/int1(digital pins 2/3) on other pins on the 328.

I know PWM can be "simulated" on non PWM pins and analog pins can be digital pins, Is there a similar way to "convert" a digital pin in software to function as an interrupt pin.

Im currently running the Reading RPM process in the playground at Arduino Playground - ReadingRPM to read a fan.

But I need to do it on a different digital pin for a project where both interrupt pins (digital 2 and 3) are already tied up.

Any hints of where to look or code snips greatly appreciated.

The simple answer is yes, every analogue or digital pin can generate an interrupt.

They are not quite as convenient as INT0 & INT1.
Each pin has a dedicated interrupt service routine that is called when the corresponding pin changes.

There are only three "Pin Change" interrupts for all the input & output pins. Each pin change interrupt can be triggered by upto 8 pins.
The mapping is roughly:

  • PCI0 will be triggered by pins in Port B (Arduino pins 8 to 13)
  • PCI1 will be triggered by pins in Port C (Arduino pins Analog 0 to 5 & Reset)
  • PCI2 will be triggered by pins in Port D (Arduino pins 0 to 7)

The details can be found at Atmel in the ATmega328/Atmega168/ATmega88/ATmega48 documents Currently (and this does change as new versions are released) in http://www.atmel.com/dyn/resources/prod_documents/8271.pdf

If you look in Section 12. External Interrupts, it explains:

The External Interrupts are triggered by the INT0 and INT1 pins or any of the PCINT23...0 pins. ... The pin change interrupt PCI2 will trigger if any enabled PCINT23...16 pin toggles. The pin change interrupt PCI1 will trigger if any enabled PCINT14...8 pin toggles. The pin change interrupt PCI0 will trigger if any enabled PCINT7...0 pin toggles.

Section 11. Interrupts, explains the names of the interrupt routines.

This explains the relationship between PCINTn pins and the Arduino pin numbering: http://arduino.cc/en/Hacking/PinMapping168

So, when you arrive in the interrupt routine for e.g. PCI0, it can be triggered by upto 8 pins, and you'll have to write a little bit of code to figure out which. Of course, if only one pin is set up to generate an interrupt, then there is only one pin to look at.

HTH
GB

Very informative response, thank you very much.

My conundrum for my project is I have to measure four pulse sources, currently I have one on d2(int0) and one on d4(int1) I need two more. which is why I was looking for a "soft" interrupt.

I have to be careful in mucking about because I also have serial data back and forth (on d0,d1), pwm on 4 pins(d5,d6,d10,d11) and several addressables running on the I2C bus on pins a4 and a5.

EDIT: So upon further review, the clear answer is not with out mucking up a bunch of other stuff already using timers and interrupts.

Prolly goinng to move to some other hybrid answer from here.

Thanks again

Boz

the clear answer is not with out mucking up a bunch of other stuff already using timers and interrupts.

I don't think that is so. I used the pin change interrupt function to read 6 inputs on this project:-
http://www.thebox.myzen.co.uk/Hardware/Crazy_People.html

Worked like a charm, Grumpy_mike, thanks, that was exactly what I was looking for.

One note I experienced in using your Pin Change Interrupt call

PCattachInterrupt(7, rpm_fun01, CHANGE);

Versus the original hardware interrupt call

attachInterrupt(0, rpm_fun, RISING);

Is that it doubled my resulting rpm from the following equation

 if (rpmcount >= 20) { 
     //Update RPM every 20 counts, increase this for better RPM resolution,
     //decrease for faster update
     rpm = 30*1000/(millis() - timeold)*rpmcount;
     timeold = millis();
     rpmcount = 0;
     Serial.println(rpm,DEC);
   }

Output from Hardware Interrupt was 1200 rpm
Output from Pin Change Interrupt was 2400 rpm

I know this is because the CHANGE state measures both the switch from high to low and the switch back from low to high as a trigger each where the RISING call only triggers on the low to high switch.

I thought Id just mention it if anyone else doesn't catch it reading this in the future because the first version only supports CHANGE and not RISING and FALLING.

Thanks again for your help, I was this close <-> to switching to a much more complex I2C answer.

Boz