Run HO Scale Himalaya Ride and lights off of 1 Arduino

HI! I could use a little help. :slight_smile: I belong to a model train club and we’re building an amusement park. One of the rides is an HO scale version of the Himalaya ride made by Faller. It comes with an AC motor which we can’t use so I managed to convert it to DC with a small geared motor. I designed the code using an L298N H-bridge to control the ride so it runs like the real thing.

Start slow and ramp up to full speed, Run for a while, Slow down and stop, Reverse and ramp up to full speed, Slow down and stop, Wait to load and unload run again.

The code works exactly as I want it too.

I also have an 8 letter (w/8 LED’s) sign for it that I’m lighting up and having it do weird flashing stuff to look cool.

Start by randomly blinking, Then sweep back and forth, next flash all LEDs on and off, then sweep again, next lite each letter one by one, blink all LEDs, turn off the LEDs, lite each LED in reverse and start over.

This code works exactly the way I’d like it to.

The question I have is, Can I combine them both together, to work independently and only use one Arduino UNO board? I made an attempt at it but everything works real slow and gets hung up at different places until the next event happens. So if I use two Arduino boards I can just run the code the way it is but it would be nice and easier to just use one board.

Sorry for the long code write but I wanted you to see all 3 versions.

Any help would be appreciated.

Ride code:


```cpp
// Motor control pins for an L298N H-bridge
const int enA = 10;  // Enable pin for PWM speed control
const int in1 = 11;  // Direction control pin 1
const int in2 = 12;  // Direction control pin 2

// Speed and timing constants
const int MAX_SPEED = 255;         // Max speed (PWM value)
const int RAMP_INTERVAL = 300;     // Time between speed steps (in ms)
const int RAMP_STEP = 5;           // Amount to increment/decrement speed
const int FULL_SPEED_TIME = 5000;  // Duration at full speed (in ms)
const int PAUSE_TIME = 5;          // Duration to wait between cycles (in ms)
const int LOAD_TIME = 5000;          // Duration to load for next ride

// State variables
int currentSpeed = 0;
unsigned long previousMillis = 0;
unsigned long stateStartTime = 0;
enum MotorState { FORWARD_RAMP_UP,
                  FORWARD_FULL_SPEED,
                  FORWARD_RAMP_DOWN,
                  STOPPED_WAIT,
                  REVERSE_RAMP_UP,
                  REVERSE_FULL_SPEED,
                  REVERSE_RAMP_DOWN,
                  STOPPED_WAIT2 };
MotorState currentState = FORWARD_RAMP_UP;

void setup() {
  // Set all motor control pins as outputs
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);

  // Initialize motor to stop
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  analogWrite(enA, 0);

  Serial.begin(9600);  // For debugging
  Serial.println("Starting motor cycle...");
  stateStartTime = millis();
}

void loop() {
  unsigned long currentMillis = millis();

  switch (currentState) {
    case FORWARD_RAMP_UP:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed += RAMP_STEP;
        if (currentSpeed >= MAX_SPEED) {
          currentSpeed = MAX_SPEED;
          Serial.println("Full speed forward.");
          currentState = FORWARD_FULL_SPEED;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, true);  // True for forward
      }
      break;

    case FORWARD_FULL_SPEED:
      if (currentMillis - stateStartTime >= FULL_SPEED_TIME) {
        Serial.println("Slowing down.");
        currentState = FORWARD_RAMP_DOWN;
      }
      break;

    case FORWARD_RAMP_DOWN:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed -= RAMP_STEP;
        if (currentSpeed <= 0) {
          currentSpeed = 0;
          Serial.println("Stopped. Waiting.");
          currentState = STOPPED_WAIT;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, true);
      }
      break;

    case STOPPED_WAIT:
      if (currentMillis - stateStartTime >= PAUSE_TIME) {
        Serial.println("Starting reverse ramp up.");
        currentState = REVERSE_RAMP_UP;
      }
      break;

    case REVERSE_RAMP_UP:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed += RAMP_STEP;
        if (currentSpeed >= MAX_SPEED) {
          currentSpeed = MAX_SPEED;
          Serial.println("Full speed reverse.");
          currentState = REVERSE_FULL_SPEED;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, false);  // False for reverse
      }
      break;

    case REVERSE_FULL_SPEED:
      if (currentMillis - stateStartTime >= FULL_SPEED_TIME) {
        Serial.println("Slowing down.");
        currentState = REVERSE_RAMP_DOWN;
      }
      break;

    case REVERSE_RAMP_DOWN:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed -= RAMP_STEP;
        if (currentSpeed <= 0) {
          currentSpeed = 0;
          Serial.println("UNloading and Loading");
          currentState = STOPPED_WAIT2;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, false);
      }
      break;
    case STOPPED_WAIT2:
      if (currentMillis - stateStartTime >= LOAD_TIME) {
        Serial.println("Forward Ramp up");
        currentState = FORWARD_RAMP_UP;
        setMotorSpeedAndDirection(currentSpeed, true);
      }
      break;
  }
}

// Function to set motor speed and direction
void setMotorSpeedAndDirection(int speed, bool forward) {
  if (forward) {
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
  } else {
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
  }
  analogWrite(enA, speed);
}

```

Sign code:


