LED strip sequence PWM add pushbutton change sequence

Greetings,
I am working on a project that needs some formatting. This is driving an LED strip fading between color schemes. (A PWM sequence if you will.) This code is working independently, but I want to add a button and switch patterns. I would like to use a case type structure, but I'm not sure where to break it up to use that scheme. FYI, and am also running this through some transistors so this is just the signal that gets relayed.

// *This works, but it's Output goes LOW 

int redPin = 2;
int greenPin = 3;
int bluePin = 4;

int prevRed, prevGreen, prevBlue;

void setup() {
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
}

void loop() {
  colorRGB(0, 255, 255); //red
  delay(1000);
  colorRGB(0, 230, 255); //orange
  delay(1000);
  colorRGB(0, 180, 255); //yellow
  delay(1000);
  colorRGB(255, 0, 255); //green
  delay(1000);
  colorRGB(255, 0, 0); //cyan
  delay(1000);
  colorRGB(255, 255, 0); //blue
  delay(1000);
  colorRGB(0, 255, 100); //purple
  delay(1000);
}

void colorRGB(int red, int green, int blue) {

  red = constrain(red, 0, 255);
  green = constrain(green, 0, 255);
  blue = constrain(blue, 0, 255);

  for (int i = 0; i < 1000; i++) {
    analogWrite(redPin, map(i, 0, 999, prevRed, red));
    analogWrite(greenPin, map(i, 0, 999, prevGreen, green));
    analogWrite(bluePin, map(i, 0, 999, prevBlue, blue));
    delay(1);
  }
  
  prevRed = red;
  prevGreen = green;
  prevBlue = blue;
}

I'm not sure where this is going to go or if I provided all the details. I'll try to monitor and provide more info.

What information and help for helpers is this supposed to bring? You're urged to post schematics!

Forget reading buttons.

2 Likes

Okay, thanks for your -help? The circuit is working, and my post was to ask what to change to include buttons. Tell me something I don't know please.

Second.

2 Likes

Rewrite your sequences to avoid delay() and be non-blocking, so that the processor gets a chance to read the buttons.

Not sure what you mean by this but pins 2 and 4 on a number of boards (e.g. Uno) are not capable of PWM and hence will either be on or off.

Hi,
What model Arduino are you using?

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.
WHY?
Because we do not know how you have your LEDs wired, common cathode or common anode,
Are you using current limit resistors?
How you have your switches wired, to gnd or to 5V.

How you have your hardware connected makes a big difference as to how you configure your software.

Tom.... :smiley: :+1: :coffee: :australia:

As pointed out, the problem is using delay(). Even that delay(1) is a problem because it's inside a for-loop that repeats 1000 times, so effectively it's another delay(1000).

Using delay() is an example of "blocking code" which doesn't allow anything else to happen until it is finished, including detecting button presses.

So the answer to your question is the usual one: read up on "doing more than one thing at once", using millis() for timing and making "finite state machines" (not as scary as it sounds, or at least doesn't have to be).

1 Like

The below code executes one fade after a button was pressed. Each press of the button will select the next fade and run it once. This is the simplest form and it might suite your needs. if it does not suite your needs you will have to give de detailed description.

The code is still blocking which means that during the one second that colorRGB() is running and the one second delay the button will not be read.

First an array of structs is implemented for the different colours. A struct is a type that can hold related items; e.g. a name and a phonenumber in a phonebook. In our case it can hold the three colours ref green and blue.

// struct with initial colours
struct COLOURS
{
  const int red;
  const int green;
  const int blue;
};

And the array

// array with the different colours to fade
const COLOURS colours[] = {
  { 0, 255, 255 },  // red
  { 0, 230, 255 },  // orange
  { 0, 180, 255 },  // yellow
  { 255, 0, 255 },  // green
  { 255, 0, 0 },    // cyan
  { 255, 255, 0 },  //blue
  { 0, 255, 100 },  //purple
};

You can call a fade of a specific colour as shown below; e.g. orange

colorRGB(colours[1].red, colours[1].green, colours[1].blue);

Next the pins (I've adjusted them)

const uint8_t redPin = 3;
const uint8_t greenPin = 5;
const uint8_t bluePin = 6;
const uint8_t btnPin = 2;

And the previous colours

int prevRed, prevGreen, prevBlue;

The button needs to be connected between a pin and GND. In setup() you now configure the button to use the internal pull-up.

void setup()
{
  Serial.begin(115200);
  // button between pin and GND
  pinMode(btnPin, INPUT_PULLUP);
}

There is a little more before we get to loop(). To know how many elements there are in an array we add the following to the beginning of the code

// macro to calculate the size of an array of any type (int, float, struct)
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))

