Project in progress
Model Train Control

Model Train Control © GPL3+

This code is developed to "test" drive a model train between two gates made of a LED and LDR.

  • 7,154 views
  • 3 comments
  • 14 respects

Components and supplies

A000066 iso both
Arduino UNO & Genuino UNO
Or any compatible (i used sainsmart mega 2560)
×1
Arduino Motor Shield R3
×1
LED white
×2
Adafruit industries ada161 image 75px
Photo resistor
×2
Mfr 25frf52 10k sml
Resistor 10k ohm
×2
08377 02 l
Resistor 330 ohm
×2

About this project

Like many people, my wish is a nice model train, therefore I made a nice layout plan, bought a starter set, made a  table etc. It takes a long time, of course, to build a complicated layout and in the meantime you want to (test)ride on the track you have so far.

You can of course do so just with your transformer, but if you do not pay attention you drive off the track. And model trains are fragile, a drop on the floor will do damage. So the plan is a back and forth automation. Something like this: Arduino-railroad.

All due respect to the maker but if you pop each time against a fence and reverse the motor directly, it will damage the train or the gear at some time.

I figured two gates with an LED and an LDR will sense the train.

And let the Arduino  decelerate, reverse and accelerate the train.

Code

Train ControlC/C++
Please note that the pin numbers of LED and LDR has chanced.
The pin numbers of motor control are fixed.
/*
  Train control
  This code is developed to "test" drive
  a model train between two gates made of a LED and LDR.

  Parts required:
  1 - arduino uno/mega or compatible
  1 - arduino motor shield R3
  2 - Led brite white (5mm)
  2 - Ldr (A 9013 photo resistor 5mm) 
  2 - 10K resistor
  2 - 220 Ohm resistor
  1 - model train 

  Created 4 October 2016
  by Kitemasters

  This code is part of the public domain
*/
// --------CONSTANTS (won't change)---------------

int sens_L_Pin = A4;                         // the pin number for ldr L
int sens_R_Pin = A5;                         // the pin number for ldr R
int led_L_Pin = 4;                           // the pin number for the L LED
int led_R_Pin = 5;                           // the pin number for the R LED
int motor_Pin = 3;                           // the pin number for the motor speed
int brake_Pin = 9;                           // the pin number for the motor brake
int direction_Pin = 12;                      // the pin number for the motor direction
int current_sens_Pin = A0;                   // the pin number for the current sensor

int read_sens_Interval = 200;                // millisecs between reading sensors
int motor_Acc_Interval = 100;                // millisecs between acceleration steps
int motor_Dec_Interval = 10;                 // millisecs between deceleration steps

//------------ VARIABLES (will change)---------------------

unsigned long currentMillis = 0;               // stores the value of millis() in each iteration of loop()
unsigned long previous_sens_Millis = 0;        // will store the last time sensors are read
unsigned long previous_Acc_Millis = 0;         // will store time of last acceleration step
unsigned long previous_Dec_Millis = 0;         // will store time of last deceleration step

int sensLreading = 0;                          // declare variable and set value for left sensor reading
int sensRreading = 0;                          // declare variable and set value for right sensor reading
int max_Speed = 200;                           // declare variable and set value for maximum Speed (0 to 255)
int Speed = 0;                                 // declare variable and set value for current Speed (0 to 255)
boolean direct = HIGH;                         // declare variable and set value for direction to HIGH (HIGH = left)

#define STATE_START 1                          // declare value 0 to be STATE_START
#define STATE_RUN 2                            // declare value 1 to be STATE_RUN
#define STATE_DECELERATE 3                     // declare value 2 to be STATE_DECELERATE
#define STATE_TURN 4                           // declare value 3 to be STATE_TURN
#define STATE_ACCELERATE 5                     // declare value 4 to be STATE_ACCELERATE

int state = STATE_START;                       // declare variable "state" and set value to STATE_START

//========================================

void setup() {

  Serial.begin(9600);

  pinMode(led_L_Pin, OUTPUT);                    // set led_L_Pin as output
  pinMode(led_R_Pin, OUTPUT);                    // set led_R_Pin as output
  pinMode(motor_Pin, OUTPUT);                    // set motor_Pin as output
  pinMode(brake_Pin, OUTPUT);                    // set brake_Pin as output
  pinMode(direction_Pin, OUTPUT);                // set direction_Pin as output
  pinMode(sens_L_Pin, INPUT);                    // set sens_L_Pin as input
  pinMode(sens_R_Pin, INPUT);                    // set sens_R_Pin as input
  pinMode(current_sens_Pin, INPUT);              // set current_sens_Pin as input

}
//========================================

