PICAXE Speed Controller
d. bodnar
revised 04-08-11

 

The objective of this project is to design and build a track-side controller that will operate a model train.

The controller will be based on a PICAXE 18M2 microcontroller and will be operated by a standard handheld TV remote control.

Functions will include

  • speed up
  • speed down
  • reverse direction
  • automatic timed reverse
  • gradual acceleration and deceleration
  • optional sound unit activation
  • pause / resume
  • configuration and operation with keypad on TV remote control
Consideration is being given to developing this controller as a kit.  
  1. circuit board
  2. 18M2
  3. relay
  4. 1N2004 diode
  5. 2n2222
  6. IFL530
  7. 852-GP1UX511QS - Sharp Infrared Receivers
  8. LED x 4
  9. 470 ohm resistors x 4
  10. 1000 ohm resistors x 2
  11. 10K resistor
  12. 22K resistor
  13. 7805 voltage regulator
  14. 0.1 mfd Tantalum capcaitor
  15. 0.1 mfd bypass capacitor x 2
     

 
The controller is very capable but made up of very few parts.  The schematic is shown below.  The main components are:
  • PICAXE 18M2 microcontroller
  • Infrared TV remote control
  • Infrared receiver module
  • DPDT relay (5 volt coil)
  • IRL 530 Mosfet power transistor
  • NPN transistor (2N2222)
  • Indicator LEDs
  • 7805 voltage regulator
  • DC power supply (12 to 24 volts)
TV Remote

The TV remote control is used to operate all functions of the controller.  The following buttons are used:

  • Channel Up - increase speed
  • Channel Down - decrease speed
  • Volume > or < - change direction
  • Mute - stop, remembering speed or start, at stored speed, after stop
  • Return - enter configuration mode
  • Number Keys - 1-->0 - enter configuration data

Using the Controller

The controller is connected to a source of filtered DC of between 12 and 24 volts.  Its output is connected to the rails of the track.

When first started the blue LED flashes out the software version number and the train's speed is set to zero.

Press and hold the UP ARROW key on the remote control to speed up and the DOWN ARROW to slow down.  Use either of the VOLUME keys to change direction.

Pressing the MUTE button at any time will stop the train.  Pressing it again will start it back up at the same speed that it was going when stopped.

(optional) - if a sound device is installed press number buttons 1, 2, 3 or 4 to activate the corresponding sounds.

To enter Configuration Mode press the RETURN button.  The unit will wait for you to enter 1, 2, 3 or 4.  These numbers select the following configuration modes:

   
1 Change Maximum Speed - the range is 0 to 255 with 255 being fast and 0 being stopped
2 Change Minimum Speed - the range is 0 to 255 with 255 - the minimum must be less than or equal to the maximum speed
3 Change Run Time - the range is 0 to 255 -  this is the time (in seconds) that the train will run in one direction before slowing, reversing and speeding up to the same speed.  Entering 0 will disable automatic reversing. 
4 Change Acceleration / Deceleration rate - the range is 0 to 255 with 0 being very fast acceleration / deceleration and 255 being very, very slow acceleration / deceleration - the useful range is -0 to about 30.  Beyond 30 the rate is too slow.
5 (not yet set) - Change run time before slow down to minimum speed - this is the time in seconds that will elapse before the train changes speed from its maximum speed to its minimum
6 (not yet set) - Change Acceleration rate (independent of deceleration rate)
7 (not yet set) - Change Deceleration rate (independent of acceleration rate)
   

 

Software

The software for the PICAXE 18M2 is shown here.