```cpp
// Define the LED pins
const int ledPins[] = { 2, 3, 4, 5, 6, 7, 8, 9 };  // Connect your LEDs to these pins
const int numLeds = sizeof(ledPins) / sizeof(ledPins[0]);
const int flashDelay = 50;      // The delay in milliseconds between flashes.
const int allFlashDelay = 150;  // delay set for the flashing of all LEDs

// Timing variables
unsigned long previousMillis = 0;
const long randomFlashDuration = 8000;    // 8 seconds of random flashing
const long sequenceFlashDuration = 4000;  // 4 seconds of sequential flashing
const long blickingFlashDuration = 3000;  // 3 seconds of full flashing
const long slowOnDuration = 500;          // 1/2 second between each light up of the sign
const int randomDelayMin = 50;
const int randomDelayMax = 200;
const int sequentialDelay = 50;

// State variable for the LED patterns
enum LedState { RANDOM_FLASH,
                RIGHT_TO_LEFT,
                ALL_FLASH,
                LEFT_TO_RIGHT,
                SLOW_ON,
                ALL_FLASH2,
                TURN_ALL_ON };
LedState currentState = RANDOM_FLASH;

void setup() {
  // Initialize LED pins as outputs
  for (int i = 0; i < numLeds; i++) {
    pinMode(ledPins[i], OUTPUT);
    digitalWrite(ledPins[i], LOW);  // Ensure all LEDs are on initially
  }
  randomSeed(analogRead(0));  // Seed the random number generator
}

void loop() {
  unsigned long currentMillis = millis();

  switch (currentState) {
    case RANDOM_FLASH:
      if (currentMillis - previousMillis >= randomFlashDuration) {
        previousMillis = currentMillis;
        currentState = RIGHT_TO_LEFT;
        allLedsOff();  // Turn off all LEDs before switching pattern
      } else {
        randomFlash();
      }
      break;

    case RIGHT_TO_LEFT:
      if (currentMillis - previousMillis >= sequenceFlashDuration) {
        previousMillis = currentMillis;
        currentState = ALL_FLASH;
        allLedsOff();
      } else {
        flashLeftToRight();
      }
      break;

    case ALL_FLASH:
      if (currentMillis - previousMillis >= blickingFlashDuration) {
        previousMillis = currentMillis;
        currentState = LEFT_TO_RIGHT;
        allLedsOff();
      } else {
        all_flash();
      }
      break;

    case LEFT_TO_RIGHT:
      if (currentMillis - previousMillis >= sequenceFlashDuration) {
        previousMillis = currentMillis;
        currentState = SLOW_ON;
        allLedsOff();
      } else {
        flashRightToLeft();
      }
      break;

    case SLOW_ON:
      if (currentMillis - previousMillis >= blickingFlashDuration) {
        previousMillis = currentMillis;
        currentState = ALL_FLASH2;
        allLedsOff();
      } else {
        slow_on();
      }
      break;

    case ALL_FLASH2:
      if (currentMillis - previousMillis >= blickingFlashDuration) {
        previousMillis = currentMillis;
        currentState = TURN_ALL_ON;
        allLedsOff();
      } else {
        all_flash2();
      }
      break;

    case TURN_ALL_ON:
      {
        currentState = RANDOM_FLASH;
        turn_all_on();
      }
      break;
  }
}

void allLedsOff() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
  }
}

void allLedsOn() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
  }
}

void turn_all_on() {
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(ledPins[i], LOW);
    delay(100);
  }
}

void randomFlash() {
  int randomLed = random(numLeds);                           // Choose a random LED
  int randomDelay = random(randomDelayMin, randomDelayMax);  // Choose a random delay

  digitalWrite(ledPins[randomLed], HIGH);
  delay(randomDelay);
  digitalWrite(ledPins[randomLed], LOW);
  delay(randomDelay);  // Keep a balanced on/off time for random flashes
}

void flashLeftToRight() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
}

void flashRightToLeft() {
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
}

void all_flash() {
  // Turn all the LEDs on at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
  }
  delay(allFlashDelay);  // Wait for a short period.

  // Turn all the LEDs off at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
  }
  delay(allFlashDelay);  // Wait for a short period.
}

void slow_on() {
  allLedsOff();
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
    delay(slowOnDuration);  // Wait for a short period.
  }
}

void all_flash2() {
  // Turn all the LEDs on at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
  }
  delay(allFlashDelay);  // Wait for a short period.

  // Turn all the LEDs off at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
  }
  delay(allFlashDelay);  // Wait for a short period.
}

```

Combined Code:


```cpp
// Define the LED pins
const int ledPins[] = { 2, 3, 4, 5, 6, 7, 8, 9 };  // Connect LEDs to these pins
const int numLeds = sizeof(ledPins) / sizeof(ledPins[0]);
const int flashDelay = 50;      // The delay in milliseconds between flashes.
const int allFlashDelay = 150;  // delay set for the flashing of all LEDs

// Motor control pins for an L298N H-bridge
const int enA = 10;  // Enable pin for PWM speed control
const int in1 = 11;  // Direction control pin 1
const int in2 = 12;  // Direction control pin 2

// Timing variables
unsigned long previousMillis = 0;
const long randomFlashDuration = 8000;    // 8 seconds of random flashing
const long sequenceFlashDuration = 4000;  // 4 seconds of sequential flashing
const long blickingFlashDuration = 3000;  // 3 seconds of full flashing
const long slowOnDuration = 500;          // 1/2 second between each light up of the sign
const int randomDelayMin = 50;
const int randomDelayMax = 200;
const int sequentialDelay = 50;

// Speed and timing constants
const int MAX_SPEED = 255;         // Max speed (PWM value)
const int RAMP_INTERVAL = 300;     // Time between speed steps (in ms)
const int RAMP_STEP = 5;           // Amount to increment/decrement speed
const int FULL_SPEED_TIME = 5000;  // Duration at full speed (in ms)
const int PAUSE_TIME = 5;          // Duration to wait between cycles (in ms)
const int LOAD_TIME = 5000;        // Duration to load for next ride

// State variables
int currentSpeed = 0;
unsigned long stateStartTime = 0;
enum MotorState { FORWARD_RAMP_UP,
                  FORWARD_FULL_SPEED,
                  FORWARD_RAMP_DOWN,
                  STOPPED_WAIT,
                  REVERSE_RAMP_UP,
                  REVERSE_FULL_SPEED,
                  REVERSE_RAMP_DOWN,
                  STOPPED_WAIT2 };
MotorState currentState = FORWARD_RAMP_UP;

// State variable for the LED patterns
enum LedState { RANDOM_FLASH,
                RIGHT_TO_LEFT,
                ALL_FLASH,
                LEFT_TO_RIGHT,
                SLOW_ON,
                ALL_FLASH2,
                TURN_ALL_ON };
LedState currentState2 = RANDOM_FLASH;

void setup() {
  // Initialize LED pins as outputs
  for (int i = 0; i < numLeds; i++) {
    pinMode(ledPins[i], OUTPUT);
    digitalWrite(ledPins[i], LOW);  // Ensure all LEDs are on initially
  }
  randomSeed(analogRead(0));  // Seed the random number generator
    // Set all motor control pins as outputs
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);

  // Initialize motor to stop
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  analogWrite(enA, 0);

  stateStartTime = millis();
}

void loop() {
  unsigned long currentMillis = millis();

    switch (currentState) {
    case FORWARD_RAMP_UP:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed += RAMP_STEP;
        if (currentSpeed >= MAX_SPEED) {
          currentSpeed = MAX_SPEED;
          Serial.println("Full speed forward.");
          currentState = FORWARD_FULL_SPEED;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, true);  // True for forward
      }
      break;

    case FORWARD_FULL_SPEED:
      if (currentMillis - stateStartTime >= FULL_SPEED_TIME) {
        Serial.println("Slowing down.");
        currentState = FORWARD_RAMP_DOWN;
      }
      break;

    case FORWARD_RAMP_DOWN:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed -= RAMP_STEP;
        if (currentSpeed <= 0) {
          currentSpeed = 0;
          Serial.println("Stopped. Waiting.");
          currentState = STOPPED_WAIT;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, true);
      }
      break;

    case STOPPED_WAIT:
      if (currentMillis - stateStartTime >= PAUSE_TIME) {
        Serial.println("Starting reverse ramp up.");
        currentState = REVERSE_RAMP_UP;
      }
      break;

    case REVERSE_RAMP_UP:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed += RAMP_STEP;
        if (currentSpeed >= MAX_SPEED) {
          currentSpeed = MAX_SPEED;
          Serial.println("Full speed reverse.");
          currentState = REVERSE_FULL_SPEED;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, false);  // False for reverse
      }
      break;

    case REVERSE_FULL_SPEED:
      if (currentMillis - stateStartTime >= FULL_SPEED_TIME) {
        Serial.println("Slowing down.");
        currentState = REVERSE_RAMP_DOWN;
      }
      break;

    case REVERSE_RAMP_DOWN:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed -= RAMP_STEP;
        if (currentSpeed <= 0) {
          currentSpeed = 0;
          Serial.println("UNloading and Loading");
          currentState = STOPPED_WAIT2;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, false);
      }
      break;
    case STOPPED_WAIT2:
      if (currentMillis - stateStartTime >= LOAD_TIME) {
        Serial.println("Forward Ramp up");
        currentState = FORWARD_RAMP_UP;
        setMotorSpeedAndDirection(currentSpeed, true);
      }
      break;
  }

  switch (currentState) {
    case RANDOM_FLASH:
      if (currentMillis - previousMillis >= randomFlashDuration) {
        previousMillis = currentMillis;
        currentState2 = RIGHT_TO_LEFT;
        allLedsOff();  // Turn off all LEDs before switching pattern
      } else {
        randomFlash();
      }
      break;

    case RIGHT_TO_LEFT:
      if (currentMillis - previousMillis >= sequenceFlashDuration) {
        previousMillis = currentMillis;
        currentState2 = ALL_FLASH;
        allLedsOff();
      } else {
        flashLeftToRight();
      }
      break;

    case ALL_FLASH:
      if (currentMillis - previousMillis >= blickingFlashDuration) {
        previousMillis = currentMillis;
        currentState2 = LEFT_TO_RIGHT;
        allLedsOff();
      } else {
        all_flash();
      }
      break;

    case LEFT_TO_RIGHT:
      if (currentMillis - previousMillis >= sequenceFlashDuration) {
        previousMillis = currentMillis;
        currentState2 = SLOW_ON;
        allLedsOff();
      } else {
        flashRightToLeft();
      }
      break;

    case SLOW_ON:
      if (currentMillis - previousMillis >= blickingFlashDuration) {
        previousMillis = currentMillis;
        currentState2 = ALL_FLASH2;
        allLedsOff();
      } else {
        slow_on();
      }
      break;

    case ALL_FLASH2:
      if (currentMillis - previousMillis >= blickingFlashDuration) {
        previousMillis = currentMillis;
        currentState2 = TURN_ALL_ON;
        allLedsOff();
      } else {
        all_flash2();
      }
      break;

    case TURN_ALL_ON:
      {
        currentState2 = RANDOM_FLASH;
        turn_all_on();
      }
      break;
  }
}

void allLedsOff() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
  }
}

void allLedsOn() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
  }
}

void turn_all_on() {
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(ledPins[i], LOW);
    delay(100);
  }
}

void randomFlash() {
  int randomLed = random(numLeds);                           // Choose a random LED
  int randomDelay = random(randomDelayMin, randomDelayMax);  // Choose a random delay

  digitalWrite(ledPins[randomLed], HIGH);
  delay(randomDelay);
  digitalWrite(ledPins[randomLed], LOW);
  delay(randomDelay);  // Keep a balanced on/off time for random flashes
}

void flashLeftToRight() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
}

void flashRightToLeft() {
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
}

void all_flash() {
  // Turn all the LEDs on at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
  }
  delay(allFlashDelay);  // Wait for a short period.

  // Turn all the LEDs off at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
  }
  delay(allFlashDelay);  // Wait for a short period.
}

void slow_on() {
  allLedsOff();
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
    delay(slowOnDuration);  // Wait for a short period.
  }
}

void all_flash2() {
  // Turn all the LEDs on at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
  }
  delay(allFlashDelay);  // Wait for a short period.

  // Turn all the LEDs off at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
  }
  delay(allFlashDelay);  // Wait for a short period.
}

// Function to set motor speed and direction
void setMotorSpeedAndDirection(int speed, bool forward) {
  if (forward) {
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
  } else {
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
  }
  analogWrite(enA, speed);
}

```