Because of the wiring of the button between pin and GND a press will result in LOW. To make the code easier to read and modify (if the button is wired differently) we add the following to the beginning of the code

// more readible code
#define ISPRESSED LOW

loop() consists of three sections

  1. variable declaration
  2. button handling
  3. execute a fade for a colour.
void loop()
{
  // index which colour to fade
  static uint8_t index = 0xFF;
  // previous index
  static uint8_t prevIndex = 0xFF;
  // previous state of the button
  static uint8_t prevBtnState = !ISPRESSED;

All those variables are static; the result is that, like global variables, will be remembered and that, like local variables, they will only be known inside the function (loop() in this case).
index is initialised with 0xFF (255) which indicates that it's currently not valid. prevIndex is used to check if index was changed (due to a button press).
prevBtnState is used to check if the state of the button changed.

The button handling below

  uint8_t btnState = digitalRead(btnPin);
  // if the button changed from not-pressed to pressed or vice versa
  if (btnState != prevBtnState)
  {
    // remember the new button state
    prevBtnState = btnState;
    Serial.println(F("button changed"));
    // if the button is now pressed
    if (btnState == ISPRESSED)
    {
      // increment the index
      index++;
      // print the index
      Serial.print(F("button pressed, index = "));
      Serial.println(index);
    }
  }

I think that it's self explaining.

The last part is the fading based on the index.

  // if the index is valid
  if (index < NUMELEMENTS(colours))
  {
    Serial.println(F("valid index"));
    // if the index changed
    if (index != prevIndex)
    {
      Serial.print(F("prevIndex = "));
      Serial.println(prevIndex);
      Serial.print(F("index = "));
      Serial.println(index);
      // remember the new index
      prevIndex = index;

      Serial.print(F("executing fade "));
      Serial.println(index);
      colorRGB(colours[index].red, colours[index].green, colours[index].blue);
      delay(1000);
    }
  }
  // if the index is not valid
  else
  {
    // set index back to 0xFF; next press will result in 0
    index = 0xFF;
  }
}

We first check if the index is valid; if the index is not valid it will be reset to 0xFF. If the index is valid we check if the index has changed. If it did not change nothing happens; the result is that a fade will only be executed once.
If it did change, it will be remembered and next colorRGB() will be called with the values of colour in the array indicated by the array (colorRGB(colours[index].red, colours[index].green, colours[index].blue);).

Full code

// macro to calculate the size of an array of any type (int, float, struct)
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))

// more readible code
#define ISPRESSED LOW

// struct with initial colours
struct COLOURS
{
  const int red;
  const int green;
  const int blue;
};

// array with the different colours to fade
const COLOURS colours[] = {
  { 0, 255, 255 },  // red
  { 0, 230, 255 },  // orange
  { 0, 180, 255 },  // yellow
  { 255, 0, 255 },  // green
  { 255, 0, 0 },    // cyan
  { 255, 255, 0 },  //blue
  { 0, 255, 100 },  //purple
};

const uint8_t redPin = 3;
const uint8_t greenPin = 5;
const uint8_t bluePin = 6;
const uint8_t btnPin = 2;

int prevRed, prevGreen, prevBlue;

void setup()
{
  Serial.begin(115200);
  // button between pin and GND
  pinMode(btnPin, INPUT_PULLUP);
}

void loop()
{
  // index which colour to fade
  static uint8_t index = 0xFF;
  // previous index
  static uint8_t prevIndex = 0xFF;
  // previous state of the button
  static uint8_t prevBtnState = !ISPRESSED;

  uint8_t btnState = digitalRead(btnPin);
  // if the button changed from not-pressed to pressed or vice versa
  if (btnState != prevBtnState)
  {
    // remember the new button state
    prevBtnState = btnState;
    Serial.println(F("button changed"));
    // if the button is now pressed
    if (btnState == ISPRESSED)
    {
      // increment the index
      index++;
      // print the index
      Serial.print(F("button pressed, index = "));
      Serial.println(index);
    }
  }

  // if the index is valid
  if (index < NUMELEMENTS(colours))
  {
    Serial.println(F("valid index"));
    // if the index changed
    if (index != prevIndex)
    {
      Serial.print(F("prevIndex = "));
      Serial.println(prevIndex);
      Serial.print(F("index = "));
      Serial.println(index);
      // remember the new index
      prevIndex = index;

      Serial.print(F("executing fade "));
      Serial.println(index);
      colorRGB(colours[index].red, colours[index].green, colours[index].blue);
      delay(1000);
    }
  }
  // if the index is not valid
  else
  {
    // set index back to 0xFF; next press will result in 0
    index = 0xFF;
  }
}

