PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PID-regelung mit Mega32



RP6conrad
12.10.2008, 21:49
Ein schones beispiel von einer PD regelung konnen sie in diesen Video sehen. Ist-position von die Stabe wird mit einer V2A draht vermessen. Den Draht bildet eine potentiometer, die gemessene Spannung geht nach der ADC von mega32 (µ von RP6). Der position von die Latte wird mit eine modellbau servo gesteuert. Eine reine P-regelung ergibt schnell eine oscillierung. Das D-anteil ist absolut notwendig um die Geschwindigkeit von Stabe zu behersschen. Ein I-anteil ist nicht absolut notwendig. Mit einfache mitteln is er mir endlich gelungen eine PID-regelung zu verstehen...
http://video.google.nl/videoplay?docid=5538319543444554168&hl=nl

Rofo88
13.10.2008, 11:44
Ein schönes Beispiel für die Regelungstechnik.
Ich glaube aber auch mit ner P-Regelung sollte es möglich sein das Ding zu fangen.

Jon
13.10.2008, 11:54
Hi!
Wäre es möglich, dass du mal den Code postest?
Würde mich interessieren!

Viele Grüße,
jon

HannoHupmann
13.10.2008, 13:36
Ist das überhaupt ne PID Regelung? Sieht für mich nur nach PD Regelung aus ohne I anteil.

Rofo88
13.10.2008, 13:56
Nö, ist ein PD-Regler, steht auch so im Beitrag nur der Titel sagt was von PID.

p.s. Den Quellcode würde ich auch nehmen.

RP6conrad
13.10.2008, 20:10
@ rofo88 : Hatte ich auch erst gedacht, aber dieses System bekomme ich nicht stabil mit nur das P-Anteil. Das erstes Teil von video ist nur P-regelung. Kleine P-factor : fangt langsam an zu oscillieren und nach 3-4 Schwingungen ist das ende von Bahn erreicht. Hohe P-factor : schon nach 1 Schwingung ist schluss !! Grund ist das solange der Stabe nicht in Setpoint is, wird die Bahn in die richtige Richtung gekippt, und der Stabe versnellt immer. Nach die Geschwindigkeit van Stabe wird nicht gesehen/geregelt. Probiers mall !!
Die quellcode ist recht einfach, aber da ist noch ein Fehler in I-anteil derin. Auch bei Atmel (application note 221, PID-code) findts du eine implementierte code für PID.
ADC von draht = zwischen 300 und 700 (von 2 bis 3.5 VDC)
Servoroutine = Zahl zwischen 200 und 550 (von 0.8 bis 2.2 mS)
Das ADC wird jeden 10mS vermessen und dan wird die mittelwert verwendet. Der PID-routine wird jeder 100 mS durchlaufen (stopwatch).

void Ball_Beam (void)
{
#define SETPOINT 20
#define SAMPLE_TIME 21
#define P_FACTOR 22
#define I_FACTOR 23
#define D_FACTOR 24
#define SERVO_NOM 25

static int16_t last_error = 0;
static int16_t actual_error =0;
uint16_t actual_position = 100;
uint16_t adc4[10];
uint16_t servo_nom = 100; //EEPROM B&B SERVO_NOM
uint16_t setpoint =500; //EEPROM B&B SETPOINT
uint8_t sample_time = 100; //EEPROM B&B SAMPLE_TIME
int8_t P_factor=0; //EEPROM B&B P_FACTOR
int8_t I_factor=0; //EEPROM B&B I_FACTOR
int8_t D_factor=0;
static uint8_t i=0;
static uint8_t j=0;
static int16_t som=0; //EEPROM B&B D_FACTOR
int16_t P_correction=0;
static int16_t I_correction=0;
int16_t D_correction=0;
int16_t servo_position=400;

setpoint=read_buffer[SETPOINT]*5;
if (read_buffer[26]==2) setpoint=625;
if (read_buffer[26]==3) setpoint=375;
sample_time=read_buffer[SAMPLE_TIME];
P_factor=read_buffer[P_FACTOR];
I_factor=read_buffer[I_FACTOR];
D_factor=read_buffer[D_FACTOR];
servo_nom=read_buffer[SERVO_NOM];

if (getStopwatch3()>sample_time/10)
{
setStopwatch3(0);
adc4[i]=readADC(ADC_4);
som=som+adc4[i];
i++;
}

if (i==10)
{
actual_position=(som/10);
som=0;
i=0;
actual_error=actual_position-setpoint;
P_correction=((P_factor*actual_error)/64);//P_correctie delen door 8
I_correction=(I_correction+((I_factor*actual_error *sample_time/100)/64));//I delen door 8
if(I_correction>150) I_correction=150;
if(I_correction<-150) I_correction=-150;
if(I_factor==0)I_correction=0;
D_correction=(10*D_factor/sample_time)*(actual_error-last_error);
last_error=actual_error;
servo_position=((servo_nom*4)+P_correction+I_corre ction+D_correction);
servo(1,servo_position);

if(j<100)
{
j++;
if (j==1){
writeString_P("Setpoint,");
writeString_P("Actual Pos.,");
writeString_P("Servopos");
writeString_P("P-deel");
writeString_P("I-deel");
writeString_P("D-deel");
writeChar('\n');
}
writeInteger(setpoint,DEC);writeChar(',');
writeInteger(actual_position,DEC);writeChar(',');
writeInteger(servo_position,DEC);writeChar(',');
writeInteger(P_correction,DEC);writeChar(',');
writeInteger(I_correction,DEC);writeChar(',');
writeInteger(D_correction,DEC);writeChar(',');
writeChar('\n');
}
else
if(read_buffer[26]==1) j=0;
}
}