you used millis to time things in the first code you posted which allows that code torun without blocking. If you could do the same in the 2nd code you posted, each could be a separate routine, both called within loop()

both programs could be simpler by just using a single timer in each that waits the appropriate time to perform the next action

1 Like

Look in the forum tutorials for articles like how to do several things at once, state machines. I would look at 3 of each to give you some good ideas.
The first thing though is to dump the venerable old UNO and get a modern processor in the same form factor the UNO R4 Minima. It is 3 times faser, 16X more SRAM, 8 times more flash. Pins are very similar but no EEPROM. If needed a small addon board can be used.
Also dump the old HOT L298N and get a MOSFET based solution. Take your specs to POLULU and look at what they offer.

i think an uno and driver shield are more than adequate for this application.

One glaring defect in your code is that you have two switch statements inside loop() and they both use the variable currentState even though currentState2 is the variable for your lights.

It would be a lot better to use variables like currentMotorState and currentLightState or something more descriptive.

Also, in an effort to keep loop() small, I usually put all those switch statements in their own function so loop looks like

void loop() {
updateMotorState();
updateLightState();
}

That way, you can have previousMillis local to each function, something like this:

// Define the LED pins
const int ledPins[] = { 2, 3, 4, 5, 6, 7, 8, 9 };  // Connect LEDs to these pins
const int numLeds = sizeof(ledPins) / sizeof(ledPins[0]);
const int flashDelay = 50;      // The delay in milliseconds between flashes.
const int allFlashDelay = 150;  // delay set for the flashing of all LEDs

// Motor control pins for an L298N H-bridge
const int enA = 10;  // Enable pin for PWM speed control
const int in1 = 11;  // Direction control pin 1
const int in2 = 12;  // Direction control pin 2

// Timing variables
//unsigned long previousMillis = 0;
const long randomFlashDuration = 8000;    // 8 seconds of random flashing
const long sequenceFlashDuration = 4000;  // 4 seconds of sequential flashing
const long blickingFlashDuration = 3000;  // 3 seconds of full flashing
const long slowOnDuration = 500;          // 1/2 second between each light up of the sign
const int randomDelayMin = 50;
const int randomDelayMax = 200;
const int sequentialDelay = 50;

// Speed and timing constants
const int MAX_SPEED = 255;         // Max speed (PWM value)
const int RAMP_INTERVAL = 300;     // Time between speed steps (in ms)
const int RAMP_STEP = 5;           // Amount to increment/decrement speed
const int FULL_SPEED_TIME = 5000;  // Duration at full speed (in ms)
const int PAUSE_TIME = 5;          // Duration to wait between cycles (in ms)
const int LOAD_TIME = 5000;        // Duration to load for next ride

// State variables
int currentSpeed = 0;
unsigned long stateStartTime = 0;
enum MotorState { FORWARD_RAMP_UP,
                  FORWARD_FULL_SPEED,
                  FORWARD_RAMP_DOWN,
                  STOPPED_WAIT,
                  REVERSE_RAMP_UP,
                  REVERSE_FULL_SPEED,
                  REVERSE_RAMP_DOWN,
                  STOPPED_WAIT2 };
MotorState currentMotorState = FORWARD_RAMP_UP;

// State variable for the LED patterns
enum LedState { RANDOM_FLASH,
                RIGHT_TO_LEFT,
                ALL_FLASH,
                LEFT_TO_RIGHT,
                SLOW_ON,
                ALL_FLASH2,
                TURN_ALL_ON };
LedState currentLedState = RANDOM_FLASH;

void setup() {
  // Initialize LED pins as outputs
  for (int i = 0; i < numLeds; i++) {
    pinMode(ledPins[i], OUTPUT);
    digitalWrite(ledPins[i], LOW);  // Ensure all LEDs are on initially
  }
  randomSeed(analogRead(0));  // Seed the random number generator
    // Set all motor control pins as outputs
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);

  // Initialize motor to stop
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  analogWrite(enA, 0);

  stateStartTime = millis();
}


void loop() {

  updateMotorState();
  updateLedState();
}

void updateMotorState() {
  static unsigned long previousMillis;

  unsigned long currentMillis = millis();

  switch (currentMotorState) {
    case FORWARD_RAMP_UP:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed += RAMP_STEP;
        if (currentSpeed >= MAX_SPEED) {
          currentSpeed = MAX_SPEED;
          Serial.println("Full speed forward.");
          currentMotorState = FORWARD_FULL_SPEED;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, true);  // True for forward
      }
      break;

    case FORWARD_FULL_SPEED:
      if (currentMillis - stateStartTime >= FULL_SPEED_TIME) {
        Serial.println("Slowing down.");
        currentMotorState = FORWARD_RAMP_DOWN;
      }
      break;

    case FORWARD_RAMP_DOWN:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed -= RAMP_STEP;
        if (currentSpeed <= 0) {
          currentSpeed = 0;
          Serial.println("Stopped. Waiting.");
          currentMotorState = STOPPED_WAIT;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, true);
      }
      break;

    case STOPPED_WAIT:
      if (currentMillis - stateStartTime >= PAUSE_TIME) {
        Serial.println("Starting reverse ramp up.");
        currentMotorState = REVERSE_RAMP_UP;
      }
      break;

    case REVERSE_RAMP_UP:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed += RAMP_STEP;
        if (currentSpeed >= MAX_SPEED) {
          currentSpeed = MAX_SPEED;
          Serial.println("Full speed reverse.");
          currentMotorState = REVERSE_FULL_SPEED;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, false);  // False for reverse
      }
      break;

    case REVERSE_FULL_SPEED:
      if (currentMillis - stateStartTime >= FULL_SPEED_TIME) {
        Serial.println("Slowing down.");
        currentMotorState = REVERSE_RAMP_DOWN;
      }
      break;

    case REVERSE_RAMP_DOWN:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed -= RAMP_STEP;
        if (currentSpeed <= 0) {
          currentSpeed = 0;
          Serial.println("UNloading and Loading");
          currentMotorState = STOPPED_WAIT2;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, false);
      }
      break;
    case STOPPED_WAIT2:
      if (currentMillis - stateStartTime >= LOAD_TIME) {
        Serial.println("Forward Ramp up");
        currentMotorState = FORWARD_RAMP_UP;
        setMotorSpeedAndDirection(currentSpeed, true);
      }
      break;
  }
}

