ABYS
Üye
- Katılım
- 17 Nis 2008
- Mesajlar
- 219
- Puanları
- 1
u kontrol işareti (pwm çıkışı ccp1)
ref referans işareti (analog giriş AN0)
ref referans işareti (analog giriş AN0)
Kod:
#include <htc.h>
#include "delay.h"
#define ref 1 //referans
#define T 0.1 //ornekleme zamani
#define Kpi 5 //PI-PD kontrol katsayıları
#define Kd 2.5
#define Kpd 1.3
#define Ki 2.7
float geribesleme(); // sistemin çıkışını okuyan fonksiyon (ADC)
void controller(float); // kontrolör fonksiyonu
void kontrolpwm(float); // pwm (u) üreten fonksiyon
static void interrupt kesmeler(void);
void timerbasla(); // timer1 i başlatan fonk
float h,u,e,u1,sys_out_1=0,ud; // h: geribesleme veya çıkış işareti, u:kontrol işareti
// sys_out_1 : sistem çıkışının önceki değeri ud: PD den gelen kontrol işareti
float integral=0,turev=0; // türev,integral: türev ve integral kontrol işareti
int a; // timer1'in bir periyodunu T'te eşitlemek için kullanılan sayi.
void main(void) // main fonksiyon
{
TRISA=1; // RA0 analog giriş.
TRISC=0; // C portu çıkış (PWM- CCP1)
PORTA=0;
PORTC=0;
GIE=1; // Genel kesme izin biti
a=(int)(1000000*T/8); // timer1'in bir periyodu T'ye eşit olması için timera yüklenecek sayi hesabı
timerbasla(); // Timer1 başlatılır.
while (1){
h=(geribesleme()/1023)*5; // AN0 dan alınan veri 0-5 V a çevriliyor.
controller(h); // AN0 dan alına veri kontolöre gönderiliyor.
}
}
void timerbasla(){ // Timer1 başlatan fonksiyon
TMR1H=-a/256; // Hesaplanan a değeri Timer1e yükleniyor
TMR1L=-a%256;
TMR1CS=0; // Dahili osilatör
T1CKPS1=1; // Prescaler 1:8
T1CKPS0=1;
T1SYNC=1; // Senkronizasyon yok
TMR1IF=0; // Timer1 kesme bayrağı sıfırlanıyor
TMR1IE=1; // Timer1 kesme izin biti
TMR1ON=1; // Timer1 enable biti
PEIE=1; // Yardımcı kesmeler enable biti
}
float geribesleme(){ // AN0 dan analog veri(geribesleme) okuma
float value;
ADCON1=0b10001110; // AN0 analog (PCFG0..4), sağa sola dayalı(ADFM), Fosc/8(ADCS2-0) bitleri.
ADCON0=0b01000001; // Fosc/8(ADCS1:0-01) , AN0 seçim bitleri (CHS0..3- 000), çevrim başla(ADGO-0),ADC enable(ADON-1) bitleri
DelayUs(25); // 25 uS bekler
ADGO=1; // Çevrimi başlatırr
while(!ADGO); // ÇEvrim bitene kadar bekler
value=(ADRESL+(ADRESH*256)); // Veri yi float değişkene atar.
return value;
}
void controller(float sys_out){ // PI-PD kontrol
if(timeflag==1){ // her T(örnekleme) periyotta kontrolör güncellenir
e=ref-sys_out; // dış kapalı çevrim için hata
if((u>0||e>-1.5)&&(u<4.98||e<1.5)) integral=integral+e*T*Ki; // PI için integral hesabı. sarmayı engellemek için sınırlamalar.
u1=integral+Kpi*e; // PI çıkışı u1
turev=Kd*(sys_out-sys_out_1)/T; // PD için türev hesabı. PD iç çevrimde geri besleme yolu üzerinde çıkışın
// türevini alır. sys_out_1: çıkışın önceki değeri.
ud=Kpd*sys_out+turev; // PD kontrol işareti ud
u=u1-ud; // kontrol işareti u1-ud
sys_out_1=sys_out; // çıkış değeri çıkışın önceki değerine atanır
timeflag=0; // bir sonraki T periyodu için timeflag sıfırlanır
}
if (u<0) u=0; // saturasyon
if (u>4.98) u=4.98;
kontrolpwm(u); // kontrol işareti PWM fonksiyonuna gönderilir.
}
void kontrolpwm(float value){
int duty;
value=value*50; // gelen deger 0-5 aralığında olduğu için 50 ile çarparak 0-250 aralığında bir değer elde ederiz
duty=(int)value;
PR2=249; // PEriyot
CCPR1L=duty; // duty cycle
CCP1CON= 0b00101100; // PWM modu
T2CKPS0=1; T2CKPS0=1; // Timer2 prescale 1:16
TMR2ON=1; // Timer2 enable
}
static void interrupt
kesmeler(void)
{
GIE=0;
if(TMR1IF) { // Timer1 kesme bayrağı 1 oldugunda
timeflag=1; // timeflag i bir yap. Kontrol işaretini güncelemek için gereken bayrak
TMR1H=-a/256;
TMR1L=-a%256;
TMR1IF=0;
}
GIE=1;
}