incPID Routine - Help Needed - Page 2


Closed Thread
Page 2 of 2 FirstFirst 12
Results 41 to 64 of 64
  1. #41
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default 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.

  2. #42
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  3. #43


    Did you find this post helpful? Yes | No

    Default 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

  4. #44
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default 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.

  5. #45
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  6. #46
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default 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.

  7. #47
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  8. #48
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default 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.

  9. #49
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  10. #50
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  11. #51
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default 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.

  12. #52
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  13. #53
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default 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.

  14. #54
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  15. #55
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  16. #56
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default 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.
    Last edited by HenrikOlsson; - 25th September 2013 at 11:44.

  17. #57
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  18. #58
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default 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.

  19. #59
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  20. #60
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: incPID Routine - Help Needed

    Hi Barry,
    OK, it seems you've got it covered.
    Keep us posted!

    /Henrik.

  21. #61
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  22. #62
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default 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.

    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.

    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.

    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.

  23. #63
    Join Date
    Jan 2011
    Location
    Sydney, Australia
    Posts
    166


    Did you find this post helpful? Yes | No

    Default 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

  24. #64
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default 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.

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts