PID kontrol sorunu

Başlatan berkay_91, 09 Ekim 2014, 00:37:39

berkay_91

mrb, alttaki kodları PID ile dc motorda devir sayısını ayarlamak için düzenledim ancak LCD de gördüğüm değer sadece 62-63 arasında değişiyor, set_rpm değerine ne yazdıysam lcddeki rakam hep aynı bir yerde hata var ama çözemedim yardımcı olurmusunuz?(Atmega32 kullandım)

#define F_CPU 1000000
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.h"

#define P_GAIN 0.8
#define I_GAIN 0.005
#define D_GAIN 0.01

volatile int set_rpm = 0,previous_error = 0;
volatile int error, feedback_rpm, output=0;
volatile int D_error = 0, I_error = 0;

volatile int  c = 0;
volatile int pulses;

FILE lcd_str = FDEV_SETUP_STREAM(lcd_putc, NULL, _FDEV_SETUP_WRITE);

void init_interrupts(){
	
	MCUCR|=(1<<ISC00)|(1<<ISC01);
	GICR |=(1<<INT0);
	sei();
}


//PWM Frequency: (10^6)/255=3.9 kHz
// (1024/10^6)*255*4=1;

init_timer0_and_pwm(){
	
	TCCR0=(1<<WGM00)|(1<<WGM01)|(1<<CS00)|(1<<COM01); // pwm init
	
	TCCR0|=(1<<CS00)|(1<<CS02); // prescalar is 1024
	TCNT0=0;
	TIMSK=(1<<TOIE0);
	
}

ISR(TIMER0_OVF_vect){
	
	TCNT0=0;
	c++;
	
	if(c==2){
		
	    PORTD^=(1<<7);
		feedback_rpm = pulses*5;
		
		lcd_gotoxy(0,1);
		printf("%d ",pulses);
		
		c=0;
	    pulses = 0;
		
	}		
		 
}

ISR (INT0_vect){
	
	pulses++;
}

int main(){
	 
	 DDRC=0XFF; // lcd için
	 DDRB|=(1<<3); // pwm OC0 bacağı
	 DDRD|=(1<<7); // LED İÇİN
	 
	 MCUCSR|=(1<<JTD); // JTAG PİNLLERİNİ KAPATMA
	 MCUCSR|=(1<<JTD); // JTAG PİNLLERİNİ KAPATMA
	 
	 init_timer0_and_pwm();
	 init_interrupts();
	 
	 lcd_init(LCD_DISP_ON); 

	 stdout = stdin = &lcd_str;
	 
	 lcd_clrscr();
	 lcd_gotoxy(4,0);
	 lcd_puts("PID TEST");

    set_rpm = 50;
	
	previous_error = set_rpm - feedback_rpm;
	
	while(1){
		
		error = set_rpm - feedback_rpm;
		I_error += (error);
		D_error = (error - previous_error);
		
		output = (P_GAIN * error) + (I_GAIN * I_error) + (D_GAIN * D_error);
		
		previous_error = error;
		
		 	if((OCR0 + output)>=255){
			OCR0= 255;
		    }
		
		    else if((OCR0 + output)<=0){
			OCR0= 0;
		    }
			
		    else{
			OCR0+= output;
			}
		
		
	}
	 return 0;
}

Saruman

Kimse de dememiş ki aga bu nedir..

X-Fi

PID de hazır kod üzerinden yorum yapmak zor zamanlamaları da bilmek lazım.

output = (P_GAIN * error) + (I_GAIN * I_error) + (D_GAIN * D_error);


öncelikle yukarıdaki satırdan integral ve türevi çıkart. sadece P ile dene sonra integrali ekle çalışıyorsa türevide ekler arızayı bulursun.
http://www.coskunergan.dev/    (Yürümekle varılmaz, lakin varanlar yürüyenlerdir.)

trinity

bu formül wikipedia'da bile var, PID demek bu formül demek değildir, PID demek katsayıları sisteme göre ayarlamak demektir.

ylmz

Regülatör Dns Trafo | Regülatör | Redresör | Ups

ceyhanan

#define P_GAIN 0.8f
#define I_GAIN 0.005f
#define D_GAIN 0.01f


bu şekilde değiştirerek dene bir de

berkay_91

#6
bu sorunu hallettim sorun katsayılardan değilmiş timer ı kurma biçimimden kaynaklanıyormuş, hem timer kesmesi hemde PWM için ayrı bir timer aktif olunca haliyle işlemci sapıtıyodu timer için delay_ms() frekans okuma içinde external clock source pinini kullandım ve gayet iyi çalıştı