1

Imagine a strip of LEDs with O being HIGH and X being LOW.

X O X O X

Now if I pressed the button below the second O and wanted it to switch the last two LEDs (4th one to LOW and 5th to HIGH or any opposite value of what it was), but if I pressed the first X wanted it to switch that one HIGH, the second one LOW, and the third HIGH.

I want to continue this type of pattern where each button press will result in two or three of the LEDs changing their effective state.

How might I achieve this? I have researched using the modulo function and can only get it to work every other click of a button. I have also tried using a pullup function and couldn't get it to work at all.

Can someone please just point me in the right direction?

2
  • 1
    Show your work please :)
    – Mazaryk
    May 6, 2017 at 5:02
  • I am working on it still. So far I can get one to change and when I work on a second button it changes the first back to the original state. May 6, 2017 at 5:46

2 Answers 2

0

I want to continue this type of pattern where each button press will result in two or three of the LEDs changing their effective state.

I'll assume there are nLED LEDs and buttons, and that the buttons are momentary buttons and need debouncing. I presume you have one button beneath each LED, numbered say 0 to nLED-1, and that the two or three LEDs that will change when button k is pressed have numbers k, k+1, and possibly k+2.

To simplify the coding, create an array (or a bit map), say Lsts, with nLED entries, to represent the current state of LEDs, and a similar array, say Bsts for button statuses, and an array of bytes bounce to track debouncing status.

On each pass through loop(), use a for loop to read each eligible switch. A switch with a nonzero bounce entry is debouncing and doesn't get read. If a switch is read and it changes, update the LED statuses in Lsts and at ports. For example:

enum { nLED=5, debouncePasses=50 };
byte Lsts[nLED]={0}, Bsts[nLED]={1,1,1,1,1}, bounce[nLED]={0};
const byte Lpins[nLED] = { 3,4,5,6,7 };
const byte Bpins[nLED] = { 8,9,10,11,12 };
//... etc

void setup() {
  for (byte i=0; i<nLED; ++i) {
    pinMode(Lpins[i], OUTPUT);
    // Buttons will have negative logic, hi for open, lo for pressed
    pinMode(Bpins[i], INPUT_PULLUP);
  }
  // ... any other initialization ...
}
void loop() {
  for (byte i=0; i<nLED; ++i) {
    // See if button is eligible for reading, and if it changed
    if (bounce[i]) {
      --bounce[i]; // Decrease bounce pass counter
    } else {
      if (digitalRead(Bpins[i]) != Bsts[i]){
        // Yes,  it's eligible and it changed
        bounce[i] = debouncePasses; // Set button's debounce counter
        if (Bsts[i]) { // Test if switch was pressed vs released
          // Toggle the button's light and the next one or two lights
          for (int j=i; j<nLED && j<i+3; ++j) {
            Lsts[j] = !Lsts[j];
            digitalWrite(Lpins[j], Lsts[j]);
          }
        }
        Bsts[i] = !Bsts[i]; // Toggle button state  
      }
    }
  }
  // ... any other stuff
  delayMicroseconds(500); // Delay for bounce-pass timing
  // alternately, instead of delayMicroseconds, sleep until timer tick
}

Edit 1: If there are more LEDs than buttons, then use separate constants for the counts, adjust the initializations, etc. For example:

enum { nButton=5, nLED=6, debouncePasses=50 };
byte Lsts[nLED] ={1,0,1,0,1,0};
byte Bsts[nButton]={1,1,1,1,1}, bounce[nLED]={0};

//... etc

void setup() {
  for (byte i=0; i<nLED; ++i) {
    pinMode(Lpins[i], OUTPUT);
    digitalWrite(Lpins[i], Lsts[i]);
  }
  // Buttons will have negative logic, hi for open, lo for pressed
  for (byte i=0; i<nButton; ++i) {
    pinMode(Bpins[i], INPUT_PULLUP);
  }
  // ... any other initialization ...
}

