Page 2 of 2 FirstFirst 12
Results 11 to 14 of 14

Thread: PID basics

  1. #11
    Junior Member Newbie
    Join Date
    Dec 2009
    Location
    Dehradun
    Posts
    9

    Default

    Quote Originally Posted by MohitM View Post
    I'll get back to you in a day or two. In the meantime can you read up how to generate the PWM on the AVR? That's something described in the datasheet and tutorials.
    will comply

    regards
    vaibhav
    Growing by the hour...

  2. #12
    Junior Member Newbie
    Join Date
    Dec 2009
    Location
    Dehradun
    Posts
    9

    Default

    Quote Originally Posted by naatumach View Post
    will comply

    regards
    vaibhav
    I tried to read the data sheet.
    Then i tried to reverse engineer the sample code that i had for PWM from robokits

    // MADE BY ROBOKITS INDIA.
    // VISIT US AT WWW.ROBOKITS.ORG
    // PROGRAM FOR PWM
    // WRITTEN FOR AVR 40 PIN DEV BOARD


    /*-------------------------------------------------------------------
    Description:
    This example shows how to generate average DC voltages between VCC
    and GND using Pulse Width Modulation (PWM).

    Check voltage on pin 18-19 of avr with respect to GND.

    Note:

    Change OC1A and OC1B pin pullup if used with any other AVR micro.
    ---------------------------------------------------------------------*/

    /*----------------------------------------------------------------
    -----------------HEADER FILES-------------------------------------
    -----------------------------------------------------------------*/

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include<compat/deprecated.h> //HEADER FILE FOR FUNCTIONS LIKE SBI AND CBI
    #include<util/delay.h> //HEADER FILE FOR DELAY

    #define XTAL 1000000L // Crystal frequency in Hz
    #define OC1A_PIN PD5 // OC1A pin
    #define OC1B_PIN PD6 // OC1B pin
    #define OC1_DDR DDRD // OC1 DDR


    int main(void)
    {

    DDRB=0XFF; //SET DATA DIRECTION REGISTER
    //SET 1 for OUTPUT PORT
    //SET 0 FOR INPUT PORT
    //ALL OTHERS ARE OUTPUT

    DDRD=0XF0; //SET DATA DIRECTION REGISTER
    //SET 1 for OUTPUT PORT
    //SET 0 FOR INPUT PORT
    //PD.1, PD.2 AND PD.3 ARE INPUT
    //ALL OTHERS ARE OUTPUT

    sbi(PORTD,0); //ENABLE PULL UP FOR SW1
    sbi(PORTD,1); //ENABLE PULL UP FOR SW2
    sbi(PORTD,2); //ENABLE PULL UP FOR SWITCH INT0
    sbi(PORTD,3); //ENABLE PULL UP FOR SWITCH INT1

    uint8_t i = 0;

    OC1_DDR |= _BV(OC1A_PIN) + _BV(OC1B_PIN); // set OC1A and OC1B pin as output, required for output toggling

    TCCR1A = _BV(WGM10) | _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(COM1B0); // enable 8 bit PWM, select inverted PWM

    // timer1 running on 1/8 MCU clock with clear timer/counter1 on Compare Match
    // PWM frequency will be MCU clock / 8 / 512, e.g. with 1Mhz Crystal 244 Hz.
    TCCR1B = _BV(CS11) | _BV(WGM12);

    for (;;)
    {
    for (i=0; i<255; i++)
    {
    OCR1AL = i;
    OCR1BL = i;
    _delay_ms(25); // delay 25 ms
    }

    for( i=255; i>0; i--)
    {
    OCR1AL = i;
    OCR1BL = i;
    _delay_ms(25); // delay 25 ms
    }
    }
    }


    I couldnt really understand the synatx.
    but i understood how to manipulate the output from this code.
    I tried the code on LEDs and Motors, and did a crude hit an trial method to understand the working of the code.
    what this code gave when connected to a motor was that the motor started up and then switched off then on then off.
    I understood how to increase the frequency of that activity.
    what i was most interested in was to get a steady motor rpm, so i removed the loops and got steady motor RPM, which i could vary according to the code.

    Then i implemented my pseudo-code.
    and said
    for error +2 the left motor should go at 0% RPM and Right at 100% RPM.
    for error +1 the left motor should go at 50% RPM and Right at 100% RPM.
    for error 0 the left motor should go at 100% RPM and Right at 100% RPM.
    for error -1 the left motor should go at 100% RPM and Right at 50% RPM.
    for error -2 the left motor should go at 100% RPM and Right at 0% RPM.

    This logic is obviously not tuned. and i haven't tried it on the "track" but yes i got my desired output.
    I couldn't test it on the robot as i was out of time but this is my progress.

    Regards
    Vaibhav

    I am still left with the topic of the thread PID.
    Growing by the hour...

  3. #13
    Senior Member T-1000
    Join Date
    Oct 2006
    Location
    Agra, India
    Posts
    406

    Default

    Let's say:
    a. You want to control the RPM of a PMDC motor between 0 - 1000 (so your sensor should be able to measure 0 - 1000 RPM)
    b. Your microcontroller has a PWM resolution of 10 bits i.e. a duty cycle that varies from 0-1023. For simplicity, assume that the PWM duty cycle varies from 0 to 1000 (not 0 - 1023). Additionally, you also have a MOSFET (or something can switch ON-OFF at a rate of 10 kHz) that can supply the max power without blowing up.

    Now, the operator sets the RPM at 500 RPM.
    1. The motor starts from standstill, i.e. 0 RPM.
    2. The processor calculates the difference between set RPM and actual RPM, ErrorPresent = 500 - 0 = 500

    3. Supposing, ProportionalGainConstant = 1 (this value is just for illustration)
    4. ProportionalComponent = ErrorPresent * ProportionalGainConstant = 500 * 1 = 500

    5. Supposing, IntegralGainConstant = 0.5 (this value is just for illustration)
    6. IntegralComponent = IntegralComponentPrevious + (ErrorPresent * IntegralGainConstant) = 0 + (500 * 0.5) = 250

    7. Supposing, DifferentialGainConstant = 0.1 (this value is just for illustration)
    8. DifferentialComponent = (ErrorPrevious - ErrorPresent) * DifferentialGainConstant = (0 - 500) * 0.1 = -50
    Since this is the first calculation and there is no previous error, we do not consider the differential component in the first instance.

    9. Add all these three components...
    10. PID_Value = ProportionalComponent + IntegralComponent + DifferentialComponent
    11. PID_Value = 500 + 250 + 0 = 750

    12. Now you can pass this value to the PWM module of the processor, i.e 750/1000 is the duty cycle that you switch the MOSFET on.
    13. At DutyCycle = 750, the motor speeds up. Lets say that while it is speeding up, the processor goes back to step 2 for the next round of control loop, at which point in time the motor RPM is 200.

    14. The processor saves the previous error in ErrorPrevious (= 500) and calculates the present error, ErrorPresent = 500 - 200 = 300.
    15. So, ProportionalComponent = ErrorPresent * ProportionalGainConstant = 300 * 1 = 300
    16. IntegralComponent = IntegralComponentPrevious + (ErrorPresent * IntegralGainConstant) = 250 + (300 * 0.5) = 400
    17. DifferentialComponent = (ErrorPrevious - ErrorPresent) * DifferentialGainConstant = (500 - 300) * 0.1 = 20
    18. PID_Value = 300 + 400 + 20 = 720
    19. This is the latest PWM duty cycle value for the MOSFET.

    So as you loop repeatedly, you'll realise how a PID controller responds to the system behaviour and running errors.

    Practically, you need to find out what values of GainConstants give you a good response. By which I mean that the system reaches the set value in the quickest time, yet does not overshoot the set value.

    Also, make sure that the PID value does not cross 1000. If it does, then limit it to 1000 (or whatever your processor's maximum PWM value can be).

    Run a series of experiments and ask here for any clarifications.

    Mohit Mahajan,
    www.BioZen.co.in
    --
    Mohit Mahajan,
    www.BioZen.co.in

  4. #14
    Junior Member Newbie
    Join Date
    Dec 2009
    Location
    Dehradun
    Posts
    9

    Default

    Hello
    I am sorry for the late reply
    I will continue once my exams are over.
    I guess i will get time to start again only january.

    Regards
    Vaibhav
    Growing by the hour...

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
  •