void colorRGB(int red, int green, int blue)
{
  red = constrain(red, 0, 255);
  green = constrain(green, 0, 255);
  blue = constrain(blue, 0, 255);

  for (int i = 0; i < 1000; i++)
  {
    analogWrite(redPin, map(i, 0, 999, prevRed, red));
    analogWrite(greenPin, map(i, 0, 999, prevGreen, green));
    analogWrite(bluePin, map(i, 0, 999, prevBlue, blue));
    delay(1);
  }

  prevRed = red;
  prevGreen = green;
  prevBlue = blue;
}

Notes:

  • Because colourRGB() and delay(1000) result in blocking code for two seconds, there is no need for additional debouncing of the button.
  • The code is long due to the serial print statements.
  • When you see "button changed" without the following "button pressed, index = " it indicates that the fade was completed and you can press the button again.
  • Lastly this is not perfect code. But your topic does not indicate that you have much understanding at this point so I kept it simple. As others indicated you should actually get rid of the delays but I'm a bit worried that you might not understand 90% what is needed. As mentioned in the beginning this might basically do what you need; if not, please provide an exact description.
3 Likes

Normally when you set RGB, you set 0 as off and 255 as full brightness. For some reason, this code seems to work backwards as 255 runs the LED as off and 0 runs the LED at full brightness. You can see that in the patterns. It was more of a note to my future self when I come back to visit this project.

"... see read..."

But why would you not program for the common anode so your code is not a hide-and-seek? You even describe it as "backwards." It's not cute or clever. Do not code for job security. Code for not being there to explain.

You do not appreciate the help you have been given. You are snarky, and nobody likes that. You do not know how to use punctuation.

1 Like

This is wonderful! This is the kind of help I wish others would offer. I'm guessing this forum gives points for solutions, so people nit pick on grammar to gain a point. I think some people expect someone new coming in here to grovel to become worthy of an answer. I understand electronics, and I can build and harness circuits. Given a working code, I can tweak things to where I need it, and I can follow tutorials, but where coding breaks for me is taking one piece of code with a working function and using it with another code with a working function, and implementing user input and options. Part of finding help is knowing how to ask a question. I didn't know what details would make sense or what additional information would help formulate an answer. Sometimes you have to get the conversation going to lay the groundwork so you can talk the same language.

So as a follow up as you so kindly offered, is it possible for that array to play as a continuous loop? Say, hold a color for one second, fade into the next color, so on and so forth staying within that array:

  { 0, 255, 255 },  // red
  { 0, 230, 255 },  // orange
  { 0, 180, 255 },  // yellow
  { 255, 0, 255 },  // green
  { 255, 0, 0 },    // cyan
  { 255, 255, 0 },  //blue
  { 0, 255, 100 },  //purple

Then press a button and begin this loop:

  { 255, 255, 0 },  //blue
  { 0, 180, 255 },  // yellow
  { 255, 255, 0 },  //blue
  { 255, 0, 0 },    // cyan