void loop() {

  currentMillis = millis();                      // store the latest value of millis()
  read_sens();                                   // read the sensors

  switch (state)                                 // state switch
  {
    case STATE_START:
      Start();
      break;

    case STATE_ACCELERATE:
      Accelerate();
      break;

    case STATE_DECELERATE:
      Decelerate();
      break;

    case STATE_TURN:
      Turn();
      break;

    case STATE_RUN:
      break;
  }
}
//========================================

void read_sens() {

  if (currentMillis - previous_sens_Millis >= read_sens_Interval) {   // time is up, so read sensors
    previous_sens_Millis = currentMillis;                             // because shooter and Koepel told me so.// save the time we last read sensors
    sensLreading = analogRead(sens_L_Pin);                            // read left ldr (high value means the light is off or blockt)
    sensRreading = analogRead(sens_R_Pin);                            // read right ldr (high value means the light is off or blockt)

    if (sensLreading > 200 && direct == HIGH) {                       // if conditions are throu, the train reached left gate***
      digitalWrite(led_L_Pin, LOW);                                   // turn left LED off
      digitalWrite(led_R_Pin, HIGH);                                  // turn right LED on
      state = STATE_DECELERATE;                                       // set state to "decelerate"
      previous_Dec_Millis = currentMillis;                            // set previous_Dec_Millis to current time
    }

    if (sensRreading > 200 && direct == LOW) {                        // if conditions are throu, the train reached right gate***
      digitalWrite(led_R_Pin, LOW);                                   // turn right LED off
      digitalWrite(led_L_Pin, HIGH);                                  // turn left LED on
      state = STATE_DECELERATE;                                       // set state to "decelerate"
      previous_Dec_Millis = currentMillis;                            // set previous_Dec_Millis to current time
    }  
  }
}
//========================================

void Start() {

  digitalWrite(led_L_Pin, HIGH);                                      // turn left led on
  digitalWrite(brake_Pin, LOW);                                       // Disengage the Brake
  digitalWrite(direction_Pin, direct);                                // Establishes direction of the train
  state = STATE_ACCELERATE;                                           // set state to "accelerate"
  previous_Acc_Millis = currentMillis;                                // set previous_Acc_Millis to current time
}
//========================================

void Accelerate() {

  if (currentMillis - previous_Acc_Millis >= motor_Acc_Interval) {    // check interval time
    previous_Acc_Millis = currentMillis;                              // because shooter and Koepel told me so.//last time of acceleration step
    Speed = Speed + 1;                                                // add 1 to speed
    analogWrite(motor_Pin, Speed);                                    // send Speed to motor_Pin
    if (Speed == max_Speed) {                                         // if speed reach max speed
      state = STATE_RUN;                                              // set state to "run"
    }
  }
}
//========================================

void Decelerate() {

  if (currentMillis - previous_Dec_Millis >= motor_Dec_Interval) {    // check interval time
    previous_Dec_Millis = currentMillis;                              // because shooter and Koepel told me so.//last time of acceleration step
    Speed = Speed - 1;                                                // subtract 1 of speed
    analogWrite(motor_Pin, Speed);                                    // send Speed to motor_Pin
    if (Speed == 0) {                                                 // if speed reach 0
      state = STATE_TURN;                                             // set state to "turn"
    }
  }
}
//========================================

void Turn() {

  if (direct == HIGH) {                                               // flip direction
    direct = LOW;
    digitalWrite(direction_Pin, direct);                              // establishes right direction of train
  }
  else {
    direct = HIGH;
    digitalWrite(direction_Pin, direct);                              // establishes left direction of train
  }
  state = STATE_ACCELERATE;                                           // set state to "accelerate"
  previous_Acc_Millis = currentMillis;                                // set previous_Acc_Millis to current time
}
//========================================END

Schematics

scematic
Traincontrol zpshnjui20s

Comments

Author

Masters
Masters
  • 1 project
  • 5 followers

Additional contributors

  • For al the help on the dutch arduino forum. by Koepel
  • For al the help on the dutch arduino forum. by shooter

Published on

October 7, 2016

Members who respect this project

Seth rollins wallpaper 2016 by crazyscarry da3u3pfPs07 8x10DefaultSteve massikkerImg013 3wk6r3an54E93826c2 9a64 46a5 8bc1 a25cf0a172ae

and 8 others

See similar projects
you might like

Similar projects you might like

Servo Control with TV Remote Control

Project showcase by eldo85

  • 5,596 views
  • 5 comments
  • 17 respects

Control an LED with the Remote Control

Project showcase by Nicholas_N

  • 3,192 views
  • 2 comments
  • 9 respects

Control Your Computer With A Remote Control

Project tutorial by

  • 6,679 views
  • 1 comment
  • 8 respects

Tutorial Arduino Mini Laser Turret Control

Project in progress by Josh From BreakoutBros.com

  • 9,401 views
  • 5 comments
  • 29 respects
Add projectSign up / Login