Multi-way Switch Advice

Hello everyone!

I'm actually quite new to Arduino's and have been tinkering with a starter kit I purchased recently. I wanted to build a device for class that would reflect what we're learning currently, which is matrices. We had an example from the book that worked like this, and I want to recreate it:

There are five switches (let's just call them A, B, C, D, E, F) that correspond to five LEDs (L1, L2, L3, L4, L5). Whenever a switch is hit, the corresponding LED and any of its adjacent lights will either turn on or off. So, for example, initially all lights will be off.

From here, if I were to hit Switch B, L2 will turn on along with adjacent lights L1 & L3.
After that, let's say I hit Switch D, then L4 will turn on along with L5 and L3 will turn off.
Finally, if I'm to hit Switch E, L5 switches on and L4 switches off (only two lights are affected in Switch A and Switch E cases, as they have only one adjacent light instead of two).

If anyone is familiar with matrices, an easier way to describe it I think would be to represent the effects of each switch as such:

L1 L2 L3 L4 L5
A= [ 1 1 0 0 0 ]
B= [ 1 1 1 0 0 ]
C= [ 0 1 1 1 0 ]
D= [ 0 0 1 1 1 ]
E= [ 0 0 0 1 1 ]

Where each number will correspond to an on/off action.

Would anyone know how I should set this up and with what parts?

Thank you very much!

You very quickly run out of pins with that many LED outputs. You've already got 16 LEDs in the simple matrix and that's not even counting the 8 input switches. You also run out of current - the Arduino can't drive that many LEDs at full power.

There are a number of solutions but my favourite is the MAX7219. It is able to drive large numbers of LEDs with the correct current and it only uses a couple of Arduino pins. It's available as a through-hole DIP chip that will go into a breadboard.

Switches can be basically any switches. "Tac switches" are the simplest. You could put a bunch of them on a perfboard or veroboard prototype very easily. Bend the pins a little to fit the standard 0.1" hole spacing.

I know you have drawn a grid in your Original Post but your description leads me to think you only plan to have 5 LEDs in a line. If that is the case it could easily be managed on an Uno. One pin for each LED and one pin for each of 5 switches. Note that the analog pins can also be used as normal digital pins.

Continuing the assumption that there are only 5 LEDs ...

I suggest you make a two dimensioned array - one row corresponding to each switch and on that row store the pin numbers of the LEDs to be lit when that switch is pressed. Something like

byte ledSelect[5][3] = {{1,2,3}, {3,4,5}, ....  }

Remember that a 5 element array is addressed 0-4

...R

ronikun:
Would anyone know how I should set this up and with what parts?

5 buttons and 5 LEDs = 10 pins total, try an Arduino UNO, plus:

  • 5 buttons
  • 5 low-power (20mA) LEDs
  • 5 resistors (depends on LED color and current you want, i.e. 330 Ohm should fit for any color)
  • 1 breadboard (or custom made PCB)
  • cables
  • case (if needed)

And of course a sketch that does what you want.

I apologize, guys! I think that I didn't explain it right with the matrix bit. Each line was only meant to represent the action of each light. Each new line is not a separate set of lights--it's the same set of lights, but with different actions. So, for example, if we hit the button C in the example, the first (0) means that L1 is unchanged, second number (1) means L2 goes on, third number (1) means L3 goes on, fourth number (1) means L4 goes on, fifth number (0) means L5 is unchanged. And then from there on, hitting a letter would mean that the lights would change from the configuration of lights above based on the letter of the switch hit. Sorry if it's kind of confusing, I should have clarified.

Beyond that, though, so something like this would be possible without the use of relays? I'm worried because each light will be controlled by more than a single button, and each button will control more than a single light. In a case like that, is a relay needed (don't have one at the moment, and other than ordering online, it's pretty impossible to get it where I live)?

I do actually have an Arduino Uno R3 kit that I've purchased already, but that took over a month to arrive where I live, even with the expedited shipping. So I'm worried that if I lack parts and try to order them, they'll only arrive long after the semester is over.

Thanks a lot for the insight, by the way! Again, still relatively new to this Arduino stuff.

ronikun:
I do actually have an Arduino Uno R3 kit that I've purchased already, but that took over a month to arrive where I live, even with the expedited shipping. So I'm worried that if I lack parts and try to order them, they'll only arrive long after the semester is over.

An Arduino UNO R3, 5 buttons, 5 LEDs, 5 resistors (330 Ohm or similar), a breadboard and a few cables is all you need to create your circuit.

No relays or transistors or external power supply needed, except you want to switch real "power LEDs", powered 1 Watt each (or more like 240V AC / 100 Watt LED floodlights).

The sketch is easy.
If you need one "ready made", I can create and post one accordingly to your description above.
Just let me know.

ronikun:
I'm worried because each light will be controlled by more than a single button, and each button will control more than a single light.

This is a trivial issue for an Arduino.

For any particular input your code can get any set of LEDs to light.

Don't think of any direct connection between buttons and lights. Think of it as two processes. One process reads the buttons and saves the number of the button that is pressed. The other process looks at the saved value and switches on the appropriate LEDs. The only connection between the two processes is the saved number.

...R

jurs:
An Arduino UNO R3, 5 buttons, 5 LEDs, 5 resistors (330 Ohm or similar), a breadboard and a few cables is all you need to create your circuit.

No relays or transistors or external power supply needed, except you want to switch real "power LEDs", powered 1 Watt each (or more like 240V AC / 100 Watt LED floodlights).

The sketch is easy.
If you need one "ready made", I can create and post one accordingly to your description above.
Just let me know.

Thanks for that! Maybe not the entire set-up, but would you be able to show me the way a simple three way switch would work with just one LED?

Robin2:
This is a trivial issue for an Arduino.

For any particular input your code can get any set of LEDs to light.

Don't think of any direct connection between buttons and lights. Think of it as two processes. One process reads the buttons and saves the number of the button that is pressed. The other process looks at the saved value and switches on the appropriate LEDs. The only connection between the two processes is the saved number.

...R

Thanks a lot for this! That explanation makes things way easier to understand.

ronikun:
Thanks for that! Maybe not the entire set-up, but would you be able to show me the way a simple three way switch would work with just one LED?

It's nearly the same work and programming logic for one button as for five buttons.
Three way switch?

As far as I have understood you are using simple momentary switches as buttons.

This toggle logic is implementing what I have understood from your description,
please change pin numbers in the two arrays as you need it:

const byte ledPins[]={8,9,10,11,12};
#define NUMLEDS sizeof(ledPins)
const byte buttonPins[]={3,4,5,6,7};
#define NUMBUTTONS NUMLEDS
#define INPUTMODE INPUT_PULLUP
#define BOUNCETIME 10
boolean buttonPressed[NUMBUTTONS];


void updateButtons(){
  static uint16_t lastState;
  long nowMillis=millis(); // read the current time
  // read the input state and state changes of all buttons
  static unsigned long lastButtonTime; // time stamp for remembering the time when the button states were last read
  memset(buttonPressed,0,sizeof(buttonPressed)); // clear pressed state of all buttons
  if (nowMillis-lastButtonTime<BOUNCETIME) return;  // within bounce time: leave the function
  lastButtonTime=nowMillis; // remember the current time
  for (int i=0;i<NUMBUTTONS;i++) 
  {
    byte curState=digitalRead(buttonPins[i]);        // current button state
    if (INPUTMODE==INPUT_PULLUP) curState=!curState; // logic is inverted with INPUT_PULLUP
    if (curState!=bitRead(lastState,i))              // state change detected
    {
      if (curState==HIGH) buttonPressed[i]=true;
      bitWrite(lastState, i, curState); 
    }
  }
}

void togglePinState(int pin)
{ // read pin state, invert state and write inverted state back to same pin
  digitalWrite(pin, !digitalRead(pin));
}

void toggleLED(int index)
{ // toggles LED and neighbor LEDs
  togglePinState(ledPins[index]); // togggle LED for corresponding button
  if (index>0) togglePinState(ledPins[index-1]); // toggle LED left
  if (index<NUMLEDS-1) togglePinState(ledPins[index+1]); // toggle LED right
}

void serialDebug()
{ // show state of all LEDs on serial monitor
  for (int i=0; i<NUMLEDS; i++) Serial.print(digitalRead(ledPins[i]));
  Serial.println();
}


void setup()
{
  Serial.begin(9600); // just for serial debugging
  for (int i=0; i<NUMLEDS; i++)
  {
    pinMode(buttonPins[i], INPUTMODE);
    pinMode(ledPins[i], OUTPUT);
  }
}

void loop()
{
  updateButtons();
  for (int i=0; i<NUMBUTTONS; i++)
  {
    if (buttonPressed[i]) 
    {
      toggleLED(i);
      serialDebug();
    }
  }
}

The buttons are to be connected between GND and their buttonPins.

Please let me know if this is what you wanted!

ronikun:
There are five switches (let's just call them A, B, C, D, E, F)

Ahem! :astonished:

jurs:
Please let me know if this is what you wanted!

Thanks a lot for the time you put into this! Looking at it, I don't think I ever could have arrived at something like this. However, I did try running it, and for some reason, I can't get it to work properly. Pushing some buttons turns some on, pushing others doesn't. I think it may have to do with the way I wired it? The way I have it right now is with pins 3, 4, 5, 6, 7 going to a breadboard where they each meet their respective button, and then each button leads to ground. I have a similar set up with the LEDs coming from 8, 9, 10, 11, 12; but those just include resistors before heading to ground. Should I have set it up differently?

Paul__B:
Ahem! :astonished:

Loool, I'm an idiot, I can't believe I hadn't caught that.

Check your wiring. It's easy to get an LED backwards.

Check the debug output. Is it detecting a button and then failing or is the button faulty?

ronikun:
The way I have it right now is with pins 3, 4, 5, 6, 7 going to a breadboard where they each meet their respective button, and then each button leads to ground. I have a similar set up with the LEDs coming from 8, 9, 10, 11, 12; but those just include resistors before heading to ground. Should I have set it up differently?

The description of the wiring is correct.

The D in LED stands for "diode", so watch out for correct polarity of that diodes, if some of them won't light up!

And watch out for the output in the serial monitor, I have provided serial debugging in the sketch.

For example:

  • load program
  • open the serial monitor
  • press each button one time, from left to right
  • output you see in the serial monitor by doing so? Copy and paste it here!

jurs:
The description of the wiring is correct.

The D in LED stands for "diode", so watch out for correct polarity of that diodes, if some of them won't light up!

And watch out for the output in the serial monitor, I have provided serial debugging in the sketch.

For example:

  • load program
  • open the serial monitor
  • press each button one time, from left to right
  • output you see in the serial monitor by doing so? Copy and paste it here!

I'm actually coming across something quite strange at this point... The shorter cathode of the LED should be the one leading to ground, right? When I set it up that way, I hit the buttons and get absolutely no response in the Serial Monitor. No lights will light up either..

I then tried the other way with the anode hitting ground just to test as it's kind of late over here and I thought that I might have not properly seen them, and I get the proper configurations for the sequence of the status based on buttons pressed in the Serial Monitor (in order of A, B, C, D, E):

11000
00100
01010
01101
01110

However, the LEDs only give off very dull light that don't stay on (and don't follow the proper configuration anyway from what I can see).

In the middle of me switching back to the anode-to-ground set-up, that's when lights actually came on. However, only some were coming up properly in the Serial Monitor, and though the lights would light up and stay on, they didn't match the Serial Monitor anyway.

Sorry if this is all a bit of a mess, but for the life of me, I can't figure it out..

ronikun:
I'm actually coming across something quite strange at this point... The shorter anode of the LED should be the one leading to ground, right?

That's not strange, that's always the correct wiring:
LED long wire = Anode = positive voltage
LED short wire = Cathode = GND

ronikun:
When I set it up that way, I hit the buttons and get absolutely no response in the Serial Monitor. No lights will light up either..

RED ALERT! You possibly created a short circuit!
Better double-check the pins and the wiring!

ronikun:
I then tried the other way with the cathode hitting ground just to test as it's kind of late over here and I thought that I might have not properly seen them, and I get the proper configurations for the sequence of the status based on buttons pressed in the Serial Monitor (in order of A, B, C, D, E):

So if none of the LEDs is powered, the serial monitor shows some output?
LED wiring is wrong!

ronikun:
11000 // correct toggle for 1st button
00100 // correct toggle for 2nd button
01010 // correct toggle for 3rd button
01101 // correct toggle for 4th button
01110 // correct toggle for 5th button

So all the buttons seem to work correctly and I state, that the buttons are wired correctly.

But the LEDs seem to create a short circuit and have wrong wiring.
With a correct wiring, the LED states should correspond to:
0 - LED OFF
1 - LED ON

BTW: Your "starter kit" only contains LEDs that create visible light, such as red, yellow, green, blue or white?

Or maybe you used LEDs that create "invisible" light, like IR LEDs (infrared) and UV LEDs (ultraviolet)? The human eye cannot see the wave lengths of IR or UV LEDs.

jurs:
So all the buttons seem to work correctly and I state, that the buttons are wired correctly.

But the LEDs seem to create a short circuit and have wrong wiring.
With a correct wiring, the LED states should correspond to:
0 - LED OFF
1 - LED ON

BTW: Your "starter kit" only contains LEDs that create visible light, such as red, yellow, green, blue or white?

Or maybe you used LEDs that create "invisible" light, like IR LEDs (infrared) and UV LEDs (ultraviolet)? The human eye cannot see the wave lengths of IR or UV LEDs.

I'm not quite sure what the issue may be then. So, for the LED pins, it's 8, 9, 10, 11, 12 that go to the breadboard. Each wire meets a 330 ohm resistor, then leads to the LEDs' longer leg and the shorter leg to the ground on the breadboard. Is there something I should change here?

As for the LEDs, they do emit visible light. I was able to get each of them to light up on their own out of this kind of circuit.

ronikun:
I'm not quite sure what the issue may be then. So, for the LED pins, it's 8, 9, 10, 11, 12 that go to the breadboard. Each wire meets a 330 ohm resistor, then leads to the LEDs' longer leg and the shorter leg to the ground on the breadboard. Is there something I should change here?

I tried to create a Fritzing drawing with an UNO, breadboard, buttons, resistors, LEDs and all the wire connections.

Hopefully this is it.

Edit 03/12/2015: Unfortunately, no feedback in any way.
I really don't know why I'm doing circuit drawings elaborately, which takes me some time, if I don't even get any feedback then, after posting the drawing, whether it was helpful and could solve the problem, or not.