void updateLedState() {
  static unsigned long previousMillis;

  unsigned long currentMillis = millis();

  switch (currentLedState) {
    case RANDOM_FLASH:
      if (currentMillis - previousMillis >= randomFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = RIGHT_TO_LEFT;
        allLedsOff();  // Turn off all LEDs before switching pattern
      } else {
        randomFlash();
      }
      break;

    case RIGHT_TO_LEFT:
      if (currentMillis - previousMillis >= sequenceFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = ALL_FLASH;
        allLedsOff();
      } else {
        flashLeftToRight();
      }
      break;

    case ALL_FLASH:
      if (currentMillis - previousMillis >= blickingFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = LEFT_TO_RIGHT;
        allLedsOff();
      } else {
        all_flash();
      }
      break;

    case LEFT_TO_RIGHT:
      if (currentMillis - previousMillis >= sequenceFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = SLOW_ON;
        allLedsOff();
      } else {
        flashRightToLeft();
      }
      break;

    case SLOW_ON:
      if (currentMillis - previousMillis >= blickingFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = ALL_FLASH2;
        allLedsOff();
      } else {
        slow_on();
      }
      break;

    case ALL_FLASH2:
      if (currentMillis - previousMillis >= blickingFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = TURN_ALL_ON;
        allLedsOff();
      } else {
        all_flash2();
      }
      break;

    case TURN_ALL_ON:
      {
        currentLedState = RANDOM_FLASH;
        turn_all_on();
      }
      break;
  }
}



void allLedsOff() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
  }
}



void allLedsOn() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
  }
}

void turn_all_on() {
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(ledPins[i], LOW);
    delay(100);
  }
}

void randomFlash() {
  int randomLed = random(numLeds);                           // Choose a random LED
  int randomDelay = random(randomDelayMin, randomDelayMax);  // Choose a random delay

  digitalWrite(ledPins[randomLed], HIGH);
  delay(randomDelay);
  digitalWrite(ledPins[randomLed], LOW);
  delay(randomDelay);  // Keep a balanced on/off time for random flashes
}

void flashLeftToRight() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
}

void flashRightToLeft() {
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
    delay(sequentialDelay);
    digitalWrite(ledPins[i], LOW);
  }
}

void all_flash() {
  // Turn all the LEDs on at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
  }
  delay(allFlashDelay);  // Wait for a short period.

  // Turn all the LEDs off at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
  }
  delay(allFlashDelay);  // Wait for a short period.
}

void slow_on() {
  allLedsOff();
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
    delay(slowOnDuration);  // Wait for a short period.
  }
}

void all_flash2() {
  // Turn all the LEDs on at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
  }
  delay(allFlashDelay);  // Wait for a short period.

  // Turn all the LEDs off at the same time.
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
  }
  delay(allFlashDelay);  // Wait for a short period.
}

// Function to set motor speed and direction
void setMotorSpeedAndDirection(int speed, bool forward) {
  if (forward) {
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
  } else {
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
  }
  analogWrite(enA, speed);
}

This final piece would be to get rid of all those delay() functions which will take some more refactoring of your LED effects code

look this over to see how your train control could be done a bit easier, fewer states

// Motor control pins for an L298N H-bridge
const int enA = 10;  // Enable pin for PWM speed control
const int in1 = 11;  // Direction control pin 1
const int in2 = 12;  // Direction control pin 2

// Speed and timing constants
#if (0)
const unsigned long RAMP_INTERVAL   = 300;
const unsigned long FULL_SPEED_TIME = 5000;
const unsigned long LOAD_TIME       = 5000;
#else
const unsigned long RAMP_INTERVAL   = 10;
const unsigned long FULL_SPEED_TIME = 2000;
const unsigned long LOAD_TIME       = 3000;
#endif

const int MAX_SPEED = 255;
const int RAMP_STEP = 5;

enum { For = true, Rev = false };

enum MotorState {
    FORWARD_RAMP_UP,
    FORWARD_RAMP_DOWN,
    REVERSE_RAMP_UP,
    REVERSE_RAMP_DOWN,
};
int state = FORWARD_RAMP_UP;

// State variables
int  speed = 0;
bool dir;

unsigned long msecPeriod;
unsigned long msec0;

char s [90];

// -----------------------------------------------------------------------------
void setMotorSpeedAndDirection (
    int  speed,
    bool forward )
{
    if (forward) {
        digitalWrite (in1, HIGH);
        digitalWrite (in2, LOW);
    }
    else {
        digitalWrite (in1, LOW);
        digitalWrite (in2, HIGH);
    }

    analogWrite (enA, speed);

    sprintf (s, "setMotorSpeedAndDirection: %3d %s",
        speed, forward ? "For" : "Rev");
    Serial.println (s);
}

// -----------------------------------------------------------------------------
void trainControl () {
    unsigned long msec = millis ();

    if (msec - msec0 < msecPeriod)
        return;

    msec0 += msecPeriod;

    switch (state) {
    case FORWARD_RAMP_UP:
        if (MAX_SPEED <= ++speed)  {
            state      = FORWARD_RAMP_DOWN;
            msecPeriod = FULL_SPEED_TIME;
            Serial.println ("full forward");
        }
        else
            msecPeriod = RAMP_INTERVAL;
        dir = For;
        break;

    case FORWARD_RAMP_DOWN:
        if (0 >= --speed)  {
            state      = REVERSE_RAMP_UP;
            msecPeriod = LOAD_TIME;
            Serial.println ("forward stop");
        }
        else
            msecPeriod = RAMP_INTERVAL;
        dir = For;
        break;

    case REVERSE_RAMP_UP:
        if (MAX_SPEED <= ++speed)  {
            state      = REVERSE_RAMP_DOWN;
            msecPeriod = FULL_SPEED_TIME;
            Serial.println ("full reverse");
        }
        else
            msecPeriod = RAMP_INTERVAL;
        dir = Rev;
        break;

    case REVERSE_RAMP_DOWN:
        if (0 >= --speed)  {
            state      = FORWARD_RAMP_UP;
            msecPeriod = LOAD_TIME;
            Serial.println ("reverse stop");
        }
        else
            msecPeriod = RAMP_INTERVAL;
        dir = Rev;
        break;
    }

    setMotorSpeedAndDirection (speed, dir);
}

