Universal Motor Speed Control

Bridges

New Member
I am trying to use a router as a spindle motor for a cnc machine. The problem with cheaper controllers that are available is that the motor will slow down when load is applied. Here is what I have been experimenting with. The schematic is pretty straight forward and isolation from the mains is provided via the optocoupler. The code is also very straightforward as I'm not much of a programmer. It is only a proportional control so the motor does slow down but still has plenty of torque to machine wood or alloy without problems. The feedback sensor is a 2mm magnet inserted into the collet body and the pickup is just a coil housed in a metal body from a very very old hard disk drive. Any suggestions by members to improve the software would be much appreciated.
Unfortunately I don't know how to insert the code so hopefully doing it this way won't annoy anyone to much. I just need to reduce the proportional error and it would be simple and work well. The Picaxe 08M doesn't seem to have a /16 option for the pwm which would be nice or an 8M clock speed which would really help. Is there a newer version of the 08M that has these options?
Thanks folks,
RogerRabbit

['Universal Motor Controller'
'Using Picaxe08M 08.02.25.
symbol setpointport=1 'reference setting
symbol setpointvalue=w0
symbol tachoport=4 'tacho
symbol tachovalue=w1
symbol pwmport=2 'pwm to optocoupler
symbol sum=w2

start:readadc10 setpointport,setpointvalue 'read setpoint
readadc10 tachoport,tachovalue 'read tacho
tachovalue=tachovalue *2 'bring tacho into range
w2= w0-w1 'setpoint-tacho fb
pause 5
if w1>w0 then start 'if it's -ve do nowt
pwmout pwmdiv16,pwmport,255,sum 'output difference
goto start]

The schematic:
ControllerSchematic.JPG
 
Code:
'Universal Motor Controller'
'Using Picaxe08M   08.02.25. 
symbol setpointport=1                'reference setting
symbol setpointvalue=w0
symbol tachoport=4                   'tacho
symbol tachovalue=w1                 
symbol pwmport=2                    'pwm to optocoupler
symbol sum=w2

start:readadc10 setpointport,setpointvalue   'read setpoint
       readadc10 tachoport,tachovalue           'read tacho
       tachovalue=tachovalue *2                     'bring tacho into range
       w2= w0-w1                                            'setpoint-tacho fb
       pause 5
       if w1>w0 then start                                'if it's -ve do nowt
       pwmout pwmdiv16,pwmport,255,sum   'output difference
       goto start
 
My first suggestion would be to add some logging command/s so that you can see what is actually happening.

Try the following piece of code. Its Tacho/MOSFET control is unchanged from your original code. It logs your critical values every second (LoopMax x 5mS)

Rich (BB code):
'Universal Motor Controller'
#PICAXE 08M   '08.02.25
#TERMINAL 4800
symbol setpointport=1                'reference setting
symbol setpointvalue=w0
symbol tachoport=4                   'tacho
symbol tachovalue=w1                 
symbol pwmport=2                     'pwm to optocoupler
symbol sum=w2
Symbol LoopMax = 200
Symbol LoopCount = b13

Init: LoopCount = 0
      SerTxd ("Booted", CR, LF)
      Pause 500
