Controlling LEDS with momentary inputs

Hi,

My apologies if this appears a brainless question. I am trying to get my head round the programming any help is very appreciated.

What I want to do is control the output of 24 LED's using 12 momentary contact toggle switches. Pushing the switch one way will cause the respective LED to light (and stay on) with the other LED associated to that switch going out. The switches are (on)off(on). The other 11 pairs / led groups are to remain in their last state until a new input is given by its respective toggle switch.

The switches are easy to wire with a common center pin which will then give an input to the board dependent on which way the switch is moved.

From the same board I want to run a PWM motor speed controller and a single servo (position from potentiometer).

Any thoughts on elegant code to do this so that will leave it as a standalone unit.

Its probably a really easy thing to do, but right now I'm brain dead!!

Hi, why don't you say what kind of Arduino you have or want to use?

Also, why did you not get ordinary SPDT toggle switches and wire the leds directly to the switches?

These momentary toggle switches: is it likely that two or more will be used at the same instant?

You could read your switches with 10 Arduino digital inputs. Arranged as 6 pairs of switches, 6 digital pins set as outputs would scan the switch pairs and 4 pins set as inputs (with internal pullups) would read the switch states.

It may be possible to reduce this to 7 pins using a technique called charlieplexing, but you would need 24 diodes, and it would be impossible to deal with 2 or more switches activated at once.

Paul

Thanks for your reply.

Its a Mega2560 R3 board.

The switches are DPDT and the second part of each switch triggers an event in a separate circuit' To avoid burning out the other circuitry its a momentary trigger, hence why I dont want to use the switches to set the LED's. Its just an indication as to which side (position) of each switch that was triggered last.

I know I could use flip flop latches to act as my indicator but so that I can learn more about the Arduino, its program setup and capabilities, it would be nice to try to get this to work (It also stops me having to produce a PCB full of logic chips!).

It would only be 1 switch activation at a time and physically its unlikely that inputs would be faster than 1 - 2 seconds apart - never simultaneously.

I am interested in the technique you mentioned - any pointers for me to find further information to help me with my learning my learning curve.

Regards

Kevin

Kevin, do you mean Charlieplexing or the "regular" matrix technique? And if you are using a Mega, do you need to use either?

With charlieplexing, you would organise your switches into 4 groups of 3 switches. Each group of 3 switches would have their 3 centre pins commoned and a diode on each of the remaining 6 switch pins. The common pin connection from each of the 4 groups would each go to 4 different Arduino pins. I said before that 7 Arduino pins would be needed, so 3 more Arduino pins would also be used. The 6 diodes from each group would connect to the other 6 Arduino pins.... its hard to explain and i need to draw a diagram for you when i have time.

The sketch would start out with all 7 Arduino pins set as INPUT_PULLUP. Each group of 3 switches would be scanned in turn by making the Arduino pin connected to that group's common pin OUTPUT & LOW. The other 6 pins would then be read. If any switch in the group was closed, the corresponding input pin would read LOW.

Hi,

I am very much a newbie to Arduino, so I am trying to understand the best ways of working with the device to get the best results. I appreciate there are many different ways to achieve the same end result. My quest is simple - I want to start by learning how to use the device efficiently (code that is small and efficient)

I guess the simplest answer to my problem is to take the 24 inputs from the switch lines direct into the unit. Each input can then go to an output.

My next question is with regards the latching of the output (there seems to be a number of ways to do that)

In simple terms this is what I want (See below) to do for my inputs and outputs. for this example I am only looking at the inputs from two of the switches and outputs on 4 leds.

Inputs

switch a - (two control/ input positions a1 or a2 with logic only going to high momentarily - normally logic 0).

switch b - (two control/ input positions a1 or a2 with logic only going to high momentarily - normally logic 0).

Outputs

led 1
led 2
led 3
led 4

In operation the device starts with all LEDs off.

As each switch is operated it gives a momentary logic high to the input line for that respective switch.

For arguments sake lets say

input pin 2 = switch a1
input pin 3 = switch a2
input pin 4 = switch a3
input pin 5 = switch a4

output pin 7 = led 1
output pin 8 = led 2
output pin 9 = led 3
output pin 10 = led 4

in operation all leds start off

Switch a is operated to trigger switch a1, that should light led 1 (sends output to pin 7 as high,) That should latch and remain on when the input from a1 goes back to 0

Switch a is operated this time to trigger switch a2 - Led 2 should light (pin 8 high and latched) and led 1 should go out.

Switch b is operated, this should light and latch the respective led (either led 3 or led 4 dependant if its a high from b1 or b2) This should not alter the last configuration indicated from switch a (leds 1 and 2).

