Maximum number of mini rocker switches on Mega?

Hello all! Longtime Arduino hobbyist, new poster to the forum. I have a Mega sitting on my desk in front of me and 32 small rocker switches. I am using the internal pull-up resistor to have all these switches on the single Arduino Mega.

This method works so far for one switch. Does anyone know if I will damage my board by connecting them all at once to the main GND pin and then routing each input to a different Digital pin?

Thanks!

EDIT: I meant GND pin.

Wire your switches as S3 is wired.

There will be no issue with connecting all your switches.

1 Like

If you are using the internal pullup resistors, the other end of each switch will be connected to the Arduino Ground!!!

1 Like

If you are using INPUT_PULLUP, they'd all be wired to GND, not 5 volts.

And no, no special problem with 32 switches. Just the usual problems of any switch.

a7

1 Like

if you wire like this

pin (INPUT_PULLUP) --- rocker switch -- GND

you'll be fine (50KΩ PULLUPS so minimal current flowing). You'll read HIGH when open and LOW when closed - with bouncing in between probably

The bouncing may cause errors in my project's application. Would reducing the read rate to once per second fix this?

And oops- yes, I meant ground! Not 5V! Thank you all.

Just scan you switches every 100ms; look for a change in state and then a LOW to see if the switch is pressed.

I would just like to clarify that rather than simply reading the state and assigning that value as output, to read the value and ONLY change the output when it's a LOW value?

That seems sensible, thank you.

You may want to consider hardware debounce for the switches.

SPST rocker switch with hardware debounce.
image

Active low switch reads HIGH when off (NC) and LOW when activated (NO).

Typical sketch code:


//*******************************************************************************
//switches are checked every 100ms
void checkSwitches()
{
  byte currentState;

  //***********************************************         m a s t e r  P i n
  //masterPin switch
  currentState = digitalRead(masterPin);

  if (lastMasterState != currentState)
  {
    //update to the new state
    lastMasterState = currentState;

    //************************
    //is the switch pushed ?
    if (currentState == PUSHED)
    {
         //do something
    }

  } //END of this switch

//other switches


} //END of   checkSwithes()

35 switches :thinking:
Arrays would probably be wise to use.

anti-bouncing "of the poor" is to add some software delay after detecting a state change. 15ms usually works fine with most switches I played with.

But don't write a delay right away - it depends how long the action you trigger with the switch takes. if it's long enough until you come back reading the switch then no delay is needed

you can of course record the time of the change and take that into account to decide if you are bouncing or not. depends if you can afford to block the rest of the code for some ms (which is long in microcontroller's time)

@groundFungus Do you mean alter the hardware the Arduino is connected to? I'd rather go from Mega to Teensy or Leo Bodnar in this case.

@LarryD That code is pretty much the structure I was thinking. How does it differ from the standard code design?

@J-M-L So make the delay longer than a typical bounce, like a filter? That's totally fine as I only need to read the 32 switches once every one or two seconds.

Thanks guys! Learning a lot.

Well, that’s the standard code design I always use.
:slight_smile:

Edit

You do need this in loop( )


  //***********************************************         check switches T I M E R
  //is it time to check the switches ?
  if (millis() - switchMillis >= 100)
  {
    //restart the TIMER
    switchMillis = millis();

    checkSwitches();
  }

@LarryD Hah! No disrespect meant at all. And yes that timing trigger is important.

Non taken.

I have thick skin anyway :wink:

1 Like

but delay only once after checking all the rockers if they changed state.

something like that

struct Rocker {
  const byte pin;
  void (*callback)(const byte activePin);
  byte state;
};

// forward declaration of the callbacks, some could be shared and use the pin to differentiate action
void r2(const byte);
void r3(const byte);
void r4(const byte);
void r5(const byte);

Rocker rockers[] = {{2, r2}, {3, r3}, {4, r4}, {5, r5}};

void r2(const byte pin) {Serial.println(pin);}
void r3(const byte pin) {Serial.println(pin);}
void r4(const byte pin) {Serial.println(pin);}
void r5(const byte pin) {Serial.println(pin);}

void check() {
  bool antiBounceNeeded = false;
  for (auto && r : rockers) {
    byte s = digitalRead(r.pin);
    if (s != r.state) {
      antiBounceNeeded = true;
      r.state = s;
      r.callback(r.pin);
    }
  }
  if (antiBounceNeeded) delay(15); // anti bounce of the poor
}

void setup() {
  for (auto && r : rockers) {
    pinMode(r.pin, INPUT_PULLUP);
    r.state = digitalRead(r.pin);;
  }

  Serial.begin(115200);
}

void loop() {
  check();
}

you could also take a full OOP approach

I would put it differently. It depends on whether the rest of the code can tolerate not getting the switch event. Timing out a debounce period does not require blocking the rest of the code.

With switches that are wired correctly and aren't picking up any spurious readings, you won't read a LOW from a switch that wasn't on its way to fully closed, nor HIGH from switch that wasn't on its way to fully open. So you can react virtually instantly to switch events. Important for percussionists, not so much for receptionists.

Looking at the switches frequently and regularly is the way to go as at least one solution above covers. 100 ms will seem sluggish to many. I do have switches where such an eternity woukd be needed, spent too little on some arcade-style pushbutton switches. Try not looking again for 20 ms, that shoukd be plenty.

Not sluggish - unresponsive to another press come too soon.

a7

Yes, I will not delay after every single rocker- instead, delay after all have been checked once per cycle.

Looks like that code double-checks the state of the rocker after a short delay, thereby allowing the code to speed up instead of having a constant delay every cycle?

I will be very honest @alto777 ... I'm not sure what you mean by the second and third paragraphs. Do, in layman's, you mean bouncing is not much of an issue anyway if you scan regularly?

These buttons will initiate a change in a simulated aircraft's state, for instance, landing gear coming down. That takes a full second to register in real life anyway. I'm not too worried about speed.

That is the best policy.

If you control looking at the switches as @LarryD outlines in #13 above, where there is no use of the delay() function, you will get the fastest response to switch events.

If you do as @J-M-L proposes and takes the trouble to demonstrate (THX!), you are always adding 15 ms to the possibility of reacting to an event, and you are stalling the processing for the same period.

As you say, it may not matter. I'm in the end of things where paying attention to odd milliseconds here and there is of value. There is no need for delay(), certainly not in switch debouncing nor its old brother general signal conditioning, where you may have more things going on than contact bounce.

@groundFungus can be depended on to suggest using hardware. I agree and never do, not even when I am in a hurry and just need a damn switch.

Speaking of hardware, something I can be depended on to suggest is using real pull-up resistors of a substantial lower value, like 10K. Just call me old; there was a time when it was always important, instead of just sometimes these days.

a7

1 Like