// -----------------------------------------------------------------------------
void loop () {
    trainControl ();
}

void setup () {
    // Set all motor control pins as outputs
    pinMode (enA, OUTPUT);
    pinMode (in1, OUTPUT);
    pinMode (in2, OUTPUT);

    setMotorSpeedAndDirection (0, For);

    Serial.begin (115200);  // For debugging
    Serial.println ("Starting motor cycle...");
    msec0 = millis ();
}

something similar could be done for your LEDs where each state invokes a different display routine that is written to be invoked after the desired delay. It would return TRUE when it is complete so that the switch in the LedControl routine knows when to advance to the next state

look this over.
ledController() is non-blocking and can be called within loop() along with other non-blocking routines.
it has various routines to turning leds on/off but the timing is set in the switch statement which allows them to be called with different timings and # of iterations

const byte PinLeds [] = { 13, 12, 11, 10 };
const int  Nleds      = sizeof(PinLeds);

enum { LedOff = HIGH, LedOn = LOW };

// -----------------------------------------------------------------------------
enum { Done = true, Running = false };

const unsigned long MsecSwpPeriod = 200;

      unsigned long msecLedPeriod;
      unsigned long msec0;


int ledIdx;

// -----------------------------------------------
bool
ledAll (
    byte onOff )
{
    Serial.println (__func__);

    for (int n = 0; n < Nleds; n++)
        digitalWrite (PinLeds [n], onOff);
    return Done;
}

// -----------------------------------------------
bool
ledFlash (
    int  cntMax)
{
    Serial.println (__func__);

    static int cnt = 0;

    if (cnt % 2)
        ledAll (LedOff);
    else
        ledAll (LedOn);

    if (cntMax <= ++cnt)  {
        cnt = 0;
        return Done;
    }
    return Running;
}

// -----------------------------------------------
bool
ledRandom ()
{
    static int idx = 0;
    digitalWrite (PinLeds [idx], LedOff);

    idx = random (Nleds);
    digitalWrite (PinLeds [idx], LedOn);

    return Done;
}

// -----------------------------------------------
bool
ledSwpLeft ()
{
    Serial.println (__func__);

    static int idx = Nleds -1;
    digitalWrite (PinLeds [idx], LedOff);

    if (0 > --idx)  {
        idx = Nleds -1;
        return Done;
    }

    digitalWrite (PinLeds [idx], LedOn);
    return Running;
}

// -----------------------------------------------
bool
ledSwpRight ()
{
    Serial.println (__func__);

    static int idx = 0;
    digitalWrite (PinLeds [idx], LedOff);

    if (Nleds <= ++idx)  {
        idx = 0;
        return Done;
    }

    digitalWrite (PinLeds [idx], LedOn);
    return Running;
}

// -----------------------------------------------
int state = 0;
int cnt   = 0;

void
ledController ()
{
    unsigned long msec = millis ();
    if (msec - msec0 < msecLedPeriod)
        return;

    msec0 += msecLedPeriod;

    switch (state)  {
    case 0:
        ledAll (LedOff);
        msecLedPeriod = 500;
        state++;
        break;

    case 1:
        msecLedPeriod = 250;
        if (Done == ledFlash (8))
            state++;
        break;

    case 2:
        msecLedPeriod = 100;
        if (Done == ledSwpLeft ())
            if (6 <= ++cnt) {
                cnt = 0;
                state++;
            }
        break;

    case 3:
        msecLedPeriod = 100;
        if (Done == ledSwpRight ())
            if (6 <= ++cnt) {
                cnt = 0;
                state++;
            }
        break;

    case 4:
        msecLedPeriod = 100;
        ledRandom ();
        if (10 <= ++cnt)  {
            cnt = 0;
            state++;
        }
        break;

    default:
        state = 0;
        break;
    }
}

// -----------------------------------------------------------------------------
void loop ()
{
    ledController ();
}

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);

    for (int n = 0; n < Nleds; n++)
        pinMode (PinLeds [n], OUTPUT);

    ledAll (LedOff);
}

oh crap I didn’t even think of that! :frowning: I used Mills in the case statement and Delay in the routines. Still learning this stuff. I appreciate the catch and will have to try and work on that.

Hi Everyone! Just a quick update…

I managed to use part of each of your suggestions, with a little of my own, and was able to get the program working exactly as I want it too!! Using Mills has made the program run very smooth and I can’t wait to get it all hooked up permanently to show it off to the public. :slight_smile:

Thanks again for all the help and suggestions!

Bob………..

Care to share the final, working code?

1 Like
I know it's probably a bit bloated but it does work. I have two places where I couldn't get the MILLS function to work so I used DELAY but it's only for a short time and doesn't affect the ride at all. When I get it all together and wired up I'll upload a video. 

Thanks again for the help!!