12 switches / 24 leds with 24 inputs and 24 outputs is of course within the boards logic capability = will I need anything extra as potentially the power consumption of the leds will be somewhere around (20ma x 12) 240 ma / (30ma x12) 360ma - Should I power the leds off a separate supply?

My biggest question is one of code - can any one suggest an elegant way of doing the latched outputs, the cancellation of an output (switch a led off) when an input is received and the latching of the respective output.

There seems many many ways of getting to the same result, but some of the methods use a lot of code. Any suggestions for a "small" way to code this (rather than bloat ware)

Regards

OK, so we are talking about the straight-forward way of using 24 inputs and 24 outputs on the Mega.

I would suggest the use of arrays to hold the pin numbers. Four separate arrays, in fact, each of length 12. Two for the switches, one to hold the pin numbers for the momentary "up" positions, the other for the "down" positions. The other two arrays would hold the pin numbers for the led pins. One for the leds corresponding to the "up" indicators and one for the "down" indicators.

For example:

const byte switch_up[12] = {3,5,7,9,11,13,15,17,19,21,23,25};
const byte switch_down[12] = {2,4,6,8,10,12,14,16,18,20,22,24};
const byte led_up[12] = {26,28,30,32,34,36,38,40,42,44,46,48};
const byte led_down[12] = {27,29,31,33,35,37,39,41,43,45,47,49};

Then you can write a for() loop inside loop() that goes through the array, checks for closed switches and updates the leds.

for (byte i = 0; i < 12; i++) {
  if (digitalRead(switch_up[i]) == LOW) {
    digitalWrite(led_up[i], HIGH);
    digitalWrite(led_down[i], LOW);
  }
  if (digitalRead(switch_down[i]) == LOW) {
    digitalWrite(led_down[i], HIGH);
    digitalWrite(led_up[i], LOW);
  }
}

By the way, if you connect your switch common pins to ground, you can make use of the Arduino's internal pullup resistors and save yourself 24 resistors. When a switch is closed it would read LOW, hence my code suggestion above.

As for latching, the outputs will naturally do that for you, as you can also see from my suggestion above.

360mA for the leds is too close for comfort to the maximum for the Mega chip itself. You will have other components also drawing some current. However, do you really need 20mA per led? You may find they are acceptably bright with 10mA or even 5mA.

"360mA for the leds is too close for comfort to the maximum for the Mega chip itself. "
The Mega chip can switch up to 800mA, with 4 VCC pins each capable of 200mA. I have documented this from Atmel directly.
The current per port limitations do need to be observed per the notes following the table in 31-1:
3. Although each I/O port can sink more than the test conditions (20mA at VCC = 5V, 10mA at VCC = 3V) under steady state conditions (non-transient), the following must be observed:
ATmega640/1280/2560:
1.)The sum of all IOL, for ports J0-J7, A0-A7, G2 should not exceed 200mA.
2.)The sum of all IOL, for ports C0-C7, G0-G1, D0-D7, L0-L7 should not exceed 200mA.
3.)The sum of all IOL, for ports G3-G4, B0-B7, H0-B7 should not exceed 200mA.
4.)The sum of all IOL, for ports E0-E7, G5 should not exceed 100mA.
5.)The sum of all IOL, for ports F0-F7, K0-K7 should not exceed 100mA.
If IOL exceeds the test condition, VOL may exceed the related specification. Pins are not guaranteed to sink current greater than the listed test condition.
4. Although each I/O port can source more than the test conditions (20mA at VCC = 5V, 10mA at VCC = 3V) under steady state conditions (non-transient), the following must be observed:
ATmega640/1280/2560:
1)The sum of all IOH, for ports J0-J7, G2, A0-A7 should not exceed 200mA.
2)The sum of all IOH, for ports C0-C7, G0-G1, D0-D7, L0-L7 should not exceed 200mA.
3)The sum of all IOH, for ports G3-G4, B0-B7, H0-H7 should not exceed 200mA.
4)The sum of all IOH, for ports E0-E7, G5 should not exceed 100mA.
5)The sum of all IOH, for ports F0-F7, K0-K7 should not exceed 100mA.
If IOH exceeds the test condition, VOH may exceed the related specification. Pins are not guaranteed to source current
greater than the listed test condition.

"Thank you for contacting Atmel Technical support.

The 200mA is the absolute maximum current rating of the power supply pin. Whatever may be the power supply voltage (The power supply voltage should be within the specification), the current through the Vcc pin should not exceed 200mA.

