pid_pic_corso_2k6.c

00001 #include <18F2520.h>
00002 #include <float.h>
00003 
00004 #device adc=10
00005 
00006 /**************   Device Config     ******************/
00007 
00008 #FUSES NOWDT                    //No Watch Dog Timer
00009 #FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
00010 #FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
00011 #FUSES NOPROTECT                //Code not protected from reading
00012 #FUSES BROWNOUT                 //Reset when brownout detected
00013 #FUSES BORV20                   //Brownout reset at 2.0V
00014 #FUSES NOPUT                    //No Power Up Timer
00015 #FUSES NOCPD                    //No EE protection
00016 #FUSES STVREN                   //Stack full/underflow will cause reset
00017 #FUSES NODEBUG                  //No Debug mode for ICD
00018 #FUSES LVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
00019 #FUSES NOWRT                    //Program memory not write protected
00020 #FUSES NOWRTD                   //Data EEPROM not write protected
00021 #FUSES IESO                     //Internal External Switch Over mode enabled
00022 #FUSES FCMEN                    //Fail-safe clock monitor enabled
00023 #FUSES PBADEN                   //PORTB pins are configured as analog input channels on RESET
00024 #FUSES NOWRTC                   //configuration not registers write protected
00025 #FUSES NOWRTB                   //Boot block not write protected
00026 #FUSES NOEBTR                   //Memory not protected from table reads
00027 #FUSES NOEBTRB                  //Boot block not protected from table reads
00028 #FUSES NOCPB                    //No Boot Block code protection
00029 #FUSES LPT1OSC                  //Timer1 configured for low-power operation
00030 #FUSES MCLR                     //Master Clear pin enabled
00031 #FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
00032 
00033 #use delay(clock=16000000)
00034 #use rs232(baud=57600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
00035 
00036 #byte T0CON = 0xFD5
00037 
00038 
00039 /**************   Defines    ******************/
00040 #define IN_CLK    PIN_C0
00041 #define PULS_A    PIN_B0
00042 #define PULS_B    PIN_A4
00043 
00044 #define TIMEOUT_RELOAD     3  // 60Hz ovvero 13ms
00045 
00046 /**************   Typedefs   ******************/
00047 typedef unsigned int16  WORD;
00048 typedef unsigned int32  DWORD;
00049 
00050 /**************   Variables   ******************/
00051 
00052 int8  bReadRPMTimeout = TIMEOUT_RELOAD;
00053 WORD  wTimer0Counts;
00054 
00055 WORD  velocita;
00056 WORD  wMotorRPMSetpoint;
00057 
00058 float fPWM_duty      = 0.0;
00059 float fPWM_duty_prev = 0.0;    //previus cycle PWM value
00060 
00061 float fMotorRPM      =0.0;
00062 int8  bTimer1_Overflows=0;
00063 DWORD tempo;
00064 
00065 WORD tempo_ciclo_ms;
00066 WORD delay_todo_ms;
00067 
00068 int8  bSelect_Input=0;
00069 int8  bSelect_Input_prev=0xFF;
00070 
00071 /**************   PID  Variables ******************/
00072 float err   =  0.0;  //errore
00073 float err1  =  0.0;  //errore ciclo precedente
00074 float err2  =  0.0;  //errore due cicli precedenti
00075 
00076 float K_P   =  0.01;
00077 float K_I   =  0.001;
00078 float K_D   =  0.001;
00079 
00080 #define PID_TIME_CYCLE (100) // 100 ms //attenzione max val 255
00081 #define tempo_pid      PID_TIME_CYCLE  //constant time mode
00082 
00083 /**************   Prototypes   ******************/
00084 void Measure_Speed();
00085 void LoopTimeWait();
00086 void User_Interface();
00087 void PID_algo();
00088 void Update_PWM();
00089 
00090 
00091 
00092 /**************   Interrupts   ******************/
00093 #int_TIMER1
00094 void TIMER1_isr()
00095 {
00096    bTimer1_Overflows ++;
00097    output_toggle(PIN_B3);
00098 
00099    if(bReadRPMTimeout)
00100         bReadRPMTimeout--;
00101 }
00102 
00103 
00104 
00105 /**************   Main   ******************/
00106 
00107 void main()
00108 {
00109 
00110 
00111 /**************   Peripherals Config   ******************/
00112    setup_adc_ports(AN0|VSS_VDD);
00113    setup_adc(ADC_CLOCK_DIV_64|ADC_TAD_MUL_0);
00114    setup_wdt(WDT_OFF);
00115 
00116    setup_timer_0(RTCC_INTERNAL);
00117    setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);      //T1 65ms interrput (15Hz)
00118    setup_timer_2(T2_DIV_BY_16,255,1);           //PWM 977Hz 10bit res
00119    setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
00120 
00121    setup_ccp1(CCP_PWM);
00122    setup_comparator(NC_NC_NC_NC);
00123    setup_vref(FALSE);
00124    setup_low_volt_detect(FALSE);
00125 
00126    setup_oscillator(OSC_4MHZ|OSC_NORMAL|OSC_31250|OSC_PLL_ON);    //clock CPU a 16Mhz
00127 
00128 /**************   I/O Config   ******************/
00129    input(IN_CLK);
00130    output_high(PIN_B1);
00131    output_high(PIN_B2);
00132 
00133    setup_uart(57600);
00134 
00135    printf("\r\n\r\n");
00136      printf("HELLO TEST PID MOTOR CONTROL\r\n");
00137 
00138    set_timer1(0);
00139 
00140 
00141    enable_interrupts(INT_TIMER1);
00142    enable_interrupts(GLOBAL);
00143 
00144 
00145 /**************   Main loop   ******************/
00146    while(1)
00147    {
00148 
00149         Measure_Speed();
00150         
00151         LoopTimeWait();
00152         
00153         User_Interface();
00154         
00155         PID_algo();
00156         
00157         Update_PWM();
00158         
00159          //   printf("vel=%lu-setpt=%lu\r\n",velocita,wMotorRPMSetpoint);
00160          //   printf("vel=%f-setpt=%lu\r\n",fMotorRPM,wMotorRPMSetpoint);
00161         
00162                                         printf("velocita=%f-wMotorRPMSetpoint=%lu-fPWM_dutycycle=%f-tempo=%lu \r\n",fMotorRPM,wMotorRPMSetpoint,fPWM_duty,tempo);
00163                         
00164    }
00165 }
00166 
00167 
00168 /*********************************************************/
00169 /********************   Functions   **********************/
00170 /*********************************************************/
00171 
00172 
00173 /**************   Measure Motor Speed   ******************/
00174 void Measure_Speed()
00175 {
00176     bReadRPMTimeout = TIMEOUT_RELOAD;
00177 
00178     T0CON &= 0x7F;       //timer OFF
00179     set_timer0(0);
00180 
00181     while(input(IN_CLK) && bReadRPMTimeout);       //wait for H2L
00182     delay_cycles(5); 
00183 
00184     while(!input(IN_CLK) && bReadRPMTimeout);      //wait for L2H    1st positive edge
00185     T0CON |= 0x80;    //timer ON
00186     delay_cycles(5); 
00187 
00188     while(input(IN_CLK) && bReadRPMTimeout);       //wait for H2L
00189     delay_cycles(5); 
00190 
00191     while(!input(IN_CLK) && bReadRPMTimeout);      //wait for L2H   2nd positive edge
00192     T0CON &= 0x7F;       //timer OFF
00193 
00194     if(!bReadRPMTimeout)
00195         fMotorRPM = 0;
00196     else
00197     {
00198        wTimer0Counts = get_timer0();
00199        velocita = wTimer0Counts;
00200         
00201 //     fMotorRPM = 60*(1*1000*1000)/((float)velocita * 16.0);//rpm
00202        fMotorRPM = (2*1000*1000)/((float)wTimer0Counts);    //rpm
00203        fMotorRPM /=   16;   //Number of holes
00204        fMotorRPM *=   60;   //Hz to RPM
00205      }
00206 }
00207 
00208 /**************   Measure Loop Time   ******************/
00209 void LoopTimeWait()
00210 {
00211     
00212     disable_interrupts(INT_TIMER1);
00213         tempo =  (DWORD)get_timer1();
00214         tempo += ((DWORD)bTimer1_Overflows)<<16; // * 65536;
00215     enable_interrupts(INT_TIMER1);
00216     
00217     tempo_ciclo_ms = tempo / (2*1000);  //tempo ms
00218     
00219     printf("t=%lu-OWF=%u-tcy=%lu ",tempo,bTimer1_Overflows,tempo_ciclo_ms);
00220     //            bTimer1_Overflows=0;
00221       
00222     if(PID_TIME_CYCLE > tempo_ciclo_ms)
00223     {
00224        delay_todo_ms = (PID_TIME_CYCLE - tempo_ciclo_ms);
00225        printf("d=%lu ",delay_todo_ms);
00226        while (delay_todo_ms > 255)
00227        {
00228           delay_ms(255);
00229           delay_todo_ms -=255;
00230        }
00231        delay_ms((int8)(delay_todo_ms));
00232     }
00233     
00234     disable_interrupts(INT_TIMER1);
00235         set_timer1(0);
00236         bTimer1_Overflows=0;
00237     enable_interrupts(INT_TIMER1);
00238 }
00239 
00240 /**************   PID Algorithm   ******************/
00241 void PID_algo()
00242 {
00243     err2=err1;                    //errore due cicli precedenti
00244     err1=err;                     //errore ciclo precedente
00245     err=(float)wMotorRPMSetpoint-fMotorRPM;     //errore
00246     
00247     if(0==bSelect_Input)        //PID mode
00248     {
00249         fPWM_duty +=  K_P * err;                                   //P
00250         fPWM_duty +=  K_I *  tempo_pid * (err-err1);               //I
00251         fPWM_duty +=  K_D * (err - 2*err1 + err2) / tempo_pid;     //D
00252     }
00253     else if (1==bSelect_Input)  //P mode
00254     {
00255         fPWM_duty +=  K_P * err;                                   //P
00256     }
00257     else if (2==bSelect_Input)  //I mode
00258     {
00259      fPWM_duty +=  K_I *  tempo_pid * (err-err1);                  //I
00260     }
00261     else if (3==bSelect_Input)  //D mode
00262     {
00263      fPWM_duty +=  K_D * (err - 2*err1 + err2) / tempo_pid;        //D
00264     }
00265     
00266     
00267     //limit fPWM_duty 0-1023
00268     if (fPWM_duty > 1023)
00269        fPWM_duty = 1023;
00270     
00271     if (fPWM_duty < 0.0)
00272        fPWM_duty = 0;
00273 }
00274 
00275 /**************   Set PWM Output   ******************/
00276 void Update_PWM()
00277 {
00278    //update PWM only if fPWM_duty changes
00279    if (fPWM_duty != fPWM_duty_prev)
00280    {
00281       set_pwm1_duty((WORD)fPWM_duty);
00282       fPWM_duty_prev = fPWM_duty;
00283    }
00284 }
00285 
00286 
00287 /**************   User Interface - Buttons   ******************/
00288 void User_Interface()
00289 {
00290     if(input(PULS_A))      //button polling
00291     {
00292         wMotorRPMSetpoint = read_adc();   //range 0-3048
00293         wMotorRPMSetpoint += read_adc();  
00294         wMotorRPMSetpoint += read_adc();  
00295     }
00296     else
00297     {
00298         K_P = (float)read_adc()/1000.0;     //0-1
00299         K_I = K_P/10.0;                     //0-0,1
00300         K_D = K_I;                          //0-0,1
00301         
00302         printf("P=%f-D=%f-I=%f\r\n",K_P,K_D,K_I);
00303     }
00304     
00305     
00306     if(!input(PULS_B))      //button polling
00307     {
00308       while(!input(PULS_B)); //wait for button release
00309     
00310       bSelect_Input++;
00311       if(bSelect_Input>3)
00312          bSelect_Input=0;
00313     }
00314     
00315     if (bSelect_Input != bSelect_Input_prev)
00316     {
00317         bSelect_Input_prev = bSelect_Input;
00318         
00319         if(0==bSelect_Input)        //PID mode
00320         {
00321             output_low(PIN_B1);
00322             output_low(PIN_B2);
00323             printf("Proporzionale-integrativo-derivativo\r\n");
00324         }
00325         else if (1==bSelect_Input)  //P mode
00326         {
00327             output_low(PIN_B1);
00328             output_high(PIN_B2);
00329             printf("Proporzionale\r\n");
00330         }
00331         else if (2==bSelect_Input)  //I mode
00332         {
00333             output_high(PIN_B1);
00334             output_low(PIN_B2);
00335             printf("Integrativo\r\n");
00336         }
00337         else if (3==bSelect_Input)  //D mode
00338         {
00339             output_high(PIN_B1);
00340             output_high(PIN_B2);
00341             printf("Derivativo\r\n");
00342         }
00343 
00344                 delay_ms(500);
00345         }
00346     
00347 }

Generato il Tue Dec 12 23:51:30 2006 per PID MOTOR PIC da  doxygen 1.4.7