PWM problem on a simple programme - relative beginner

I am building a garden railway loco to be controlled by the Picaxe IR kit. The motor is an MFA 12v motor controlled by an L298 controller connected to a 20M2 chip.
Functions at the moment are: slow forward, fast forward, reverse, stop and horn.

Everything is installed in the loco and works well except for one thing:- Every time I press a key on the remote the loco takes a lurch forward as if it was receiving full power from the batteries. (8 NiMh cells) Nowhere in the programme is the duty cycle high enough to cause this.
Even if I press a non functioning button the motor take this lurch. Initially debug would not work and I read somewhere that putting a Pause 500 command at the beginning would help with this. If I put this in, holding ANY button down sends surges to the motor every half second. Changing the value changes the rate of this pulse. The desired functions still operate normally.

I have played about with this kind of thing for a while but this is the first time that I have used a decent motor to drive a loco.
Perhaps someone out there can tell me what I am doing wrong. I know my programming is probably clumsy but I really want to keep it simple at this stage

#picaxe 20M2 ;to make debug work

main:
Low B.0 ;to make debug work
irin C.7,b0
debug b0

if b0 = 16 then
gosub speed1
endif

if b0 = 19 then
gosub speed2
endif

if b0 = 17 then
gosub back
endif

if b0 = 8 then
gosub horn
endif

if b0 = 18 or b0 = 21 then
gosub still
endif
goto main


speed1: ;slow speed
low B.3
high B.2
pwmout C.3,14 ,30 ;last variable may be changed
let b1 = 30 ;to confirm current duty cycle
goto main

speed2: ;faster speed
high B.2
low B.3
pwmout C.3,14 ,40
let b1 = 40
goto main

back: ;reverse
high B.3
low B.2
pwmout C.3,14 ,35
let b1 = 35
goto main

still: ;stop
low B.3
low B.2
goto main

horn: ;horn sound
sound B.1,(100,80)
pause 100
sound B.1,(100,100 )
goto main
 

lbenson

Senior Member
Welcome to the forum.

This (maybe) doesn't address your immediate problem, but whenever you GOSUB to a label, you must use RETURN to finish that block of code, not GOTO MAIN. The GOSUBs with no corresponding RETURN will quickly cause your program to overflow the GOSUB stack, and the program will fail.

What exact calculation did you use to get your PWM values? You might put a comment on each PWMOUT command to signify what you intend the duty and cycle values to represent.

For STILL:, do you not want to issue the command PWMOUT pin, OFF?

It would help if you could link to the specifications for your motor.

Finally, as a matter of forum practice, it's best to post your code within the tags "[ code]" and "[ /code]" (without the spaces) so that any indentation you have in your code to demarcate blocks of code will be retained.
 
Last edited:

The bear

Senior Member
Hi,
From a beginner, using Gosub & Return, as suggested above.
This is just fill-in, until you get some expert advice.
bear..
Code:
#picaxe 20M2 ;to make debug work
main:
Do
 Do
  Do
   Do
    Do
 Low B.0 ;to make debug work
 Readadc C.7,b0 ;Readadc instead of Irin, so I could adjust b0
;Irin C.7,b0
;Debug b0
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  If b0 = 16 Then
Gosub speed1
 Pause 1000
 Loop
  endif
  If b0 = 19 Then
Gosub speed2
 Pause 1000
 
 Loop
  endif
  If b0 = 17 Then
Gosub back
 Pause 1000  
 Loop
  endif
  If b0 = 8 Then
Gosub horn
 Pause 1000  
 Loop
  endif
  If b0 = 18 Or b0 = 21 Then
Gosub still
 Pause 1000
 Loop
  endif
;Goto main
;-------------------------------------------------------------
speed1: ;slow speed
  Low B.3
  High B.2
  Pwmout C.3,14 ,30 ;last variable may be changed
  Let b1 = 30 ;to confirm current duty cycle
Return
;Goto main
speed2: ;faster speed
  High B.2
  Low B.3
  Pwmout C.3,14 ,40
  Let b1 = 40
Return
;Goto main
back: ;reverse
  High B.3
  Low B.2
  Pwmout C.3,14 ,35
  Let b1 = 35
Return
;Goto main
still: ;stop
  Low B.3
  Low B.2
Return
;Goto main
horn: ;horn sound
  Sound B.1,(100,80)
  Pause 100
  Sound B.1,(100,100 )
