Hallo zusammen,
ich habe für eine Hydraulik ein digitalen PID Regler gebaut. Differenzsignal geht auf einen AD, dann in den µC und am Ende wird die Stellgröße mit einem DAC ausgespuckt. Soweit so gut. Im Prinzip läuft das Ding auch recht gut.
Abtastfrequenz beträgt 10kHz. Mein Code sieht so aus (ein paar Dinge rausgemacht, die damit nichts zu tun haben):
So, nun zu dem Problem:Code:#include <avr/io.h> #include <avr/interrupt.h> //#include <avr/eeprom.h> #include <pid.h> #include <adc.h> #include <dac.h> double Kp = 0; double Ki = 0; double Kd = 0; double y = 0; double e = 0; double e_alt = 0; double e_sum = 0; #define Ta 0.0001 //unsigned char Kp_eeprom EEMEM; //unsigned char Ki_eeprom EEMEM; //unsigned char Kd_eeprom EEMEM; void init_pid(void) { // die gespeicherten Parameter laden und Regler initialisieren //Kp = (double) eeprom_read_byte(&Kp_eeprom); //Ki = (double) eeprom_read_byte(&Ki_eeprom); //Kd = (double) eeprom_read_byte(&Kd_eeprom); // PID Timer TCCR0 |= (1 << WGM01) | (1 << CS01) | (1 << CS00); //OCR0 = 250 ergibt 1kHz OCR0 = 25; // ergibt 10kHz } void pid_set_parameters(unsigned char p, unsigned char i, unsigned char d) { // Den aktuellen Variablen die neuen Parameter zuweisen Kp = (double) p; Ki = (double) i; Kd = (double) d; // Die neuen Parameter nicht-flüchtig ablegen, damit sie beim nächsten mal geladen werden können //eeprom_write_byte(&Kp_eeprom, (unsigned char) Kp); //eeprom_write_byte(&Ki_eeprom, (unsigned char) Ki); //eeprom_write_byte(&Kd_eeprom, (unsigned char) Kd); } void pid_start(void) { // Regler starten TIMSK |= (1 << OCIE0); } void pid_stop(void) { // Regler stoppen TIMSK &= ~(1 << OCIE0); } void pid_calculate(void) { // e = w-x ; Differenz soll-ist e = (double) adc_read(); // ADC Wert transformieren if (e >= 2048) { e -= 4096; } // WindUp vermeiden if (y < 4095) { e_sum += e; } // PID Stellgrößen Berechnung y = -Kp*0.1*e; y -= Ki*e_sum; y -= Kd*(e-e_alt); e_alt = e; // Stellgröße beschränken if (y > 2047){y = 2047;} if (y < -2048){y = -2048;} // Stellgröße für den DAC transformieren y += 2048; // Stellgröße für das Ventil ausgeben dac_write((unsigned short)y); } ISR(TIMER0_COMP_vect) { // mit 10kHz Abtastrate PID Algorithmus aufrufen, also alle 100µs pid_calculate(); }
Ich möchte während der Regler seinen Dienst tut die Regelparameter on the fly ändern.
Angesprochen wird der Regler über Rx/Tx und der Fleury Lib für UART, interruptgesteuerter Empfang.
Wenn der Regler noch nicht gestartet wurde, kann ich wunderbar die Parameter ändern. Starte ich diesen jedoch einmal, kann ich ihn weder anhalten noch Parameter ändern.
Sprich er reagiert über UART nicht mehr.
Wo liegt hier das Problem? Ist die Abtastfrequenz zu hoch und die UART Interrupts kommen nicht "durch", weil ständig der Timer Interrupt zuschläge oder was ist hier los?
Abtastfrequenz muss bei 10kHz bleiben, da ich die Hydraulik sonst nicht stabil bekomme.
Viele Grüße,
hacker







Zitieren

Lesezeichen