Compare PINA to LAST_PINA in loop() (Mega 2560)

I think I'm starting to understand how the port registers work, but would like some input.

Let's say I have 8 doors in my house to monitor using reed switches. According to the following section in pins_arduino.h I'm thinking I should connect these N/C reed switches to digital pins 22-29

    PD  , // PD 0 ** 21 ** I2C_SCL  
    PA  , // PA 0 ** 22 ** D22  
    PA  , // PA 1 ** 23 ** D23  
    PA  , // PA 2 ** 24 ** D24  
    PA  , // PA 3 ** 25 ** D25  
    PA  , // PA 4 ** 26 ** D26  
    PA  , // PA 5 ** 27 ** D27  
    PA  , // PA 6 ** 28 ** D28  
    PA  , // PA 7 ** 29 ** D29  
    PC  , // PC 7 ** 30 ** D30

Reason being, they all appear to be part of PINA to me, making me think I can do something like the following instead of using a digitalRead on all 8 pins on each iteration of loop().

uint16_t LAST_PINA = PINA;

void setup(){}

void loop()
{
    if(PINA != LAST_PINA)
    {
        // determine which pin changed state and do something
    }
}

Do I have the right idea here?

Do I have the right idea here?

If speed is important, yes. If portability, and the ability to use Arduinos other than the Mega, is important, no.

joebert: I think I'm starting to understand how the port registers work, but would like some input.

Let's say I have 8 doors in my house to monitor using reed switches. According to the following section in pins_arduino.h I'm thinking I should connect these N/C reed switches to digital pins 22-29

  PD  , // PD 0 ** 21 ** I2C_SCL  
    PA  , // PA 0 ** 22 ** D22  
    PA  , // PA 1 ** 23 ** D23  
    PA  , // PA 2 ** 24 ** D24  
    PA  , // PA 3 ** 25 ** D25  
    PA  , // PA 4 ** 26 ** D26  
    PA  , // PA 5 ** 27 ** D27  
    PA  , // PA 6 ** 28 ** D28  
    PA  , // PA 7 ** 29 ** D29  
    PC  , // PC 7 ** 30 ** D30

Reason being, they all appear to be part of PINA to me, making me think I can do something like the following instead of using a digitalRead on all 8 pins on each iteration of loop().

uint16_t LAST_PINA = PINA;

void setup(){}

void loop() {     if(PINA != LAST_PINA)     {         // determine which pin changed state and do something     } }




Do I have the right idea here?

Yes that is the how one could do it at a real speed advantage over doing single digitalRead() statements and comparing with previous value stored for the pin(s).

You might also want to research pin change interrupt function. It generates a interrupt if any bit in a port changes without you having to poll the port. Inside the ISR you can do the compare with the last value read from the port.

Lefty

As Paul says you can do that but you will break the code from working on any other Arduino because the pin mapping will be different.

As in this case you don't need the speed I'd stick with digitalRead() and save that technique for one day when you do.


Rob

Thank you.

I think in this case, since these are door/window/etc contacts, I want to keep them working as close to real time as possible. I'm thinking using interrupts may be a better way to go.

"real time". Yes indeed.

With interrupts your code can react to a window opening within approximatly 0.1 microsecond. The speed of light (and that of electricty in wires is slower) will travel 30 meters. So if the wiring is long you Arduino will still be late in sensing the opening.

Reed switches take a while to react, too - how far is the window open before the magnetic fields lets go of the swinging element?

What is the output when you have detected a dorr/window changing? Sending a serial message to a logger? With the speed of serial that is going to be WAY late.

Of course we know the time it happened. Getting a timestamp is getting tricky - microseconds() is only accurate to 4 us, and reading time from a RTC (realTimeClock) is certainly going to be off ... they only give it to the nearest second, but you can supplement by some microseconds manipulation.

If you want to exercise your code skills, or otherwise want to use interrupts / port reading for the sheer hell of it, then that is a good reason.

Otherwise do a simple digitalRead(Item[idx]) like construct. You will be late by maybe 100 microseconds. Does it matter if the window opened at 10:24:44.334561 AM or 10:24:44.334761 ?

uint16_t LAST_PINA = PINA;

PINA is an eight bit register.

While that particular assignment will work there are similar things that will not work. I strongly suggest you get in the habit of putting executable initialization in setup...

uint8_t LAST_PINA;

void setup( void )
{
  LAST_PINA = PINA;
}
 if(PINA != LAST_PINA)
    {
        // determine which pin changed state and do something
    }

That's the tricky bit isn't it? Now you have to work out which one changed.

Make life easy for yourself. Burglars don't open a window in a nanosecond. Write code that is easy to read. In a couple of years' time, you'll thank me, when you go to modify it.