Using array to toggle multiple momentary switches

Hello, I tried searching but couldn't phrase or find what I need help with.

I have 8 momentary switches which are used as toggles. Each switch toggles a relay on/off

My code right now for each btn/relay combo look like this:

int btn1 = 2;
int ch1 = 14;

int state1 = HIGH;
int reading1;
int previous1 = LOW;

long time = 0;
long debounce = 200;

void setup() {
  // put your setup code here, to run once:

pinMode (ch1, OUTPUT);

pinMode (btn1, INPUT_PULLUP);


void loop()
{

  reading1 = digitalRead(btn1);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading1 == HIGH && previous1 == LOW && millis() - time > debounce) {
    if (state1 == HIGH)
      state1 = LOW;
    else
      state1 = HIGH;

    time = millis();    
  }

  digitalWrite(LED, state1);
  

  previous1 = reading1;

And it works as intended but to control 8 btn/relays i have just duplicated the function 8 times and renamed each state with the next number like so:

reading1 = digitalRead(btn1);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading1 == HIGH && previous1 == LOW && millis() - time > debounce) {
    if (state1 == HIGH)
      state1 = LOW;
    else
      state1 = HIGH;

    time = millis();    
  }

  digitalWrite(ch1, state1);
  

  previous1 = reading1;

//Next Channel/BTN

 reading2 = digitalRead(btn2);

  if (reading2 == HIGH && previous2 == LOW && millis() - time > debounce) {
    if (state2 == HIGH)
      state2 = LOW;
    else
      state2 = HIGH;

    time = millis();    
  }

  digitalWrite(ch2, state2);

  previous2 = reading2;

  

  //Next Channel/BTN

 reading3 = digitalRead(btn3);

  if (reading3 == HIGH && previous3 == LOW && millis() - time > debounce) {
    if (state3 == HIGH)
      state3 = LOW;
    else
      state3 = HIGH;

    time = millis();    
  }

  digitalWrite(ch3, state3);

  previous3 = reading3;

How could I do this with an array instead? Im very new to this.

Here is an example of one way to do what you want


struct dataLayout
{
  byte buttonPin;
  byte relayPin;
  byte previousButtonState;
} data[4];  //4 sets of data

void setup()
{
  Serial.begin(115200);
  data[0] = {A3, 3, HIGH};  //initial data
  data[1] = {A2, 5, HIGH};
  data[2] = {A1, 6, HIGH};
  data[3] = {A0, 9, HIGH};
  for (int x = 0; x < 4; x++)
  {
    pinMode(data[x].buttonPin, INPUT_PULLUP);
    pinMode(data[x].relayPin, OUTPUT);
    digitalWrite(data[x].relayPin, HIGH);  //start with relays off
  }
}

void loop()
{
  for (int x = 0; x < 4; x++)
  {
    byte currentButtonState = digitalRead(data[x].buttonPin);
    if (currentButtonState == LOW)  //button is pressed
    {
      if (currentButtonState != data[x].previousButtonState)  //button just became pressed
      {
        digitalWrite(data[x].relayPin, !digitalRead(data[x].relayPin));
        data[x].previousButtonState = currentButtonState;
      }
    }
    data[x].previousButtonState = currentButtonState;
  }
}

The key is an array of structs that lets us hold data of different types unlike na simple array

2 Likes

how about

// check multiple buttons and toggle LEDs

enum { Off = HIGH, On = LOW };

byte pinsLed [] = { 10, 11, 12 };
byte pinsBut [] = { A1, A2, A3 };
#define N_BUT   sizeof(pinsBut)

byte butState [N_BUT];

// -----------------------------------------------------------------------------
int
chkButtons ()
{
    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        byte but = digitalRead (pinsBut [n]);

        if (butState [n] != but)  {
            butState [n] = but;

            delay (10);     // debounce

            if (On == but)
                return n;
        }
    }
    return -1;
}

// -----------------------------------------------------------------------------
void
loop ()
{
    int n = chkButtons ();

    if (0 <= n)
        digitalWrite (pinsLed [n], ! digitalRead (pinsLed [n]));
}

// -----------------------------------------------------------------------------
void
setup ()
{
    Serial.begin (9600);

    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        pinMode (pinsBut [n], INPUT_PULLUP);
        butState [n] = digitalRead (pinsBut [n]);
    }

    for (unsigned n = 0; n < sizeof(pinsLed); n++)  {
        digitalWrite (pinsLed [n], Off);
        pinMode      (pinsLed [n], OUTPUT);
    }
}
2 Likes

My take on it:

const byte ChannelCount = 1;

struct Channel
{
  byte buttonPin;
  byte relayPin;
  int previousButtonState;
  int relayState;
} Channels[ChannelCount] =
{
  {2, A0, HIGH, HIGH},
};

unsigned long DebounceTime = 0;
const unsigned DebounceInterval = 10;

