Mam problem z Regulatorem PID na ATmega16.
kod programu:
Zamieszczam cały bo może gdzieś indziej jest błąd a nie w kodzie PID
Wartość pomiaru na razie jest zadawana potencjometrem przez ADC
docelowo PID ma sterować temperaturą w układzie poprzez PWM.
Dla samego regulatora P działa pięknie i to juz na regulacji temperatury mam zaimplementowane, Ale z kodem na PID nie mogę sobie poradzić
Proszę o pomoc.
kod programu:
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <stdlib.h>
#include "delay.h"
#include "lcd.h"
#include "stdint.h"
#define F_OSC 8000000UL
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
// Zdefiniowanie uzywanych portów.
#define PORT_AD PORTA // Port z wejściami analogowymi
#define DDR_AD DDRA
#define PORT_F PORTC // Port do którego przyłączony jest przycisk. Bit 4 tego portu
// jest wykorzystany jako flaga naciśnięcia klawisza
#define DDR_F DDRC
#define PIN_F PINC
char buffer_n[5];
char buffer[5]; // Bufor do przechowywania wyniku konwersji z "unsigned int" na ASCII
#define Kp 1.00
#define SF 100
#define MAX_INT INT16_MAX
#define MAX_LONG INT32_MAX
#define MAX_I_TERM (MAX_LONG / 2)
unsigned char a,b,licz=32;
signed long warodn;
signed long pomiar, pomiara, pomiarb;
signed long error, errorpop,temp;
signed long Sff,Kpp,Ki,Kd,P,I,D;
signed long wynik,wartost;
signed short wartpop,wart,reszta;
signed short maxError;
signed long sumerror, maxsumerror;
signed short rozniczka;
SIGNAL (SIG_OVERFLOW0)
{
ADCSRA |= _BV(ADSC); // Rozpoczęcie przetwarzania
while(bit_is_set(ADCSRA,ADSC)) // Oczekiwanie na zakończenie przetwarzania
{};
//pomiarb=ADCL;
pomiar=ADCH;
pomiara=pomiar*5;
//pomiar=pomiar;
//pomiar=1180;
maxError = MAX_INT / ( Kpp+ 1);
error=warodn-pomiara;
/*if (error > maxError){
P = MAX_INT;
}
else if (error < -maxError){
P = -MAX_INT;
}
else{*/
P=Kpp*error;
// }
maxsumerror = MAX_I_TERM / (Ki+1);
temp=sumerror+error;
if(temp > maxsumerror){
I = MAX_I_TERM;
sumerror = maxsumerror;
}
else if(temp < -maxsumerror){
I = -MAX_I_TERM;
sumerror = -maxsumerror;
}
else{
sumerror = temp;
I = Ki*sumerror;
}
rozniczka=error-errorpop;
D=Kd*rozniczka;
wynik=((P)+(I)+D)/SF;
//wynik=sizeof(unsigned short);
errorpop=pomiara;
//if(wynik> MAX_INT){
// wynik = MAX_INT;
// }
// else if(wynik < -MAX_INT){
// wynik = -MAX_INT;
// }
wartost=(1023*wynik)/1275;
//wartpop=sizeof(wart);
wart=(short)wartost;
OCR1A=wart;
LCD_clr();
LCD_xy(0,0);
write_text("Wynik: \n");
itoa(wynik, buffer_n, 10); // Konwersja liczby unsigned int do asci
write_text(buffer_n); // Wysłanie na ekran LCD wyniku konwersji
LCD_xy(0,1);
write_text("Wzad: \n");
itoa(warodn, buffer, 10); // Konwersja liczby unsigned int do asci
write_text(buffer); // Wysłanie na ekran LCD wyniku konwersji
delay_ms(200);
}
void Inicjalizacja(void)
{
DDR_AD=0x00; // Port jako wejścia
PORT_AD=0x00; // Port C wejścia bez podciągania
DDR_F=0xF0; // Młodsza połowa portu jako wejścia starsze cztery bity jako wyjścia
PORT_F=0xFF; // Wejścia z podciąganiem wyjścia w stanie wysokim
DDRD=0x00;
PORTD=0xff;
// Inicjalizacja LCD
lcd_init(); // Inicjalizacja wyswietlacza
LCD_clr();
// Wybranie wewnętrznego żródła napięcia odniesienia
ADMUX |= _BV(REFS0);
ADMUX |= _BV(REFS1);
// Wybranie sposobu zapisu wyniku z wyrównaniem do lewej (osiem starszych bitów wyniku w rejestrze ADCH)
ADMUX |= _BV(ADLAR);
// Zezwolenie na konwersję
ADCSRA |= _BV(ADEN);
// Wybranie częstotliwości dla taktowania przetwornika (1/8 częstotliwosci zegara kontrolera)
ADCSRA |= _BV(ADPS0);
ADCSRA |= _BV(ADPS1); //
}
int main(void)
{
pomiar=0;
pomiara=0;
error=0;
rozniczka=0;
warodn=1275;
Kpp=Kp*SF;
Ki=50;
Kd=0;
wartpop=0;
sumerror=0;
errorpop=0;
Inicjalizacja();
sbi(DDRD,PD5);
TCCR1A = _BV(COM1A1)|_BV(COM1A0)|_BV(WGM10)|_BV(WGM11);
TCCR1B = 0x03;
TCNT1L=0x00;
TCNT1H=0x00;
OCR1AH=0x03;
OCR1AL=0xff;
TCCR0 = _BV(CS01)| _BV(CS00);
TIMSK = _BV(TOIE0);
sei();
for (;;) {}
}
Zamieszczam cały bo może gdzieś indziej jest błąd a nie w kodzie PID
Wartość pomiaru na razie jest zadawana potencjometrem przez ADC
docelowo PID ma sterować temperaturą w układzie poprzez PWM.
Dla samego regulatora P działa pięknie i to juz na regulacji temperatury mam zaimplementowane, Ale z kodem na PID nie mogę sobie poradzić
Proszę o pomoc.