Hallo hai1991,
ich nutze eine Version zum Abbrechen, ähnlich der, die du als erstes aufgeführt hast.
Aber nicht mit dem !=, sondern auch mit einem <, wie in deinem ersten Programm. (Das != ist ja schnell vorbei, wenn das Rad noch etwas weiterdreht. Und schon arbeitet die Loop wieder weiter.)
Ich würde folgendes machen:
Code:
while (count_a < count_a_soll || count_i < count_i_soll)
{
// Innenleben
}
Ich habe nochmal meine Antwort und dein erstes Programm verglichen.
Du machst eigentlich auch 'meinen' Ansatz, dass du das Verhältnis der Tik's nutzt. Mir ist nicht klar gewesen, dass beide Verhältnisse (ich Tiks; du Radius) identisch sind. (Also kannst du auch sagen, dass ich deinen Ansatz benutze
)
OK, somit muss das Problem doch eher in der Loop zu suchen sein.
Dein Hinweis, dass du in deinem main() vergessen hattest, EncoderInit() aufzurufen, führt mich zu folgender Überlegung:
Code:
while(count_a<count_a_soll) // Egal, wie abgebrochen wird
{
// Interruptsystem ist aktiv.
// In encoder[] werden einzelne Tiks gesammelt.
// Nun werden die aktuell ermittelten Tiks gelesen und lokal addiert.
// ---> encoder[] kann nun z.B. [0, 1] enthalten, da RECHTS ja
// schneller gefahren wird.
count_a+=encoder[RIGHT];
count_i+=encoder[LEFT];
// count_a ist nun um eins vergrößert,
// count_i hat sich nicht geaendert.
// Das Interruptsystem erzeugt nun genau an dieser Stelle eine
// Aenderung in encoder [LEFT] auf 1.
// Dieser Tik ist NICHT in count_i abgelegt worden.
if(count_a<(count_i*quot)) speed_a+=5; //zu großer radius
if(count_a>(count_i*quot)) speed_a-=5; //zu kleiner radius
// Nun werden die encoder[]-Inhalte beide auf 0 gesetzt.
//reset encoder
EncoderSet(0,0);
MotorSpeed(speed_i,speed_a);
Msleep(1);
// Hier nun der 2.te Durchlauf der Loop
// Das Interruptsystem ist natürlich weiterhin aktiv.
// In encoder[] werden wieder einzelne Tiks gesammelt.
// Nun wieder die ermittelten Tiks lesen und lokal addieren.
// ---> encoder[] kann nun schon wieder [0, 1] enthalten
// da ja das rechte Rad immer noch schneller ist.
count_a+=encoder[RIGHT];
count_i+=encoder[LEFT];
// Jetzt ist count_a nun schon um zwei vergrößert,
// und in count_i hat sich immer noch nichts geaendert.
// Auch jetzt liefert das Interruptsystem wieder an dieser Stelle eine
// Aenderung in encoder [LEFT] auf 1.
// Auch dieser Tik ist NICHT in count_i abgelegt worden.
// Durch diese if's reduziert du nun permanent speed_a, da ja in count_a
// die Tikzahl waechst, aber count_i 'immer' bei 0 bleibt.
if(count_a<(count_i*quot)) speed_a+=5; //zu großer radius
if(count_a>(count_i*quot)) speed_a-=5; //zu kleiner radius
// Und schon wieder den einen Tik "verlieren".
//reset encoder
EncoderSet(0,0);
MotorSpeed(speed_i,speed_a);
Msleep(1);
// usw.
}
Folgende Änderung würde ich mal probieren:
Code:
//reset encoder VOR DIE SCHLEIFE
EncoderSet(0,0);
while(count_a<count_a_soll) // Egal, wie abgebrochen wird
{
// NICHT addieren, SONDERN zuweisen
count_a = encoder[RIGHT];
count_i = encoder[LEFT];
if(count_a<(count_i*quot)) speed_a+=5; //zu großer radius
if(count_a>(count_i*quot)) speed_a-=5; //zu kleiner radius
MotorSpeed(speed_i,speed_a);
Msleep(1);
// WEG MIT DEM "reset encoder"
MotorSpeed(speed_i,speed_a);
Msleep(1);
}
Mit der Konstruktion, solltest du keine Tiks mehr verlieren.
Ob es tatsächlich hilft?
Zumindest kommt es nun meiner Konstruktion ein Stückchen näher, und ich kann Kurven fahren.
Zu deiner Bemerkung über die Startgeschwindigkeit noch ein Wort:
Code:
...
quot=((float)radius_a)/((float)radius_i);
...
//anfangsgeschwindigkeiten berechnen
speed_a=speed;
speed_i=speed/quot;
if (speed_i < MIN_SPEED)
{
speed_i = MIN_SPEED;
speed_a = MIN_SPEED * quot;
if (speed_a > 255)
speed_a = 255;
}
...
Ich halte den Ansatz von dir für sinnvoll, auch den Speed anhand des quot vorzubelegen.
Das Anfahren aber mit MIN_SPEED sicherstellen. Der Rest sollte von deinem 'Regler' erledigt werden. Wobei bei dir aber noch keine Grenzbetrachtungen vorhanden sind.
Frohes testen wünscht
Sternthaler
Lesezeichen