Also the 200mA specification under the absolute maximum rating is for individual Vcc pin. And the AVCC pins should not be considered along with the VCC pins for the total absolute maximum rating. Hence, for the device ATmega1284P, for the DIP package, the maximum current rating will be 200mA, whereas for the TQFP package, the max. current rating will be 600mA.

For 328P, the max current rating is 400mA for the TQFP package. For ATmega2560, the max current rating is 800 mA. Also, please note that this is absolute maximum rating and exposing the device to absolute maximum conditions for longer duration of time could possibly cause damage to the device.

Hope this clarifies. Please get back to us in case of further queries.

Best Regards,
Ineyaa N
Atmel Technical Support Team"

OK, so 360mA won't be a problem. I was probably thinking atmega328 limits. Thanks Bob.

Thank you all for that - thats so simple, Paul its brilliant - its easy to think of a complex way of addressing a problem (and over complicating it) its getting to the simple (small code) answer that is very difficult.

I shall breadboard that tonight and see how it goes - its no problem (I shall keep a close eye on the power) to supply the Leds separately as the system has a switched mode power supply with 5 and 12v available.

Thanks crossroads for the input - that again is appreciated

In order to expand my very limited knowledge (as stated I am a newbie to Arduino) I decided to use 123D to simulate the circuit.

Unfortunately they do not have a DPDT (on)off(on) switch in the library so I used momentary push switches instead. I have just used two of the 12 switches required to develop as a working example.

I have declared the variables, I get the following error: error: invalid types 'int[byte {aka unsigned char}]' for array subscript

what am I missing?

int switch_up ;
int switch_down ;
int led_up ;
int led_down ;

 void setup() {

const byte switch_up[2] = {3,5};
const byte switch_down[2] = {2,4};
const byte led_up[2] = {8,10};
const byte led_down[2] = {9,11}; 

}

void loop() {
 for (byte i = 0; i < 2; i++) {
 if (digitalRead(switch_up[i]) == LOW) {
   digitalWrite(led_up[i], HIGH);
   digitalWrite(led_down[i], LOW);
 }
 if (digitalRead(switch_down[i]) == LOW) {
   digitalWrite(led_down[i], HIGH);
   digitalWrite(led_up[i], LOW);
 }
 }
// put your main code here, to run repeatedly:

}

Well, for starters, you are missing code tags. You should always use them when posting code here, as it says in the "read me first" post at the top of each area of the forum, and which new members never seem to bother reading. If you look closely at your post, you can see that it has been corrupted by the forum because you missed the code tags. The array indexes have disappeared and some of the code is in italics. Please edit your post above and put them in!

Try this, but also read it carefully and figure out what you were doing wrong. Ask if unsure.

const byte switch_up[2] = {3,5};
const byte switch_down[2] = {2,4};
const byte led_up[2] = {8,10};
const byte led_down[2] = {9,11}; 

void setup() {
  for (byte i = 0; i < 2; i++) {
    pinMode(switch_up[i], INPUT_PULLUP);
    pinMode(switch_down[i], INPUT_PULLUP);
    pinMode(led_up[i], OUTPUT);
    pinMode(led_down[i], OUTPUT);
  }
}

void loop() {
  for (byte i = 0; i < 2; i++) {
    if (digitalRead(switch_up[i]) == LOW) {
      digitalWrite(led_up[i], HIGH);
      digitalWrite(led_down[i], LOW);
    }
    if (digitalRead(switch_down[i]) == LOW) {
      digitalWrite(led_down[i], HIGH);
      digitalWrite(led_up[i], LOW);
    }
  }
}

Hi Paul

Thanks for that.

I'm struggling, I have now tried your suggested code (I think I understand where I went wrong)

Your latest proposed code came up with a strange error -

#In function 'void loop()':
23:31: error: name lookup of 'i' changed for ISO 'for' scoping [-fpermissive]
23:31: note: (if you use '-fpermissive' G++ will accept your code)

I have tried Google,but that's not helped me much, any pointers to help me move forward? So far your help has moved me a long way forward

Thanks

krc2015:
I decided to use 123D to simulate the circuit.

krc2015:
Your latest proposed code came up with a strange error

Are you still using that simulator? I just compiled my suggested code on Arduino IDE 1.6.5 with no errors or warnings.

Thanks - Yes I have again tried the circuit / program. The good news is that its working well. I have NOidea why it did not run the first time, I reloaded the code and its working fine.

Thank you for your help. My next task is the intergration of the PWM motor control and servo control. Each works well on its own, so now to see how they compile with all three elements running at the same time

Regards