PICAXE Speed
Controller
with MP3 Player
d. bodnar revised 11-23-2015
Introduction The PICAXE Speed Controller that is described here http://www.trainelectronics.com/PicaxeSpeedController/article.htm has been updated so that the same infrared controller that is used to change speed, direction and other functions can now access sound files on a small MP3 player.
|
Playing Sound Files Sound files are stored on a micro SD card that is inserted into the DFPlayer. The files are stored in a subdirectory called mp3 and named 0001.mp3, 0002,mp3 and so on. The current software revision can address up to 255 sound files. To play a sound file press the "Source" button on the TV remote control until the blue LED illuminates (it may take more than one press). Once the LED is lit enter the three digit file number. For single or double digit file names you MUST enter leading zeros. For example, to play file number 7 you must enter 007 on the keypad. |
Schematic The schematic has been modified to accommodate the DFPlayer. Pins 18 is used to send commands to the DFPlayer and pin 17 is used to sense when a sound file is being played. |
Hardware The DFPlayer is mounted on a secondary board and connects to the main PICAXE board with four wires, +5 volts, ground, data and busy.
The wiring on the back of the DFPlayer is shown here - note the 1K resistor that goes to the RX pin. The yellow and orange wires connect as shown here on the front of the PICAXE board. +5 volts and ground can be picked up as shown. |
Acrylic Plastic Case This case was cut from 1/8" acrylic using a laser cutter. It has cutouts for the heat sink, power plug, track connection and speaker.
|
Software The code below is the original program plus the MP3 player code. 'added DFPlayer code 11-23-2015 'd. bodnar - 11-02-2011 v6.3 ' note about direction added 2-24-12 #PICAXE 18M2 #TERMINAL 9600 #no_data SETFREQ m8 ' needed to get baud to work with DFPlayer Symbol Direction2 = b.0 'pin 6 - one high & one low - swap to change direction 'Symbol NOTUSEDb1 = b.1 'pin 7 Symbol IRSense = b.2 'pin 8 Symbol Motor = b.3 'pin 9 - PWM output for motor speed 'Symbol NOTUSEDb4 = b.4 'pin 10 Symbol Direction1 = b.5 'pin 11 - one high & one low - swap to change direction-if = fast motor stop 'Note - change above from pin 11 to pin 7 - b.1 for older circuit board 'Symbol NOTUSEDb6 = b.6 'pin 12 'Symbol NOTUSEDb7 = b.7 'pin 13 Symbol MP3Busy = c.0 'pin 17 - TEST FOR Busy from DFPlayer Symbol MP3Tx = pinc.1 'pin 18 - TEST FOR TX to DFPlayer 'Symbol Aux1 = c.2 'pin 1 - can be used for current sensing - OR OTHER PURPOSES! 'Symbol NOTUSEDc3 = c.3 'pin 2 'Symbol NOTUSEDc4 = c.4 'pin 3 'Symbol Aux4 = c.5 'pin 4 input only Symbol LEDAmber = c.6 'pin 15 Symbol LEDBlue = c.7 'pin 16 'Symbol HalfAC = pinb.4 'pin 10 Symbol InfraRED = b27 'store IR value symbol Digit = b26 'Flash Value symbol Value = b25 'Flash Value & Version Symbol ValueTemp = b24 'Flash Value symbol divisor = b23 'Flash Value symbol temp5 = b22 'Flash Value & GetRndOnce symbol temp = b21 'Flash Value & Version Symbol CruiseTime = b20 'Time to run before reversing symbol digitsbyte = b19 'Get number routine Symbol TempByte = b18 'Flash Value & Version & Get IR Num Symbol WaitTime = b17 'pause before reverse Symbol ADRate = b16 'accel / decel rate Symbol DecelTime = b15 'point where decel beings on p-2-p Symbol RndmWait = b14 'RANDOM - needed? Symbol mp3file = b13 Symbol temp2 = b12 Symbol UnUsedb11 = b11 Symbol TempWord = w5 'RANDOM - needed? Symbol Loopie0 = w4 'Decel & Random Symbol MinSpeed = w3 Symbol SetSpeed = w2 Symbol DecelFlag = Bit0 '=1 if decel time has caused deceleration otherwise =0 Symbol FwdBkwFlag = Bit1 '=1 if forwrad / =0 if backward Symbol SlowDnFlag = Bit2 '=0 if no slow down point set, =1 if set Symbol Decel2Zero = Bit3 '=1 if we want deceleration to zero, not minimum speed 'Also Using 'Memory 30 for Decel loop start value (word) 'Memory 32 for Decel loop end value (word) 'Memory 34 for time temp storage (byte) Symbol LStart = 0'120'450 Symbol TTrigger = 7000 Symbol Period = 150 Symbol PWMMax = 1023'600 Symbol ChUp = 16 Symbol ChDown = 17 Symbol VolUp = 18 Symbol VolDown = 19 Symbol OK = 20 Symbol Retrn = 59 Symbol One = 0 Symbol Two = 1 Symbol Three = 2 Symbol Four = 3 Symbol Five = 4 Symbol Six = 5 Symbol Seven = 6 Symbol Eight = 7 Symbol Nine = 8 Symbol Zero = 9 Symbol Power = 21 Symbol MENU = 96 Symbol VChip = 14 Symbol Exxit = 99 Symbol VerWhole = 6 Symbol VerDecimal = 3 Symbol Source = 37 ' source button used to initiate MP3 sound from DFPlayer high direction1:low direction2 VeryTop: Read 0, WORD SetSpeed 'read variables from memory Read 2, WORD MinSpeed Read 4, WaitTime Read 5, ADRate Read 6, DecelTime Read 7, RndmWait Read 8, slowdnflag if DecelTime=0 then DecelTime=WaitTime endif decelflag=0 if deceltime <> waittime then decelflag=1 slowdnflag=1 endif pwmout motor,50,500' set pwm duty pwmduty motor, 0 Pause 500 sertxd("d. bodnar",13,10,"11-23-2015 v6.3- DFPlayer 1.1",13,10,13,10) '9600 baud @ this clock speed ;Routine to flash out version number of software for tempbyte=1 to VerWhole:high LEDBlue:pause 150:low LEDBlue:pause 150:next tempbyte:pause 400 temp=verdecimal IF temp > 0 then for tempbyte=1 to VerDecimal:high LEDBlue:pause 150:low LEDBlue:pause 150:next tempbyte else high ledblue:pause 10:low ledblue endif Pause 1000 GOSUB ShowReadValues gosub accel time=0 Cruise: Random TempWord if time <=2 then gosub GetRndOnce 'Routine to show time that has passed on Terminal PEEK 34, TempByte if time>254 then time=0 endif if time <> TempByte then sertxd("t=",#time," ") POKE 34, time toggle ledamber endif 'if no auto-reverse (waittime) has been set don't reverse or decel if waittime=0 then goto SkipReverse endif 'Slow down to minspeed if decel point has been set - do it only once via decelflag if time >= DecelTime and decelflag =0 and DecelTime<>CruiseTime then sertxd("@deceltime ",#deceltime," f ",#decelflag,13,10) gosub DecelSet2Min DecelFlag=1 endif 'Run time has expired - bring to complete stop & reverse if time >=CruiseTime then sertxd("Time= ",#time,13,10) time=0 decelflag=0 goto Revers endif SkipReverse: 'Get IR input and act on it {Infrared=255 Irin [1, Cruise],IrSense, InfraRED sertxd("IR 0= ",#infrared," ") if InfraRed = Source then sertxd(10,13,"@ Source Button ",10,13) gosub getirnumber sertxd("mp3 # = ",#digitsbyte," ") MP3File = digitsbyte gosub pmp3 endif if InfraRED = Power then 'use POWER button to set deleration point DecelTime=time SlowDnFlag=1 Write 6, DecelTime Write 8, Slowdnflag gosub ShowReadValues endif if InfraRED = OK then 'Mute on Westinghouse Remote - hit it to set minimum speed MinSpeed=SetSpeed Write 2, word MinSpeed Write 8, Slowdnflag gosub ShowReadValues endif if InfraRED = Retrn then GetOption 'after RETURN button choose 1-->4 to set options if InfraRED = VolUp and FwdBkwFlag =0 then ' VOLUME UP and DOWN to change direction FwdBkwFlag = 1 goto revers endif if InfraRED=VolDown and FwdBkwFlag =1 then ' VOLUME UP and DOWN to change direction FwdBkwFlag = 0 goto revers endif if InfraRed = MENU then 'press MENU to pause & save speed or to restart after pausing Sertxd("@ MENU",13,10) if SetSpeed > 0 then POKE 30,WORD SetSpeed if MinSpeed <> 0 then Decel2Zero=1 endif gosub decel SetSpeed=0 disabletime pause 1000 else PEEK 30, WORD SetSpeed gosub accel enabletime endif endif if InfraRED=ChUp then 'CHANNEL UP and DOWN to speed up or down high LEDBlue SetSpeed = SetSpeed +5 pwmduty motor,SetSpeed write 0, WORD SetSpeed Write 8, Slowdnflag sertxd(#setspeed,13,10) else low LEDBlue endif if InfraRED=ChDown then 'CHANNEL UP and DOWN to speed up or down high LEDBlue if SetSpeed > 5 then SetSpeed = SetSpeed -5 sertxd(#setspeed,13,10) endif pwmduty motor,SetSpeed write 0, WORD SetSpeed Write 8, Slowdnflag else low LEDBlue endif} goto Cruise: { GetRndOnce: 'Put time to run train into Temp Random TempWord loopie0=65535/rndmwait Temp5=tempword/loopie0 CruiseTime=WaitTime+temp5 return GetOption: pwmduty motor,0 ; STOP sertxd("@GetO",13,10) pause 1000 StayHere2: Infrared=255 Irin [1, StayHere2],IrSense, InfraRED sertxd("IR= ",#infrared," ") if infrared = VChip then goto ReadyReset: endif if infrared >4 then 'only accepts number buttons 1-->4 goto cruise endif Branch infrared, (speedmax, speedmin, runtime, acceldecelrate, RndmSetting) goto cruise RndmSetting: value = RndmWait gosub flashvalue gosub getirnumber RndmWait=digitsbyte sertxd("RndmWait= ",#RndmWait,13,10) write 7, RndmWait Write 8, Slowdnflag gosub ShowReadValues gosub accel goto cruise: speedmax: value = setspeed gosub flashvalue gosub getirnumber setspeed=digitsbyte sertxd("max= ",#setspeed,13,10) write 0, word setspeed Write 8, Slowdnflag gosub ShowReadValues gosub accel goto cruise: speedmin: value = minspeed gosub flashvalue gosub getirnumber minspeed=digitsbyte sertxd("min= ",#minspeed,13,10) write 2, word MinSpeed gosub ShowReadValues gosub accel goto cruise: runtime: value = waittime gosub flashvalue gosub getirnumber waittime=digitsbyte write 4, WaitTime Write 8, Slowdnflag sertxd("wait= ",#waittime,13,10) time=0 if DecelTime=0 then DecelTime=WaitTime endif gosub ShowReadValues gosub accel goto cruise: acceldecelrate: value = adrate gosub flashvalue gosub getirnumber adrate=digitsbyte write 5, adrate Write 8, Slowdnflag gosub ShowReadValues sertxd("ad= ",#adrate,13,10) goto cruise: ReadyReset: Infrared=255 Irin [1, ReadyReset],IrSense, InfraRED if infrared = Exxit then DoIt if infrared = Power then Cruise goto readyreset DoIt: deceltime=0:setspeed=0:minspeed=0:waittime=0:adrate=0:RndmWait=0:slowdnflag=0 Write 0, WORD SetSpeed Write 2, WORD MinSpeed Write 4, WaitTime Write 5, ADRate Write 6, DecelTime Write 7, RndmWait Write 8, slowdnflag goto VeryTop: AutoReverse: for b0=1 to 10:toggle IrSense:pause 100:next b0 goto cruise} Revers: sertxd("@Revers",13,10) Decel2Zero=1 gosub decel pause 1000 toggle direction1:toggle direction2 gosub accel goto Cruise: Accel: disabletime sertxd("@Accel",13,10) for loopie0= 0 to SetSpeed step 5 sertxd(#loopie0," ") pwmduty motor,loopie0 ; set pwm duty toggle ledblue pause adrate next loopie0 sertxd(13,10) enabletime return Decel: disabletime sertxd("@Decel",13,10) if decelflag=1 then return endif if SlowDnFlag=1 then for loopie0=minspeed to 0 step -3 gosub DecelLoop: next loopie0 goto skip0: endif if Decel2Zero=1 then Decel2Zero=0 for loopie0=setspeed to 0 step-3 gosub DecelLoop: next loopie0 goto skip0: endif DecelSet2Min: sertxd("@DecelSet2Min",13,10) for loopie0= SetSpeed to MinSpeed step -5 gosub DecelLoop: next loopie0 Skip0: sertxd(13,10) enabletime low LEDBlue return DecelLoop: toggle LEDBlue sertxd(#loopie0," ") pwmduty motor, loopie0 pause adrate return FlashValue: 'Flash out current reading sertxd(13,10,"@FV ",#value,13,10) ValueTemp=Value for TempByte= 2 to 0 step -1 if TempByte=2 then divisor=100 endif if TempByte=1 then divisor=10 endif if TempByte=0 then divisor=1 endif Digit=ValueTemp /divisor sertxd("digit ",#digit," ",13,10)' debug Digit temp5=Digit * divisor ValueTemp=ValueTemp - temp5 if Digit=0 then high LEDBlue:pause 50:low LEDBlue:pause 100:pause 600:goto skipover3: endif for temp=1 to Digit high LEDBlue:pause 200:low LEDBlue:pause 200 next temp pause 600 SkipOver3: next TempByte return GetIRNumber: sertxd(13,10,"@GetIR 2",13,10) DigitsByte=0:digit=3 GetDigits0: InfraRED=0 'pause 40 irin [10, GetDigits0],irsense, InfraRED 'Irin [1, StayHere2],IrSense, InfraRED 'pause 20 if infrared=37 then high ledblue sertxd ("3--7",10,13) goto getdigits0 endif high ledblue sertxd("@Blue LED!!!!!!!!!!!!",13,10) high ledblue sertxd("IRx ",#InfraRED," ",13,10) if infrared > 9 then return endif infrared =infrared +1 if infrared = 10 then infrared=0 endif if digit=3 and infrared>2 then getdigits0:'can't be above 2hundreds if digit=2 and digitsbyte = 2 and infrared > 5 then getdigits0 if digit=1 and digitsbyte =25 and infrared > 5 then getdigits0 skiprnd: sertxd("Digit= ",#digit,13,10) if infrared=0 then high LEDBlue:pause 50:low LEDBlue endif for tempbyte=1 to infrared:high LEDBlue:pause 100:low LEDBlue:pause 100:next tempbyte DigitsByte=DigitsByte*10+infrared digit=digit-1 pause 200':'command=0 if digit=0 then sertxd("Digitsbyte ",#digitsbyte," ",13,10) return endif goto GetDigits0: ShowReadValues: SERTXD("SPD, MIN, WAIT, AD, RdomWait,DecelFlag ",#setspeed," ",#minspeed," ",#waittime, " ", #adrate," ",#RndmWait," ",#deceltime," ",#b0, 13,10) sertxd ("sdf=",#slowdnflag,13,10) RETURN PMP3: sertxd(13,10,"@PMP3 ",#mp3file,13,10) temp = mp3file+1 temp5=$e9-temp serout c.1 ,T9600_8,( $20,$20,$7e,$ff,$06,$12,0,0,temp,$fe, temp5, $ef ,$20,$20) 'Play 1 return
|