// Define the LED pins
const int ledPins[] = { 2, 3, 4, 5, 6, 7, 8, 9 };  // Connect LEDs to these pins
const int numLeds = 8;                             //sizeof(ledPins) / sizeof(ledPins[0]);
const int flashDelay = 50;                         // The delay in milliseconds between flashes.
const int allFlashDelay = 150;                     // delay set for the flashing of all LEDs
long previousMillis[numLeds];                      // Stores the last time each LED was updated
int ledState[numLeds];                             // Stores the current state of each LED (HIGH or LOW)
long interval[numLeds];                            // Stores the random interval for each LED
long sweepinterval = 50;                           // Initial delay interval for flashing
unsigned long pryorMillis = 0;                     // Stores the last time an LED was updated
const long blinkinterval = 250;                    // Blink interval in milliseconds (e.g., 500ms for 0.5 second)
int ledState2 = LOW;                               // Variable to store the current state of the LEDs (HIGH or LOW)
unsigned long previousMillis2 = 0;
const unsigned long slowinterval = 500;  // Time in milliseconds between turning on each LED being lit
//unsigned long previousMillis3 = 0;       // Stores the last time an LED was turned on
//int currentLed = 0;                      // Index of the current LED to turn on
//bool sequenceComplete = false;           // Flag to indicate if the sequence has finished

bool rightToLeft = true;  // Flag to control direction
int currentLedIndex = 0;  // Index of the current LED being processed

// Motor control pins for an L298N H-bridge
const int enA = 10;  // Enable pin for PWM speed control
const int in1 = 11;  // Direction control pin 1
const int in2 = 12;  // Direction control pin 2

// Timing variables
//unsigned long previousMillis = 0;
const long randomFlashDuration = 8000;     // 8 seconds of random flashing
const long sequenceFlashDuration = 4000;   // 4 seconds of sequential flashing
const long blinckingFlashDuration = 3000;  // 3 seconds of full flashing
const long slowOnDuration = 500;           // 1/2 second between each light up of the sign
const int randomDelayMin = 50;
const int randomDelayMax = 200;
const int sequentialDelay = 50;

// Speed and timing constants
const int MAX_SPEED = 240;         // Max speed (PWM value)
const int RAMP_INTERVAL = 300;     // Time between speed steps (in ms)
const int RAMP_STEP = 5;           // Amount to increment/decrement speed
const int FULL_SPEED_TIME = 30000;  // Duration at full speed (in ms)
const int PAUSE_TIME = 5;          // Duration to wait between cycles (in ms)
const int LOAD_TIME = 20000;        // Duration to load for next ride

// State variables
int currentSpeed = 0;
unsigned long stateStartTime = 0;
enum MotorState { FORWARD_RAMP_UP,
                  FORWARD_FULL_SPEED,
                  FORWARD_RAMP_DOWN,
                  STOPPED_WAIT,
                  REVERSE_RAMP_UP,
                  REVERSE_FULL_SPEED,
                  REVERSE_RAMP_DOWN,
                  STOPPED_WAIT2 };
MotorState currentMotorState = FORWARD_RAMP_UP;

// State variable for the LED patterns
enum LedState { RANDOM_FLASH,
                RIGHT_TO_LEFT,
                ALL_FLASH,
                LEFT_TO_RIGHT,
                SLOW_ON,
                ALL_FLASH2,
                TURN_ALL_ON };
LedState currentLedState = RANDOM_FLASH;

void setup() {
  // Initialize LED pins as outputs
  for (int i = 0; i < numLeds; i++) {
    pinMode(ledPins[i], OUTPUT);
    digitalWrite(ledPins[i], LOW);  // Ensure all LEDs are on initially
  }
  randomSeed(analogRead(0));  // Seed the random number generator
    // Set all motor control pins as outputs
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);

  // Initialize motor to stop
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  analogWrite(enA, 0);

  stateStartTime = millis();
  Serial.begin(9600);  // For debugging
  Serial.println("Starting light cycle...");
}


void loop() {

  updateMotorState();
  updateLedState();
}

void updateMotorState() {
  static unsigned long previousMillis;

  unsigned long currentMillis = millis();

  switch (currentMotorState) {
    case FORWARD_RAMP_UP:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed += RAMP_STEP;
        if (currentSpeed >= MAX_SPEED) {
          currentSpeed = MAX_SPEED;
          Serial.println("Full speed forward.");
          currentMotorState = FORWARD_FULL_SPEED;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, true);  // True for forward
      }
      break;

    case FORWARD_FULL_SPEED:
      if (currentMillis - stateStartTime >= FULL_SPEED_TIME) {
        Serial.println("Slowing down.");
        currentMotorState = FORWARD_RAMP_DOWN;
      }
      break;

    case FORWARD_RAMP_DOWN:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed -= RAMP_STEP;
        if (currentSpeed <= 0) {
          currentSpeed = 0;
          Serial.println("Stopped. Waiting.");
          currentMotorState = STOPPED_WAIT;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, true);
      }
      break;

    case STOPPED_WAIT:
      if (currentMillis - stateStartTime >= PAUSE_TIME) {
        Serial.println("Starting reverse ramp up.");
        currentMotorState = REVERSE_RAMP_UP;
      }
      break;

    case REVERSE_RAMP_UP:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed += RAMP_STEP;
        if (currentSpeed >= MAX_SPEED) {
          currentSpeed = MAX_SPEED;
          Serial.println("Full speed reverse.");
          currentMotorState = REVERSE_FULL_SPEED;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, false);  // False for reverse
      }
      break;

    case REVERSE_FULL_SPEED:
      if (currentMillis - stateStartTime >= FULL_SPEED_TIME) {
        Serial.println("Slowing down.");
        currentMotorState = REVERSE_RAMP_DOWN;
      }
      break;

    case REVERSE_RAMP_DOWN:
      if (currentMillis - previousMillis >= RAMP_INTERVAL) {
        previousMillis = currentMillis;
        currentSpeed -= RAMP_STEP;
        if (currentSpeed <= 0) {
          currentSpeed = 0;
          Serial.println("UNloading and Loading");
          currentMotorState = STOPPED_WAIT2;
          stateStartTime = currentMillis;
        }
        setMotorSpeedAndDirection(currentSpeed, false);
      }
      break;
    case STOPPED_WAIT2:
      if (currentMillis - stateStartTime >= LOAD_TIME) {
        Serial.println("Forward Ramp up");
        currentMotorState = FORWARD_RAMP_UP;
        setMotorSpeedAndDirection(currentSpeed, true);
      }
      break;
  }
}