Start:Do 
         readadc10 setpointport, setpointvalue        'read setpoint
         readadc10 tachoport, tachovalue              'read tacho
         tachovalue=tachovalue * 2                    'bring tacho into range
         Sum = setpointvalue - tachovalue             'setpoint-tacho fb
         pause 5
         If LoopCount = 0 Then
            LoopCount = LoopMax
            SerTxd ("Tacho = ", #TachoValue, ", RefPoint = ", #SetPointValue, ", PWMVal = ", #Sum, CR, LF)
         EndIf
         Dec LoopCount
         if setpointvalue > tachovalue then start     'if it's -ve do nowt
         pwmout pwmdiv16, pwmport, 255, Sum           'output difference
      Loop
 
Hi Pete, Thanks for your suggestion which I tried today. I did get data from the 08M but it was of no value because while it was being send control of the motor was lost so it was just oscillating between full speed then to slow down and through the cycle again at the next send. With the earlier program I can see on the scope that motor is accelerating when a load is applied but it is insufficient to reach the setpoint value because it is only a proportional controller. I think I need some way of introducing gain into the system so that the speed continues to increase until the feedback is closer to the setpoint. Some more back round information. Initially the router was designed to run on 240V and the speed range was 11,000 to 30,000. I only need 3,000 for cutting plastics and up to 10,000 for wood, aluminium and stone. Using 150Vdc I have isolation plus the desired speed range. I don't know how to introduce gain in software so maybe I need to incorporate an op amp into the feedback loop. Your ideas would be much appreciated.
ps I have also removed the "pause 5" from the program so the feedback is monitored more closely.
 
Hi,

The present 08M2 is a more capable version of the 08M with operation up to a clock speed of 32 MHz and a DIV64 mode for the PWM (although these two factors will tend to cancel themselves out in practice). I haven't looked at the 08M data sheet, but the 08M2 also has numerous goodies, such as in internal analogue comparator, although not directly supported by the PICaxe Basic.

As for the control loop, a PICaxe is basically a "number cruncher", and (analogue) "Gain" is simply multiplication, which can be easily done within the Program (i.e. in the "Digital Domain"). Similarly, (low or high pass) Filtering, "Feed Forward" and even full PID control can be done with a PICaxe (the forum search won't accept 3-letter acronyms, but Google will, in association with a keyword such as "PICaxe" ;) ).

In control systems the greatest enemy is often time delay (or phase lag), so keeping the program as simple as possible may be beneficial: Restrain the "gain" to modest levels and perhaps use a few MAX and MINs to keep the control variables within range. As Pete suggests a modest degree of "Diagnostics" may be helpful, but use only the absolute minimum of characters and certainly NOT DEBUG.

Cheers, Alan.
 
SerTxd does use bit-banging to transmit serial data. To meet the strict bit timing requirements required for asynch data, the firmware temporarily disables the chip's internal interrupts. I'm surprised that it has a significant effect on the motor control. One option would be to increase the 08M's internal clock speed with SetFreq M8. That will halve to duration of execution of the SerTxd instruction (you'll also have to double the #Terminal speed to 9600 baud). However, it will also double the minimum PWM frequency.

Using an 08M2 will allow the chip to run faster again. That will also introduce the PWM divide-by-64 option.

Finally, controlling the motor speed both up and down is just a matter of mathematics: + - / *. I can't help you very much there because you will have to experiment with your milling machine working together with the PICAXE. I think it should be doable but the task may be beyond the capabilities of the humber PICAXE.
 
Today I went and purchased Picaxe 08M2, quickly programmed using 8Mhz clock and added a multiply to the result of setpoint-feedback and the control has improved to where it can at least be used. I tried a number of multiply factors 2,3,4 and settled on 4. I tried setfreq M16 and M32 but it seemed to make no difference to the pwm frequency, I don't think I've got that right somehow but will try again tomorrow.

Code:
'Universal Motor Controller'
'Using Picaxe08M2   18.02.25. 
symbol setpointport=1
symbol setpointvalue=w0                'setpoint
symbol tachoport=4
symbol tachovalue=w1                  'tacho
symbol pwmport=2
symbol sum=w2
setfreq M8

start:readadc10 setpointport,setpointvalue'read setpoint
    readadc10 tachoport,tachovalue     'read tacho
    tachovalue=tachovalue               'bring tacho into range
    w2= w0-w1                    'setpoint-tacho fb
    w2=w2*4
      if w1>w0 then start              'if it's -ve do nowt
here: pwmout pwmdiv16,pwmport,255,sum     'output difference
    goto start
To be continued
 
Today I have got this spindle running the best that I've been able to do. I have it running at M16, don't know what I did wrong yesterday, and it runs beautifully and under load as well. There is still a drop in speed but it's only about 500 to 600rpm when cutting heavily. I didn't change the pwm freq which is now about 1khz. The motor seems happy with that and I've used fast recovery diodes so snubbing is fine. So no other changes to the program. For the w2 multiplier I wanted to try 3.5 and since this value can't be used directly the old manual2 suggested * 21/6 but that didn't seem to work as 3.5, so went for 4. I also read through the Picaxe PID article AlleyCat suggested but it was to complicated for me to implement. I'm really happy with this project now so thank you for your advise and help gentlemen. Thank you.
Regards,
Bridges.

Code:
'Universal Motor Controller'
'Using Picaxe08M2   19.02.25. 
symbol setpointport=1
symbol setpointvalue=w0                'setpoint
symbol tachoport=4
symbol tachovalue=w1                  'tacho
symbol pwmport=2
symbol sum=w2
setfreq M16

start:readadc10 setpointport,setpointvalue'read setpoint
    readadc10 tachoport,tachovalue     'read tacho
    tachovalue=tachovalue               'bring tacho into range
    w2= w0-w1                    'setpoint-tacho fb
    w2=w2*4
      if w1>w0 then start              'if it's -ve do nowt
here: pwmout pwmdiv16,pwmport,255,sum     'output difference
    goto start
 
Without actually seeing the numbers in a log from the controller, it's difficult to see why * 21 /6 doesn't give an incremental improvement over just 4. It is possible that your initial difference value in 'sum' (w2) is very small and, as a result, with PICAXE's integer mathematics gives a result of 3 (or 4). The solution may be to play around with the PWMOut statement to get a better result with a much larger 'sum' value. That is why it so important to use logging. I suggest you try the following, revised piece of code.

As an aside, just looking at your speed management algorythm, it does not appear to be suitable for managing motor speed. You set the required speed on the potentiometer, then take a reading from the 'tacho' feedback and then use the DIFFERENCE to control the PWM and thus the motor speed. I think this logic is flawed because the difference is intended to reduce to zero as the motor speed theoretically approaches the desired speed. When the difference reaches zero, the PWM and motor drive is zero.
Rich (BB code):
'Universal Motor Controller'
#PICAXE 08M2  '08.02.25
#TERMINAL 19200                      'For operation at 16MHz
symbol setpointport=1                'reference setting
symbol setpointvalue=w0
symbol tachoport=4                   'tacho
symbol tachovalue=w1                 
symbol pwmport=2                     'pwm to optocoupler
symbol Sum=w2
Symbol Sum1=w3
Symbol LoopMax = 500
Symbol LoopCount = w7

Init: LoopCount = 0
      SetFreq M16
      Pause 500
      SerTxd ("Booted", CR, LF)
Start:Do 
         readadc10 setpointport, setpointvalue        'read setpoint
         readadc10 tachoport, tachovalue              'read tacho
         tachovalue=tachovalue * 2                    'bring tacho into range
         Sum1 = setpointvalue - tachovalue            'setpoint-tacho fb
         Sum = Sum1 * 21 / 6
         'pause 5
         If LoopCount = 0 Then
            LoopCount = LoopMax
            SerTxd ("T=", #TachoValue, ", R=", #SetPointValue, ", S1=", #Sum1, ", S=", #Sum, CR, LF)
         EndIf
         Dec LoopCount
         if setpointvalue > tachovalue then start     'if it's -ve do nowt
         pwmout pwmdiv16, pwmport, 255, Sum           'output difference
      Loop
 
Yes I am aware that this controller is only a proportional controller and when the feedback equals the setpoint the output will be zero but in practice it never will because of windage and IR losses. The aim was to increase the speed towards setpoint under load in as simple a way as possible.
I will try your suggested code today and come back tomorrow with some results tomorrow
 
I have tried the program you suggested but cannot get the motor to run at all. It does stream data but it's not tacho, setpoint or sum data because none of the data changes with varying the setpoint resistor and since the motor is not spinning there should be a zero in amongst it but there isn't. When I rem out everything that you added it still won't spin the motor at all. If I run the program in simulate it appears to run ok, do what it should and compiles ok. I am trying to work my way through the program but because it's not a strong point of mine it's taking a bit of time sorry.
 
I have finally worked out the data being sent from the 08M2 as follows T=50 44, R=50 52 53, S1= 50 52 51, S=56 53 48 CR LF. However this data is not valid since the motor is stationary tacho should be T= 00 00. R= followed by 3 bytes when there should be two and the same for S1 and S. The setpoint value R is also not valid because it does not change with the speed setting potentiometer. I still can't get the motor to spin even with everything now remmed out. It seems to do everything right in simulate but not in the 08M2.
Using my old program, I am planning now to move it to a 230V supply rather than "fudge" the error value with a multiplier although this has markedly reduced the difference between no load and full load speed.
 
A late reply - we have been away camping in an area with practically no mobile network coverage (bliss!).
I have finally worked out the data being sent from the 08M2 as follows T=50 44, R=50 52 53, S1= 50 52 51, S=56 53 48 CR LF. However this data is not valid since the motor is stationary tacho should be T= 00 00. R= followed by 3 bytes when there should be two and the same for S1 and S. The setpoint value R is also not valid because it does not change with the speed setting potentiometer. I still can't get the motor to spin even with everything now remmed out. It seems to do everything right in simulate but not in the 08M2.
Using my old program, I am planning now to move it to a 230V supply rather than "fudge" the error value with a multiplier although this has markedly reduced the difference between no load and full load speed.
To translate the data above into characters:
"I have finally worked out the data being sent from the 08M2 as follows T=2, R=245, S1=243, S=850, CR LF"
So recalculating manually,
If TachoValue(T)=2; SetPoint (ie Reference Value):(R)=245; Sum1(S1)=R-T=243; Sum(S)=Sum1*21/6=243*21/6=850;
The mathematics is correct, according to your algorythm.

The TachoValue of 2 indicates that there is an input calibration error that needs to be zeroed, either in hardware or software.
 
What a difference it makes when you understand. Thanks for explaining. So things are working as expected. In the meantime I have now changed from 110V to a 240V supply and for the the same change in pulse width I have a lot more power on full load. I have had to reduce the feedback multiplier because of an unseen problem when starting from stopped to full speed. In my next post I will include some oscilloscope screen shots to show this problem.
 
The unseen problem I mentioned in my last post has been solved by changing the pwm rate. The last thing for me to solve is how to get full power at lower speeds. I attach 4 screen shots showing the pwm. I would like to get more torque at the lower speed settings. To do this I need to be able to increase the pwm ratio to the same value as if the motor were running at full speed and full load. Sounds simple but I havn't been able to do it so far I have been thinking that I could use input only pin 3 as a switch from high to low speed range and then add a new part to the program.
Any idea would be much appreciated.
 

Attachments

  • FullSpeedNoLoad.JPG
    FullSpeedNoLoad.JPG
    131 KB · Views: 3
  • FullSpeedFullLoad.JPG
    FullSpeedFullLoad.JPG
    133.4 KB · Views: 3
  • HalfSpeedNoLoad.JPG
    HalfSpeedNoLoad.JPG
    128.5 KB · Views: 2
  • HanfSpeedFullLoad.JPG
    HanfSpeedFullLoad.JPG
    135.9 KB · Views: 3
This all points back to the algorythm used to determine the level of PWM required to maintain the motor RPM as any speed and load.

My thoughts are to do something like the following:
1. In its simplest form you will need four word variables: Required speed (R), Tacho reading (T), Adjusted Motor Speed (S), PWM Value (P). I will use the abbreviated variable names here to save space in my description.
2. Determine the ranges of both the input potentiometer and the tacho.
3. Create a representation of the tacho input range to match the range of the pot. This is likely to be in the form S=T*X+A or S=T*X/Y+A or similar. So, start your development by finding the maximum value you get from the Tacho ADC when the motor is running at full speed and no load.
4. Compare S with R: this will produce three results (branches) S>R (slow the motor); S<R (speed up the motor) and S=R (do nothing)
5. If the motor needs to be sped up, add a value to P but not more the maximum allowed in the PWM statement.
6. If the motor needs to be slowed, subtract a value from P but don't allow it to go below zero.
This would form a starting point for controlling the motor speed. You will also need to allow for motor response time when the PWM % is changed.

The general idea in pseudo code:
Code:
P = <midrange>                 ;To be determined
Initialise PWMOut to P
Do
    R = <Read Reference Value Potentiometer>
    T = <Read Tacho Value>
    S = <Adjusted Tacho Value> ;Formula to be determined
    If R > S Then              ;Increase PWM 'on' percentage
        P = P + Y MAX X        ;PWM must not go higher than X
    ElseIf R < S Then          ;Decrease PWM 'on' percentage
        P = P MIN Y - Y        ;PWM must not go lower than 0 (PICAXE unsigned integers)
    EndIf
    Set PWM Duty to P          ;PWM Duty
    Pause Z                    ;May be required
Loop
 
The unseen problem I mentioned in my last post has been solved by changing the pwm rate. The last thing for me to solve is how to get full power at lower speeds. I attach 4 screen shots showing the pwm. I
Hi,

You didn't say which way you changed the PWM frequency, but a lower frequency (than 622 Hz) may give more torque. You should be able to achieve as much torque as at higher rpm, but not more (which a gearbox would achieve), and with less inertia to overcome transitional loads, etc..

The basic principle of a feedback loop is to have sufficient gain that a relatively small "error" signal can generate any required variation in the output control (PWM) range. But you need to look at the limits of the control range, particularly with PICaxe which does not natively handle negative numbers (e.g. if calculating w2 - w1 ensure that w2 => w1 ! ). In particular, "wrapping around" down through zero generates a large positive number, which MIN or IF xx < 0 will NOT detect! You can use a conditional test such as IF word => 32768 THEN ; It's negative or actually perform genuine "Two's Complement" maths (which is almost "automatic" for addition and subtraction, but needs some "checks" for multiplication and division). I've written various code snippets (and some larger programs) so won't go into any more detail here.

Cheers, Alan.
 
Firstly a big thank you for your replies. It will take me a little time to absorb. I'm working on it for sure. I'm now running at 32Mhz and using debug to see whats happening so I do have some numbers now I can include. The control of the motor isn't affected by debug with 32Mhz.
Regarding pwm frequency. 622Hz seems to be the lowest pwm I can get with the wizard. Interesting that the mosfet runs cooler at the higher pwm frequency I was using earlier at 8 and then 16Mhz.
 
You should able to get 488Hz at 32MHz for the 08M2: pwmout pwmdiv64, C.2, 255, 511
and 244Hz at 16MHz if you drop the clock frequency to 16MHz etc
 
Today I tried the following program without to much success possibly because I didn't have a "dead band" but I do think it has potential but it's difficult to have it with little over and undershoot. with a fast response if I take out debug then I have to insert a delay but then can't see what happening. I guess it's going to move more and more towards a pid controller.

In my earlier program I can now see that it would be very difficult at low speeds to increase the pwn since the setpoint is much lower and consequently the pwm is narrower. It took me a while....

Code:
'Universal Motor Controller'
'Using Picaxe08M   18.02.25. 
symbol setpointport=1
symbol setpointvalue=w0                    'setpoint
symbol tachoport=4
symbol tachovalue=w1                        'tacho
symbol pwmport=2
symbol actual=w2
#no_data
setfreq M32

start:readadc10 setpointport,setpointvalue    'read setpoint  
    actual=setpointvalue 'starting point for actual
   
here:    readadc10 setpointport,w0    'read setpoint
            readadc10 tachoport,w1         'read tacho
            if tachovalue= setpointvalue then here
            if tachovalue> setpointvalue then dn
one:     if tachovalue< setpointvalue then up
two:     pwmout pwmdiv16,pwmport,200,actual
            'pause 50
            debug w2
    
           goto here
    
up: actual=actual+1
    goto two
    
dn:  actual=actual-2
    goto one
 
I forgot to include in the above post a question to Pete, why do I need a lower frequency pwm. Are there advantages?
 
In simple terms, the windings in an electric motor are inductors. When you connect a power source (voltage) to an inductor, current starts to increase as the magnetic field builds up. When the power source is disconnected, the magnetic field collapses, generating a (typically higher) voltage across the motor (inductor).

At lower PWM frequencies, more energy can be put into the magnetic field before the applied voltage is turned off. At higher PWM frequencies, while the average time that input power is present might equal that of the lower frequency, the more frequent toggling of the applied power does not allow the same level of energy to be available to turn the motor's armature. The result is more heat in the motor and less usable (rotational) power.
 
Thanks for the explanation, now I see the benefit.
I also now see the need for boundaries since the software decrements or increments much faster than the motor slows down or accelerates and then goes into a negative values and looses control.
I have to put this project away for a few days and do other work but will be back.
 
I also now see the need for boundaries since the software decrements or increments much faster than the motor slows down or accelerates and then goes into a negative values and looses control.
The problems you are having would not have occurred if you had fully understood the pseudocode I provided in post #16. Perhaps the 3 most important points you missed are the operators/commands MIN, MAX and PAUSE. Also, for your particular situation, the Debug command is causing an unseen delay that will cause a problem when you eventually remove it.

I have rewritten the code, based on your post #20. It incorporates MIN, MAX, Pause and SerTxd which should solve most of the problems you mention. I'm assuming that you are actually using an 08M2, since the 08M will not run at 32MHz. Also, I have kept your PWM frequency of 2490Hz for the time being.
Rich (BB code):
'Universal Motor Controller'
#PICAXE 08M2                  '05-March-2025
#TERMINAL 38400               'For operation at 32MHz
symbol setpointport  = C.1
symbol tachoport     = C.4
symbol pwmport       = C.2
symbol IncVal        = 1      'PWM step size: Up
symbol DecVal        = 2      'PWM step size: Down
symbol PWMMax        = 803    'Upper limit of 100% PWM at 2490Hz for PWM period=200

symbol setpointvalue = w0     'setpoint
symbol tachovalue    = w1     'tacho
symbol actual        = w2
#no_data

Init: setfreq M32
      readadc10 setpointport, setpointvalue     'read setpoint  
      actual=setpointvalue                      'starting point for actual
      '
      Do
         ReadADC10 setpointport, w0             'read setpoint
         ReadADC10 tachoport, w1                'read tacho
         '
         If tachovalue > setpointvalue then
            actual = actual MIN DecVal - DecVal 'PWM must not go lower than 0
         ElseIf tachovalue < setpointvalue then
            actual = actual + IncVal MAX PWMMax 'PWM must not go higher than PWMMax
         EndIf
         '
         pwmout pwmdiv16, pwmport, 200, actual  'Period of 200 sets freq. to 2490Hz @32MHz
         pause 800                              '100mS @32MHz
         SerTxd (#actual, CR, LF)
      Loop
 
I'm back on the project today and tried the code you kindly wrote for me and the results are better in that control is always maintained thanks to the limits imposed but under and overshoot continues to be a big problem. If I increase the incval to 2 and decval to 4, the acceleration improves a little and somewhat in deceleration but because of the immediate removal of load when the cut is finished the overshoot remains high and inertia takes a while to dissipate, if that's the right word. In practice the code in my #2 post performs better especially at 32Mhz. So I will try with that code for 2 days while I try to think of a solution to reduce the difference between setpoint and actual speed. Maybe breaking down to two speed ranges, a high and low.
Thank you for your help with my project. I'm learning just from looking at how you code.
 
Perhaps you could remove the "pause" statement from where it is and put two "pauses" of different values in the if/elseif/endif structure. With a shorter pause when speed is too high, the PWM %age would be brought down quicker.
 
I was able to try your suggested program yesterday with differing values of "pause" but the overshoot is still very large. Control was best with pause 800 and as I reduced the value the router began to hunt increasingly around the setpoint value.
 
The next stage is to vary the PWM step size according to the size of the speed overshoot. I expect you'll have to play around with the Difference branching numbers and the DecVal values. Perhaps add more ElseIf branches.
Rich (BB code):
'Universal Motor Controller'
#PICAXE 08M2                  '12-March-2025
#TERMINAL 38400               'For operation at 32MHz
symbol setpointport  = C.1
symbol tachoport     = C.4
symbol pwmport       = C.2
symbol IncVal        = 1      'PWM step size: Up
'symbol DecVal        = 2      'PWM step size: Down
symbol PWMMax        = 803    'Upper limit of 100% PWM at 2490Hz for PWM period=200

symbol setpointvalue = w0     'setpoint
symbol tachovalue    = w1     'tacho
symbol PWMVal        = w2
symbol Difference    = w3     'Magnitude of error
symbol DecVal        = b8
#no_data

Init: setfreq M32
      readadc10 setpointport, setpointvalue     'read setpoint  
      PWMVal = setpointvalue                    'starting point for actual
      '
      Do
         ReadADC10 setpointport, w0             'read setpoint
         ReadADC10 tachoport, w1                'read tacho
         '
         If tachovalue > setpointvalue then     'Faster than required
            Difference = tachovalue - setpointvalue
            If Difference < 5 Then              'Vary the speed step-down value according to the overshoot speed
               DecVal = 1
            ElseIf Difference < 10 Then
               DecVal = 2 
            Else
               DecVal = 5
            EndIf
            PWMVal = PWMVal MIN DecVal - DecVal 'PWM must not go lower than 0
         ElseIf tachovalue < setpointvalue then 'Slower then required
            Difference = setpointvalue - tachovalue
            SerTxd ("-")                        'Show speed is slow
            PWMVal = PWMVal + IncVal MAX PWMMax 'PWM must not go higher than PWMMax
         EndIf
         '
         pwmout pwmdiv16, pwmport, 200, PWMVal  'Period of 200 sets freq. to 2490Hz @32MHz
         pause 800                              '100mS @32MHz
         SerTxd (#Difference, ", ", #PWMVal, CR, LF)                             'EDIT - Difference should be #Difference
      Loop
 
Last edited:
I am late to this thread but allow me to give a little hardware advice;
Any gate drive voltage higher than 10 volts will cause the MOSFET to remain in linear mode during the switching transitions longer than necessary. This is aggravated by the fact that the gate is only passively turned-off with a resistor.
Replace the 18 volt zener with a 12 volt one.

Of course, I can be accused of nitpicking, but my experience as a power engineer has shown that improper gate drive is one of the leading Mosfet failure modes.
 
I will further intrude into your design and recommend a proper opto isolated gate driver like the Texas Instruments UCC23513.
But there are many others.
No intrusion from my perspective. I have to admit that, after a superficial check, I did not pay alot of attention to the hardware detail. A MOSFET driver would be wise, especially where higher PWM frequencies are being used. FWIW, I have used the Microchip TC4428 MOSFET Driver in the past. The TC4428 has one inverting and one noninverting driver.

Edit: As noted by fernando_g below, the TC442x drivers are not suitable for interfacing with higher voltage circuits without an optocoupler. I have only used PICAXEs to drive low voltage DC motors.
 
Last edited:
Those Microchip Mosfet drivers are ubiquitous and low cost, but it appears that you do require galvanic isolation? Am I correct?
That is the reason I recommended an optocoupled device.
 
Today I managed to get testing on the larger motor as follows. with the pause 800 there is slow hunting around the setpoint. A very smooth increase in speed when load is added and it does reach the setpoint speed but it takes time. I have reduced the pause 800 in steps down to pause 50 but it worsens the hunting but does recover from being loaded much quicker but there is still a lot of overshoot when the load comes off as at the end of a cut. It took me some time to get the hang of the numbers being sent to the terminal but here is a print out. Yellow is overspeed and orange is underspeed. This is about 50% speed, 4,000 rpm and no load at all to highlight the hunting. I did have a short .mp4 video of the hunting on the scope but am unable to upload it. Thanks for the advise re mosfet drivers. I do plan to buy differing ones to the 4N25 and will change to a 12v zener in the morning.
 

Attachments

  • DSCN3253.JPG
    DSCN3253.JPG
    77.2 KB · Views: 10
It's difficult to comment on your latest results. There was also an error in my code for the logging: the second last line should have been
SerTxd (#Difference, ", ", #PWMVal, CR, LF)

It would help if you logged the output as ASCII, rather than decimal values of each character. The "-", CR and LF characters that I included in the code were to allow formatting of the data so that it would be easier to read. If you use the PE terminal for logging, select the "Display all Rx Data as ASCII" option in the Settings menu.
-7, 18
or
11, 12

... where the first number is the difference between the actual and target speed (minus indicating underspeed) and the second number being the calculated new PWM rate. Much easier to read
Now that I have seen your data, I can see that underspeed treatment needs similar graduated increments as overspeed. Try the following code.
Rich (BB code):
'Universal Motor Controller'
#PICAXE 08M2                  '12-March-2025
#TERMINAL 38400               'For operation at 32MHz
symbol setpointport  = C.1
symbol tachoport     = C.4
symbol pwmport       = C.2
'symbol IncVal        = 1      'PWM step size: Up
'symbol DecVal        = 2      'PWM step size: Down
symbol PWMMax        = 803    'Upper limit of 100% PWM at 2490Hz for PWM period=200

symbol setpointvalue = w0     'setpoint
symbol tachovalue    = w1     'tacho
symbol PWMVal        = w2
symbol Difference    = w3     'Magnitude of error
symbol DecVal        = b8
symbol IncVal        = b9
#no_data

Init: setfreq M32
      readadc10 setpointport, setpointvalue     'read setpoint  
      PWMVal = setpointvalue                    'starting point for actual
      '
      Do
         ReadADC10 setpointport, w0             'read setpoint
         ReadADC10 tachoport, w1                'read tacho
         '
         If tachovalue > setpointvalue then     'Faster than required
            Difference = tachovalue - setpointvalue
            If Difference < 5 Then              'Vary the speed step-down value according to the overshoot speed
               DecVal = 1
            ElseIf Difference < 10 Then
               DecVal = 2 
            Else
               DecVal = 5
            EndIf
            PWMVal = PWMVal MIN DecVal - DecVal 'PWM must not go lower than 0
         ElseIf tachovalue < setpointvalue then 'Slower then required
            Difference = setpointvalue - tachovalue
            If Difference < 5 Then              'Vary the speed step-up value according to the undershoot speed
               IncVal = 1
            ElseIf Difference < 10 Then
               IncVal = 2 
            Else
               IncVal = 5
            EndIf
            SerTxd ("-")                        'Show speed is slow
            PWMVal = PWMVal + IncVal MAX PWMMax 'PWM must not go higher than PWMMax
         EndIf
         '
         pwmout pwmdiv16, pwmport, 200, PWMVal  'Period of 200 sets freq. to 2490Hz @32MHz
         pause 800                              '100mS @32MHz
         SerTxd (#Difference, ", ", #PWMVal, CR, LF)
      Loop
 
I will try your suggestion in the morning and report back. Would it be helpful to try to capture the overshoot tacho value?
I have changed to a 12V zener and have ordered some UCC23513's to help the hardware.
Today I went back to running my original code and noted that there was no overshoot when the motor load is removed. I suppose this is because the full load speed is less than the setpoint by about 600 at 4,000rpm. Is this correct do you think?
 
I don't understand why you don't get overshoot when the load is removed. I would expect the PWM level the go relatively high under load and then the router would rev high when the load is removed. On the logging side, it mat be of benefit to include #tachovalue, #setpointvalue in the SerTxd statement but #Difference captures and logs the overshoot/undershoot anyway.
 
Today I tried your code. Plus I have learnt to change setting to Askii. Learning learning all the time thank you. I have reprinted the hunting at high and low speeds. Also tried to capture the overshoot when the load is removed. Interesting to see it. A graph would much more informative and I am going to try and find a way to do this. Maybe once the speed rises to greater than the setpoint the pwm should be 0 or bypassed and then it would cut off immediately and the overshoot would be less. What do you think? Unfortunately your programming skills are way above mine so I struggle a little to follow it.
 

Attachments

  • DSCN3254.JPG
    DSCN3254.JPG
    82.5 KB · Views: 7
  • DSCN3255.JPG
    DSCN3255.JPG
    101.5 KB · Views: 8
Back
Top