PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Schleife while(1) und for (...) läuft nur ein Mal :: gelöst



oberallgeier
25.03.2009, 23:27
Schönen Abend, allen,

meine C-Kenntnisse sind bekannt schlecht. Wie schlecht habe ich bei der Adaption des ordentlich funktionierenden und vielfach getesteten Programms meines R2D03/Dottie an mein MiniD0/R3D01 (https://www.roboternetz.de/phpBB2/viewtopic.php?p=432909#432909) gemerkt.

Sachstand: Zur Aufnahme der Sprungfunktion muss ein Fahren des Gerätes ohne Regelung möglich sein. Daher habe ich die Regelung ausgeschaltet (wird garnicht aufgerufen). Für einen längeren Fahrtest sollten die Motoren jetzt getrennt fahren:
Stop - allmählich schneller - niedrige Endgeschwindigkeit - allmählich langsamer - Stop
nächster Motor (gleiche Fahrweise).

Zur Sicherstellung, dass das ohne Störung geht - es ist eine gemeinsame Energieversorgung für Controller und Motoren, nur eine Pufferung mit 1x200µF und 1x100nF (ja - dazu noch die 100nF direkt am Controller) - sollte das Fahrzeug ne Weile fahren - da nur ein Motor dreht, gehts immer im Kreis. Codeschnippsel im main (AVRStudio, WinXPpro):


/* while (1)
{
Motst_12(); // Fahre ohne Regelung+Sensoren
Motst_34(); // Fahre ...
} */


for(i=0; i<200; i++) // Fahrtest
{
Motst_12(); // Fahre ohne Regelung+Sensoren
Motst_34(); // Fahre ...
} Die for-Schleife habe ich gemacht, weil die while-Schleife nur 1mal durchlaufen wurde - danach stand alles - danach kommt auch nur noch das "return 0;". Leider läuft auch die for-Schleife nur 1 mal.

Definiert wurde i als uint_8. Sowohl while(1)- als auch for-Schleifen laufen im Code unmittelbar vor diesem Testabschnitt störungsfrei. Für den Fall dass es hilfreich sein könnte, hier auch noch die aufgerufene Routine.

/* ================================================== ============================ */
/*### Motortest 12 "auf-ab", am 24 Mrz 2009, 1710
================================================== ============================== */
void Motst_12(void) // Motor12 vor+zur, aufab
{
uint16_t iwt=1000; //wait-Dauer beim Hoch-/runterfahren der Motoren

uint8_t mimo = 15, mamo = 50; // Min-/Max-Geschwindigkeitsvorgabe Motoren
uint8_t mdiff = 5; // Auf-/Ab-Increment für Motorspeed
uint8_t ll = 0; // Laufvariable

// Einmal hinfahren (vorwärts) ...

Mrechtsvor();
Mlinksstop();
setPWMrechts(0);
waitms(40);

for(ll = mimo; ll<=mamo; ll = ll + mdiff)
{
kre=ll;
setPWMrechts(kre);
waitms(iwt);
}
setPWMrechts(mamo);
waitms(1000);

for(ll=mamo; ll>=mimo; ll = ll - mdiff)
{
kre=ll;
setPWMrechts(kre);
waitms(iwt);
}

waitms(10);
setPWMrechts(0);
setPWMlinks(0);
Mlinksstop();
Mrechtsstop();
waitms(10);

// ... und einmal rückwärts
// ... =================

// mimo = 5;
// mamo = 25;

Mlinksstop();
Mrechtszur();
setPWMrechts(0);
waitms(40);

for( ll=mimo; ll<=mamo; ll = ll + mdiff)
{
kre=ll;
setPWMrechts(kre);
waitms(iwt);
}
setPWMrechts(mamo);

waitms(1000);
for( ll=mamo; ll>=mimo; ll = ll - mdiff)
{
kre=ll;
setPWMrechts(kre);
waitms(iwt);
}
waitms(10);
setPWMlinks(0);
setPWMrechts(0);

Mlinksstop();
Mrechtsstop();
waitms(10);
return;
}
/* ================================================== ============================ */

Als Massnahme des ratlosen Programmierers hatte ich erstmal die Optimierung von -Os geändert auf -O0. Keine Besserung - nur etwas längerer Hexfile.

Danke für Hilfe

radbruch
25.03.2009, 23:45
Hallo

Das "void" void Motst_12(void)... zeigt an dass die Funktion keinen Rückgabewert liefert. Dann darf am Ende wohl auch kein Return stehen. (Ich vermute die Werte werden über den Stack übergeben und ein Return zuviel nimmt die eigentliche Rücksprungadresse vom Stapel)

Ist aber eher geraten als gewußt.

mic

oberallgeier
25.03.2009, 23:52
Hallo mic,

danke für den Rat. Der Compiler (na ja, der Softwarer/Entwickler hinter dem Compiler) ist ja klüger als der Programmierer (ich) - der pollt seinen Stack richtig - egal ob da ein return steht oder nicht - wenn´s nur eine "void"-Funktion ist. Leider, oder besser: Gottseidank. Steht auch irgendwo in der Hilfe. Seit ich das gelesen hatte, mache ich meistens ein return hin und wundere mich, dass es auch ohne störungsfrei läuft.

Nachtrag: steht auch so im C-Tutorial von RN. (https://www.roboternetz.de/wissen/index.php/C-Tutorial#return-Anweisung)

Danke.

oberallgeier
26.03.2009, 10:47
Noch mehr Unklarheiten. Ich habe die for-Schleife geändert, meiner Meinung nach sind die drei Varianten zulässiges C und deckungsgleich bis auf den jeweils momentanen Wert von "i" innerhalb der Schleife. "Ich dachte halt...." dass vielleicht die Präfix-Notation oder die ausgeschriebene Form "richtiger" sei.

/* for(i=0; i<200; i++) // Fahrtest
// for(i=0; i<200; i = 1 + 1) // Fahrtest
// for(i=0; i<200; ++i) // Fahrtest
Nun läuft die Schleife - einschließlich die mit der ursprünglichen Postfix-Notation i++ und auch die while(1)-Schleife funktioniert. Die Befriedigung der erreichten Funktion wird nur vom Frust übertroffen, dass die gleiche Schreibweise vor ein paar Stunden nicht ging.

Was solls: das MiniD0 dreht seit rund 20 Minuten auf meiner PMMA-Teststrecke (350mmx500mm) eifrig und störungsfrei seine Runden - vor und zurück. Mal sehen, wann der Akku (4xAAA) leer oder die Hackeservos defekt sind . . . . . Und leise ist der Antrieb, man hört sozusagen die weggelassene Getriebestufe.

vohopri
26.03.2009, 11:25
Hallo Joe,

ja sowas gibt es einfach. Man fühlt sich dann oft um den angestrebten Erkenntnisgewinn betrogen, aber ich verspreche dir: Wenn das Problem wichtig ist, kommt es ohnehin wieder. Wirklich Wichtiges verschwindet nicht einfach so.

Aber im Ernst: gratuliere zum Erfolg und den störungsfreien Runden.

grüsse,
Hannes

vklaffehn
26.03.2009, 11:38
Moin!
@obeerallgeier:
Nur eine kleine Anmerkung : Die mittlere Schleife in Deinem letzten Post macht nicht viel Sinn, weil i immer gleich 2 wäre (Tippfehler?), und zwischen 'i++' und '++i' gibt es einen Unterschied.
Bei 'i++' wird erst der Wert der Variablen genommen und in diesem Fall verglichen, danach wird die Variable um eins erhöht, bei '++i' wird erst erhöht und dann verglichen.
MfG
Volker

oberallgeier
26.03.2009, 11:49
Hallo Volker,

danke für Deinen Kommentar


... Die mittlere Schleife in Deinem letzten Post macht nicht viel Sinn, weil i immer gleich 2 wäre ...Uuuuups - keine Ahnung wie die "1" statt des "i" reinkam. Ich habe leider diese dämlichen Zeilen schon ins elektronische Nirwana geschickt und kann den Fehler nicht nachvollziehen. Aber er ist mir schon klar. Danke.


... zwischen 'i++' und '++i' gibt es einen Unterschied ...Danke, ja. Diese Geschichte mit der Post- und Präfix-Notation hatte ich vor einiger Zeit mühselig durchgefisselt und sozusagen verstanden. Wobei mir die Konsequenzen nicht wirklich ganz klar sind - oder besser ausgedrückt: der nutzbare Effekt. Das Beispiel im Kernighan-Ritchie dazu kommt mir ein bisschen konstruiert vor. Vermutlich verstehe ich das nicht wirklich, weil ich noch nie so komplexen Code geschrieben hatte, dass das von Bedeutung war oder gewesen wäre. Aber ich hoffe, dass ich mit meinen Cäh-(Er-)Kenntnissen weiter voranschreite.

PS: die Akkus - ED 100% - sind noch immer nicht leer und die Motoren - ED 50% - weil abwechselnd - sind noch heil *ggggg*.