Then pressing a button again goes back to the first loop? (I'm saying loop, but it lives in a container and gets handled by the terms that references that container.)

One more thing. I don't see anywhere that makes the output high rather than low. I can use this -as is- which is why all my colors are inverted. One would expect red to be 255, 0, 0 rather than 0, 255, 255. If this overly complicates things ignore this part.

Thank you so much for getting the ball rolling!

I will chew on that.

You can subtract the calculated value from 255.

E.g. something like

analogWrite(redPin, 255 - map(i, 0, 999, prevRed, red));

Yes. Are you asking how, or for someone to do the work for you?

I see. You want someone to do the work. That is fair. It will help you become ondependent.

Here. Fully commented. 16 million colors.

Look xfpd, if I'm bothering you, I'd rather you not help me. Don't let me ruin your day. I provided my code in the first post, so you're making a lot of assumptions. This is suppose to be a place for help, not criticism. Yes I'm ignorant in coding, and I come here for help. I do read a lot of similar topics, and I do find some clues, but still get stuck. I do stumble on some working examples, but not everything is broken down into what each part of the code is doing what. I can follow along and make changes, but not enough to change the whole architecture. Most threads I see here is someone asking a question, some legitimate, some trivial, but a majority of responses are people reiterating the problem rather than provide a constructive solution. We all start somewhere, and everyone needs help along the way. There's a lot of people who like to stomp on anyone venturing into a new environment. I sought help knowing there's mentoring people willing to share their passion and work with someone who's interested in learning.

Here's what I thought I was going to migrate to down below. This was a button project where I hit a button and it cycles through two functions. (It has 3, but one auto advances to the 3rd)

Red relay - switches the reds on a LED strip.
Green relay - switches the greens on the same LED strip.
White relay - switches a white LED strip.
Pin 13 - has an addressable LED strip that animates 246 LEDs

Main Page:

#include <FastLED.h>
#include <OneButton.h>

#define NUM_LEDS  246
#define LED_PIN   13
#define BTN_PIN   12

CRGB leds[NUM_LEDS];
uint8_t patternCounter = 0;
bool isRunning = false;

void checkTimer();

// Push button connected between pin 7 and GND (no resistor required)
OneButton btn = OneButton(BTN_PIN, true, true);

#include "RedZero.h"
#include "ChargingOne.h"
#include "GreenTwo.h"

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(255);
  Serial.begin(57600);
  pinMode(11, OUTPUT);  //Red Relay
  pinMode(10, OUTPUT);  //Green Relay
  pinMode(9, OUTPUT);  //White Relay

  btn.attachClick(nextPattern);
}

void loop() {
  
  switch (patternCounter) {
    case 0:
      runRedZero();
      break;
    case 1:
      runChargingOne();
      break;
    case 2:
      runGreenTwo();
      break;
  }
}

void checkTimer() {
  EVERY_N_SECONDS(2) {
    nextPattern();
  }
}

void nextPattern() {
  isRunning = false;
  patternCounter = (patternCounter + 1) % 3;
}

void runRedZero(){
  isRunning = true;
  RedZero redZero = RedZero();
  while(isRunning) redZero.runPattern();
}

void runChargingOne(){
  isRunning = true;
  ChargingOne chargingOne = ChargingOne();
  while(isRunning) chargingOne.runPattern();
}

void runGreenTwo(){
  isRunning = true;
 GreenTwo greenTwo = GreenTwo();
  while(isRunning) greenTwo.runPattern();
}

Case 0:

#include "Arduino.h"

class RedZero {
  public:
    RedZero(){
      // Blank constructor  
    };
    void runPattern();
  private:
};

void RedZero::runPattern() {

fill_solid( leds, NUM_LEDS, CRGB(200,0,0));

  btn.tick();
  FastLED.show();
  digitalWrite(11, HIGH);  //Red Relay (ON)
  digitalWrite(10, LOW);  //Green Relay (OFF)
  digitalWrite(9, LOW);  //White Relay (OFF)
}

Case 1:
(plays through and jumps to Case 2)

#include "Arduino.h"

class ChargingOne {
  public:
    ChargingOne(){};
    void runPattern();
  private:
};

void ChargingOne::runPattern() {

 checkTimer();
     digitalWrite(11, LOW);  //Red Relay (OFF)
     digitalWrite(10, LOW);  //Green Relay (OFF)
     digitalWrite(9, LOW);  //White Relay (OFF)
     fill_solid( leds, NUM_LEDS, CRGB(0,0,0));
     FastLED.show();
     delay(500);
          // 03 Turn lights from Off to White from left to right   R G B 
  for (int i=0; i<NUM_LEDS; i++){
    leds[i] = CRGB::White;
    FastLED.show();
    delay(5);
  }
  }

Cas 2

#include "Arduino.h"

class GreenTwo {
  public:
    GreenTwo(){};
    void runPattern();
  private:
};