In loop(), change the initial for from for (byte i=0; i<nLED; ++i) to for (byte i=0; i<nButton; ++i). This will work ok if there is an extra LEDs after the LEDs that line up with buttons.


Edit 2:

Why when using an array doesn't the arduino recognize the HIGH or LOW state of an led? I tried adding this simple code:
if (42 && 44 && 46 && 48 && 50 == HIGH){
digitalWrite (ledWin, LOW); } else {digitalWrite (ledWin, HIGH);}

Evidently you want to test if all the LEDs are on, and apparently the numbers 42, 44, ... 50 are supposed to somehow represent LED states.

However, numbers like 42, 44, ... are constant values and cannot properly represent the value of something that varies. The condition in that if statement will always evaluate to the same value, false, as follows.

According to the C/C++ standard, a condition like 42 && 44 && 46 && 48 && 50 == HIGH consisting of a series of terms separated by && operators will be evaluated left to right until either one is false (making the whole expression false) or all are true (making it true). (For example, see the Remarks section of Logical AND Operator: &&.)

In this case, 42 is non-zero, hence true. Next, 44 is true, 46 is true, and 48 is true. But 50 == HIGH is false – the value of HIGH is 1, and 50 is not equal to 1. Therefore the whole expression is false.

A better approach to finding out if all the LEDs are on or off is to test the values of Lsts[] entries. For example, you could add them up, and then see if the sum is equal to 0 (all off) or equal to nLED (all on):

byte nOn = 0;
for (byte i=0; i<nLED; ++i) nOn += Lsts[i];
digitalWrite (ledWin, nOn < nLED);

That will set the ledWin pin if not all of the LEDs are on, else will clear it.

4
  • Can an array be declared as something else later in a sketch? ie; When Lsts[nLED]= {1,1,1,1,1}, can that be used to set one additional pin to a high state rather than declaring new variable for the same purpose? May 6, 2017 at 7:45
  • @upstartlilevil, yes, you could treat an extra LED and LED initialization as shown in edit 1 of answer. However, re “Can an array be declared as something else later in a sketch?”, it can be used as something else (which can make code difficult to understand and maintain) but cannot be re-declared as something else in the same scope as the original declaration. Note, if the additional pin gets treated about the same as other LED pins, it makes sense to handle it via the loops and code for other LED pins; but if it's treated differently, just set up a simple var for it. May 6, 2017 at 14:52
  • @jwpat7 I understand how to do that and had actually already made it 5 buttons and 6 leds, I want a "prize" so my kids can see that when they get it correct something happens, a green led comes on and a relay for a magnet release a matchbox car down a track or something like that. Adding an led in this way just makes it an additional led. My question is then; Why when using an array doesn't the arduino recognize the HIGH or LOW state of an led? I tried adding this simple code: <br> if (42 && 44 && 46 && 48 && 50 == HIGH){ digitalWrite (ledWin, LOW); }else{digitalWrite (ledWin, HIGH);} May 6, 2017 at 17:05
  • @upstartlilevil, see edit 2 May 6, 2017 at 18:33
0

Can someone please just point me in the right direction?

what is "right" is highly subjective. I would consider a good solution to be one where the functionalities desired is broken down into natural modules that are then integrated to perform the desired functions. By that (highly subjective) standard, the solution posted earlier would be a poor one -> due to its tightly coupled / inter-mingled approach.

if I were to take a shot at this, I would consider the implementation below:

  key_state = read_keys(); //read keys / buttons, with or without debouncing
  led_process(key_state);  //process the key_state, and light up / off leds based on key_state

Essentially, you scan the keys / buttons, and based on that, turn on / off the leds.

All you need to do after that is to implement the individual functions based on your particular hardware design, or even software approaches: for example, read_keys() can be implemented in the isr, as can led_process().

A solution like this is highly portable: it works on pretty much anything that supports a C compiler, and is implementation-independent: the logic holds true, and all you do is to change the two functions to perform different kinds of lighting.

To me, modulizing your code is a huge advantage for a high-level language like C, and vital in taking on a real life project of moderate complexity.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.