Train Control
In this simple project, we create a basic model train controller by interfacing a Scamp to an LMD18200 H-bridge. The H-bridge provides high current and high(er) voltage to drive a motor. Model train motors typically require a voltage of up to 12V, and a supply current of a few hundred milliamps. The design uses pulse-width modulation, or PWM, to control the motors inside the locomotives. As PWM uses pulses of fixed amplitude to drive the motor, the problems of low-voltage stalls disappear. Further, since the PWM is controlled by software, very slow speeds can be achieved giving very realistic operation. All the real “work” is done in the software, and you can keep it as simple or as fancy as you want.
The speed control is simply a 50 kΩ potentiometer, used as voltage divider. The wipers of these pots provide a voltage of between 0V and 3V3 to the analog inputs of the Scamp. Thus, the position of the control can easily be read by sampling an analog input in software. The direction control is a simple single-pole, single-throw (SPST) toggle switch.
The basic schematic for using the LMD18200 H-bridge is:
The speed control is simply a 50 kΩ potentiometer, used as voltage divider. The wipers of these pots provide a voltage of between 0V and 3V3 to the analog inputs of the Scamp. Thus, the position of the control can easily be read by sampling an analog input in software. The direction control is a simple single-pole, single-throw (SPST) toggle switch.
The basic schematic for using the LMD18200 H-bridge is:
This converts the PWM output of the processor to voltage levels appropriate for driving the small DC motors found in model locomotives, or for that matter, any sort of small DC motor. In the schematic, VS is the supply to drive the motor, and is +12V. The H-bridge has internal over-current sensing, and will shut itself off if its temperature rises too high (such as would happen if the outputs were shorted together). The FLAG output indicates when this occurs. This low-active, open-drain output can used to control an optional LED, or can be optionally connected to a switch input (pullup on) on the Scamp, so that the software can be made aware the fault condition and perhaps flash the LED. In this project, we will ignore FLAG as the H-bridge turns itself off in the unlikely event of a short.
To interface to the Scamp:
To interface to the Scamp:
- Wire pin 6 of the Scamp to pin 3 of the H Bridge.
- Wire pin 5 of the Scamp to pin 4 of the H Bridge.
- Wire pin 9 of the Scamp to pin 5 of the H Bridge.
Connect a toggle switch to pin 7 of the Scamp, and wire a potentiometer between 3V3 and GND on the Scamp, with the potentiometer output going to pin 0 of the Scamp.
An external voltage regulator circuit is used to convert the +12V supply to +5V so that the Scamp can run without a USB power source. The regulator chosen is a standard (and cheap) LM7805 that provides a constant +5 V output from an input voltage of between +7 V and +35 V. Since the motors of model locomotives run on a nominal maximum of +12 V, this is the actual supply voltage we will use for the system.
An external voltage regulator circuit is used to convert the +12V supply to +5V so that the Scamp can run without a USB power source. The regulator chosen is a standard (and cheap) LM7805 that provides a constant +5 V output from an input voltage of between +7 V and +35 V. Since the motors of model locomotives run on a nominal maximum of +12 V, this is the actual supply voltage we will use for the system.
Initializing
We create a word init to initialize the hardware. First, pin 1 of the Scamp is configured as an analog input and selected as the channel for sampling. The H-bridge has 3 inputs, brake, direction and pwm (speed). Brake isn't used in this application, as it causes a hard stop, but we still need to connect it for the H-bridge to work. Pin 6 of the Scamp is set as an output for the direction control, pin 5 is set as an output for the brake control and cleared (brake off). PWM channel 1 will be used to drive the PWM input of the H-bridge. PWM channel 1 is initialized with a duty cycle of 0 (off) and a period of 511. This will give a PWM frequency outside the range of human hearing. (The smaller the period, the higher the frequency.) Finally, pin 9 is configured as PWM channel 1.
: init
1 analog \ pin 1 is potentiometer
1 channel \ select pot for sampling
#6 output \ direction control for H bridge
#5 output \ brake control for H bridge
#5 clear \ brake off
#7 switch \ user switch for direction
0 1 duty \ speed to 0 for PWM channel 1
#511 1 period \ set PWM channel 1 period
#9 1 pwm \ set pin 9 to be PWM channel 1
;
Run init at the prompt to initialize the hardware:
init
Control Words
The 12-bit ADC has a range of 0 ... 4095. To scale this down to the PWM period of 511, we (unsigned) divide it by 8. So an ADC range of 0 ... 4096 will give a PWM duty cycle of 0 ... 511. Putting this together into a single word to set speed:
: speed
8 u/
1 duty
;
By typing a value followed by speed at the prompt, the train should move. Typing 0 speed will cause the train to stop.
We can create a word to read the direction switch and set the direction output:
We can create a word to read the direction switch and set the direction output:
: direction 7 get 6 out ;
If the control knob is at some random setting when our controller is first turned on, we don't want trains to spontaneously start moving. Therefore, we create a word to read the control knob and do nothing until it is 0. The LED blinks as an indicator that the controller is waiting:
: wait
begin
blink
sample 0=
until
;
Finally, we put it all together in a single control word:
: control
init
wait
begin
direction
sample speed
key?
until
0 speed
;
The word exits if we type a key on the keyboard, otherwise it will run forever. When we exit, we set the speed to 0 just in case the knob wasn't set to off when we exited.
Run control and test it.
Run control and test it.
Making it Turnkey
Once we are satisfied that control works as we want, we can set it to be our turnkey word. First though, we need to modify control to remove key? otherwise it will wait for USB comms to be established.
forget control \ forget the previous version
: control \ new version
init
wait
begin
direction
sample speed
again \ endless loop
0 speed
;
And then we can make it the startup word.
' control is turnkey
We now have a dedicated train controller that operates whenever it is turned on.
Create : Train Control