void GreenTwo::runPattern() {

  digitalWrite(11, LOW);  //Red Relay (OFF)
  digitalWrite(10, HIGH);  //Green Relay (ON)
  digitalWrite(9, HIGH);  //White Relay (ON)
  fill_solid( leds, NUM_LEDS, CRGB(0,255,0));
  btn.tick();
  FastLED.show();
  digitalWrite(11, LOW);  //Red Relay (OFF)
  }

The button behaves the way similar to this project, but I want my original code to be one of the cases, and a modified one to be the second, and each button press would flip to the other case. I know my code isn't going to be drop in compatible, but I don't know how to structure to make it compatible with this code. This is why I come here to seek help. Any help from constructive people is appreciated.

This part worked perfect! Inverted everything:

// array with the different colours to fade
const COLOURS colours[] = {
  { 255, 0, 0 },  // red
  { 255, 25, 0 },  // orange
  { 255, 75, 0 },  // yellow
  { 0, 255, 0 },  // green
  { 0, 255, 255 },    // cyan
  { 0, 0, 255 },  //blue
  { 255, 0, 150 },  //purple
};

Thank you.

That makes my outboard stuff a lot simpler:

I feel like I am close. I might need a little push to cross the finish line. I have the structure of 3 codes I'd like to merge. The first code is the button function which cycles through two processes. For now, the two pages (Electric.h, and Rainbow.h) are place holders for what I'd like to replace. For now they throw out a simple output.

Main page:

#include <OneButton.h>

#define BTN_PIN   5

uint8_t patternCounter = 0;
bool isRunning = false;

void checkTimer();

// Push button connected between pin 7 and GND (no resistor required)
OneButton btn = OneButton(BTN_PIN, true, true);

#include "Electric.h"
#include "Rainbow.h"

void setup() {
  pinMode(2, OUTPUT);  //Red Relay
  pinMode(3, OUTPUT);  //Green Relay
  pinMode(4, OUTPUT);  //Blue Relay

  btn.attachClick(nextPattern);
}

void loop() {
  
  switch (patternCounter) {
    case 0:
      runElectric();
      break;
    case 1:
      runRainbow();
      break;
  }
}

void nextPattern() {
  isRunning = false;
  patternCounter = (patternCounter + 1) % 2;
}

void runElectric(){
  isRunning = true;
  Electric electric = Electric();
  while(isRunning) electric.runPattern();
}

void runRainbow(){
  isRunning = true;
 Rainbow rainbow = Rainbow();
  while(isRunning) rainbow.runPattern();
}

Electric.h

#include "Arduino.h"

class Electric {
  public:
    Electric(){
      // Blank constructor  
    };
    void runPattern();
  private:
};

void Electric::runPattern() {

  btn.tick();
  digitalWrite(2, HIGH);  //Red Relay (ON)
  digitalWrite(3, LOW);  //Green Relay (OFF)
  digitalWrite(4, LOW);  //Blue Relay (OFF)
}

Rainbow.h

#include "Arduino.h"

class Rainbow {
  public:
    Rainbow(){};
    void runPattern();
  private:
};

void Rainbow::runPattern() {

  digitalWrite(2, LOW);  //Red Relay (OFF)
  digitalWrite(3, LOW);  //Green Relay (ON)
  digitalWrite(4, HIGH);  //Blue Relay (ON)
  btn.tick();
  }

So, this works as far as cycling back and forth.

I bashed my code and rewrote it for millis. This works as a stand alone:

Electric:

const uint16_t interval[] {100, 1500, 100, 250, 100, 1000, 500, 1000};  // time to wait in each intervall

const byte redPin = 2;
const byte greenPin = 3;
const byte bluePin = 4;

int prevRed,prevGreen, prevBlue; 

void handleLeds()
{

  static uint32_t previousMillis = 0;
  static byte state = 7;
  if (millis() - previousMillis >= interval[state])
  {
    // it's time for next state
    state++;
    state = state % 8;
    Serial.print(F("state=")); Serial.println(state);

    // act according state
    switch (state)
    {
      case 0: // 1 1000
        colorRGB(0, 0, 255); //blue
        break;
      case 1: // 2 2000                             
        colorRGB(0, 255, 255); //cyan
        break;
      case 2: // 3 3000
        colorRGB(0, 0, 255); //blue
        break;
      case 3: // 4 4000 
        colorRGB(255, 100, 0); //yellow
        break;                   
      case 4: // 5 5000
        colorRGB(0, 0, 255); //blue
        break;
      case 5: // 6 6000
        colorRGB(255, 100, 0); //yellow
        break;       
      case 6: // 7 7000
        colorRGB(0, 0, 255); //blue
        break;
      case 7: // 8 8000
        colorRGB(0, 255, 255); //cyan
        break;        
    }
    previousMillis = millis();
  }
}

