Reading Pins via Loop: Good or Bad Idea

I have been curious if this topic would help answer my question. On an Electron, I would like to loop through the pins, note which are set as output, and then note if they are set high or low. My intention is to send that back through a heartbeat every so often so the cloud app can sync up the states of the pins.

I don’t know even if its the best way but I had been thinking about looping through the pins programatically, collect the information, and send it back to the cloud app.0

I’ve seen reference to spark_wire.h which defines the Pin labels as Int’s. Where can I find that file?

Is looping through a good or bad approach?

Do you mean to loop through all of the available I/O pins?

In general, constantly monitoring pins and dealing with them is known as “polling”. Usually, if that’s pretty much all your code has to do anyway, you might as well do it. One caveat is if you have reason to care about the power consumption (e.g. your setup is battery-powered).

A more “elegant” approach would be to use pin change interrupts. I’m not sure if you can do this for every pin on the electron, as the documentation only lists which pins are capable of interrupts for the photon/core.

The idea of an interrupt is to use a special function (an “Interrupt Service Routine”, aka. an ISR) which is called whenever a condition is triggered. For standard GPIO pins, there are a variety of conditions to trigger the interrupt: on RISING, FALLING, CHANGE, HIGH, or LOW. These are triggered when the input to a pin reaches those states. What you can do is to write an ISR which will look at the values for all the pins and then publish them (probably with a minimum delay because you’re using an electron).

Do note that ISRs can only access static and global variables, and that if you’re using global variables you should declare them as volatile to tell the compiler not to optimize them away.

Ernest314 - Thank you for the response. The intention is to loop through the pins on the order of 1 or 2 times per day, just to make sure the back end is synced. What I am looking to do is to see if a pin that is previously set as HIGH is still set as HIGH, etc.

If you’re just looking for spark_wiring.h, it’s on their repo:

It doesn’t define the pins though, and it seems like you’ll have to dig through quite a few headers to find where it’s actually defined.


Edit: They’re defined in pinmap_hal.h, which can be found here:


Edit 2: Yeah, looping through the pins seems fine to me. Although I would definitely include comments pointing to the pinmap_hal.h file, and maybe include a table of the relevant ones for the electron.

AFAIK on STM32 µC used with the Particles there are no level triggers (HIGH/LOW) and you can’t really use them (without extra effort) independently on some pins due to shared EXTI lines.

But if you want to poll the pin states you can do that with a few read instructions to the port registers to acquire all GPIOs at once.

Or you can simply build a pin array and cycle through the array using getPinMode() and digitalRead() for each pin. You could even build an integer with individual bits representing a pin. :smiley:

1 Like

That depends on your ultimate goal :wink:
It definetly works and I don’t see a problem in general - but there are other options you could consider (as mentioned above by others too)

Peekay123 - Thank you for taking the time to reply. I must be doing something wrong.

I setup a test and got this result:
{“data”:“null”,“ttl”:“60”,“published_at”:“2016-07-08T13:11:57.201Z”,“coreid”:"",“name”:“ReadD1”}

My test returned NULL, not HIGH or LOW which is what I had expected.

The ultimate goal is:

Is it improper to poll a pinMode set to OUTPUT with digitalRead() ?

Here is a fragment of the code I’m using to test this. Did I get it right?

int Relay1 = D7;
void setup() {
    pinMode(Relay1, OUTPUT);
    digitalWrite(Relay1,HIGH);
}

int ReadPin(String command) {
            x=0;
            x=digitalRead(Relay1);
            Particle.publish("ReadD1", x);
}

Nope, you just get the bit of the ODR (output data register) of that pin, which usually reflects the status of the pin.

You can’t publish x like this since the data payload of an event (second parameter) has to be a string.

You could do this tho’

Particle.publish("ReadD1", String(x));

I don’t see the declaration of x but I guess it’s int x;

And you should have a return x; statement in a function that states that it will return an int as your

int ReadPin(String command)

This way you’d even get the current state of that pin as return value for your function call delivered for free.

int ReadPin(String pinNr) 
{ // possible numbers see https://github.com/spark/firmware/blob/master/hal/inc/pinmap_hal.h
  int pin = pinNr.toInt();
  int x = digitalRead(pin);
  Particle.publish("Read", String::format("PinNr %d: %d", pin,  x), PRIVATE);
  return x;
}

And you’d need this in setup()

  Particle.function("readPin", ReadPin);
1 Like

ScruffR - I missed that bit of detail.

After correcting the code, it works like it should.

I appreciate all the help from everyone.

Tony

1 Like