void setup()
{
  for (int channel = 0; channel < ChannelCount; channel++)
  {
    pinMode(Channels[channel].buttonPin, INPUT_PULLUP);

    digitalWrite(Channels[channel].relayPin, Channels[channel].relayState);
    pinMode(Channels[channel].relayPin, OUTPUT);
  }
}

void loop()
{
  for (int channel = 0; channel < ChannelCount; channel++)
  {
    int reading = digitalRead(Channels[channel].buttonPin);

    // if the input just changed and we've waited long enough
    // to ignore any noise on the previous change...
    if (reading != Channels[channel].previousButtonState &&
        millis() - DebounceTime > DebounceInterval)
    {
      // Remember the time the last state change happened
      DebounceTime = millis();
      Channels[channel].previousButtonState = reading;

      // if the input just went from LOW and HIGH, toggle the
      // output pin.
      if (reading == HIGH)
      {
        if (Channels[channel].relayState == HIGH)
          Channels[channel].relayState = LOW;
        else
          Channels[channel].relayState = HIGH;

        digitalWrite(Channels[channel].relayPin, Channels[channel].relayState);
      }
    }
  }
}
3 Likes

Guys this is so nice, thanks to all of you I will try your code out and write here. I just have to say, it is so nice I can just come here with an issue my smooth brain cant solve and 3 people within hours have solutions just like that. Thanks for your time :smiley:

Hello
I also have another sketch.
It uses a classless OOP approach. An object has been formed from the combination of switch and relay, which can be extended as desired.

[code]
/* BLOCK COMMENT
  ATTENTION: This Sketch contains elements of C++.
  https://www.learncpp.com/cpp-tutorial/
  https://forum.arduino.cc/t/using-array-to-toggle-multiple-momentary-switches/938405
*/
#define ProjectName "Using array to toggle multiple momentary switches"
// HARDWARE AND TIMER SETTINGS
// YOU MAY NEED TO CHANGE THESE CONSTANTS TO YOUR HARDWARE AND NEEDS
#define OutPutTest
constexpr unsigned long ScanTime {20};
constexpr unsigned long OutPutTestTime {500};
struct BUTTONRELAY {
  byte  buttonPin;         // portPin o---|button|---GND
  byte  relayPin;          // portPin o---|relay|---GND
  int   statusQuo;         // state (t-1)
  unsigned long stamp;
} buttonRelays [] {          // add button and relay combinations as you like
  {A0, 3, false, 0},
  {A1, 5, false, 0},
  {A2, 6, false, 0},
  {A3, 7, false, 0},
};
// -------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  Serial.println(F("."));
  Serial.print(F("File   : ")), Serial.println(__FILE__);
  Serial.print(F("Date   : ")), Serial.println(__DATE__);
  Serial.print(F("Project: ")), Serial.println(ProjectName);
  pinMode (LED_BUILTIN, OUTPUT);  // used as heartbeat indicator
  for (auto buttonRelay : buttonRelays) {
    pinMode(buttonRelay.buttonPin, INPUT_PULLUP);
    pinMode(buttonRelay.relayPin, OUTPUT);
#ifdef OutPutTest // check outputs
    digitalWrite(buttonRelay.relayPin, HIGH), delay(OutPutTestTime), digitalWrite(buttonRelay.relayPin, LOW);
#endif
  }
}
void loop () {
  unsigned long currentTime = millis();
  digitalWrite(LED_BUILTIN, (currentTime / 500) % 2);
  for (auto &buttonRelay : buttonRelays) {
    if (currentTime - buttonRelay.stamp >= ScanTime) {
      buttonRelay.stamp = currentTime;
      int stateNew = !digitalRead(buttonRelay.buttonPin);
      if (buttonRelay.statusQuo != stateNew) {
        buttonRelay.statusQuo = stateNew;
        if (stateNew) digitalWrite(buttonRelay.relayPin, !digitalRead(buttonRelay.relayPin));
      }
    }
  }
}
[/code]

Have a nice day and enjoy coding in C++.

1 Like

:sweat_smile: just for fun, mine
.
.

byte Down, Stat, Togl, tempo;                  // variables for 6 keys together 
unsigned long previousmillis;                  // debounce period     

void setup() {                                 // INITIALIZATION CODE 
  PORTD |= B11111100;                          // PD input with pullups (pin7...pin2)
  DDRB  |= B00111111;                          // PB as output          (pin13..pin8)
}

void loop() {                                  // MAIN CODE 
  if (millis() - previousmillis > 20) {        // delay for debounce, usually 10 or 20 ms
    previousmillis = millis();                 //
    byte iii = ~PIND & B11111100;              // reading PORTD pins 7..2 (with pullups)
    byte jjj = Stat;                           // 
    Stat     = iii & tempo;                    // while key is maintained pressed
    Togl    ^= (jjj ^ Stat) & Stat;            // flip-flop on each keys      
    tempo    = iii;                            // key configuration stored for next use
    PORTB    = Togl >> 2;                      // relays: PORTB  pins 13..8  are set
  }
}

2 Likes

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