C:\Shared_stuff\PICAXE-18M2\18M2-IR_motor_control-MultiFunctionv3-0.bas
1
2 'd. bodnar 4-6-2011 v3.0 Working Well!
3 Symbol Sound1 = b.4 'pin 10
4 Symbol Sound2 = b.5 'pin 11
5 Symbol Sound3 = b.6 'pin 12
6 Symbol Sound4 = b.7 'pin 13
7 Symbol Motor = b.3 'pin 9
8 Symbol Relay = b.0 'pin 6
9 Symbol Track = pinc.5 'pin 4 input only
10 Symbol T1 = b.1 'pin 7
11 Symbol IRSense = b.2 'pin 8
12 Symbol T3 = c.0 'pin 17
13 Symbol T4 = c.1 'pin 18
14 Symbol LEDBlue = c.6 'pin 15
15 Symbol LEDAmber = c.7 'pin 16
16 Symbol L3 = b.6 'pin 12
17 Symbol L4 = b.7 'pin 13
18
19 symbol Loop1 = b27
20 symbol Digit = b26
21 symbol Value = b25
22 Symbol ValueTemp = b24
23 symbol divisor = b23
24 symbol temp5 = b22
25 symbol temp = b21
26 symbol temp6 = b20
27 symbol TimeTemp = w5
28 Symbol ADRate = b16
29
30 symbol digitsbyte = b19
31 Symbol Loopie0 = W1
32 Symbol SetSpeed = w2
33 Symbol MinSpeed = w3
34 Symbol InfraRED = b12
35 Symbol TempStore= w4
36 Symbol TempByte = b18
37 Symbol WaitTime = b17 'pause before reverse
38
39 Symbol LStart = 0'120'450
40 Symbol TTrigger = 7000
41 Symbol Period = 150
42 Symbol PWMMin = 0'350
43 Symbol PWMMax = 1023'600
44 Symbol ChUp = 16
45 Symbol ChDown = 17
46 Symbol VolUp = 18
47 Symbol VolDown = 19
48 Symbol OK = 20
49 Symbol Retrn = 59
50 Symbol One = 0
51 Symbol Two = 1
52 Symbol Three = 2
53 Symbol Four = 3
54 Symbol Five = 4
55 Symbol Six = 5
56 Symbol Seven = 6
57 Symbol Eight = 7
58 Symbol Nine = 8
59 Symbol Zero = 9
60 Symbol Power = 21
61 Symbol VerWhole = 3
62 Symbol VerDecimal = 0
63
64 high sound1:high sound2:high sound3:high sound4
65
66 WaitTime = 0
67 ADRate = 10
68 Read 0, WORD SetSpeed
69 if SetSpeed = 0 then
70 SetSpeed = LStart
71 endif
72 SetSpeed=0
73 pwmout motor,50,500'150 ; set pwm duty
74
75 pwmduty motor, SetSpeed
76 for tempbyte=1 to VerWhole:high LEDBlue:pause 200:low LEDBlue:pause 200:next tempbyte:pause 900
77 temp=verdecimal
78 IF temp > 0 then
79 for tempbyte=1 to VerDecimal:high LEDBlue:pause 200:low LEDBlue:pause 200:next tempbyte
80 else
81 high ledblue:pause 10:low ledblue
82 endif
83 sertxd("d. bodnar",13,10,"4-6-2011 v3.0",13,10,13,10) '4800 baud @ this clock speed
84
85 Cruise:
86 if waittime=0 then SkipReverse:
87 if time >=WaitTime then
88 sertxd("Time= ",#time,13,10)
89 time=0
90 goto Revers
91 endif
92 SkipReverse:
93 Infrared=255
94 Irin [50, Cruise],IrSense, InfraRED
95 sertxd("IR= ",#infrared,13,10)
96 if InfraRED = Retrn then GetOption
97 if infrared= One then
98 low sound1:pause 200:high sound1
99 endif
100 if infrared= Two then
101 low sound2:pause 200:high sound2
102 endif
103 if infrared= Three then
104 low sound3:pause 200:high sound3
105 endif
106 if infrared= Four then
107 low sound4:pause 200:high sound4
108 endif
109
110
111 if InfraRED = VolUp or InfraRED=VolDown then Revers
112
113 if InfraRed = OK then
114 Sertxd("@ OK",13,10)
115 if SetSpeed > 0 then
116 TempStore=SetSpeed
117 gosub decel
118 SetSpeed=0
119 disabletime
120 pause 1000
121 else
122 SetSpeed = TempStore
123 gosub accel
124 enabletime
125 endif
126 endif
127
128 if InfraRED=ChUp then
129 high LEDAmber
130 SetSpeed = SetSpeed +5
131 pwmduty motor,SetSpeed
132 write 0, WORD SetSpeed
133 sertxd(#setspeed,13,10)
134 else
135 low LEDAmber
136 endif
137 if InfraRED=ChDown then
138 high LEDAmber
139 if SetSpeed > 5 then
140 SetSpeed = SetSpeed -5
141 sertxd(#setspeed,13,10)
142 endif
143 pwmduty motor,SetSpeed
144 write 0, WORD SetSpeed
145 else
146 low LEDAmber
147 endif
148 goto Cruise:
149
150 GetOption:
151 sertxd("@GetOption",13,10)
152 pause 1000
153 StayHere2:
154 Infrared=255
155 Irin [50, StayHere2],IrSense, InfraRED
156 sertxd("IR= ",#infrared,13,10)
157 if infrared >3 then
158 goto cruise
159 endif
160
161 Branch infrared, (speedmax, speedmin, runtime, acceldecelrate)
162 goto cruise
163
164 speedmax:
165 value = setspeed
166 gosub flashvalue
167 gosub getirnumber
168 setspeed=digitsbyte
169 sertxd("setspeed= ",#setspeed,13,10)
170 goto cruise:
171
172 speedmin:
173 value = minspeed
174 gosub flashvalue
175 gosub getirnumber
176 minspeed=digitsbyte
177 sertxd("minspeed= ",#minspeed,13,10)
178 goto cruise:
179
180 runtime:
181 value = waittime
182 gosub flashvalue
183 gosub getirnumber
184 waittime=digitsbyte
185 sertxd("waittime= ",#waittime,13,10)
186 goto cruise:
187
188 acceldecelrate:
189 value = adrate
190 gosub flashvalue
191 gosub getirnumber
192 adrate=digitsbyte
193 sertxd("adrate= ",#adrate,13,10)
194 goto cruise:
195
196 AutoReverse:
197 for b0=1 to 10:toggle IrSense:pause 100:next b0
198 goto cruise
199
200 Revers:
201 sertxd("@Revers",13,10)
202 gosub decel
203 toggle relay
204 pause 1000
205 gosub accel
206 goto Cruise:
207
208 Accel:
209 disabletime
210 low sound1:pause 200:high sound1
211 sertxd("@Accel",13,10)
212 for loopie0= PWMMin to SetSpeed step 5
213 sertxd(#loopie0," ")
214 pwmduty motor,loopie0 ; set pwm duty
215 pause adrate
216 next loopie0
217 sertxd(13,10)
218 enabletime
219 return
220
221 Decel:
222 low sound2:pause 200:high sound2
223 disabletime
224 sertxd("@Decel",13,10)
225 for loopie0= SetSpeed to PWMMin step -5
226 sertxd(#loopie0," ")
227 pwmduty motor, loopie0
228 pause adrate
229 next loopie0
230 sertxd(13,10)
231 enabletime
232 return
233
234 FlashValue: 'Flash out current reading
235 sertxd(13,10,"@FlashValue ",#value,13,10)
236 ValueTemp=Value
237 for Loop1= 2 to 0 step -1
238 if Loop1=2 then
239 divisor=100
240 endif
241 if Loop1=1 then
242 divisor=10
243 endif
244 if Loop1=0 then
245 divisor=1
246 endif
247
248 sertxd("divisor ",#divisor," ")'debug divisor
249 Digit=ValueTemp /divisor
250 sertxd("digit ",#digit," ",13,10)' debug Digit
251 temp5=Digit * divisor
252 ValueTemp=ValueTemp - temp5
253 sertxd("valuetemp ",#valuetemp," ",13,10)'debug ValueTemp
254 if Digit=0 then
255 high LEDAmber:pause 50:low LEDAmber:pause 100:pause 600:goto skipover3:
256 endif
257 for temp=1 to Digit
258 high LEDAmber:pause 200:low LEDAmber:pause 200
259 next temp
260 pause 600
261 SkipOver3:
262 next Loop1
263 return
264
265 GetIRNumber:
266 sertxd(13,10,"@GetIRNumber",13,10)
267 DigitsByte=0:digit=3
268 GetDigits0:
269 Infrared=255
270 irin [50, GetDigits0],irsense, InfraRED
271 sertxd("infrared ",#infrared," ",13,10)
272 if infrared > 9 then
273 return
274 endif
275 infrared =infrared +1
276 if infrared = 10 then
277 infrared=0
278 endif
279 if digit=3 and infrared>2 then getdigits0:'can't be above 2hunderds
280 if digit=2 and digitsbyte = 2 and infrared > 5 then getdigits0
281 if digit=1 and digitsbyte =25 and infrared > 5 then getdigits0
282 skiprnd:
283 sertxd("Digit= ",#digit,13,10)
284 if infrared=0 then
285 high LEDAmber:pause 50:low LEDAmber
286 endif
287 for tempbyte=1 to infrared:high LEDAmber:pause 200:low LEDAmber:pause 200:next tempbyte
288 DigitsByte=DigitsByte*10+infrared
289 digit=digit-1
290 pause 200':'command=0
291 if digit=0 then
292 sertxd("Digitsbyte ",#digitsbyte," ",13,10)
293 return
294 endif
295 goto GetDigits0:
296