
Zitat von
SlyD
Läuft los ja, aber hält er bei 46 auch wieder an?
Das ist nämlich meistens nicht der Fall
Wenns mal läuft dann läufts leichter...
Danke für den Hinweis, hab ich ganz vergessen, aber wär mir bestimmt bald aufgefallen 
Mit der Hyterese sollte das dann auch kein Problem sein.

Zitat von
SlyD
Einfacher wäre es natürlich, wenn man dem Motor der später losläuft beim Start direkt etwas mehr Power gibt.
(also nur beim Start z.B. dem Integrierer eine Konstante hinzuaddieren... )

Zitat von
SlyD
Ich meinte damit die Integral Variablen left_i und right_i beim standard I Regler in der Lib.
Also da muss ich jetzt ein bissl was erzählen. Und zwar habe ich einen völlig eigenen Regler programmiert und den anderen Regler aus dem Code entfernt. Grund: Eingreifen in das Regelgeschehen war nicht einfach, wegen dem Soft-PWM etc. und ich wollte nicht Speed und Direction getrennt angeben. Ich habe jetzt die Funktion runSpeedController(int left, int right) und da kann ich die Geschwindigkeit in mm/s von -300mm/s bis +300mm/s eingeben. Was bei einer Positionsregelung dann auch von Vorteil ist, weil wenn die Dirfferenz negativ ist, ich nicht die Richtung ändern muss sondern der zweite Regler einfach mit Minus weiterrechnen kann.
Deshalb brauch ich auch eine Hyterese um den Nullpunkt, da happerts im Moment noch.
Ich stell mal den Code hier rein. Im Code siehst du auch den Grund, warum ich das mit einer Voreinstellung des I-Wertes nicht machen kann, weil mein Regler nicht einen I-Wert speichert sondern immer zur momentan eingestellten Stellgröße dazurechnet oder abzieht. Der Korrekturfaktor ist der Wert, wo ich die maximale Pulsweite(180, eigentlich 210 aber von meinem Programm begrenzt auf 180) durch die daraus resultierende Geschwindigkeit in [mm/s] dividiere.
Der Code läuft im Timer0 Interrupt ab:
Code:
if(speedController == 1)
{
if(speedControllCounter++ >= speedControllTimer)
{
//Linke Raupe
speedControllCounter = 0;
sclE = sclW - getLSpeed();
if(speedKp > 0)
delta_y = speedKp * (180/267.0) * ((sclE - sclE1) + speedKi * sclE * speedControllTimer/10000.0 +
speedTv * (sclE - 2*sclE1 + sclE2)/(speedControllTimer/10000.0));
else
delta_y = (180.0/267.0) * (speedKi * sclE * speedControllTimer/10000.0 +
speedTv * (sclE - 2*sclE1 + sclE2)/(speedControllTimer/10000.0));
difE2 = difE1;
difE1 = difE;
if(delta_y > scMaxUp)
delta_y = scMaxUp;
if(delta_y < scMaxDown)
delta_y = scMaxDown;
if((PORTC & 0x04) >= 1) //BWD?
y1 = OCR1BL * (-1); //=>y ist dann eigentlich negativ
else
y1 = OCR1BL; //sonst positiv
//Umwandeln von PW 46 bis 180 auf 0 bis 180 zur Kompatibilität zum Regler
//bzw. bei Rückwärtlauf von PW -42 bis -180 auf 0 bis -180
if(y1 >= 46)
y1 = (y1-46) * (180.0/(180.0-46.0));
else if(y1 <= (-42))
y1 = (y1-(-42)) * ((-180.0)/((-180.0)-(-42.0)));
else
y1 = 0;
//neues delta_y einfließen lassen und Signal in den vorgegebenen Grenzen halten
y1 += delta_y;
if(y1 > 180)
y1 = 180;
if(y1 < -180)
y1 = -180;
//Zurückrechnen auf Werte zwischen 46 und 180 bzw. -42 bis -180
if(y1 > 0 || (y1 == 0 && delta_y >= 0))
y1 = 46 + y1 * ((180.0-46.0)/180.0);
else if(y1 < 0 || (y1 == 0 && delta_y < 0))
y1 = -42 + y1 * (((-180.0)-(-42.0))/(-180.0));
if(y1 < 0)
{
PORTC |= (1<<PORTC2); //BWD
y1 *= (-1); //y muss wieder positive Zahl sein weils auf OCR geschrieben wird
}
else
{
PORTC &= ~(1<<PORTC2); //FWD
}
sclE2 = sclE1;
sclE1 = sclE;
OCR1BL = y1;
//Rechte Raupe
scrE = scrW - getRSpeed();
if(speedKp > 0)
delta_y = speedKp * (180.0/284.0) * ((scrE - scrE1) + speedKi * scrE * speedControllTimer/10000.0 + speedTv * (scrE - 2*scrE1 + scrE2)/(speedControllTimer/10000.0));
else
delta_y = (180.0/284.0) * (speedKi * scrE * speedControllTimer/10000.0 + speedTv * (scrE - 2*scrE1 + scrE2)/(speedControllTimer/10000.0));
if(delta_y > scMaxUp)
delta_y = scMaxUp;
if(delta_y < scMaxDown)
delta_y = scMaxDown;
if((PORTC & 0x08) >= 1) //BWD?
y2 = OCR1AL * (-1); //=>y ist dann eigentlich negativ
else
y2 = OCR1AL; //sonst positiv
//Umwandeln von PW 20 bis 180 auf 0 bis 180 zur Kompatibilität zum Regler
//bzw. bei Rückwärtlauf von PW -18 bis -180 auf 0 bis -180
if(y2 >= 20)
y2 = (y2-20) * (180.0/(180.0-20.0));
else if(y2 <= (-18))
y2 = (y2-(-18)) * ((-180.0)/((-180.0)-(-18.0)));
else
y2 = 0;
//neues delta_y einfließen lassen und Signal in den vorgegebenen Grenzen halten
y2 += delta_y;
if(y2 > 180)
y2 = 180;
if(y2 < -180)
y2 = -180;
//Zurückrechnen auf Werte zwischen 20 und 180 bzw. -18 bis -180
if(y2 > 0 || (y2 == 0 && delta_y >= 0))
y2 = 20 + y2 * ((180.0-20.0)/180.0);
else if(y2 < 0 || (y2 == 0 && delta_y < 0))
y2 = -18 + y2 * (((-180.0)-(-18.0))/(-180.0));
if(y2 < 0)
{
PORTC |= (1<<PORTC3); //BWD
y2 *= (-1); //y muss wieder positive Zahl sein weil auf OCR geschrieben wird
}
else
{
PORTC &= ~(1<<PORTC3); //FWD
}
scrE2 = scrE1;
scrE1 = scrE;
OCR1AL = y2;
}
}
Mit freundlichen Grüßen
Schwammi
Lesezeichen