LED Strip, Wave Code Help

We are trying to make a strip of LED lights make a wave motion (one bulb at a time) to the left when one button is pushed and to the right when another button is pushed. We only want the wave to happen one time per button press. This might be simple but we're really new to using Arduino. Let me know if you have any suggestions for this code:

int switchPin1 = 8;
int switchPin2 = 9;
int led1 = 10;
int led2 = 11;
int led3 = 12;
int led4 = 13;

void setup() {
pinMode(switchPin1, INPUT);
pinMode(switchPin2, INPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);

}

void loop() {

if (digitalRead(switchPin1) == HIGH && digitalRead(switchPin2) == LOW)
{digitalWrite(led1, HIGH);
delay(1000);
digitalWrite(led1, LOW);
digitalWrite(led2, HIGH);
delay(1000);
digitalWrite(led2, LOW);
digitalWrite(led3, HIGH);
delay(1000);
digitalWrite(led3, LOW);
digitalWrite(led4, HIGH);
delay(1000)
digitalWrite(led4, LOW);
end}

if (digitalRead(switchPin2) == HIGH && digitalRead(switchPin1) == LOW)
{digitalWrite(led4, HIGH);
delay(1000);
digitalWrite(led4, LOW);
digitalWrite(led3, HIGH);
delay(1000);
digitalWrite(led3, LOW);
digitalWrite(led2, HIGH);
delay(1000);
digitalWrite(led2, LOW);
digitalWrite(led1, HIGH);
delay(1000)
digitalWrite(led1, LOW);
end}

else
{digitalWrite(led1, led2, led3, led4, LOW)}

}

Thanks for the help!

Hi, this sounds very similar indeed to another recent question on this forum. Is it a College assignment?

When posting code on this forum you should use code tags. Please edit your original post and put them in.

This line

digitalWrite(led1, led2, led3, led4, LOW)

won't work, may not even compile. Change it to 4 separate digitalWrite() as you have done in other places.

You asked for suggestions.

  1. Remove the delay() functions and use millis() to time switching the switching of the leds. This will allow immediate response to button presses.

  2. Use an array to hold the led pin numbers. This will enable you to rewrite your code to be shorter and less repetitive.

  3. Use variables to record the position of the led that is lit at any instant and the current direction of movement.

Paul

if (digitalRead(switchPin1) == HIGH && digitalRead(switchPin2) == LOW)The lines like this are checking whether the switches ARE HIGH or LOW not whether they have BECOME HIGH or LOW (ies have just been pressed)

Look at the StateChangeDetection example in the IDE to see how to determine when a switch becomes pressed.

Yes, you are right, because the request was

We only want the wave to happen one time per button press.

Otherwise if the button was still held down when the wave sequence had completed, it would immediately start again.

Here's the deal.

If the OP returns, I will give him code.

{Given 24 hours or so.}

Paul__B:
Here's the deal... I will give him code.

You came over as a bit bossy there, Paul.

click learning and press examples then you search for arrays and then you'll find the circuit of it and the code

PaulRB:
You came over as a bit bossy there, Paul.

I though I was being rather generous.

Anyway, he seems to be a "one-hit wonder". :frowning:

Hey! I'm back.

Thanks everyone for posting.

PaulRB can you still help me out?

OK, so if I read this correctly, you want one wave to travel across in one direction each time you press a button.

And I gather that the terminal condition is all LEDs OFF.

OK, here is my basic button-and LED code:

// Blink without "delay()" - multi!

const int led1Pin =  13;    // LED pin number
const int led2Pin =  10;
const int led3Pin =  11;
const int button1 =  4;
int led1State = LOW;        // initialise the LED
int led2State = LOW;
int led3State = LOW;
char bstate1 = 0;
unsigned long count1 = 0;   // will store last time LED was updated
unsigned long count2 = 0;
unsigned long count3 = 0;
unsigned long bcount1 = 0; // button debounce timer.  Replicate as necessary.

// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check 
boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) { 
    *marker += interval;    // move on ready for next interval
    return true;       
  } 
  else return false;
}

// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {               // Odd states if was pressed, >= 2 if debounce in progress
  case 0: // Button up so far, 
    if (button == HIGH) return false; // Nothing happening!
    else { 
      *butnstate = 2;                 // record that is now pressed
      *marker = millis();             // note when was pressed
      return false;                   // and move on
    }

  case 1: // Button down so far, 
    if (button == LOW) return false; // Nothing happening!
    else { 
      *butnstate = 3;                 // record that is now released
      *marker = millis();             // note when was released
      return false;                   // and move on
    }

  case 2: // Button was up, now down.
    if (button == HIGH) {
      *butnstate = 0;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 1;               // jackpot!  update the state
        return true;                  // because we have the desired event!
      }
      else 
        return false;                 // not done yet; just move on
    }

  case 3: // Button was down, now up.
    if (button == LOW) {
      *butnstate = 1;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 0;               // Debounced; update the state
        return false;                 // but it is not the event we want
      }
      else 
        return false;                 // not done yet; just move on
    }
  default:                            // Error; recover anyway
    {  
      *butnstate = 0;
      return false;                   // Definitely false!
    }
  }
}

void setup() {
  pinMode(led1Pin, OUTPUT);      
  pinMode(led2Pin, OUTPUT);      
  pinMode(led3Pin, OUTPUT);      
  pinMode(button1, INPUT);      
  digitalWrite(button1,HIGH);        // internal pullup all versions
}

void loop() {
  // Toggle LED if button debounced
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
    if (led1State == LOW) {
      led1State = HIGH;
    }
    else {
      led1State = LOW; 
    } 
    digitalWrite(led1Pin, led1State);
  } 

  // Act if the latter time (ms) has now passed on this particular counter,
  if (timeout(&count2, 300UL )) {
    if (led2State == LOW) {
      led2State = HIGH;
    }
    else {
      led2State = LOW; 
    } 
    digitalWrite(led2Pin, led2State);
  } 

  if (timeout(&count3, 77UL )) {
    if (led3State == LOW) {
      led3State = HIGH;
    }
    else {
      led3State = LOW; 
    } 
    digitalWrite(led3Pin, led3State);
  } 
}

You may care to adapt it to your circuit and try it out. While it does not do what you presently want, it contains all the core functions necessary to do so, which I will look into later. Sadly - perhaps - I have to go to work just now. :grinning:

In the meantime for clarity, can I ask you to go back to your first post, select "modify", selectively highlight the code section and use the little "scroll" icon with the brackets to mark that as code?

Thanks for the help guys. I was the one who made the similar forum post about a week or so ago. I am working with ebax on a college project yes. I think there is a little bit of confusion on what we are doing. We understand how to do this now with LEDS as separate outputs. Although, we want to have this effect for a addressable LED 5M long strip (WS2810). So therefore would only have one pin output. I have a code that I have been working on I will post in a little bit. We are using the adafruit Neopixel library. We are confused on some of the syntax and oddly couldn't find a good enough example to help explain it. Thanks for explaining the switch code Paul_B. i will be looking at this forum all day so shoot over any questions that would help you help me. Unfortunately our LEDs will come in about a week so we cannot test yet.

ws2812****

#include<Adafruit_NeoPixel.h>
#include<avr/power.h>
#define BUTTON_PIN 2
#define PIN 6
#define NUMPIXELS 30


bool oldState = HIGH;
int showType = 0;
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}


void loop() {
// Get current button state.
bool newState = digitalRead(BUTTON_PIN);
// Check if state changed from high to low (button press).
if (newState == LOW && oldState == HIGH) 
{Short delay to debounce button.
delay(20);
// Check if button is still low after debounce.
newState = digitalRead(BUTTON_PIN);
if (newState == LOW) {
showType++;
if (showType > 1)
showType=0;
startShow(showType);
 }
}
// Set the last button state to the old state.
oldState = newState;
}

