HSG |
|
In der Mathematik haben Funktionen klare Eingaben und klare Ausgaben. Mathematische Funktionen haben keine Seiteneffekte wie Ansteuern von Motoren u.s.w. . Eine Funktionsvereinbarung beginnt mit dem Datentyp der Rückgabe. Im Beispiel ist das float, also eine Fließkommazahl. Dann folgt der Name der Funktion, im Beispiel - wie so oft in der Mathematik - f. Bisher sieht alles wie eine Variablenvereinbarung aus. Bei einer Funktionsvereinbarung folgt jetzt in Klammern eine Argumentliste. Das, was man in Funktionen einsetzt, nennt man Parameter. Im Beispiel kann nur ein Parameter x vom Typ float eingesetzt werden. In der Funktionsvereinbarung muss also vor jedem 'formalen Parameter' der zugehörige Datentyp stehen. NXC nennt die Kombination Datentyp und Parameter Argument. In NXC wird durch das Schlüsselwort return in einer Funktionsvereinbarung die Funktion abgebrochen und der Wert des Ausdrucks hinter dem return 'zurückgegeben'.
// Funktionsvereinbarung float f(float x) { return 2*x+3; } task main() { float x = f(5); // Funktionsaufruf string s = NumToStr(x); TextOut(0,32,s); Wait(5000); }
Unterprogramme oder Subroutinen haben typisch keine Rückgabe. Daher steht bei der
Funktionsvereinbarung statt eines Datentyps hier void (engl. leer). Ebenso
entfällt die Rückgabe, daher gibt es hier keine return-Zeile. Die in der Mathematik
verpönten 'Nebeneffekte' sind hier die Hauptsache. Im Beispiel soll die Turtle-Funktion
forward bzw. fd nachgebildet werden. Der Robotor soll bei Ausführung
der Subroutine fd(s) genau s cm vorwärts fahren. Die eingebaute Funktion RotateMotorEx
erlaubt, die Motoren eine ganz bestimmte Gradzahl drehen zu lassen. Im Beispiel wurde
zunächst 1080 eingesetzt, dh. der Motor soll genau 3 Umdrehungen machen. Im vorliegenden
Fall legt er dann 53 cm zurück. Für 1 cm muss er also 1080/53 Grad drehen. Dieser
Proportionalitätsfaktor sf ist von der Reifengröße abhängig und ergibt sich hier
als etwa 20.4. Mit der Anweisung #define sf 20.4 wird die Konstante sf 'definiert'. Es lohnt sich
sicherlich die Konstante sf noch 'feinzutunen'.
Man kann sf auch rechnerisch bestimmen. Der Durchmesser der Räder beträgt ca. 56 mm. Bei
einer vollen Umdrehung also 360° wird eine Strecke von 5,6 cm * π ≈ 17,6 cm zurückgelegt.
Für einen cm ergeben sich dann 360°/17,6 cm ≈ 20,46 °/cm .
#define sf 20.4 // sf = Faktor fuer Strecke s, hier: 1080 --> 53 cm, 1080/53 --> 1cm // Funktionsvereinbarung void fd(float s) { RotateMotorEx(OUT_AB,70,s*sf,0,true,true); Wait(200) // nötig? minimaler Wert? } task main() { Wait(1000); fd(73.0); // Funktionsaufruf }
Zur Steuerung des Roboters wäre eine 'Turtle-Funktion' leftturn bzw. lt nützlich. Die NXC-Funktion RotateMotorEx(Ausgang,Leistung,Drehwinkel,turnratio,bSync,bStop) lässt die Motoren solange drehen, bis der 'Drehwinkel' erreicht ist. Der Parameter 'turnratio' stellt ein festes Verhältnis zwischen den Motoren ein. Ein Wert von 100 sorgt dafür, dass sich die Motoren gegenläufig drehen. bSync = true bewirkt eine exakte Synchronisation. bStop = true stoppt die Motoren hart. Beim gegenläufigen Drehen der Räder dreht sich der Roboter um sich selbst. Sind die Räder b entfernt, so durchläuft jedes Rad bei einer 360°-Drehung die Strecke b * π. Für diese Strecke müssen die Motoren je b * π * sf °/cm drehen. Für eine 1°-Drehung ergibt sich der Faktor wf zu b * π * sf / 360. Bei b = 12 cm wäre der Faktor etwa wf ≈ 2.14. Der Faktor muss jetzt experimentell getestet und angepasst werden
#define wf 2.14 // wf = Faktor fuer Winkel w // Funktionsvereinbarung void lt(float w) { RotateMotorEx(OUT_AB,70,w*wf,100,true,true); Wait(200) // nötig? minimaler Wert? } task main() { Wait(1000); lt(360); // Funktionsaufruf fuer 360°-Drehung }
In die Funktionen fd und lt dürfen auch negative Werte eingesetzt werden. Es sollte also nicht schwierig sein, Funktionen bk fürs Rückwärtsfahren und rt fürs Rechtsdrehen zu definieren.
Lasse den Roboter ein Quadrat mit der Seitenlänge 50 cm fahren.