PID-filter routine (2nd try).


Closed Thread
Results 1 to 40 of 132

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,623


    Did you find this post helpful? Yes | No

    Default

    Hi Robert,
    I'm sorry but I'm having a hard time understanding you. I like to help you but it's just hard when you don't even answer my questions. Now you say it's close to being PID? What exactly is it that doesn't work?

    If the motor isn't "stiff" enough you need to tune the PID parameters, I see you have Kp, Ki & Kd exactly as in my example code - which is just that - an example. You need to change them to suit your application.

    Also, you could as well changed your code to read pid_Out_Clamp = 640 instead of hardcoding 640 into the incPID routine. In any case if you only have 10bits of PWM resolution why allow the output to swing to +/-640 which is 11bits?

    Another thing I notice is that you preset TMR 0 with the value 237, but you do that only at the beginning of the program, so it will go from 237->256, cause an interrupt, then it will start from 0 again. With the pescaler at 1:256 that will be an interrupt rate of 38Hz which might be a bit slow. You need to preset TMR0 again in your ISR.

    You can change this:
    Code:
    advalue = y
    pid_Error = Setpoint - ADValue
    To simply read
    Code:
    pid_Error = Setpoint - y
    It won't work any better but a little faster and it'll save you a byte or two ;-)

    And, try removing the LCDOut statements as a test and see what impact that has on it. Do you have an oscilloscope? Connect it to a pin, set the pin high the first thing you do in the ISR and low again before returning - then you can see if you have the correct interrupt frequency.

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


    Did you find this post helpful? Yes | No

    Default

    ok in UHU or any other PID control if POSITION= SETPOINT motor must clip +/- for to make break in position.
    when you set SETPOINT increment +1 or +XXX then PID must move motor in that direction and when MOTOR come to SETPOINT PID must again clip motor +/- in new POSITION becous POSITION is again = SETPOINT.
    If you probe to mechanic move MOTOR SHAFT from locked position PID rutine must give reaction to back motor to lock POSITION.
    Your PID control work good maybe with L2XX motor driver chip but with real output driver like HP UHU output stage NOT work.
    In uhu sistem you have two pins on output stage.One for motor enable / disable (logic 1 enable , logic 0 disable.That is use for motor protect with current detector via resistor in DRAIN of output MOSFETS.
    Second pin is in same time PWM drive / direction.
    When PWM on these pin is 50/50% that is 512 on 10bit then motor is in stop condition.When on these pin come PWM from 512-0 you have movement of motor from slow 511 to full spid PWM close 10.And when you go from 513 to 1024 you have slow to full speed of motor at close 1014.
    My motor have gear 6.25 motor full turn for one shaft full turn.That mean I must use wariable for position storage from 0 - 6250 which represent full range for one full turn of output gear shaft.
    When I use your PID rutine it break motor to go from lock position to minus CCW and it give PWM to motor 511 , 510,...492...400 and move motor CW to lock dead point.But when i move output shaft to CW position your PID giwe PWM 511 and normaly that must be to give 513,515....600 to mowe motor in CCW to motor come to lock point.That is becouse in your position is :
    Code:
    '*******************************************************************************
    '*******************************************************************************
    'Calculate the total drive.
    
    pid_Out = pid_P + pid_I + pid_D         'Calculate total drive....
    
     pid_Sign = pid_Out.15                   'Save Sign
     pid_Out = ABS pid_Out                   'Convert from two's comp. to abs.
    if  pid_Out >= pid_Out_Clamp then        'Output is saturated...
        pid_Status_Out_Sat = 1              'set status bit and...
         pid_out = pid_Out_Clamp '  pid_Out_Clamp = 511 
    
    Endif
    If pid_Sign then pid_out = -pid_out     'Re-apply sign.
    
    RETURN                                  'And return to sender.
    SkipPID:
    Ok and your suggestions are good but I was spend 10..hours and my head is like baloon...sorry.
    Regards Robert

  3. #3
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,623


    Did you find this post helpful? Yes | No

    Default

    Hi Robert,
    Don't worry, I know the difference between sign & magnitude and locked antiphase.

    If you're working with locked anti-phase, like the UHU chip does, then you need to look at the output from the PID filter, if it's positive you add to the dutycycle and if it negative you subtract the ABS value of the PID_Out from the duty cycle. Basically....
    Code:
    'At startup set the PWM dutycycle to 50%
    PID_Error = Position - Setpoint
    Gosub PID
    
    If PID_Out.15 = 1  then           'Output is negative 
      DutyCycle = 512 - ABS PID_Out
    Else                           'Output is positive
      DutyCycle = 512 + PID_Out
    Endif
    So again, if your dutycycle register is 50% (512) when no torque is delivered (ie. you are working with locked antiphase) then you really should clamp the output of the PID to +/-511, if you don't do that the dutycycle register may over- or underflow. If, for example, the output of the PID filter is allowed to swing to -640, and you subtract that from 512 you end up with -128. -128 in a 16bit variable is the same as 65407 so if you take the lower 10 bits (=895) of that and stuff it into your dutycycle register you'll end up with a dutycycle of 87% instead of 0 - torque will get delivered in wrong direction.....

    Also, with a powerstage such as the one on the HP-UHU you need to make sure that dutycycle never reaches 0 or 100% because then the bootstrap capacitors in the highside MOSFET drivers no longer have any time to recharge and bad things will happen.

    And, to show you that it does work, here's a link to a video I just uploaded:


    Yes, it uses sign & magnitude and no it's not step and direction. It takes serial commands from a host CPU or PC. I've also got a couple of videos there featuring the HP-UHU. I've been quite involved in the HP-UHU project so I know it pretty well.

    And as a friendly note, if you think that this PID-code doesn't work for your application then by all means feel free to use something else.

    Sincerely,
    /Henrik.

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


    Did you find this post helpful? Yes | No

    Default

    No I mean it work good and many thanks to you for writing that...
    My best regards and I will continue to test it for my machine.
    Regards Robert

  5. #5
    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 21:30.

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


    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.

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

  8. #8
    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 ?

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


    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.

  10. #10


    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

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


    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 19:19.

  12. #12
    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

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


    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.

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, 02: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, 20:03
  3. Atod Digital Filter
    By GeoJoe in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 2nd April 2008, 18:04
  4. PID controller in 16F737
    By joeri in forum mel PIC BASIC
    Replies: 8
    Last Post: - 24th June 2006, 12:39
  5. 2nd Order Digital Filter for 24-bit
    By sefayil in forum mel PIC BASIC
    Replies: 0
    Last Post: - 2nd December 2005, 22:55

Members who have read this thread : 2

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