Return
;Goto main
 
Last edited by a moderator:

inglewoodpete

Senior Member
I would do two things with your project to better understand what is happening.

The first is to correct the subroutine exit methods as the previous posts describe.

It is possible that there is a wiring problem and the motor's starting current surge is causing the PICAXE to reboot. My second modification would be to temporarily add an LED with current limiting resistor to a spare pin. Then, at the start of your code, before the Main: label, add a PulsOut {pin}, 500 command. The LED will indicate whenever the PICAXE reboots.

Finally, 65kHz is quite a high PWM frequency for a motor. You might want to try a much lower frequency like 10 or 20kHz
 

hippy

Technical Support
Staff member
Code:
#picaxe 20M2 ;to make debug work
main:
Do
 Do
  Do
   Do
    Do
 Low B.0 ;to make debug work
Those DO's and LOOP's elsewhere are not going to help things. You are better off using your original post #1 code and just changing the 'goto main' command sin your subroutines to 'return'.

Even with 'goto main' I believe the original code should run on an actual PICAXE chip without noticeable issues.

That you get surges when any button is pressed suggests there may be some problem other than a code issue,

Perhaps post a circuit diagram of how you have the L298 and everything else wired.
 

lbenson

Senior Member
Here's your code with RETURNs but also with the IFs reduced through the use of ELSEIF (you could also use a SELECT statement). If you uncomment the SERIN statement you can run this in the simulator and single-step through the code to see what is happening.

Code:
'Derelict48.bas
#picaxe 20M2 ;to make debug work

main:
  Low B.0 ;to make debug work
  irin C.7,b0
'  serin C.7,N2400_4,b0 ' use this to test in simulator
  ' debug b0 ' debug is slow--sertxd may work better
  sertxd("irin: ",#b0,cr,lf)

  if b0 = 16 then
    gosub speed1
  elseif b0 = 19 then
    gosub speed2
  elseif b0 = 17 then
    gosub back
  elseif b0 = 8 then
    gosub horn
  elseif b0 = 18 or b0 = 21 then
    gosub still
  endif
  goto main

speed1: ;slow speed
  low B.3
  high B.2
  pwmout C.3,14 ,30 ;last variable may be changed
  let b1 = 30 ;to confirm current duty cycle
  return

speed2: ;faster speed
  high B.2
  low B.3
  pwmout C.3,14 ,40
  let b1 = 40
  return

back: ;reverse
  high B.3
  low B.2
  pwmout C.3,14 ,35
  let b1 = 35
  return

still: ;stop
  low B.3
  low B.2
  PWMOUT C.3, OFF
  return

horn: ;horn sound
  sound B.1,(100,80)
  pause 100
  sound B.1,(100,100 )
  return
It would still be a good idea to make the PWM values meaningful.
 

hippy

Technical Support
Staff member
And the main lump of what lbenson posted can be further improved with a SELECT CASE -

Code:
main:
  irin C.7,b0
  sertxd("irin: ",#b0,cr,lf)
  select case b0
    case 16     : gosub speed1
    case 19     : gosub speed2
    case 17     : gosub back
    case  8     : gosub horn
    case 18, 20 : gosub still
  end select
  goto main
 
Many thanks to all who gave me help. All of you recommended replacing GOTO MAIN with GOSUB.
I really should have spotted this. All I have to learn from is the online manual and the pages on each command many of which do not give clear examples. Hippy's use of SELECT CASE totally solved the problem of the lurching. Other tips I will try at a later date. I had a chip die on me - reason unknown, which held me back.
However the loco is working to my satisfaction at the moment and will be demonstrated to colleagues on Sunday.

I will try to post the working code, minus the GOSUBs. I have learned a few things from your responses, so again, many thanks, Derelict48

Code:
Main:
irin C.7,b0
sertxd (b0,b1) 
select case b0
    case 16    :gosub speed1
    case 19    :gosub speed2
    case 17    :gosub back
    case 8    :gosub horn
    case 18,21    :gosub still
end select
goto main
 
Many thanks!
Welcome to the forum.

This (maybe) doesn't address your immediate problem, but whenever you GOSUB to a label, you must use RETURN to finish that block of code, not GOTO MAIN. The GOSUBs with no corresponding RETURN will quickly cause your program to overflow the GOSUB stack, and the program will fail.

What exact calculation did you use to get your PWM values? You might put a comment on each PWMOUT command to signify what you intend the duty and cycle values to represent.

For STILL:, do you not want to issue the command PWMOUT pin, OFF?

It would help if you could link to the specifications for your motor.

Finally, as a matter of forum practice, it's best to post your code within the tags "[ code]" and "[ /code]" (without the spaces) so that any indentation you have in your code to demarcate blocks of code will be retained.

Many thanks! I have learned a lot from this. I will investigate PWM values later, but at the moment the loco is working well and I will change the STILL command to us the OFF term. Derelict48
 

lbenson

Senior Member
Glad to hear you got it working to your satisfaction.

I'd still be interested to know what your PWM values represent, and what motor you're using.
 
Glad to hear you got it working to your satisfaction.

I'd still be interested to know what your PWM values represent, and what motor you're using.

Hello again, Yesterday I added another subroutine which slows the motor to a halt (for next ...step -1 etc) but kept the red on/off button on the remote control for an 'emergency stop.' Today I tried it on my outdoor layout and was very impressed by the performance. It pulled lots of wagons at a very nice scale speed.

The motor I am using is an MFA 4.5 -15V running on 8 NiMh cells. The motor reference is 719-RE385 and is easily found on the net. As far as the PWM values are concerned I used a period value of 14 which is the value I used to get the cheaper motors I am used to working with to perform properly. Using the Picaxe wizard this equates to 66.7 kHz. The duty cycle works out at about 65% for the higher speed. I hope this is of interest to you.
 

lbenson

Senior Member
Nice motor--thank you for the information. Can you at your convenience provide a video of your setup in action?
 
Nice motor--thank you for the information. Can you at your convenience provide a video of your setup in action?
Indeed I will do this as soon as I can. It will be a day or two though, as I am now packing for two model shows at the weekend and my power will be off tomorrow - not today, as I previously said.
 

Dartmoor

Member
Finally, 65kHz is quite a high PWM frequency for a motor. You might want to try a much lower frequency like 10 or 20kHz
Yes, 65kHz is quite high. I guess this is to avoid the annoying whine that gets generated by the motor. 30kHz is adequate, as it is well above what the human ear can detect. Many even say 30kHz is too high.
The PE6 "PWM wizard" is pretty good for working out duty cycles etc.
I have fitted a similar control to several locos. If you want to vary the speed, then you only need 4 to 6 steps to get reasonably smooth accel/braking. To achieve that, I use a variable for speed & increment/decrement it each time the appropriate button is pressed. I include a delay of 500ms which allows you to keep your finger on the button and achieve full/zero speed in a steady 2-3 secs. The limited number of steps means it is easy to keep track of which "notch" you are in. Suggest a panic button as emergency stop too.
 
Yes, 65kHz is quite high. I guess this is to avoid the annoying whine that gets generated by the motor. 30kHz is adequate, as it is well above what the human ear can detect. Many even say 30kHz is too high.
The PE6 "PWM wizard" is pretty good for working out duty cycles etc.
I have fitted a similar control to several locos. If you want to vary the speed, then you only need 4 to 6 steps to get reasonably smooth accel/braking. To achieve that, I use a variable for speed & increment/decrement it each time the appropriate button is pressed. I include a delay of 500ms which allows you to keep your finger on the button and achieve full/zero speed in a steady 2-3 secs. The limited number of steps means it is easy to keep track of which "notch" you are in. Suggest a panic button as emergency stop too.
Many thanks for the information about PWM values. I came up with the value 14 (67KHz) while experimenting with cheap motors. This value seemed to make them vary their speed the way I wanted. I will try other frequencies shortly but my main priorities are to get the loco built. I have already added an incremental slow down and a panic button. My main reason for approaching the forum was to find out about the annoying lurch every time I pressed a key. Removing the debug command seems to have solved this. Regards Derelict48.Simplex 40HP.JPGInternals.JPG
 
Nice motor--thank you for the information. Can you at your convenience provide a video of your setup in action?
Hi there, I have tried to send you a video but the MOV files are too large and the MP4s are not allowed. I do not know which format to use. As you can gather I am not an iPhone or Facebook junkie. You can judge the size of the loco from the AA cells. The actual scale is 16mm to the Foot running on Gauge 'O' track.
Internals.JPGSimplex 40HP.JPG
 
Top