HI! I could use a little help.
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);
}
```