Making a sequence of fading leds with a button

I've been trying to create a sequence of LEDs that will fade then one they fade will move to the next and repeat the process. it's activated by pressing the button and will reverse the sequence once the button is released. I've been trying to use different types of code but I'm not really experienced with coding and I ask the community for help. Anything I can use or do to achieve this? also I'm trying to go after the power system in Astroneer.

Welcome.

Show us a good schematic of your proposed circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.


In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.

Use the </> icon from the ‘reply menu’ to attach the copied sketch.

You can also do all of this virtually: https://wokwi.com/

when you write the LED should fade, does that mean that it should smoothly increase brightness?
What should happen with the first LED when the second LED starts "fading"? Will the first LED remain on in full brightness?

A class like this would fade LEDs. I wrote it as non-blocking so you could still reliably read a button press while it's running. I guess you could use an array of these FadingLEDs and switch to the next element of the array when the current led's atMax() returns true ? I also added a turnOff() that might be helpful.

class FadingLED {
  public:
    byte pin;
    byte brightness = 0;
    byte targetMin = 0;
    byte targetMax = 255;
    int8_t adjustment = -1;
    uint32_t updateFreq = 5;
    uint32_t timeCapture;

    void update() {
      if ((millis() - timeCapture) >= updateFreq) {
        timeCapture = millis();
        if (atMax() || atMin())
          adjustment *= -1;
        analogWrite(pin, brightness += adjustment);
      }
    }

    bool atMax() { return brightness >= targetMax; }
    bool atMin() { return brightness <= targetMin; }
    void turnOff() { analogWrite(pin, brightness = 0); }

    FadingLED(byte pin) 
    : pin(pin) { pinMode(pin, OUTPUT); }
};

FadingLED led(13);

void setup() {
}

void loop() {
  led.update();
}

Might not be the best way to approach this, but it's a nice start for you!

Technically, this is bad. You can't call arduino functions inside your constructor since there is no guarantee of the state of the system when called. That is why many, many libraries have a .begin() function since that gets called in setup() after all initialization is complete.

You are right, although I've not had any issues with it myself so far :smiley:

Easy fix:

class FadingLED {
  public:
    byte pin;
    byte brightness = 0;
    byte targetMin = 0;
    byte targetMax = 255;
    int8_t adjustment = -1;
    uint32_t updateFreq = 5;
    uint32_t timeCapture;

    void update() {
      if ((millis() - timeCapture) >= updateFreq) {
        timeCapture = millis();
        if (atMax() || atMin())
          adjustment *= -1;
        analogWrite(pin, brightness += adjustment);
      }
    }

    bool atMax() { return brightness >= targetMax; }
    bool atMin() { return brightness <= targetMin; }
    void turnOff() { analogWrite(pin, brightness = 0); }
    void begin() { pinMode(pin, OUTPUT); }

    FadingLED(byte pin) 
    : pin(pin) { }
};

FadingLED led(13);

void setup() {
  led.begin();
}

void loop() {
  led.update();
}

the idea is that as long as the button is held
the first led will fade until it shuts off then the next will fade then the third. when the button is released the opposite will happen from the other side or wherever the fade stopped.

#define BTN_PIN 7
#define NUM_LEDS 4

class FadingLED {
  public:
    byte pin;
    int16_t brightness = 0;
    int16_t targetMin = 0;
    int16_t targetMax = 255;
    int16_t adjustment = 3;
    uint32_t updateFreq = 5;
    uint32_t timeCapture;

    void fadeUp() {
      if (!atMax() && (millis() - timeCapture) >= updateFreq) {
        timeCapture = millis();
        if ((brightness += adjustment) > targetMax)
          brightness = targetMax;
        analogWrite(pin, brightness);
      }
    }

    void fadeDown() {
      if (!atMin() && (millis() - timeCapture) >= updateFreq) {
        timeCapture = millis();
        if ((brightness -= adjustment) < targetMin)
          brightness = targetMin;
        analogWrite(pin, brightness);
      }
    }

    bool atMax() { return brightness >= targetMax; }
    bool atMin() { return brightness <= targetMin; }

    void begin(){ pinMode(pin, OUTPUT); }

    FadingLED(byte pin)
      : pin(pin) { }
};

FadingLED leds[NUM_LEDS] = {13, 12, 11, 10};
FadingLED* currentLed = &leds[0];

void setup() {
  for (int i = 0; i < NUM_LEDS; i++)
    leds[i].begin();
  pinMode(BTN_PIN, INPUT_PULLUP);
}

void loop() {
  if (!digitalRead(BTN_PIN)) {
    if (currentLed->atMax()) {
      if (currentLed != &leds[NUM_LEDS - 1])
        currentLed++;
    }
    else
      currentLed->fadeUp();
  }
  else {
    if (currentLed->atMin()) {
      if (currentLed != &leds[0])
        currentLed--;
    }
    else
      currentLed->fadeDown();
  }
}

Likely simpler ways of doing this but seems to work okay in my quick test.