Make Struct of pins

Hello everyone, I need to make a structure with different pins, example: 13, 10, 7, 3, then I want to address these pins as the bottom of a register, example: 13 = register,0 / 10 = register,1 / 7 =register,2 / 3 =register,3

I don't know if I have explained this well.
Thank you!

You didn't :wink:

Are you talking about putting the pin numbers into an array?

const byte pins[4] = {13, 10, 7, 3};

Hi Paul, I want to group these 4 pins into the same "reg_pins" register, so that when I put reg_pins = 0b00001111 all the pins turn on at the output.
I hope I have made myself understood.
Is it possible?

Here is an article on port manipulation https://www.instructables.com/Arduino-and-Port-Manipulation/ just one of many similar articles.

Yes. You can use "direct port manipulation" and write many bits from one register all at once. Or read them.

Google

Arduino direct port manipulation 

it is not too hard.

a7

Thanks guys, this looks good.

I did not test it, but it compiles.

class Like4OutputPins {
  uint8_t pins[4];
 public:
  void begin() {
    for (auto p: pins) {
      pinMode(p, OUTPUT);
    }
  }
  Like4OutputPins(uint8_t pin0, uint8_t pin1, uint8_t pin2, uint8_t pin3)
  : pins{pin0, pin1, pin2, pin3} {}
  Like4OutputPins& operator=(uint8_t vals) {
    for (auto p: pins) {
      digitalWrite(p, vals&1 ? HIGH : LOW);
      vals >>= 1;
    }   
  }
} reg_pins(13, 10, 7, 3);

void setup() {
  reg_pins.begin();
  reg_pins = 0b00001111;
}

void loop() {}

Thank you Wandall, I'll test it.

Is it important that those pins turn on simultaneously? Or do you have a tolerance for how close to simultaneous they would need to come up?

a7

With free configurable pins, no synchronicity can be guaranteed.

The Arduino "MegaAVR Core" (Nano Every, Uno WiFi 2) implements something like this in the name of Uno compatibility. It's horribly slow compared to direct port writes (especially since the pins are all higgly-piggly), but faster than a series of digitalWrite calls.

See: ArduinoCore-megaavr/UNO_compat.h at master · arduino/ArduinoCore-megaavr · GitHub

To control all the pins simultaneously you MUST choose it in the same controller port.
Let's say you use Arduino Uno (atmega328).
Look to the Atmega328 pinout - pins 3 and 7 belongs to the PORTD, but 10 &13 - to PORTB, so you can't turn it all in one operation.
Take, for example, 8,9,10 & 13 - all this pins are on the PORTB

Yes and no. You can group your pins together in an array. You can create a function which enables you to set all pins using a single call to your function to set each pin according to a pattern of bits.

Others have suggested using port manipulation. The problems with that idea are

  1. You don't get to choose which pins are grouped together as a port. The pins that belong to each port are fixed in the chip hardware design.
  2. The ports, and the pins that belong to each port, are different for different chip designs. If you write code on one type of Arduino using port manipulation, it will not work on other types of Arduino.

Please explain why you need to do this. Is it because you want to conveniently set multiple pins with a single command? Or is it that you need all the pins to change together at the same instant? If the latter, is that because you don't want to be able to see the pins changing one after the other? If that is your concern, do not be concerned. Whether you use port manipulation or the standard digitalWrite() function for each pin in turn, it will happen far too fast for a human to perceive it as anything other than instantaneous.

Try this:

void setPins(byte pattern) {
  digitalWrite(13, bitRead(pattern,0)==1 ? HIGH : LOW);  
  digitalWrite(10, bitRead(pattern,1)==1 ? HIGH : LOW);
  digitalWrite(7, bitRead(pattern,2)==1 ? HIGH : LOW);
  digitalWrite(3, bitRead(pattern,3)==1 ? HIGH : LOW);
}

Then you can write setPins(0b00001111); elsewhere in your code

It doesn't have to be simultaneous, but it should be within a few microseconds.

Yes, it would be better if they were in the same port, but in this case it can't be like that

I have to drive these pins like this because I'm going to use an existing board and I just have to make a new program for it.

I had already thought about creating a function as efficient as possible to activate pin one after another

This code looks good, I'll try it

OK, I think digitalWrite() is not going to make that.

So use direct port manipulation and go to whatever trouble it means. Because for some reason you must pick pins that are not on one port.

What else do you have on I/O pins?

The fastest solution will not be a general one, is this a special case thing or are you trying to solve this with something you could easily deploy next time you have N random pins that must all go uo or down within microseconds of each other?

If you really need those microseconds, go to this trouble

// https://wokwi.com/projects/351674089577906776
// https://forum.arduino.cc/t/struct-of-pines/1067726

// 13, 10, 7 and 3

void setup() {

  Serial.begin(115200);
  Serial.println("hello world.\n");

  pinMode(13 , OUTPUT);
  pinMode(10 , OUTPUT);
  pinMode(7 , OUTPUT);
  pinMode(3 , OUTPUT);
}

void loop()
{
  static unsigned char tt;

  set4Bits(tt);
  delay(474);

  tt++;
}

// place theBits into output pins 13, 10, 7 and 3

void set4Bits(unsigned char theBits)
{
  PORTB = (PORTB & 0xdb) | ((theBits & 0x8) << 2) | (theBits & 0x4);
  PORTD = (PORTB & 0x77) | ((theBits & 0x2) << 6) | ((theBits & 0x1) << 3);
}

Fix any errors I made, play with it here:

Direct Port Manipulation wokwo demo.

a7

Yes, the most efficient way to do this is to manage ports, managing pin by pin is very inefficient, but it's the only option, I'll have to make a function as fast as possible

It may take a little longer to deliver all the data, but between each bit there should be little

Really? Please explain why.