void updateLedState() {
  static unsigned long previousMillis;

  unsigned long currentMillis = millis();

  switch (currentLedState) {
    case RANDOM_FLASH:
      if (currentMillis - previousMillis >= randomFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = RIGHT_TO_LEFT;
        allLedsOff();  // Turn off all LEDs before switching pattern
      } else {
        randomFlash();
      }
      break;

    case RIGHT_TO_LEFT:
      if (currentMillis - previousMillis >= sequenceFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = ALL_FLASH;
        allLedsOff();
      } else {
        flashLeftToRight();
      }
      break;

    case ALL_FLASH:
      if (currentMillis - previousMillis >= blinckingFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = LEFT_TO_RIGHT;
        allLedsOff();
      } else {
        all_flash();
      }
      break;

    case LEFT_TO_RIGHT:
      if (currentMillis - previousMillis >= sequenceFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = SLOW_ON;
        allLedsOff();
      } else {
        flashRightToLeft();
      }
      break;

    case SLOW_ON:
      if (currentMillis - previousMillis >= blinckingFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = ALL_FLASH2;
        allLedsOff();
      } else {
        slow_on();
      }
      break;

    case ALL_FLASH2:
      if (currentMillis - previousMillis >= blinckingFlashDuration) {
        previousMillis = currentMillis;
        currentLedState = TURN_ALL_ON;
        allLedsOff();
      } else {
        all_flash2();
      }
      break;

    case TURN_ALL_ON:
      {
        currentLedState = RANDOM_FLASH;
        turn_all_on();
      }
      break;
  }
}



void allLedsOff() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], HIGH);
  }
}



void allLedsOn() {
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
  }
}

void turn_all_on() {
  for (int i = numLeds - 1; i >= 0; i--) {
    digitalWrite(ledPins[i], LOW);
    delay(100);
  }
}

void randomFlash() {
  unsigned long currentMillis = millis();  // Get the current time

  for (int i = 0; i < numLeds; i++) {
    // Check if it's time to change the state of the current LED
    if (currentMillis - previousMillis[i] >= interval[i]) {
      previousMillis[i] = currentMillis;  // Update the last time the LED was updated

      // Toggle the LED state
      if (ledState[i] == LOW) {
        ledState[i] = HIGH;
      } else {
        ledState[i] = LOW;
      }

      digitalWrite(ledPins[i], ledState[i]);  // Update the LED output

      // Generate a new random interval for the next state change
      interval[i] = random(50, 500);
    }
  }
}

void flashLeftToRight() {
  unsigned long currentMillis = millis();  // Get the current time

  if (currentMillis - pryorMillis >= sweepinterval) {
    pryorMillis = currentMillis;  // Update the last update time

    // Turn off the previously active LED
    digitalWrite(ledPins[currentLedIndex], LOW);

    if (rightToLeft) {
      currentLedIndex++;  // Move to the next LED (right to left)
      if (currentLedIndex >= numLeds) {
        currentLedIndex = numLeds - 1;  // Reset to the last LED
        rightToLeft = false;            // Change direction to left to right
      }
    } else {
      currentLedIndex--;  // Move to the previous LED (left to right)
      if (currentLedIndex < 0) {
        currentLedIndex = 0;  // Reset to the first LED
        rightToLeft = true;   // Change direction to right to left
      }
    }

    // Turn on the current LED
    digitalWrite(ledPins[currentLedIndex], HIGH);

    // Generate a new random interval for the next flash
    //    interval = 50; // Random interval between 50ms and 300ms
  }
}

void flashRightToLeft() {
  unsigned long currentMillis = millis();  // Get the current time

  if (currentMillis - pryorMillis >= sweepinterval) {
    pryorMillis = currentMillis;  // Update the last update time

    // Turn off the previously active LED
    digitalWrite(ledPins[currentLedIndex], LOW);

    if (rightToLeft) {
      currentLedIndex++;  // Move to the next LED (right to left)
      if (currentLedIndex >= numLeds) {
        currentLedIndex = numLeds - 1;  // Reset to the last LED
        rightToLeft = false;            // Change direction to left to right
      }
    } else {
      currentLedIndex--;  // Move to the previous LED (left to right)
      if (currentLedIndex < 0) {
        currentLedIndex = 0;  // Reset to the first LED
        rightToLeft = true;   // Change direction to right to left
      }
    }

    // Turn on the current LED
    digitalWrite(ledPins[currentLedIndex], HIGH);

    // Generate a new random interval for the next flash
    //    interval = 50; // Random interval between 50ms and 300ms
  }
}

void all_flash() {
  unsigned long currentMillis = millis();

  // Check if it's time to toggle the LEDs
  if (currentMillis - previousMillis2 >= blinkinterval) {
    // Save the current time as the last time the LEDs were toggled
    previousMillis2 = currentMillis;

    // Toggle the LED state
    if (ledState2 == LOW) {
      ledState2 = HIGH;
    } else {
      ledState2 = LOW;
    }

    // Set all LEDs to the new state
    for (int i = 0; i < numLeds; i++) {
      digitalWrite(ledPins[i], ledState2);
    }
  }
}

void slow_on() {
  allLedsOff();
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], LOW);
    delay(slowOnDuration);  // Wait for a short period.
  }
}

void all_flash2() {
  unsigned long currentMillis = millis();

  // Check if it's time to toggle the LEDs
  if (currentMillis - previousMillis2 >= blinkinterval) {
    // Save the current time as the last time the LEDs were toggled
    previousMillis2 = currentMillis;

    // Toggle the LED state
    if (ledState2 == LOW) {
      ledState2 = HIGH;
    } else {
      ledState2 = LOW;
    }

    // Set all LEDs to the new state
    for (int i = 0; i < numLeds; i++) {
      digitalWrite(ledPins[i], ledState2);
    }
  }
}

// Function to set motor speed and direction
void setMotorSpeedAndDirection(int speed, bool forward) {
  if (forward) {
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
  } else {
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
  }
  analogWrite(enA, speed);
}