-
Re: incPID Routine - Help Needed
Hi Barry,
Either is fine - whatever works....
Since you're only looking for velocity and not position (right?) you could either use the motion feedback module in Velocity Mode (something I've never done myself) or use a standard timer/counter as outlined earlier.
As for the timer interrupt... A neat feature of the PCPWM module is that you can use IT (or rather its timer) to generate an interrupt every Nth PWM cycle. That's what the PostScale setting is for. But the available post scale ratios are limited so if your PWM frequency is high and you're looking for a low(ish) interrupt frequency it might not be the best to use.
Again, either works.
What's the lowest speed you expect to run the motor at?
/Henrik.
-
Re: incPID Routine - Help Needed
Thanks for the feedback Henrik.
The PCPWM frequency is 8kHz and I would like to be able to slow the motor down to 60rpm (1 revolution per second) if possible. This would allow me to perform threading operations on my lathe at a safe speed (the ultimate use for this project is to re-power my 9x20 lathe).
I also need a way of determining and displaying the rotational speed. I know this is possible by manipulating the data from the counter/timer but would it be simpler to use the period measurement function (input capture mode) of the Motion Feedback Module on the 18F2431? Have you, or any of the other forum members, had any experience using the period measurement function?
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
Hello Barry,
I am working on a similar project and following this thread.
A while back I found this code some where maybe here? Not sure who the author is?
It calculates RPM using the 18F4431, but not using the velocity mode. Maybe you can use some ideas
Code:
'--------Program Desciption--------
' Program uses Timer0 Interrupt to average motor rpm over one minute.
' Motor power set by potentiometer before program begins.
' LCD display updates time, position count and average rpm every second.
'---Review PicBasic Pro Command----
' The PicBasic Pro Compiler Manual is on line at:
' http://www.microengineeringlabs.com/resources/index.htm#Manuals
'---------PIC Connections----------
' 18F4331 Pin Wiring
' --------- ----------
' RA0(AN0) Potentiometer, controls motor power
' RA3 Signal 1 from Encoder
' RA4 Signal 2 from Encoder
' RB5 In Circuit Serial Programming (ICSP) PGM
' 100K Resistor to GND
' RB6 ICSP PGC (Clock)
' RB7 ICSP PGD (Data)
' RC0 Brake Motor 1 on Xavien XDDCMD-1 (Pin 1)
' RC1 PWM Motor 1 on Xavien XDDCMD-1 (Pin 2)
' RC3 Direction Motor 1 on Xavien XDDCMD-1 (Pin 3)
' RD4 LCD Data Bit 4
' RD5 LCD Data Bit 5
' RD6 LCD Data Bit 6
' RD7 LCD Data Bit 7
' RE0 LCD Register Select
' RE1 LCD Enable
' MCLR 4.7K Resistor to +5V & ICSP Vpp
' VDD +5V
' VSS GND
' OSC1 & OSC2 4 MHz Crystal w/ 2-22 pF Cap. to GND
'----Xavien XDDCMD-1 Connections---
' Xavien 2x5 Header Pin Wiring Pin Layout 2x5 Header
' --------------------- ------ ---------------------
' 2 4 6 8 10
' Pin 1 Motor 1 Brake RC0 o o o o o
' Pin 2 Motor 1 PWM RC1 o o o o o
' Pin 3 Motor 1 Direction RC3 1 3 5 7 9
' See schematic at:
' http://cornerstonerobotics.org/schematics/18f4331_hpwm_motor_encoder.pdf
'--Sample POSCNTH, POSCNTL Values and Corresponding Position Counter--
' position = 256 * POSCNTH + POSCNTL
' POSCNTH POSCNTL Position Counter
' ------- ------- ----------------
' 0 0 0
' 0 1 1
' 1 0 255
' 0 128 128
' 128 0 32768
' 0 255 255
' 255 0 65280
' 255 255 65535
'-------------Defines--------------
DEFINE LCD_DREG PORTD ' Set LCD Data port
DEFINE LCD_DBIT 4 ' Set starting Data bit to 4
DEFINE LCD_BITS 4 ' Set LCD bus size to 4
DEFINE LCD_RSREG PORTE ' Set LCD Register Select port to E
DEFINE LCD_RSBIT 0 ' Set LCD Register Select bit to 0
DEFINE LCD_EREG PORTE ' Set LCD Enable port to E
DEFINE LCD_EBIT 1 ' Set LCD Enable bit to 1
DEFINE LCD_LINES 2 ' Set number of lines on LCD to 2
DEFINE LCD_COMMANDUS 2000 ' Set command delay time to 2000 us
DEFINE LCD_DATAUS 50 ' Set data delay time to 50 us
DEFINE ADC_BITS 8 ' Set number of bits in result to 8
DEFINE ADC_CLOCK 3 ' Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in us
DEFINE CCP2_REG PORTC ' Set HPWM Channel 2 port to C
DEFINE CCP2_BIT 1 ' Set HPWM Channel 2 bit to 1
'------------Variables-------------
mot_pwr var byte ' Declare mot_pwr variable, reserve byte
pot_val var byte ' Declare pot_val, reserve byte
position var word ' Declare position, reserve word
second VAr word ' Declare second, reserve word
ticks var byte ' Declare ticks, reserve byte
update var byte ' Declare update, reserve byte
rpm var word ' Declare rpm, reserve word
'----------Initialization----------
CCP1CON = %00111111 ' Set Capture/Compare/PWM Module Control
' Register CCP1CON in PWM mode (bits 0-3),
' bits 4,5 set LSBs of 10-bit duty cycle,
' see 18F4331 datasheet page 151 +/-.
ANSEL0 = %00000001 ' Set AN0 to analog, AN1-AN7 to digital,
' see datasheet page 249 +/-.
ANSEL1 = %00000000 ' Set AN8 to digital, see datasheet
' page 249 +/-.
TRISA = %00011111 ' Set TRISA register, RA7-RA5 as outputs,
' RA4-RA0 as inputs, see datasheet
' page 107 +/-.
LATA = %00000000 ' Set all LATA register bits to 0.
TRISB = %00000000 ' Set RB7-RB0 pins in PORTB as outputs.
TRISC = %00000000 ' Set RC7-RC0 pins in PORTC as outputs.
QEICON = %10001000 ' Set Quadrature Encoder Interface Control
' Register. See page 171 +/- for
' encoder set up.
T0CON = %11010101 ' Set TMR0 configuration and enable PORTB
' pullups. Set Timer0 Prescaler Select bits
' (bits 2-0) to 1:64 prescaler value. Timer0
' interrupt occurs every 256 us for a
' 4 MHz crystal so 256us * 64 = 16.384ms.
' 16.384ms * 61 ticks = 0.9994 seconds.
' See Timer0 Control Register 18F4331
' datasheet page 135 +/-.
INTCON = %10100000 ' Enable Timer0 interrupts.
ON INTERRUPT GoTo tickint ' Jump to interrupt handler "tickint"
' after receiving an interrupt.
PORTC.0 = 1 ' Turn on brake.
PORTC.1 = 0 ' Set PWM bit for Channel 2 of HPWM to LOW.
'-------------Main Code------------
pause 500 ' Pause to start up LCD
PORTC.0 = 0 ' Turn off brake
PORTC.3 = 0 ' Set direction of motor
' If position value on LCD is in the 65,000s
' and counting down, then change the
' motor direction: PORTC.3 = 1.
second = 0 ' Set initial values for second and ticks.
ticks = 0
update = 1 ' Enable first display
' Set counter starting position:
POSCNTH = 0 ' Set counter for encoder, H bit
POSCNTL = 0 ' Set counter for encoder, L bit
' position = 256 * POSCNTH + POSCNTL
' With POSCNTH and POSCNTL = 0,
' position counter will start at 0.
' See table above for more sample values.
' Read motor power setting, set motor power before main loop:
ADCIN 0, pot_val ' Read AN0 and store result in pot_val.
' This potentiometer (connected to AN0)
' sets the motor power.
mot_pwr = 11 * pot_val / 16 + 77
' mot_pwr = 11/16 * pot_val + 77
' (Can't write equation as 11/16 * pot_val
' since interger division truncates: any
' fractional part is discarded. Since 11
' and 16 are integers, 11/16 would be
' truncated to zero.)
' 77 is the minimum power to start motor.
' 11/16 is the slope of the line to give
' mot_pwr values from 77 to about 255.
' See graph & equation in schematic.
HPWM 2, mot_pwr, 20000 ' Send PWM signal from RC1 to Pin 2 on
' the Xavien XDDCMD-1 DC motor driver.
loop:
if update = 1 then
POSITION = 256 * POSCNTH + POSCNTL ' Read position
rpm = 60 * (position/32) / second
' 60, (60 seconds/minute)
' position/32, number of revolutions
' (Our motor has 16 holes which generates
' 32 position counts/revolution)
' second, number of seconds
' rev 60 seconds position counts 1 revolution 1
' rpm = --- = ---------- * * ------------------ * ---------
' min 1 minute 32 position counts # seconds
LCDOUT $FE, $80, "rpm=",dec5 rpm, " s=", dec3 second
' Display rpm and seconds on the first line
LCDOUT $FE, $C0, "position = ",DEC5 POSITION
' Display position on second line
' Position will count to 65535, then
' cycle back to 0 and continue counting.
' in 5 decimal digits.
update = 0 ' Reset update to 0
endif
' After 60 seconds, shut down:
if second = 60 then gosub shut_down
' Stop program at 60 seconds
goto loop:
Disable ' Disable interrupts during interrupt handler
' Interrupt handler:
tickint:
ticks = ticks + 1 ' Count parts of a second
if ticks < 61 then tiexit ' Timer0 interrupt occurs every 256 us for
' a 4 MHz crystal so 256us * 64 = 16.384ms.
' 16.384ms * 61 ticks = 0.9994 seconds.
' (61 ticks per 0.9994 seconds)
' One second elapsed, reset ticks and update time:
ticks = 0 ' Reset ticks to 0
second = second + 1 ' Add one second
update = 1 ' Permits LCD update
tiexit: INTCON.2 = 0 ' Reset timer interrupt flag,
' (Reset Timer0 to 0 - next Timer0
' interrupt is in 16.384ms)
resume
' End of interrupt handler
enable ' Enable interrupts
shut_down:
PORTC.0 = 1 ' Turn on motor controller brake
end
-
Re: incPID Routine - Help Needed
Hi Barry,
Oh, only 8kHz PWM frequency....
If using the PCPWM timer with a 1:16 postscale it would interrupt at 8k/16=500Hz which, I'd say would be fairly good for a large inertia system like a lathe spindle. BUT, I think the limited resolution of your spindle encoder will present you with some issue if you're simply going to count pulses for the duration of interrupt period. At 500Hz interrupt rate and 60rpm there will be a single count every ~8th interrupt and none in between - even at 100Hz interrupt rate the resolution will be quite limited at the low end.
Still, this might work due to the high inertia but from the PID-filters point of view it's going to look like the spindle isn't moving at all, then all of a sudden it is moving, then it's not moving at all and so on. Depending on the tuning of the filter you're going to have a lot of ripple on the output which will result in some large torque variations in the motor - which will then get filtered by the inertia of system.
I'm thinking that perhaps it would be better to use a capture module and measure the width of each input pulse instead of counting them over time.
/Henrik.
-
Re: incPID Routine - Help Needed
Hi Henrik,
Nothing is set in concrete on this project!
8kHz is the PWM frequency now but it can be changed. I don't know what the down side would be, if any, to increasing the PWM frequency but I am willing to give it a go if it will help things overall.
I chose 60 steps per revolution on the encoder wheel because a) it was easy to achieve and b) it made RPM calculation easy.
I have now played with period measurements using the 18F2431's IC module so there is less reliance on the original step rate.
Given the inertia of the final system, what would be the expectation for the number of steps per revolution, interrupt rate and minimum motor speed to achieve a nice, tight PID operation?
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
Hi Barry,
The drawback with a switching frequency as low as 8kHz is that it is in the audible range, ie you or people around you can hear it "whine". The ripple current thru the motor will also be larger - which might or might not matter (think current limiting etc). Going to a higher switching frequency helps with both of the above points but introduces more switching losses in the H-bridge. Normal switching frequencies for motor control tends to be in the 20-50kHz range. but if 8kHz works for you I see no reason to change it.
I can't give you a definitive answer to the second question. I could blame that on not knowing the inertia of your final system but honestly, even if I did I couldn't calculate that for you.
If counting pulses, basically you want as much granularity as you can get at the lower end without overflowing the counter at the top end. If timing pulses it's the other way around, then you risk overflowing the timer at the low end.
To illustrate an example: Lets, for easy of calculation, say that your interrupt rate is 60Hz. If you count pulses and the motor is turning 60rpm you'll get a single count each interrupt. But if its turning say 66rpm the PID filter would only notice that as an "extra" count every 10th interrupt. And when it notices that extra count IT thinks the motor is turning 120rpm (since 1 count per interrupt equals 60rpm). Now all of a sudden tit sees an error of 100% (where did THAT come from) when in reallity the error is 10%. Again, the inertia of the spindle will filter this to some degree but it's something to be aware of.
Again, it might work just fine.
/Henrik.
-
Re: incPID Routine - Help Needed
Thanks for the sanity check Henrik.
One of the reasons I chose 8kHz switching frequency is that I need to drive the H-Bridge via opto-couplers to achieve isolation between mains power and the controller.
I have been able to achieve sub-10uS opto rise and fall times but need to apply 12uS dead-time for the PWM signal to alleviate MOSFET shoot-through. Increasing the switching frequency just isn't possible without losing a heap of top motor speed.
After careful consideration I believe I might have been setting my sights a bit high on the final performance specifications. I have pulled back on the desired minimum rotational speed and will set it somewhere that is workable within the limits of the sample rate and the number of encoder pulses.
I have also decided not to incorporate the RPM display into the main 18F2431 function. If need be I will add the RPM display at a later date using a dedicated setup.
So now it is a matter of getting back to setting up the timer/counter arrangement and implementing the incPID routine. I will keep you updated with my progress.
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
Hi Barry,
I see no reason that the RPM display can't be integrated in the same system but you're doing the right thing in getting one thing at a time going.
With a PID update frequency in the low hundreds there is PLENTY of processing power left to run a display. It's just a matter of not allowing the display update to block or take priority of the PID.
Is this some kind of serial display or is it the standard HD44780 type?
Anyway, I'm glad you're moving forward and I'm looking forward to see your progress!
/Henrik.
-
Re: incPID Routine - Help Needed
Hi Henrik,
I can use a serial display connected to the 18F24321's EUSART or a standard HD44780 type. I suspect the serial device with take up much less overhead once the whole system is running but for the time being I will use the standard HD44780.
I will continue with the PID implementation using the smaller 24V 200W scooter motor - I feel much safe playing with lower, less lethal voltages for my prototyping purposes. Once I have that system operating successfully I will then step up to the 180V treadmill motor.
I will send regular progress details as I achieve various project milestones.
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
OK, I now have a PIC18F2431 with acounter set up on Timer1 and a time base set up on Timer0.
The counter was pretty straight forward but i have a few questions regarding the operation of Timer0
1/. Timer Pre-Load
Timer0 is a 16 bit timer which gives an output as it rolls over from $FFFF to 0.
An 8MHZ clock speed will provide one instruction every 500ns. For a 100Hz time base (10ms period) I would need 20000 instruction cycles (20000 x 500ns = 10ms).
A free running timer wiith no pre-load would roll over every 65536th cycle so to achieve a 20000 cycle roll over I need to pre-load the timer with 65536 - 20000 = 45536.
All good - nice clean theory however, a 45536 pre-load results in ~50Hz time base!
Here is my code:
Code:
#CONFIG
CONFIG OSC = IRCIO
CONFIG FCMEN = ON
CONFIG IESO = OFF
CONFIG PWRTEN = ON
CONFIG BOREN = ON
CONFIG BORV = 42
CONFIG WDTEN = OFF
CONFIG WDPS = 512
CONFIG WINEN = OFF
CONFIG PWMPIN = OFF
CONFIG LPOL = HIGH
CONFIG HPOL = HIGH
CONFIG T1OSCMX = OFF
CONFIG MCLRE = ON
CONFIG STVREN = ON
CONFIG LVP = OFF
CONFIG DEBUG = OFF
CONFIG CP0 = ON
CONFIG CP1 = ON
CONFIG CP2 = ON
CONFIG CP3 = ON
CONFIG CPB = OFF
CONFIG CPD = OFF
CONFIG WRT0 = OFF
CONFIG WRT1 = OFF
CONFIG WRT2 = OFF
CONFIG WRT3 = OFF
CONFIG WRTC = OFF
CONFIG WRTB = OFF
CONFIG WRTD = OFF
CONFIG EBTR0 = OFF
CONFIG EBTR1 = OFF
CONFIG EBTR2 = OFF
CONFIG EBTR3 = OFF
CONFIG EBTRB = OFF
#ENDCONFIG
' Set up interrupt routine
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ; Include if using PBP interrupts
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR0_INT, _ISR, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE TMR0_INT ; Enable Timer 0 Interrupts
' Define LCD registers and bits
Define LCD_DREG PORTB
Define LCD_DBIT 4
Define LCD_RSREG PORTA
Define LCD_RSBIT 1
Define LCD_EREG PORTA
Define LCD_EBIT 2
Define LCD_BITS 4
Define LCD_LINES 2
' Set up Internal Oscillator @ 8MHz
DEFINE OSC 8
OSCCON = %01110010 ' Internal oscillator, 8MHz
' Set up Timer0
T0CON = %00001000 ' Timer off
' 16 bit
' Internal clock
' Prescaler not assigned
T0CON.7 = 1 ' Start Timer0
' Set up I/O Ports
ANSEL0 = 0 ' No analogue input, all digital
TRISA = 0 ' ALL PORTA as outputs
PORTA = 0 ' All outputs low
TRISB = 0 ' ALL PORTB as outputs
PORTB = 0 ' All outputs low
TRISC = 0 ' Set PORTC as output
PORTC = 0 ' All outputs low
Pause 100
LCDOUT $FE,1," Baztronics "
Pause 100
TMR0_Reload CON 55750 ' Reload value for ~100Hz interrupt frequency at 8MHz, prescaler 1:1
TMR0_Temp VAR WORD ' Temporary variable use for reloading the timer
LED1 VAR PortC.2
Main:
Pause 100
Goto Main
' This is the interrupt routine for the TMR0 interrupt.
ISR:
T0CON.7 = 0 ' Stop timer
TMR0_Temp.LOWBYTE = TMR0L
TMR0_Temp.HighByte = TMR0H ' Get current "time"
TMR0_Temp.LOWBYTE = TMR0L
' TMR0_Temp.HighByte = TMR0H
TMR0_Temp = TMR0_Temp + TMR0_Reload ' Add reload value to get correct interval
TMR0L = TMR0_Temp.LOWBYTE
TMR0H = TMR0_Temp.HIGHBYTE ' Move result back to timer
TMR0L = TMR0_Temp.LOWBYTE
' TMR0H = TMR0_Temp.HIGHBYTE
T0CON.7 = 1 ' Start timer
Toggle LED1
@ INT_RETURN
I know my internal oscillator is operating at 8MHz because my LCDOUT commands work properly.
Can anyone explain why the time base is not as predicted?
2/. TMR0L and TMR0H
The datasheet states that "TMR0H is not the high byte of the timer/counter in 16bit mode, but is actually a buffered version of the high byte of Timer0" and that it "is not directly readable nor writable."
It goes on to explain that "TMR0H is updated wth the contents of the high byte of TMR0 during a read of TMR0L" The same conditions apply for write operations.
The way I understand this, I must read the TMR0L first, this transfers the buffered data to the high byte of TMR0H and THEN I can read the high byte directly.
Obviously I have mis understood the operation as this does not work.
The only way I can get the timer to provide a stable time base is to read TMR0L twice and TMR0H once OR read TMR0H twice and TMR0L once.
Would someone be able to describe how/why the low and high bytes of TMR0 should be read/written?
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
Hi Barry,
1) Are you sure you're not getting 100Hz interrupt rate? You are using TOGGLE in the ISR so if the interrupt frequency IS 100Hz it will blink the LED at 50Hz.
2) The way I understand it is that when reading TMR0 you should first read TMR0L, this triggers a transfer (in hardware, nothing you need to worry about) of the content of the actual high byte of the counter into TMR0H which you can then read. When writing you do it the other way around, first load TMR0H then you write TMR0L and that write operation triggers a transfer from TMR0H to the actual high byte of counter.
This hardware buffering prevents the possibillity of the counter rolling over in between reading or writing each individual byte but it's important to do it the correct order.
If you're not using TMR2 for anything it might be easier to use that since it doesn't really require reloading. It counts from 0 to PR2, generates an interrupt and start over at 0. No need to stop the timer, get the value, add reload, write new value and restart the timer. Its only 8 bits but it does have a prescaler so and postscaler so you should be able to get 100Hz. Of course using TMR1 works too!
/Henrik.
-
Re: incPID Routine - Help Needed
Hi Henrik,
Thanks for the quick reply.
1/. Yes, I wasn't using a LED to check the time base - I measured the frequency on my digital oscilloscope
2/. Hmmm.... OK, I will do a bit more playing around to see what I can come up with.
I will check out TMR2 and see if I can get it working as a 100Hz time base.
Lot's of ways to skin a cat. I will try them all and see what I can learn along the way :)
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
Hi Barry,
I'm still not convinced....
If the PIC is toggling the output at 100Hz the measured frequency will be 50Hz because it turns the output ON 50 times per second and OFF 50 times per second. Replace the TOGGLE LED1 with LED1 = 1 : PAUSEUS 100 : LED1 = 0 and see if that convinces you it actually IS interrupting at 100Hz.
/Henrik.
-
Re: incPID Routine - Help Needed
Hi Henrik,
Yes, you were right on both instances.
I now have a nice, stable 100Hz time base and most importantly - I understand why :)
Next step is to incorporate the timer/counter setup with the PWM motor drive to count encoder steps.
From there it is a matter of getting it all to work with the PID routine.
Once more I am indebted to you, Henrik, and the other forum members for the invaluable assistance. Thank you.
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
Hi All,
I am pleased to report that I now have the PID system operating with a timer/counter configuration (100Hz time base) AND a 4 x 20 serial LCD being driven via the 18F2431's EUSART and HSEROUT commands.
My original design only allowed single direction motor drive but the new design has the motor driven by a MOSFET H-Bridge allowing for forward and reverse direction.
Henrik, you suggested to limit the pid_Out result to allow only positive drive outcomes for my original design. Now that I have forward and reverse direction capability, should I re-introduce positive and negative pid_Out drive conditions or do you think switching the motor/H-Bridge between forward and reverse state will cause undue stress on the motor?
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
Hi Barry,
I'm delighted to hear you've got it going, nice work!
Can we see some photos of the thing or perhaps even a video?
It depends on the motor, the H-bridge and if you have any sort of current limiting built into the circuit or not. When the motor is turning CW and you apply a voltage to make it turn CCW the EMF of the motor will end up in series with the supply voltage from the bridge.
IF the motor is doing full speed in one direction and the operator decides it should go full speed in the other direction there will basically be twice the supply voltage across the motor when it starts to decelerate (if you don't apply a ramp on the control signal), if you do have current limiting this shouldn't be too much of any issue but if you're operating this without a current limit there is a chance that you'll damage the H-bridge and possibly the motor (depending on it's peak current rating etc etc). (It might even throw the chuck of the spindle....)
How do you drive the H-bridge? Are you using the PCPWM module in full bridge mode?
If you are controlling position then I'd say you need 4 quadrants but if you're "only" controlling velocity, though both CW and CCW, then I think you'll be fine limiting the output to only positive (or only negative, depending on direction). The motor will still be able to "brake" and regenerate, you just can't generate torque in one direction while it's turning in the other.
/Henrik.
-
Re: incPID Routine - Help Needed
Hi Henrik,
The whole system is rather messy at the moment as a result of the changes made during prototype development. I am happy to send some photos once I have it back in some resemblance of order :)
The power drive for the 1500W motor will ultimately be fed from rectified 240V mains and three large filter caps for a supply rail of around 360Vdc. Right now I am merely driving a 200W 24 volt scooter motor of a 3A bench power supply.
I have overcurrent protection built in to the design by sniffing voltage across a low resistance between the bottom of the H-Bridge and ground. This circuit is designed to trip under overcurrent situation (eg motor stall) but that is the extent of it.
The H-Bridge consists of four APT5010LVR MOSFETS fed by a pair of NCP5181P half-bridge drivers. The 18F2431 feeds the MOSFET drivers from the PCPWM module in full bridge mode. For added safety I have the control circuitry optically isolated from the power circuitry.
I am a little confused by the statement in your last sentence - If I limit the output to only positive (or only negative, depending on direction) how is the motor "still able to brake and regenerate? Do you mean that with pid_Out = 0 the two bottom "legs" of the H-Bridge effectively provide a short circuit across the motor terminals thus providing a brake force via back EMF? Please explain.
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
Hi Barry,
It depends on how you are driving the bridge.
If I understand correctly you're feeding the MOSFETs (thru their drivers) from two of the PWM generators - both in complementary mode, ie four outputs from the PIC. PWM0 & PWM1 are feeding the left leg while PWM2 & PWM3 are feeding the right leg of the bridge (or the other way around). Is that correct so far?
Now, what do you do when you want the motor to turn clockwise (or counter clockwise)?
Do you set one of the PWM generators to 0% (effectively turning on the LOW side switch of that leg) and then apply the output of the PID-filter to the other PWM generator? If you ARE doing this then the motor IS shorted thru the lower two switches during the off-period of the PWM cycle (and, obviously, when the dutycycle of both generators are 0). This will brake the motor but won't regenerate (I think), ie it won't feed energy back to the powersupply. Instead, the energy will be absorbed by the armature resistance of the motor, the rds-on of the MOSFET, wiring, connectors and so on. If this IS what you're doing please note that the braking current this generates does not flow thru your current sense resistor. If the motor is spinning, generating 200V of EMF and you suddenly set both dutycycle registers to 0% the motor will be shorted thru the bottom two switches, how much current will that result in?
The other option is to run the bridge in what's called locked antiphase mode. In this mode you typically use a single PWM generator and drive one diagonal pair of switches with the "true" output and the other diagonal pair with the inverted output.
In this mode the bridge switches between the two diagonal pairs during the PWM cycle. When the dutycycle is 50% each diagonal pairs are "on" for 50% of the PWM cycle resulting in a net current of zero thru the motor. When "forward torque" is to be generated the "balance" is shifted so that one diagonal pair is "on" for a larger amount of time during the PWM cycle resulting in "actual" current thru the motor. In this case the motor will brake AND regenerate when the voltage produced by the bridge is LESS than the motor produced by the EMF of the motor. The motor will never be shorted out.
Phew, I hope I got that right....don't quote me though!
/Henrik.
-
Re: incPID Routine - Help Needed
Hi Henrik,
Thank you for the detailed response.
Yes, I am using two of the PWM generators - both in complementary mode.
I have configured my PWM drive per your first description; I am NOT running it in locked antiphase mode.
I plan do code my program such that the operator (ie me) cannot reverse the motor direction instantly. If the motor is spinning clockwise and the operator flicks the switch to make it spin anti-clockwise, the program will not reverse the direction until the pulse train frequency from the encoder wheel reaches zero - the motor stops spinning. I could also add a short time delay between motor stop and reverse direction.
When the operator goes from one motor direction to "off" I plan to allow the motor to free spin rather than shorting the motor terminals via the two lower MOSFETS. This should negate any major issues with high current cycles being generated from the back EMF of the motor. If the "spin-down" time is too excessive I will look to ramp down the PWM duty cycle for a more controlled response.
The circuit will also have an "Emergency Stop" function. In this case the PWM signal is set to zero, the bottom two MOSFETS are turned on and maximum braking is applied to the motor. I should be able to arrange the circuit such that this condition does not fry any part of the H-Bridge but I figure if I really need to hit the Emergency Stop button (worse case scenario for personal safety) then I can live with having to re-build electronics rather than losing a limb, or worse.
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
Hi Barry,
OK, it seems you've got it covered.
Keep us posted!
/Henrik.
-
Re: incPID Routine - Help Needed
Hi Henrik,
I have been doing some more research on locked antiphase and I see some benefits of this configuration for my application - but some disadvantages too.
Life is full of compromise, why would a motor speed controller design be any different? :)
Before I go off on a dead end:
1/. Can a locked antiphase arrangement be configured on a PIC18F2431 using the PCPWM Module? If not, can it be done via other hardware PWM modules within this PIC?
2/. I have read in other posts on the forum that your incPID routine will work with locked antiphase configuration. Please confirm this is the case.
3/. Will regenerative braking become a major issue to handle for a 180Vdc 1500W treadmill motor with a rectified mains supplied power supply?
As usual, I don't expect anyone to do all the work for me. What I am after is some yes/no type answers from people who have dealt with this type of project and maybe some guidance on the best way forward.
I do this type of work as a hobby and for the enjoyment of learning along the way but it is always better if I don't have to "re-invent the wheel" if someone has already "been there, done that!" :)
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
Hi Barry,
First I want to stress that I'm in no way an expert on motor control, I only know what I've learned from my own experiments. There will certainly be things which I either don't know, is missing or even get wrong.
Quote:
1/. Can a locked antiphase arrangement be configured on a PIC18F2431 using the PCPWM Module? If not, can it be done via other hardware PWM modules within this PIC?
Yes but as far as I know not the way you have it wired now. You need one PWM generator in complementary mode and wire it so that PWM0 drives the upper right and lower left switch while PWM1 drives the upper left and lower right switch.
Quote:
2/. I have read in other posts on the forum that your incPID routine will work with locked antiphase configuration. Please confirm this is the case.
If you've read that you've probably also read that the incPID routine does not know, nor does it care, what it is controlling or what you do with the value it puts out - all it is doing is crunching numbers. It's up to you as the user of it to take its output and apply it accordingly. Be it locked antiphase PWM, basic "unipolar" PWM, sign magnitude PWM, a +/-10V DAC or whatever, it doesn't matter.
Quote:
3/. Will regenerative braking become a major issue to handle for a 180Vdc 1500W treadmill motor with a rectified mains supplied power supply?
I don't think regenerative braking per se will be a problem but I think you need to make sure you don't allow "instant" reversals or stops - like you explained earlier. Never allow the setpoint value to change from one value to another "instantly", always apply ramping and I think you should be fine. Especially so since you don't really have an active current limiting scheme.
If you rectify your 240V mains you'll end up with almost twice the rated voltage of the motor....
I guess the only way to find out is try it. Be careful though!
/Henrik.
-
Re: incPID Routine - Help Needed
Thanks for the sanity check Henrik.
I appreciate your claim not to be a motor control expert but your experimental knowledge is still quantum leaps ahead of mine. I promise to take your comments on board and apply the concepts with due diligence in my designs :)
1/. OK, and understand. I need to redesign the power control PCB anyway because I want to move from phototransistor opto isolators to logic opto devices to reduce turn-on/turn-off times and thereby reduce dead-time.
2/. I thought that was the case - I just wanted to make sure there was a proven method of adjusting pid_Out around the 50% duty cycle setting.
3/. As described in my earlier post, potential for direction reversal will be eliminated by my program and instant stop available only in emergency situations.
I am aware that the rail voltage of my rectified mains power supply will be twice that of the treadmill motor. My original intention was to limit the PWM to 50% maximum such that the average voltage applied would be around the motor voltage rating. Yes, peak voltages will be higher but from my knowledge of treadmill motor drive configurations, these motors are used this way all the time. Actually, it was the fact that locked antiphase configurations only apply half rail voltage to the motor at any one time that sparked my interest to their use in my application - or have I got that concept all mixed up too?
Lots more reading and thinking to be done on my part but I will keep you updated with my progress milestones.
Cheers
Barry
VK2XBP
-
Re: incPID Routine - Help Needed
Hi Barry,
1) OK. You can always run some mod wires on the one you've got to verify before committing to new FR4.
2) Yes. At startup you set your dutycycle register so that you get a 50% dutycycle output. If pid_Out is positive you ADD it to the 50% value, if pid_Out is negative you subtract the ABSolute value of pid_Out from the 50% value.
3) Well, in locked antiphase mode it's not only when YOU reverse direction. If the speed setpoint is changed (even though it is still in the same direction) the PID filter will react to this sudden error and, depending on the tuning of the filter, do more or less violent things with the output to bring the actual speed back to the setpoint. This can in reality mean that the polarity of the average voltage applied to the motor is reversed, ending up in series with the EMF. I'm not saying it's GOING to be an actual problem, just be aware of it. Of course you can always clamp the output to either positive or negative IF it turns out to be an issue in the future.
In locked antiphase mode the full rail voltage is always applied across the motor (except during the dead time period). It's either applied in one polarity or the other.
* If the duty cycle is 50% and the motor is stationary and you measure the average voltage across the motor you'll read 0V.
* If you use a differential probe and look at the voltage with a 'scope you'll see voltage swing of +/- the rail voltage.
* If you measure the average voltage from either motor terminal to ground (still at 50% dutycycle, stationary motor) you'll measure half the rail voltage.
* If the dutycycle is 0% or 100% (don't do that you'll probably fry the high side driver) the voltage across the motor will obviously be + or - the full rail voltage.
/Henrik.