PIDT_Regler_Code/TimerInterruptV1.ino
2023-03-25 16:20:31 +01:00

202 lines
4.4 KiB
C++

//#include <Arduino.h>
#include <math.h>
#include <U8g2lib.h>
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); //Andreas
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); //Leonhard
void TIM1_init();
void TIM2_init();
void LCD_printData();
double get_tempValue(int SensorValue);
void LCD_printGrid();
int Temperatur;
int TempSensor = 0;
float Voltage;
int Ausgangssignal = 0;
int status = 0;
int Stellsignal = 0;
int counterx=0;
int i=2;
//Variablen Regelung
//Eingangssignal
double Sollwert=70;
//Abtastzeit
double Ta=1;
//PIDT-Regler Zeitkonstanten (multiplikative Form)
double VR=2;
double TN=80;
double TV=1;
double TR=TV/10.0;
//PIDT-Regler Zeitkonstanten (additive Form)
double VR_Stern=VR*(1.0+(TV/TN));
double TN_Stern=TN*(1.0+(TV/TN));
double TV_Stern=TV/(1.0+(TV/TN));
double TI=TN_Stern/VR_Stern;
double TD=TV_Stern*VR_Stern;
//Eingangssignal Regler ek
double ek=0;
//Globale Variable für Zeitdiskrete Regelung
double yk1=0;
double yk1vorher=0;
double yk2=0;
double yk2vorher=0;
double yk3=0;
double yk3vorher=0;
double yk4=0;
double yk4vorher=0;
//Ausgangssignal Regler yk
double yk=0;
void setup()
{
pinMode(13, OUTPUT);
pinMode(3, OUTPUT);
digitalWrite(3, LOW);
u8g2.begin();
u8g2.clearBuffer();
LCD_printGrid();
cli(); //disable global interrupts
TIM1_init(); //Timer 1 für Ta=100ms
TIM2_init(); //Timer 2 für PWM
sei(); //enable global interrupts
}
void loop()
{
LCD_printData();
}
ISR(TIMER1_COMPA_vect)
{
status=1;
digitalWrite(13, !digitalRead(13)); // toggle LED with T=TA
TempSensor=analogRead(A0);
if(595<=TempSensor)
{
Temperatur=get_tempValue(TempSensor);
}
ek=Sollwert-Temperatur; //Eingangssignal
//PT1-Anteil:
yk1vorher=yk1vorher*(TR/(Ta+TR));
yk1=ek*(Ta/(Ta+TR))+yk1vorher;
yk1vorher=yk1;
//P-Anteil:
yk2=yk1*VR_Stern;
//I-Anteil:
yk3=yk1*(Ta/TI)+yk3vorher;
yk3vorher=yk3;
//D-Anteil:
yk4=yk1*(TD/Ta)-yk4vorher;
yk4vorher=(TD/Ta)*yk1;
//Addition P-, I-, und D-Anteil
yk=yk2+yk3+yk4;
//Begrenzung Ausgangssignal auf 100
if(yk>=100)
{
yk=100;
}
//PWM Ausgangssignal
Stellsignal=255*(yk/100);
if(yk>=100)
{
Stellsignal=255;
}
if(yk<=0)
{
Stellsignal=0;
}
OCR2B = Stellsignal; //PWM Duty Cycle
counterx++;
}
void TIM1_init()
{
TCNT1 = 0; //Timer Counter 1
TCCR1A = 0; //Timer Counter Controll Register A
TCCR1B = 0; //Timer Counter Controll Register B
OCR1A = 15625; //Output Compare Register A -> Interrupt each second (1/16*10^6)*1024*15625 = 1s
TCCR1B |= 0x5; //Prescaler = 1024
TCCR1B |= 0x8; //CTC Bit -> TOP of Counter = OCR1A
TIMSK1 |= 0x2; //Tim1 Interrupt @ Output Compare Match A
}
void TIM2_init()
{
TCNT2 = 0; //Timer Counter 2
TCCR2A = 0; //Timer Counter Controll Register A
TCCR2B = 0; //Timer Counter Controll Register B
TCCR2A |= 0x23; //Non Inverting Mode
TCCR2B |= 0x7; //Prescaler = 1024
OCR2B = 0; //PWM Duty Cycle
DDRD |= (1 << PD3); //Port Output
}
double get_tempValue(int SensorValue)
{
double a=0.0231;
double b=0.26;
double c=5.22;
double calculatedVoltage=5.0*(SensorValue/1023.0);
return log((c-calculatedVoltage)/b)*(1/a);
}
void LCD_printData()
{
if(status==1)
{
if(i>123)
{
LCD_printGrid();
i=2;
}
u8g2.setFontMode(1);
u8g2.setFont(u8g2_font_6x10_tf);
u8g2.setDrawColor(1);
u8g2.drawBox(0, 0, 127, 9);
u8g2.setDrawColor(2);
u8g2.drawBox(0, 0, 127, 9);
u8g2.setCursor(2,8);
u8g2.print(F("Ti:"));
u8g2.print(get_tempValue(TempSensor),0);
if(counterx%5==0) //each 5seconds new TempPlot
{
if(get_tempValue(TempSensor)>-5&&get_tempValue(TempSensor)<100)
{
u8g2.drawPixel(i++, 63-((get_tempValue(TempSensor)/100.0))*55);
}
}
u8g2.setCursor(42,8);
u8g2.print(F("Ts:"));
u8g2.print(Sollwert,0);
u8g2.setCursor(84,8);
u8g2.print(F("St:"));
u8g2.print(yk,0);
u8g2.sendBuffer();
status=0;
}
}
void LCD_printGrid()
{
u8g2.clearBuffer();
u8g2.setFontMode(1);
u8g2.drawLine(1, 63, 127, 63);
u8g2.drawLine(0, 10, 0, 63);
for(int a=10; a<=100; a=a+10)
{
u8g2.drawLine(0, (63-(a/100.0)*55), 2, (63-(a/100.0)*55));
}
for(int a=10; a<127; a=a+10)
{
u8g2.drawLine(a, 61, a, 63);
}
u8g2.sendBuffer();
}