Saving pin states

I want to save the state of various pins, so I can restore them when I want.
I'm using Arduino Nano board ATM, but also got some ESP8266 & ESP32 boards.
I've searched Library for 'save pin state' and got nothing.

A classic example (or is it?) is saving the status of LED_BUILTIN, jumping to some ICSP code (which uses LED_BUILTIN as SCK), then setting LED_BUILTIN back again.
BTW That's just ONE example; there are more I want to save.

At a minimum, saving whether pin is

  • pinMode(, OUTPUT) + digitalWrite(, HIGH)
  • pinMode(, OUTPUT) + digitalWrite(, LOW)
  • pinMode(, INPUT)
  • pinMode(, INPUT_PULLUP)
    would be needed

Nice bonus would be

  • analogWrite(, MyValue) // MyValue number

Of course, more information would be nice (PWM clock & count info maybe), but not essential.

Any pointers would be good.

Since you set all those states using code, have the code keep a record of the current status. Update that status whenever anything is changed.

1 Like

I was hoping for a more OOP approach than a bunch of global variables.

A structure is what I had in mind.

I use 3 states for LED_BUILTIN

  • off (=OUTPUT, LOW - but could also be INPUT for Hi-Z),
  • bright (=OUTPUT, HIGH), and
  • dim (=INPUT_PULLUP - saves power).

All the information I need is in the various PORT registers, so I was hoping someone might have done the work already.
Maybe that'll be one of my next projects.

Learn to use the Arduino "bit" macros.
https://www.arduino.cc/reference/en/ "Bits & Bytes"

You could create a byte variable to store the states of 8 pins, for example, LED_BUILTIN on Nano is pin 13 or PORTB bit 5.

void loop()
{
  static byte pinStates = 0:

Before calling SPI, store the current state of LED_BUILTIN to
pinStates bit 0.

bitWrite(pinStates,0, bitRead(PINB,5));

After SPI routine is done, restore state of LED_BUILTIN.

bitWrite(PORTB,5, bitRead(pinStates,0))

Use the remaining 7 bits (1 ~ 7) of pinStates likewise if needed.

brewmanz: "All the information I need is in the various PORT registers"
meanwhile the various PORT registers: 2

You can use a union to name 2 bits as pin states but that's not OOP.
You can use an enum to name off, dim and bright as 0, 1, 2 and then use a switch-case to reset the pin but that's not OOP either.

But if you put them in a Class, it's OOP.

Yes. You did. When you wrote that information to those registers you did all the work that needs to be done. At that point you had this information. If you want to save it then save it.

Umm, it might not have been me who wrote that information to the digital pin registers.
There seems to be a presumption from several writers here, that Arduino code is a monolithic chunk, each part knowing about all the other parts, rather than a bunch of library/object calls where each part knows only about itself, and encapsulates how it actually works.

To take an extreme example, maybe I want to hijack pins 0 & 1 (I don't, but just sayin'), do some stuff, then reset them back ready for Serial.

Decades ago I was an IBM Mainframe Systems Programmer, patching operating systems and telecommunication controllers on the fly, so the thought of modifying hardware settings doesn't frighten me.

you can find all the information about port register here -> PortManipulation

here is an example


void setup() {
  Serial.begin(9600);
}


void loop() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH); 
  PINinfo();
  delay(1000);                      
  digitalWrite(LED_BUILTIN, LOW); 
  PINinfo();
  delay(1000);  
  pinMode(LED_BUILTIN, INPUT_PULLUP); 
  PINinfo();
  delay(1000);

}
void PINinfo(){
  Serial.print("Pin directions ");
  Serial.println(DDRB, BIN);
  Serial.print("Pin states: ");
  Serial.println(PORTB, BIN);

}

-------->Code Simulation on Wokwi

I'm not one since I use Main Loop Code techniques to write tasks but AFAIC when I write programs, I am responsible for what goes on and that includes the libraries,etc, that I bring in. If I am going to mess with pin states, I have to make sure it's done right.

Do you know how to task on a single thread w/o using interrupts or an O/S except for what you write, small computing style?

What you're used to would probably be great in a multi-processor system, something with sub-systems serving files and comms. You might be a top guy in a robot project?

I worked for an IBM VAR before it got caught up in the Boesky scandal. That part of the shop got frustrated getting answers from IBM, like having teeth pulled difficulty! They went public then hatchetmen came in and fired key office people and shut projects down including mine but they offered to teach me RPG which is when I left. Last I heard, the owner lost his house on Long Island and the company folded. I couldn't figure out how they stayed in business up till then, it was a madhouse anyway.

Thank you, @amitf; that's the sort of useful information I'll need.

One that's only useful for Port B pins on an AVR Processor.

While I agree with nearly every other poster in this thread that such a function is completely unnecessary because @brewmanz's code already knows what the state is (because it set that state to begin with), a more general implementation might look like this:

class ioPin {
    using stateType = decltype(HIGH);
  public:
    ioPin(uint8_t p) : pinNum(p) {
    }

    void begin() {
      pinMode(pinNum, OUTPUT);
      digitalWrite(pinNum, LOW);
    }

    stateType getState() {
      return state;
    }

    void setState(stateType s) {
      digitalWrite(pinNum, s);
      state = s;
    }

    const uint8_t pinNum;

  private:
    stateType state {LOW};
};

void setup() {
  Serial.begin(115200);
  delay(2000);

  ioPin pins[] {13, 14, 15, 16, 17};

  for (auto &p : pins) {
    p.begin();
  }

  for (auto &p : pins) {
    p.setState((random(0, 2) == 1) ? HIGH : LOW);
  }

  for (auto &p : pins) {
    Serial.print("Pin: ");
    Serial.print(p.pinNum);
    Serial.print(", State: ");
    Serial.println((p.getState() == HIGH) ? "HIGH" : "LOW");
  }
}

void loop() {
}
Pin: 13, State: LOW
Pin: 14, State: LOW
Pin: 15, State: HIGH
Pin: 16, State: HIGH
Pin: 17, State: LOW

yes because i only wrote for PORTB (pin d8 to d13). you can access Port D (d0-d7) & Port C (A0-A5).

the OP has already told the libraries could change the pin state. although it is not good to interfere with pin you have assigned to a library but let OP experiment with his project.

isn't it easier to just read the port register. at least on AVR microcontrollers.
also, it won't work if a library changed the pin state.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.