void setup() {
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
}

void colorRGB(int red, int green, int blue) {

  red = constrain(red, 0, 255);
  green = constrain(green, 0, 255);
  blue = constrain(blue, 0, 255);

  for (int i = 0; i < 50; i++) {
    analogWrite(redPin, map(i, 0, 999, prevRed, red));
    analogWrite(greenPin, map(i, 0, 999, prevGreen, green));
    analogWrite(bluePin, map(i, 0, 999, prevBlue, blue));
    delay(1);
  }
  
  prevRed = red;
  prevGreen = green;
  prevBlue = blue;
}

void loop() {
  handleLeds();  // checks if something is todo with the LEDs
  //do other important stuff here
}

Then this for the rainbow page

const uint16_t interval[] {500, 500, 500, 500, 500, 500, 500};  // time to wait in each intervall

const byte redPin = 2;
const byte greenPin = 3;
const byte bluePin = 4;

int prevRed, prevGreen, prevBlue;

void handleLeds()
{

  static uint32_t previousMillis = 0;
  static byte state = 6;
  if (millis() - previousMillis >= interval[state])
  {
    // it's time for next state
    state++;
    state = state % 8;
    Serial.print(F("state=")); Serial.println(state);

    // act according state
    switch (state)
    {
      case 0:
        colorRGB(255, 0, 0); //red
        break;
      case 1:                             
        colorRGB(255, 25, 0); //orange
        break;
      case 2:
        colorRGB(255, 75, 0); //yellow
        break;
      case 3: 
        colorRGB(0, 255, 0); //green 
        break;                   
      case 4:
        colorRGB(0, 255, 255); //cyan
        break;
      case 5:
        colorRGB(0, 0, 255); //blue
        break;       
      case 6:
        colorRGB(255, 0, 150); //purple
        break;
    }
    previousMillis = millis();
  }
}

void setup() {
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
}

void colorRGB(int red, int green, int blue) {

  red = constrain(red, 0, 255);
  green = constrain(green, 0, 255);
  blue = constrain(blue, 0, 255);

  for (int i = 0; i < 1000; i++) {
    analogWrite(redPin, map(i, 0, 999, prevRed, red));
    analogWrite(greenPin, map(i, 0, 999, prevGreen, green));
    analogWrite(bluePin, map(i, 0, 999, prevBlue, blue));
    delay(1);
  }
  
  prevRed = red;
  prevGreen = green;
  prevBlue = blue;
}

void loop() {
  handleLeds();  // checks if something is todo with the LEDs
  //do other important stuff here
}

What to I need to keep, and what do I need to move to the main page? Can all these be merged?

Yes. Every sketch should have a common configuration and setup() Then, make functions for the specific patterns, all called from loop()

Here is another example. This shows a button controlling when the next pattern is called...

Cube!

When merging, I get errors that I don't get when running the example I made. I purposely named everything the same so it should be somewhat drop in. When uploading, I get errors:

Arduino: 1.8.16 (Windows 10), Board: "Arduino Mega or Mega 2560, ATmega2560 (Mega 2560)"

F:\Control\Arduino\RGB PWM 2 Loops\09_classesHybrid_RGB_Redefine_4\09_classesHybrid_RGB_Redefine_4.ino: In function 'void runElectricZero()':

09_classesHybrid_RGB_Redefine_4:47:16: error: expected ';' before 'electricZero'

   ElectricZero electricZero = ElectricZero();

                ^~~~~~~~~~~~

09_classesHybrid_RGB_Redefine_4:48:20: error: 'electricZero' was not declared in this scope

   while(isRunning) electricZero.runPattern();

                    ^~~~~~~~~~~~

F:\Control\Arduino\RGB PWM 2 Loops\09_classesHybrid_RGB_Redefine_4\09_classesHybrid_RGB_Redefine_4.ino:48:20: note: suggested alternative: 'ElectricZero'

   while(isRunning) electricZero.runPattern();

                    ^~~~~~~~~~~~

                    ElectricZero

exit status 1

expected ';' before 'electricZero'



This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

How does it work in one project and not another?