Hello all - I am new to Arduino, this is my first project.
I have a N-Scale model train display and have not been happy with the old analog DC speed controller, so am now building this sketch to control train speeds, directions, and display lights. I will be adding additional functions as time goes to also control a number of track switches.
Please comments and advise. I also want to add a WiFi board and build a iOS app to provide a remote control function.
SKETCH FOLLOWS
// ARDUINO MEGA 2560
// MODEL TRAIN CONTROLLER
//
// Purpose of this sketch is to control model train display with following specifications
// - Two independent tracks capable of both directions using H-Bridge control
// - Both tracks capable of independent speed control using pulse width modulation (PWM)
// - Both tracks capable of independent direction control
// - Relay for lights control
// - Relay to turn on power for 18 VAC transformer
// - Spare relays for possible future use
// - LCD display to show when Arduino is powered on, and to show train speeds by percent of maximum
// - Future integration of WIFI module for remote control ability using mobile app
// - Stepper POTs to facilitate remote control
//
// Written by Stephen Breedlove
//
// Version information
//
// Beta 3 - Written for Uno R3
// Beta 4 05/24/2022 - Modify for Mega 2560 board to add LCD display and additional inputs/outputs for Relay 3 and 4, addition of Track B speed and direction control
// Beta 4A 05/24/2022 - Add LCD display coding
// Beta 5 05/25/2022 - Added LCD display to coding, beta tested on single track - tested GOOD
//
//_____________________________________________________________________________________________________________________________________________________________________
// TO-DO CHECKLIST
// 1 add directional control switch for B track - A and B currently tied together
// 2 add toggle switches to board
// 3 build 18VDC to 5VDC converter
//_____________________________________________________________________________________________________________________________________________________________________
//_______________________________________________________________________________________________________________________
// MEGA PINOUTS _______ | BOARD END CONNECTORS | SPECIFICATIONS
// | O --- SCL / D21 | |
// | O --- SDA / D20 | INSIDE EDGE |
// | O --- AREF | ___________________________ |
// NC ---- O O --- GND | |
// IOREF --- O O --- D13 PWR LED | LCD +5v +5V --- O O --- +5V LCD+ A +5V |
// +3.3V --- O O --- D12 STATUS LED | D22 --- O O --- D23 |
// +5V --- O O --- D11 enB | LCD RS D24 --- O O --- D25 |
// GND --- O O --- D10 enA | LCD R/W D26 --- O O --- D27 |
// GND --- O O --- D9 in4 | LCD ENA D28 --- O O --- D29 |
// PWR IN +5VIN --- O O --- D8 in3 | REL D D30 --- O O --- D31 |
// POT A A0 --- O O --- D7 in2 | REL C D32 --- O O --- D33 |
// RUN SW A1 --- O O --- D6 in1 | REL B D34 --- O O --- D35 |
// relA A2 --- O O --- D5 RELAY2 | REL A D36 --- O O --- D37 |
// relB A3 --- O O --- D4 RELAY1 | LCD D4 D38 --- O O --- D39 |
// dirA A4 --- O O --- D3 relB | LCD D5 D40 --- O O --- D41 |
// POT B A5 --- O O --- D2 relA | LCD D6 D42 --- O O --- D43 |
// A6 --- O O --- D1 / TX0 | LCD D7 D44 --- O O --- D45 |
// A7 --- O O --- D0 / RX0 | D46 --- O O --- D47 |
// A8 --- O O --- D14 / TX3 | D48 --- O O --- D49 |
// A9 --- O O --- D15 / RX3 | D50 --- O O --- D51 |
// A10 --- O O --- D16 / TX2 | D52 --- O O --- D53 |
// A11 --- O O --- D17 / RX2 | LCD GND GND --- O O --- GND LCD- K GND |
// A12 --- 0 O --- D18 / TX1 /| |
// A13 --- O O --- D19 / RX1 / |____________________________________________|
// A14 --- O O --- D20 / SDA / |
// A15 --- O O --- D21 / SCL / |
// 00000000 ______________ / |
// 00000000 see inset __/ |
// |
//________________________________________________________________________________________________________________________
//_______________________________________________________________________________________________________________________
// pin outs L298N | L298 H-BRIDGE MOTOR DRIVE - MED POWER - 2 AMP, 25W MAX
// ___________________ | +12V - 5V TO 35V FOR MOTOR DRIVE
// | | | +5V - 5V BOARD POWER
// OUT 2a---O O--OUT 1a |
// OUT 2b---O O--OUT 2b |
// | ___ | |
// +18AC -- O O O O O O O O O -- UNO 10 |
// GND ------| | | | | | |----- UNO 6 |
// +5DC --------| | | | |------- UNO 7 |
// | | |--------- UNO 8 |
// UNO 11 ----------| |----------- UNO 9 |
//_______________________________________________|
//_______________________________________________________________________________________________________________________
// relay board pinouts | relay pins | RELAY BOARD
// | | 4-CHANNEL RELAY
// | O O O | +5V DC BOARD POWER
// relD------| |------relB | | | | | HIGH CURRENT RELAYS, 250 VAC 10A, 30VDC 10A
// relC----| | | |----relA | NO C NC |
// VCC---| | | | | |---GND |________________|
// | | | | | | |
// __O_O_O_O_O_O_______________ |
// | | |
// | | |
// |_O_O_O__O_O_O__O_O_O__O_O_O_| |
// | | | | | | | | | | | | |
// relayD relayC relayB relayA |
//_______________________________________________|
//______________________________________________________________________________________________________________________
// LCD display | LCD DISPLAY
// | 16 CHARACTERS
// ______ | 2 LINES
// | | | Character blocks 5 x 8
// | O --- 1 / GND | +5V main power
// | O --- 2 / +5V LOGIC FROM ARDUINO | +5V LED power through 220 ohm resistor
// | O --- 3 / V0 CONTRAST INPUT | Constrast 0V - 5V
// | O --- 4 / RS REGISTER SELECT | best viewed at 4V
// | O --- 5 / R/W READ/WRITE SELECT |
// | O --- 6 / E ENABLE |
// | O --- 7 / DO DATA BUS (8 BIT MODE) |
// | O --- 8 / D1 DATA BUS (8 BIT MODE) |
// | O --- 9 / D2 DATA BUS (8 BIT MODE) |
// | O --- 10 / D3 DATA BUS (8 BIT MODE) |
// | O --- 11 / D4 DATA BUS IN |
// | O --- 12 / D5 DATA BUS IN |
// | O --- 13 / D6 DATA BUS IN |
// | O --- 14 / D7 DATA BUS IN |
// | O --- 15 / A LED+ 5V BACKLIGHT ANODE (+5V) |
// | O --- 16 / K LED- 5V BACKLIGHT CATHODE (GND) |
// |______| |
// |
//___________________________________________________________________________________________________________________
#include <LiquidCrystal.h>
int relA = 36; // RELAY A OUT
int relB = 34; // RELAY B OUT
int relC = 32; // RELAY C OUT
int relD = 30; // RELAY D OUT
int in1 = 6; // DIRECTION A
int in2 = 7; // DIRECTION A
int in3 = 8; // DIRECTION B
int in4 = 9; // DIRECTION B
int enA = 10; // PWM A OUT
int enB = 11; // PWM B OUT
int toggleOut = 12; // RUN LED
int unoLED = 13; // POWER ON LED
int potenA = A0; // PWM CONTROL A IN
int toggleIn = A1; // RUN SWITCH
int relayA = A2; // RELAY A IN
int relayB = A3; // RELAY B IN
int dirA = A4; // DIRECTION A IN
int potenB = A5; // PWM CONTROL B IN
int dirB = A6; // DIRECTION B IN
int relayC = A7; // RELAY C IN
int relayD = A8; // RELAY D IN
int speedA; // PWM CONTROL A OUT
int speedB; // PWM CONTROL B OUT
int pastPCT = 0; // SPEED CONTROL BASE
// LCD DISPLAY
const int rs = 24, en = 28, d4 = 38, d5 = 40, d6 = 42, d7 = 44;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
int lcdVo = 5; // Contrast
int lcdAK = 4; // Backlight
// ACTIVE LED
int press = 0;
boolean toggle = true;
// BOARD SETUP
void setup()
{
// Set all the pin functions
pinMode(enA, OUTPUT); // PWM A
pinMode(enB, OUTPUT); // PWM B
pinMode(in1, OUTPUT); // DIRECTION A
pinMode(in2, OUTPUT); // DIRECTION A
pinMode(in3, OUTPUT); // DIRECTION B
pinMode(in4, OUTPUT); // DIRECTION B
pinMode(toggleOut, OUTPUT); // RUN LED
pinMode(toggleIn, INPUT); // RUN SWITCH
pinMode(potenA, INPUT); // SPEED CONTROL A
pinMode(relayA, INPUT); // RELAY1 SWITCH
pinMode(relayB, INPUT); // RELAY2 SWITCH
pinMode(relayC, INPUT); // RELAY3 SWITCH
pinMode(relayD, INPUT); // RELAY4 SWITCH
pinMode(dirA, INPUT); // DIRECTION A
pinMode(dirB, INPUT); // DIRECTION B
pinMode(potenB, INPUT); // SPEED CONTROL B
pinMode(relA, OUTPUT); // RELAY1 OUT
pinMode(relB, OUTPUT); // RELAY2 OUT
pinMode(relC, OUTPUT); // RELAY3 OUT
pinMode(relD, OUTPUT); // RELAY4 OUT
pinMode(unoLED, OUTPUT); // POWER LED
pinMode(lcdVo, OUTPUT); // LCD Contrast
pinMode(lcdAK, OUTPUT); // LCD Backlight
// STARTUP - Initial state - Inputs to HIGH, Outputs to LOW
digitalWrite(enA, LOW); // PWM OUT
digitalWrite(enB, LOW); // PWM OUT
digitalWrite(relA, HIGH); // RELAY A
digitalWrite(relB, HIGH); // RELAY B
digitalWrite(relC, HIGH); // RELAY C
digitalWrite(relD, HIGH); // RELAY D
digitalWrite(relayA, HIGH); // RELAY A
digitalWrite(relayB, HIGH); // RELAY B
digitalWrite(relayC, HIGH); // RELAY C
digitalWrite(relayD, HIGH); // RELAY D
digitalWrite(A0, LOW); // POT A LOW
digitalWrite(A1, HIGH); // RUN SWITCH
digitalWrite(A2, HIGH); // RELAY A IN
digitalWrite(A3, HIGH); // RELAY B IN
digitalWrite(A4, HIGH); // DIRECTION A
digitalWrite(A5, LOW); // POT B LOW
digitalWrite(A6, HIGH); // DIRECTION B
digitalWrite(A7, HIGH); // RELAY C IN
digitalWrite(A8, HIGH); // RELAY D IN
digitalWrite(in1, LOW); // H-BRIDGE OFF
digitalWrite(in2, LOW); // H-BRIDGE OFF
digitalWrite(in3, LOW); // H-BRIDGE OFF
digitalWrite(in4, LOW); // H-BRIDGE OFF
digitalWrite(unoLED, HIGH); // POWER LED ON
analogWrite(lcdVo, 25); // Set LCD Contrast
analogWrite(lcdAK, 128); // Set LCD Backlight
Serial.begin(9600); // Begin serial communications
lcd.begin(16, 2); // Turn on LCD Display
lcd.setCursor(0,0); // LCD Cursor
}
// CONTROL LOOP
void loop()
{
if (digitalRead(toggleIn) == HIGH) //Read Run Switch
{
lcd.setCursor(0,0);
lcd.print(" COMPUTER ");
lcd.setCursor(0,1);
lcd.print(" POWERED ON ");
}
else if (digitalRead(toggleIn) == LOW && digitalRead(dirA) == LOW) // STANDARD DIRECTION
{
digitalWrite(toggleOut, HIGH);
// SPEED CONTROL
int potA=analogRead(potenA);
int potB=analogRead(potenB);
int speedA=map(potA,0,1023,0,255);
int speedB=map(potB,0,1023,0,255);
analogWrite(enA,speedA); // MOTOR A SPEED
analogWrite(enB,speedB); // MOTOR B SPEED
int sensorValueA = analogRead(potenA);
float pctA = sensorValueA * (100.0 / 1023.0);
int percentA = pctA + 0.5;
int sensorValueB = analogRead(potenB);
float pctB = sensorValueB * (100.0 / 1023.0);
int percentB = pctB + 0.5;
// RELAYS
int relayoutA=digitalRead(relayA);
int relayoutB=digitalRead(relayB);
digitalWrite(relA, relayoutA); // RELAY A
digitalWrite(relB, relayoutB); // RELAY B
// DIRECTION CONTROL
digitalWrite(in1, HIGH); // MOTOR A
digitalWrite(in2, LOW); // MOTOR A
digitalWrite(in3, HIGH); // MOTOR B
digitalWrite(in4, LOW); // MOTOR B
// SEND TO DISPLAY
String PCT = "A: ";
PCT.concat(percentA);
PCT += " | B: ";
PCT += percentB;
int currentPCT = (percentA + percentB);
if (currentPCT != pastPCT);
{
Serial.println(PCT);
lcd.setCursor(0,0);
lcd.print(" INNER OUTER ");
lcd.setCursor(0,1);
lcd.print(PCT);
int pastPCT = currentPCT;
}
}
else if (digitalRead(toggleIn) == LOW && digitalRead(dirA) == HIGH) //REVERSE DIRECTION
{
// RUN LED
digitalWrite(toggleOut, HIGH);
// SPEED CONTROL
int potA=analogRead(potenA);
int potB=analogRead(potenB);
int speedA=map(potA,0,1023,0,255);
int speedB=map(potB,0,1023,0,255);
analogWrite(enA,speedA); // MOTOR A SPEED
analogWrite(enB,speedB); // MOTOR B SPEED
int sensorValueA = analogRead(potenA);
float pctA = sensorValueA * (100.0 / 1023.0);
int percentA = pctA + 0.5;
int sensorValueB = analogRead(potenB);
float pctB = sensorValueB * (100.0 / 1023.0);
int percentB = pctB + 0.5;
// RELAYS
int relayoutA=digitalRead(relayA);
int relayoutB=digitalRead(relayB);
digitalWrite(relA, relayoutA); // RELAY A
digitalWrite(relB, relayoutB); // RELAY B
// DIRECTION CONTROL
digitalWrite(in1, LOW); // MOTOR A
digitalWrite(in2, HIGH); // MOTOR A
digitalWrite(in3, LOW); // MOTOR B
digitalWrite(in4, HIGH); // MOTOR B
// SEND TO DISPLAY
String PCT = "A: ";
PCT.concat(percentA);
PCT += " | B: ";
PCT += percentB;
int currentPCT = (percentA + percentB);
if (currentPCT != pastPCT);
{
Serial.println(PCT);
lcd.setCursor(0,0);
lcd.print(" INNER OUTER ");
lcd.setCursor(0,1);
lcd.print(PCT);
int pastPCT = currentPCT;
}
}
else if (digitalRead(toggleIn) == HIGH);
{
digitalWrite(toggleOut, LOW); // RUN LED
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
digitalWrite(enA, LOW);
digitalWrite(enB, LOW);
digitalWrite(relA, HIGH);
digitalWrite(relB, HIGH);
digitalWrite(relC, HIGH);
digitalWrite(relD, HIGH);
}
delay(10);
}