PID-filter routine (2nd try).


Closed Thread
Results 1 to 40 of 132

Hybrid View

  1. #1
    Join Date
    May 2007
    Location
    Republic Serbia
    Posts
    105


    Did you find this post helpful? Yes | No

    Default Hi Henrik again after little time

    I runing your PID rutine in 18F4431 and output is locked antiphase , all work like you explain me . I use two interrupt's one for position reding - QEI module and second to calculate PID , in main loop is only increment of setpoint. No Usart , no DEBUG or LCDOUT.
    From time to time not a linear in time it have some little noise which I can also see with scope in PWM out and I can't image from where is ?
    Simple motor have jig - agitation in range of couple step's to +/- and after couple next step's it go linear.
    I use only CW rotation not CCW all the time and PID becouse it good magnetic and precise break in position.
    Can it be from bad tuning of P,I,D parameter's ?
    Output amplifier is copy of HP UHU with 4 x IRF540N.
    Simple I am lost - it is not disaster but meke me little problems on my machin.
    Best regards
    \ ROBERT
    Last edited by phoenix_1; - 24th October 2009 at 20:30.

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,522


    Did you find this post helpful? Yes | No

    Default

    Hi Robert,
    Why do you have the position reading and PID-calculation triggered by different interrupts? You should run the PID as soon as possible after getting the current position otherwise you're working with "old" information. One timer interrupt at: Get position, get setpoint, calculate error, run PID, set PWM, other housekeeping (if necessary) - done.

    Can't say for sure... Perhaps the glitch appears when the QEI position register wraps from MaxCNT to 0 and/or from 0 to MaxCNT. There's also this thread which discusses the HPWM and how to change the dutycycle without upsetting it but IIRC you're using the power control PWM module so it doesn't apply.

    Have you solved the other issue when the setpoint is 0 and the motor overshoots?

    /Henrik.

  3. #3
    Join Date
    May 2007
    Location
    Republic Serbia
    Posts
    105


    Did you find this post helpful? Yes | No

    Thumbs up Like you meen I was rewrite

    Hi Henrik,
    Yes I was today put all in one interrupt (TMR1 , 16bit and make little trick)
    Interrupt fire at 10KHZ but I have counter variable wich increment every interrupt jump and if it not 10 then servo not operate over jump servo and pwm update but when that variable mach 10 servo will operate and reset variable to zero, that meen I have 10khz interrupt with 1khz servo drive.
    After that all work almost perfect but problem is still here and maybe it is in PWM update or I don't know - simple I am near it.
    We will see soon...
    Regards
    /Robert

  4. #4
    Join Date
    Aug 2009
    Posts
    7


    Did you find this post helpful? Yes | No

    Default Motor speed control

    Hi to all.
    Come back after so many time.
    I run dc motor and use same code made no change.
    It controls the speed fine but i found that there is always a difference between reference signal and feedback signal.Due to this motor speed increase enough when we increase proportional gain.
    Is this is a problem or not ?

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,522


    Did you find this post helpful? Yes | No

    Default

    Hello,
    If you really are controlling the speed of the motor and not the position then there shouldn't need to be any difference, if the speed never reaches the setpoint you need to increase the I-gain. That should make it come closer.

    If you use the "moving target" aproach, ie. you are in reallity controlling position then, as long as the motor is moving, there will always be a discrepency between the target and actual position, called following error. The speed however, should match the command , otherwise the following error would just grow larger and larger.

    /Henrik.

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


    Did you find this post helpful? Yes | No

    Default New version of incPID available.

    Hi,
    First, bugfix....
    I've discovered a bug/problem with the original incPID routine. When there's a persistant error present at the filter input the integrator for the I-term is supposed to accumulate and over time produce an output that will drive the error away. However, a small error in conjunction with low I-gain may actually never accumulate enough to produce an output signal like it's supposed to. This was due to truncation of the numbers during calculations. This version implements a fix for this issue.

    Be careful if you move from the previous version to this as the I-term may behave quite differently depending on how your particular application is set up. I've tested it here and it seems to work but please let me know if you find any problems.

    Second, new feature...Feed-forward
    While a PID filter by itself works on the difference between the "setpoint" and the "target" feed-forward works directly on the command signal. Let's say you're controling the speed of a motor, the friction in the bearings, brushes and in the load the motor is driving causes it to need a certain "baseline" amount of power for any given speed in order to compensate for its mechanical and electrical losses. Feedforward can provide this "baseline" which helps the actual filter and can increase the overall system response.

    There are three new "external" variables that you need to use with feed-forward:
    pid_Vel_Kff This is the velocity feedforward gain.
    pid_Acc_Kff This is the acceleration feedforward gain
    pid_Velocity_cmd This is the actual command signal.

    As motor control is my personal use for the incPID routine I've used the terms velocity and acceleration but it's applicable to whatever you are controling. Lets take an example where we want to control the temperature in an oven.
    By imperical testing you have determined that in order to maintain your desired temperature (lets say 150 degrees) under normal/optimal/stable conditions you need an "output" of 800 to your "powerstage". If you set pid_Vel_Kff to $0600 and pid_Vel_cmd to 150, this will result in a "baseline" output of 800. Then you calculate the difference between the setpoint (150) and the current temperature and send it to filter in pid_Error. The output from the actual PID-filter then gets added to or subtracted from that 800 number in order to compensate for any disturbances that occurs.

    The acceleration feedforward works in the same way as the derivative term of the PID filter but instead of acting on the derivative (ie. the difference) of pid_error it acts on the derivative of pid_Vel_cmd.

    More info is available in the file itself.

    I've tested this quite a bit but as always I'm sure there are things I've overlooked. If you have problems, please post in the thread and we'll try to work it out. If you don't have problems and it just works that's always nice to hear as well ;-)

    Sincerely,
    /Henrik.

    (Change file extension from .txt to .pbp and place it in your project folder or in the PBP installation folder).
    Attached Files Attached Files
    Last edited by HenrikOlsson; - 8th May 2010 at 17:03.

  7. #7
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,522


    Did you find this post helpful? Yes | No

    Default Example of what can be done with incPID.

    Hi,
    For anyone interested in motor control, here's a link to a Youtube video showing my latest project based on the PID code available in this thread. It's HP-UHU servo drive on which I've replaced the original UHU servo processor with my own "servo module" that I've made pin-compatible with the original chip.



    <object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/U-jrxK7u_34&hl=en_US&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/U-jrxK7u_34&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object>

    /Henrik.
    Last edited by ScaleRobotics; - 6th June 2010 at 16:12. Reason: embed video

  8. #8


    Did you find this post helpful? Yes | No

    Default Re: Hi Henrik again after little time

    Hello Henrik, All,

    I have read through this thread regarding servo PID motor control that Henrik wrote. I need to modify the code for the direction part of the code. My h-bridge has 3 i/o. PWM drive, Portd.0 and Portd.1.

    The allowable states are:
    portd.0 = 1 and portd.1 = 0
    portd.1 = 0 and portd.1 = 1

    I see that Henrik uses 1 bit to control direction. can I simply replace his code
    "Direction = pid_Out.15 'Set direction pin accordning to sign"

    with.....

    if pid_out.15 = 1 then
    portd.0 = 1
    portd.1 = 0
    else
    portd.0 = 0
    portd.1 = 1
    endif

    I am concerned about messing up timing by introducing these lines of code. Will this affect the integrity of the original code?

    Best Regards,
    Nick

  9. #9
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,522


    Did you find this post helpful? Yes | No

    Default Re: PID-filter routine (2nd try).

    Hi Nick,
    Sure, you can do that - it won't have any effect on the PID code itself and it won't have any effect on the timing of the loop if you're not running the loop at extremely high frequencies.

    However, your pins will be in an invalid state for a short period of time since you set each individual bit separately. Ie when going from 10 to 01 you first clear the high bit, now the output is 00, then you set the low bit to make the output 01. This is likely not a problem but depending on your particular hardware it's possible that 00 and/or 11 has some either undefined function or perhaps they brake the motor by shorting the two lower or two higher switches of the bridge.

    If this prooves to be a concern then you can either fix it with hardware, a single inverter is all you need and you save a PIC pin. If adding hardware is not an option then look into writing all PortD-bits in one go, perhaps something like:
    Code:
    IF PID_Out.15 = 1 THEN
       PortD = (PortD & %11111100) + 1
    ELSE
       PortD = (PortD & %11111100) + 2
    ENDIF
    I'm sure there are other ways of doing it too.

    /Henrik.

    EDIT: Aaarh, now the bloody editor keeps messing with my code again, removing the %-sign AND two digits in the binary value following it...
    Last edited by HenrikOlsson; - 7th November 2011 at 18:19.

  10. #10


    Did you find this post helpful? Yes | No

    Default Re: PID-filter routine (2nd try).

    Good point. I will make the suggested change. In your main code you have HPWM 1, pid_out, 10000 .... I know that pid_out is declared a word (2 bytes) and frequency is 10Khz? The HPWM in the manual says it works with 1 byte for duty cycle....can you explain this part of it? How does feeding a word work with HPWM?

    Best Regards,
    Nick

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


    Did you find this post helpful? Yes | No

    Default Re: PID-filter routine (2nd try).

    Uhh, I guess it doesn't really...you're the first to notice!
    That's an oversight on my behalf as far as the example goes. However, if you clamp the output to +/-255 using pid_Out_Clamp=255 I think it'll work as shown. I think PBP is smart enough to only get the low byte of the word in this case.

    All internal calculations in the PID filter are based on word-sized variables so pid_Out should and must be a WORD.

    /Henrik.

  12. #12


    Did you find this post helpful? Yes | No

    Wink Re: PID-filter routine (2nd try).

    Hello Henrik,

    I just thought you should know that the code works perfectly in my servo application with the mods. I need to tweak constants / gains. Making small incremental changes in position is smooth. Making large changes causes some jerkiness and overshoot but no oscillations!


    Best Regards,
    Nick

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


    Did you find this post helpful? Yes | No

    Default Re: PID-filter routine (2nd try).

    Hi Nick,
    It's always nice to hear that things work out.
    Large step inputs are always "hard" on the filter. It's definitely possible to tune the overshoot out, (lowering I and increasing D should help) but that has other drawbacks. In a servomotor application it's common to have a trajectory planner (think ramp up speed, run, ramp down) before the filter. Basically this "divides" a large step into several small ones making the overshoot you see with a large step input considerably smaller.

    /Henrik.

  14. #14
    Join Date
    Jan 2012
    Location
    Grid EN19MV
    Posts
    159


    Did you find this post helpful? Yes | No

    Default A couple of questions....

    I am attempting to adapt Henrik's PID routine to my smoker temperature controller project. Basically, a fan provides air to the charcoal based on a temperature sensor in the chamber.

    I set up a simulation using it, and it seems to work pretty cool, but I know I'm going to have to run on the real smoker to get it fully tuned up (I still have 3 feet of snow in my yard, so it may be a bit).

    I have set it so that, if the output of the PID routine is negative, it sets the HPWM output to 0 (fan off) since I can't go negative.

    Question 1: Why is the PID output clamp 511 in the original, when the PWM can only go to 255? Or am I missing something? When I set my simulation up so that it would drive to 100%, it was sending 511 - so I have set the PID output clamp to 255.

    Question 2: Since I am dealing with charcoal here, its not a terribly fast heat source, I'm thinking that I should check the temperature every 5 seconds and only update the integral every minute or so (12 passes). Anyone have any thoughts on this?

    Thanks Henrik for this WONDERFUL routine!
    "I have noticed that even those who assert that everything is predestined and that
    we can change nothing about it still look both ways before they cross the street"


    -Stephen Hawking

  15. #15
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,522


    Did you find this post helpful? Yes | No

    Default Re: PID-filter routine (2nd try).

    Hi,
    1) That is indeed an issue with the example code which went unobserved for a very long time, someone noticed it and mentioned it a couple of posts back in the thread. Unfortunately the forum doesn't allow me to fix it in the original post. Anyway, you are 100% right, if you're using the HPWM command then you should set the output clamp to 255. With that said the standard CCP module creating the PWM output can provide resolution of up to 10bits depending on frequency, you just can't "access" it using the HPWM command.

    2) Sounds like a good start. Getting the tuning values right can be tricky, especially so on slow systems since it takes so damn long to see if you got it right or not. I expect this particular "plant" to be extra tricky due to the somewhat unrepeatable/unpredictable "performance" of a charcoal bed - I imagine.

    One thing you might consider is to run the heater/fan/furnace whatever "open loop" until the temperature starts to approach the setpoint and only then switch on the PID. A more elegant but also a bit more complicated way is to create a ramping action in a way that the setpoint, instead of being bumped from ambient to "working temp" is ramped up at a rate that the "plant" can actually follow.

    If you're concerned that a dutycycle of 0% won't provide enough oxygen to keep the fire alive then simply don't allow it to go below a certain value to keep the fan running at all times.

    /Henrik.

  16. #16
    Join Date
    Jan 2012
    Location
    Grid EN19MV
    Posts
    159


    Did you find this post helpful? Yes | No

    Default Re: PID-filter routine (2nd try).

    Quote Originally Posted by HenrikOlsson View Post
    Hi,

    One thing you might consider is to run the heater/fan/furnace whatever "open loop" until the temperature starts to approach the setpoint and only then switch on the PID. A more elegant but also a bit more complicated way is to create a ramping action in a way that the setpoint, instead of being bumped from ambient to "working temp" is ramped up at a rate that the "plant" can actually follow.
    I had actually planned to run the fan in manual mode until I am near the setpoint, then allow the PID loop to take over in auto mode.

    The other question I had is on the reset. In the example, it is set to .5. What causes the integral ramp to get steeper? Would that be an increase in the number? What kind of range of numbers are you expecting on the reset .1 to 1 or even higher than that?

    BTW, while running it in simulation last night, I discovered that a derivative of 0 causes unpredictable results - to remove the derivative, you have to set it to 1.

    In my reading and conversations with people who deal with PID (one of which was an instructor at a local community college) I am told that temperature control only requires process and integral, not derivative.

    Thanks again,

    Andy
    Last edited by andywpg; - 17th April 2013 at 14:28. Reason: Added info
    "I have noticed that even those who assert that everything is predestined and that
    we can change nothing about it still look both ways before they cross the street"


    -Stephen Hawking

  17. #17
    Join Date
    Jan 2012
    Location
    Grid EN19MV
    Posts
    159


    Did you find this post helpful? Yes | No

    Default Re: PID-filter routine (2nd try).

    If anyone is interested, here is what I used to run the simulation (my controller has an LCD)

    Code:
    #CONFIG
     __config _CONFIG1, _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _LVP_OFF & _CP_OFF 
    #ENDCONFIG
    
    DEFINE OSC 8  'LETS PBP KNOW THE OSCILLATOR IS RUNNING AT 8MHz
    DEFINE NO_CLEARWDT 1 'NO WATCHDOG TIMER - FOR NOW - WILL DO OUR OWN CLRWDT
    
    
    OSCCON = %01110001 '8 MHz INTERNAL OSCILLATOR, INTERNAL OSCILLATOR IS USED FOR SYSTEM CLOCK
    
    
    DISABLE 'NO PBP INTERRUPTS NO PBP DEBUG
    
    ' Set LCD Data port
    DEFINE LCD_DREG PORTB
    ' Set starting Data bit (0 or 4) if 4-bit bus
    DEFINE LCD_DBIT 0
    ' Set LCD Register Select port
    DEFINE LCD_RSREG PORTB
    ' Set LCD Register Select bit
    DEFINE LCD_RSBIT 4
    ' Set LCD Enable port
    DEFINE LCD_EREG PORTB
    ' Set LCD Enable bit
    DEFINE LCD_EBIT 5
    ' Set LCD bus size (4 or 8 bits)
    DEFINE LCD_BITS 4
    ' Set number of lines on LCD
    DEFINE LCD_LINES 2
    ' Set command delay time in us
    DEFINE LCD_COMMANDUS 1500
    ' Set data delay time in us
    DEFINE LCD_DATAUS 44
    
    
    
      '// Set up hardware registers, ADC etc here (not shown) //
    
      ADValue VAR WORD                     '<---This is your variable.
      SetPoint VAR WORD                    '<---This is your variable.
      COUNTER VAR BYTE
      RUN_IND VAR BYTE
    
    
    
    
      INCLUDE "incPID.pbp"                 'Include the PID routine.
    
        'These variables are declared by the incPID routine but
        'the user needs to assign values to them.
        pid_Kp = $0700                     'Set Kp to 7.0 GAIN
        pid_Ki = $0080                     'Set Ki to 0.5 RESET
        pid_Kd = $0001                     'Set Kd to 0 (Derivative not necessary)
        pid_Ti = 8                         'Update I-term every 8th call to PID
        pid_I_Clamp = 100                  'Clamp I-term to max ±100
        pid_Out_Clamp = 255                'Clamp the final output to 0 to 255
    	Setpoint = 230		               '<---Set desired position.
    	RUN_IND = 1
    
    START:
       	FOR ADVALUE = 225 TO 235 'TEST A BUNCH OF VALUES
    		FOR COUNTER = 1 TO 10
       			pid_Error = Setpoint - ADValue     'Calculate the error
    			Gosub PID                          'Result returned in pid_Drive
       			if pid_Out.15 then pid_out = 0     'IF NEGATIVE THEN SHUT OFF FAN
       			pid_Out = ABS pid_Out              'Convert from two's comp. to absolute
    '  			HPWM 1, pid_Out, 10000             'Set PWM output
    
    			LCDOUT $FE, 1, "AD=", DEC ADVALUE, " PO=", SDEC PID_OUT
    			LCDOUT $FE, $C0, "RUN #", DEC COUNTER, " SETP ", DEC SETPOINT
    			Pause 1000                           'Wait....
    		NEXT COUNTER
    	NEXT ADVALUE
    	IF RUN_IND = 1 THEN
    		RUN_IND = 0 
    		GOTO START 'DO IT AGAIN SO THAT ITS AS IF THE TEMPERATURE DROPPED 
    	ENDIF
    	LCDOUT $FE, 1, "DONE!"
    	DO
    	LOOP 'ENDLESS LOOP
    	
    END
    Last edited by andywpg; - 17th April 2013 at 14:51.
    "I have noticed that even those who assert that everything is predestined and that
    we can change nothing about it still look both ways before they cross the street"


    -Stephen Hawking

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


    Did you find this post helpful? Yes | No

    Default Re: PID-filter routine (2nd try).

    Hi,
    I'm sure you're correct that you don't need derivative. I'm surprised though that you get unpredictable results when you set it to zero, I'll have to look into that. What exactly is it doing?
    Anyway setting it to 1 is pretty close to 0 (1/256 to be precise.) So it shouldn't have any effect on the actual control loop in your case.

    The PID_Ki isn't the "reset time" (at least I don't think it's comparable to that), it's the integral gain. To get more integral action (steeper ramp) you increase the gain.

    Here's how it works, basically:
    Each time you GOSUB PID the integral term takes the error and adds it to an accumulator. It then increments a counter and compares the counter value to PID_Ti, if the counter value is less than PID_Ti it's done. If the counter is equal to PID_Ti it takes the (value in the accumulator) * (integral gain/256) / PID_Ti, it then adds the result to the output and resets the accumulator as to not overflow it. I think you can compare the PID_Ti value to what's sometimes called "reset time". (It does a couple of other things as well but lets not go into that right now).

    As to a range of values for the integral gain..... all I can say really is that it's usually a lot less than the proportional gain, which in turn is usually a lot less than the derivative gain (which you don't use here).

    Hope it helps.
    /Henrik.
    Last edited by HenrikOlsson; - 17th April 2013 at 18:00.

  19. #19
    Join Date
    Jan 2012
    Location
    Grid EN19MV
    Posts
    159


    Did you find this post helpful? Yes | No

    Default Re: PID-filter routine (2nd try).

    Quote Originally Posted by HenrikOlsson View Post
    Hi,
    I'm sure you're correct that you don't need derivative. I'm surprised though that you get unpredictable results when you set it to zero, I'll have to look into that. What exactly is it doing?
    All this was observed using the code I posted above.

    With the derivative set to one, and the loop at 216 (degrees) it usually starts with an output to the PWM of 150 or so. As the sample gets closer to the setpoint (230) it ramps down - as it should.

    With derivative set to 0, the PWM starts at about 20, and goes down from there - I can't remember exactly where, but at some point (long before its at the setpoint) its at ZERO - with a charcoal fire, that means its never getting to the setpoint. Strangely enough, on the SECOND run through the numbers, it starts working properly - not sure why. Maybe its my fault.

    It seems to work great with the derivative set to 1, though, acts exactly as it should.


    Quote Originally Posted by HenrikOlsson View Post
    Hope it helps.
    Very much so. Now, if only this damn snow would go away........

    Thanks again,

    Andy
    Last edited by andywpg; - 18th April 2013 at 00:15. Reason: spelling
    "I have noticed that even those who assert that everything is predestined and that
    we can change nothing about it still look both ways before they cross the street"


    -Stephen Hawking

Similar Threads

  1. Darrel's latest 16 bit averaging routine?
    By jellis00 in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 17th October 2009, 01:57
  2. 2nd order Low-pass passive RC filter on PWM
    By munromh in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 29th January 2009, 19:03
  3. Atod Digital Filter
    By GeoJoe in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 2nd April 2008, 17:04
  4. PID controller in 16F737
    By joeri in forum mel PIC BASIC
    Replies: 8
    Last Post: - 24th June 2006, 11:39
  5. 2nd Order Digital Filter for 24-bit
    By sefayil in forum mel PIC BASIC
    Replies: 0
    Last Post: - 2nd December 2005, 21:55

Members who have read this thread : 3

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

Tags for this Thread

Posting Permissions

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