00001 #include <18F2520.h>
00002 #include <float.h>
00003
00004 #device adc=10
00005
00006
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
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
00047 typedef unsigned int16 WORD;
00048 typedef unsigned int32 DWORD;
00049
00050
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;
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
00072 float err = 0.0;
00073 float err1 = 0.0;
00074 float err2 = 0.0;
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
00084 void Measure_Speed();
00085 void LoopTimeWait();
00086 void User_Interface();
00087 void PID_algo();
00088 void Update_PWM();
00089
00090
00091
00092
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
00106
00107 void main()
00108 {
00109
00110
00111
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);
00118 setup_timer_2(T2_DIV_BY_16,255,1);
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);
00127
00128
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
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
00160
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
00170
00171
00172
00173
00174 void Measure_Speed()
00175 {
00176 bReadRPMTimeout = TIMEOUT_RELOAD;
00177
00178 T0CON &= 0x7F;
00179 set_timer0(0);
00180
00181 while(input(IN_CLK) && bReadRPMTimeout);
00182 delay_cycles(5);
00183
00184 while(!input(IN_CLK) && bReadRPMTimeout);
00185 T0CON |= 0x80;
00186 delay_cycles(5);
00187
00188 while(input(IN_CLK) && bReadRPMTimeout);
00189 delay_cycles(5);
00190
00191 while(!input(IN_CLK) && bReadRPMTimeout);
00192 T0CON &= 0x7F;
00193
00194 if(!bReadRPMTimeout)
00195 fMotorRPM = 0;
00196 else
00197 {
00198 wTimer0Counts = get_timer0();
00199 velocita = wTimer0Counts;
00200
00201
00202 fMotorRPM = (2*1000*1000)/((float)wTimer0Counts);
00203 fMotorRPM /= 16;
00204 fMotorRPM *= 60;
00205 }
00206 }
00207
00208
00209 void LoopTimeWait()
00210 {
00211
00212 disable_interrupts(INT_TIMER1);
00213 tempo = (DWORD)get_timer1();
00214 tempo += ((DWORD)bTimer1_Overflows)<<16;
00215 enable_interrupts(INT_TIMER1);
00216
00217 tempo_ciclo_ms = tempo / (2*1000);
00218
00219 printf("t=%lu-OWF=%u-tcy=%lu ",tempo,bTimer1_Overflows,tempo_ciclo_ms);
00220
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
00241 void PID_algo()
00242 {
00243 err2=err1;
00244 err1=err;
00245 err=(float)wMotorRPMSetpoint-fMotorRPM;
00246
00247 if(0==bSelect_Input)
00248 {
00249 fPWM_duty += K_P * err;
00250 fPWM_duty += K_I * tempo_pid * (err-err1);
00251 fPWM_duty += K_D * (err - 2*err1 + err2) / tempo_pid;
00252 }
00253 else if (1==bSelect_Input)
00254 {
00255 fPWM_duty += K_P * err;
00256 }
00257 else if (2==bSelect_Input)
00258 {
00259 fPWM_duty += K_I * tempo_pid * (err-err1);
00260 }
00261 else if (3==bSelect_Input)
00262 {
00263 fPWM_duty += K_D * (err - 2*err1 + err2) / tempo_pid;
00264 }
00265
00266
00267
00268 if (fPWM_duty > 1023)
00269 fPWM_duty = 1023;
00270
00271 if (fPWM_duty < 0.0)
00272 fPWM_duty = 0;
00273 }
00274
00275
00276 void Update_PWM()
00277 {
00278
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
00288 void User_Interface()
00289 {
00290 if(input(PULS_A))
00291 {
00292 wMotorRPMSetpoint = read_adc();
00293 wMotorRPMSetpoint += read_adc();
00294 wMotorRPMSetpoint += read_adc();
00295 }
00296 else
00297 {
00298 K_P = (float)read_adc()/1000.0;
00299 K_I = K_P/10.0;
00300 K_D = K_I;
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))
00307 {
00308 while(!input(PULS_B));
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)
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)
00326 {
00327 output_low(PIN_B1);
00328 output_high(PIN_B2);
00329 printf("Proporzionale\r\n");
00330 }
00331 else if (2==bSelect_Input)
00332 {
00333 output_high(PIN_B1);
00334 output_low(PIN_B2);
00335 printf("Integrativo\r\n");
00336 }
00337 else if (3==bSelect_Input)
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 }