Hi!
Ich versuche einen Neodym-Magneten per Elektromagnet + Lichtschranke(Fotoresistor) zum Schweben zu bekommen.
Als Regelung soll ein PID-Regler zum Einsatz kommen. Allerdings bekomme ich die Regelung einfach nicht stabil, egal wie ich an KI,KP oder KD rumdrehe. Bei kleinem KP bewegt sich erst garnichts, wenn ich KP weiter hochdrehe dann fängt das System unsichtbar zu schwingen an (aber hörbar, wie ein hochfrequenter Lautsprecher), schließlich (noch größeres KP) beginnt der Magnet hin und her zu zappeln und zu springen.
Aktuell läuft die Regelschleife bei ca. 2000Hz.
Herumstellen an KP,KI,KD ändert wie erwartet nur die Amplitude, aber nichts an der Eigenfrequenz des Systems.
Im untersten Bild (Screenshot aus Excel, von d. Seriellen Ausgabe) sieht man schön den "Derivative Kick", der mit größerem D-Term nätürlich größer wird. Um den kümmer ich mich später, wenn das System erstmal stabil ist.
Also verhält sich das System eigentlich so, wie ich es nach Zig Stunden Regelungstehnik-Vorlesung erwarten würde- nur stabil ist es immer noch nicht. Ich steh auf dem Schlauch. Irgendwas mache ich grundfalsch!
int force = 0;
float KI = 0;
int receivedValue = 0;
//Wie oft wurde die Regelschleife durchlaufen?
int Durchlaufzaehler = 0;
int t_Brennstart = 0;
int t_Brenndauer = 0;
int LEDistAN = 0;
int Regelgroesse;
int Fuehrungsgroesse;
int Regelabweichung;
int vorigeRegelabweichung;
int Integral;
int Stellgroesse;
int PTerm;
int ITerm;
int DTerm;
void setup()
{
// initialize the serial communication:
Serial.begin(115200);
// initialize the ledPin as an output:
pinMode(A3, OUTPUT);
// enable pullup
pinMode(A6, INPUT);
digitalWrite(A6, HIGH);
}
void loop() {
byte brightness;
int sensorValue = analogRead(A6);
Regelgroesse = sensorValue;
Fuehrungsgroesse = 650;
Regelabweichung = Regelgroesse - Fuehrungsgroesse;
//PID-Regler
//P-Anteil
PTerm = 0.6*(Regelabweichung);
if (PTerm <0) { PTerm=0; };
if (PTerm >255) { PTerm=255; };
//I-Anteil
ITerm = 0.001*(Integral);
if (ITerm <0) { ITerm=0; };
if (ITerm >255) { ITerm=255; };
//D-Anteil
DTerm = 2.5*(Regelabweichung - vorigeRegelabweichung);
if (DTerm <0) { DTerm=0; };
if (DTerm >255) { DTerm=255; };
Stellgroesse = PTerm + ITerm; //DTerm; // ;
vorigeRegelabweichung = Regelabweichung;
Integral = Integral + 0.01*Regelabweichung;
//Serial.println(Stelle);
//Serial.println(sensorValue);
Serial.println(Stellgroesse);
//Serial.write(Stelle);
//magnet unten (laser unverdeckt) 870
// soll: 600
//magnet oben (Laser verdeckt) 380
//Stellgroeßenbegrenzung
if (Stellgroesse <0) { Stellgroesse=0; };
if (Stellgroesse >255) { Stellgroesse=255; };
// analogWrite(A3, 255);
analogWrite(A3, Stellgroesse);
//einmal alle 100 Schleifendurchgänge LED blinken lassen
blinkeLED(); //dient der Abschätzung der Regelfrequenz
//delay(20);
}
void serialEvent()
{
int SerialCom3IncomingNumber = Serial.parseInt();
receivedValue = SerialCom3IncomingNumber;
}
void blinkeLED()
{
Durchlaufzaehler = Durchlaufzaehler + 1;
if (Durchlaufzaehler > 1000)
{
if (LEDistAN == 0)
{
digitalWrite(13, HIGH) ;
t_Brennstart = micros();
LEDistAN = 1;
}
else
{
t_Brenndauer = micros() - t_Brennstart;
if (t_Brenndauer < 10000)
{
}
else
{
digitalWrite(13, LOW);
Durchlaufzaehler = 0;
LEDistAN = 0;
}
}
}
}
http://s14.directupload.net/file/d/3105/zz7lrppa_jpg.htm
http://s7.directupload.net/file/d/3105/lkae8hf3_jpg.htm