void startShow(int i) {
switch(i){
strip.show()
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS,PIN,NEO_GRB+NEO_KHZ800);
int delayval = 500
void loop() {
  for(int=0, i<NUMPIXELS: i++) 
 pixels.setPixelColor(i, pixels.Color(0,0,255); 
pixels.show(); 
delay(delayval);
 }
}
}

OK, (Yawn! - after midnight!) here is your code:

// Sweep and back using button toggle with extreme reliability!

const int ledpins[4] = {
  10, 11, 12, 13};
const int led13 =  13;    // Diagnostic LED pin number
const int buttons[2] =  {
  8, 9};

char bstates[2] = {
  0, 0};
unsigned long bcount[2] = {
  0, 0}; // button debounce timers.  Replicate as necessary.
unsigned long ledcount;

char sweeper;                         // State switch for sweep and direction
char kitt;                            // Sweep position

// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check
// Routines by Paul__B of Arduino Forum
boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) { 
    *marker += interval;    // move on ready for next interval
    return true;       
  } 
  else return false;
}

// Initialise timeout
void timein(unsigned long *marker, unsigned long interval) {
  *marker = (millis());
}

// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
// Routines by Paul__B of Arduino Forum
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {               // Odd states if was pressed, >= 2 if debounce in progress
  case 0: // Button up so far, 
    if (button == HIGH) return false; // Nothing happening!
    else { 
      *butnstate = 2;                 // record that is now pressed
      *marker = millis();             // note when was pressed
      return false;                   // and move on
    }

  case 1: // Button down so far, 
    if (button == LOW) return false; // Nothing happening!
    else { 
      *butnstate = 3;                 // record that is now released
      *marker = millis();             // note when was released
      return false;                   // and move on
    }

  case 2: // Button was up, now down.
    if (button == HIGH) {
      *butnstate = 0;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 1;               // jackpot!  update the state
        return true;                  // because we have the desired event!
      }
      else 
        return false;                 // not done yet; just move on
    }

  case 3: // Button was down, now up.
    if (button == LOW) {
      *butnstate = 1;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 0;               // Debounced; update the state
        return false;                 // but it is not the event we want
      }
      else 
        return false;                 // not done yet; just move on
    }
  default:                            // Error; recover anyway
    {  
      *butnstate = 0;
      return false;                   // Definitely false!
    }
  }
}

void setup() {
  for (int i=0; i < 4; i++) { 
    pinMode(ledpins[i], OUTPUT); 
    digitalWrite(ledpins[i], LOW); // All LEDs OFF
  }
  for (int i=0; i < 2; i++) { 
    pinMode(buttons[i], INPUT);      
    digitalWrite(buttons[i],HIGH); // internal pullup all versions
  }
  sweeper = 0;
}

void loop() {
  switch (sweeper) {
  case 0:
    if (butndown(digitalRead(buttons[0]), &bcount[0], &bstates[0], 10UL )) { // Sweep up
      sweeper = 1; 
      kitt = 0; 
      timein(&ledcount, 1000UL);  
      digitalWrite(ledpins[kitt], HIGH);
    }
    else if (butndown(digitalRead(buttons[1]), &bcount[1], &bstates[1], 10UL )) { // Sweep down
      sweeper = 2;
      kitt = 3; 
      timein(&ledcount, 1000UL);  
      digitalWrite(ledpins[kitt], HIGH);
    }
    break;
  case 1:
    if (timeout(&ledcount, 1000UL)) {
      digitalWrite(ledpins[kitt], LOW);
      if (++kitt == 4) sweeper = 0;
      else digitalWrite(ledpins[kitt], HIGH);
    }
    break;
  case 2:
    if (timeout(&ledcount, 1000UL)) {
      digitalWrite(ledpins[kitt], LOW);
      if (kitt-- == 0) sweeper = 0;
      else digitalWrite(ledpins[kitt], HIGH);
    }
    break;
  default:
    sweeper = 0;
  }
}

mwer4c:
I think there is a little bit of confusion on what we are doing. We understand how to do this now with LEDS as separate outputs.

Well, you could have explained that earlier!