PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RP6 Neuling erste Fragen



StGla90
13.09.2014, 16:27
Guten Tag,
ich bin neu hier im Forum, erst mal was zu mir bin Stephan, 24 Jahre und gelernter Mechatroniker. Mit dem Programmieren hatte ich bisher nicht wirklich viel zu tun, also kompletter Neuling.
Da ich Interesse an Robotik und dem Programmieren habe und bei Conrad großen gefallen an dem RP6 gefunden habe, habe ich mir diesen mal bestellt. Nun habe ich mir erst mal die Anleitung durchgelesen und mir die ersten Beispiel Programme angesehen. Die Grundfunktionen sind mit soweit erst mal kla und ich habe schon kleine Programme geschrieben (LEDs ansteuern, Bumper und ACS auswerten, bestimmte wege/ winkel fahren) das funktioniert schon mal relativ gut. Nun bin ich bei dem Beispiel Move 04 angekommen und da gibt es so die ersten Verständnis Probleme.

1. ich verstehe die Funktion blocking nicht richtig.
wenn blocking true ist wird so lange gefahren bis der weg abgefahren ist, es kann nicht z.B. auf die Bumper reagiert werden
wenn blocking false ist kann während er fährt z.B. auf Bumper reagiert werden und das Programm Fahren verlassen werden
Ist das so richtig oder habe ich das Falsch verstanden?


2. dann verstehe ich Folgenden Abschnitt nicht:


void moveCommand(behaviour_command_t * cmd)
{
if(cmd->move_value > 0)
{
if(cmd->rotate)
rotate(cmd->speed_left, cmd->dir, cmd->move_value, false);
else if(cmd->move)
move(cmd->speed_left, cmd->dir, DIST_MM(cmd->move_value), false);
cmd->move_value = 0;
}
else if(!(cmd->move || cmd->rotate))
{
changeDirection(cmd->dir);
moveAtSpeed(cmd->speed_left,cmd->speed_right);
}
else if(isMovementComplete())
{
cmd->rotate = false;
cmd->move = false;
}
}

behaviour_command_t STOP = {0, 0, FWD, false, false, 0, IDLE};

void behaviourController(void)
{
behaviour_cruise();
behaviour_escape();

if(escape.state != IDLE)
moveCommand(&escape);
else if(cruise.state != IDLE)
moveCommand(&cruise);
else
moveCommand(&STOP);
}

Was bedeutet hier das cmd? Und was wird in diesem abschnitt genau gemacht/ festgelegt? Der Rest ist mir soweit ganz kla.

Danke schon mal im Voraus
MfG

Thorben W
13.09.2014, 16:50
@StGla90: bei Blocking kann ich dir leider nicht helfen
cmd ist ein struckt (eine Struktur) nach dem Muster behaviour_command_t
Der Abschnitt übergibt die Fahrbefehle. Liest sie aus dem Struckt cmd aus und übergibt sie an die Funktionen, die die Motoren ansprechen. behaviourController übergibt übergibt moveCommand die struckt, entweder escape wenn kollison erfolgt ist oder cruise wenn gefahren werden darf und sonst stop

Ich hoffe ich konnte dir helfen.

Thorben

Dirk
13.09.2014, 20:04
Hi,

zu 1.
Beim "blocking" geht es darum, ob die Funktion (z.B. rotate) sofort verlassen wird (blocking = false) oder erst dann, wenn die jeweilige Bewegung beendet ist (blocking = true).

Ob z.B. Bumper gleichzeitig ausgewertet werden können, hängt davon ab, wie man den Rest des Programms gestaltet.
Auf jeden Fall muss man entscheiden, ob das eigene Programm in einer Funktion (z.B. rotate) hängen bleiben darf, bis der Befehl abgearbeitet ist, oder ob man während der Bewegung noch etwas anderes machen muss.

StGla90
14.09.2014, 09:38
Danke erst mal für die Antworten.
ich kann jetzt soweit nachvollziehen wie das funktioniert. Ich hoffe mein Gedankengang ist so richtig:
Also wird jetzt in dem "behaviourController" abgefragt ob cruise oder escape aktiv ist? Wenn jetzt z.B. escape (wenn bumper gedrückt wird) aktiv ist ist, wird in der Funktion "moveCommand(behaviour_command_t * cmd)" im Prinzip escape eingesetzt also das sieht dann für mich gedanklich so aus: "moveCommand(escape)".

Wenn ich jetzt die Situation habe das beide Bumper gedrückt werden:
1. in dem behaviour_escape startet die Funktion ESCAPE_FRONT_START, hier werden die werte für Geschwindigkeit, Richtung etc. festgelegt und in der typdef Struct "eingetragen".
2. da ja in dem Fall "moveCommand(escape)" aktiv ist und in ESCAPE_FRONT_START die entsprechenden werte Festgelegt sind kann die Funktion "moveCommand" hier die werte auslesen und in
die bekannte Funktion "move" einsetzen, es wird gefahren.

Habe ich das bis dahin richtig verstanden?

1.Jetzt gab es aber doch noch Fragen:
Wenn jetzt move und rotate aktiv waren soll er ja wieder gerade aus fahren, das heißt "else if(!(cmd->move || cmd->rotate))" ist ja gegeben wenn move bzw. rotate fertig ausgeführt wurde(da diese ja nach Ausführung auf false gesetzt werden) also wird "MoveAtSpeed" aktiv gleichzeitig wird ja auch die Funktion cruise aktiv (da escape NICHT != IDLE ist) und die werte werden dann ja von "moveCommand(cruise)" aus "behaviour_command_t cruise" ausgelesen.

--> Ist da nicht die Funktion "else if(!(cmd->move || cmd->rotate))" überflüssig?

2. Dann nochmal zur Funktion cmd --> cmd ist also einfach eine Funktion um Daten auszulesen? In dem fall aus der vorher definierten typdef struct? Konnte zu cmd nichts in der Anleitung finden.

Ich hoffe ihr könnt das so nachvollziehen wie ich es geschrieben habe.
Danke im voraus

Dirk
14.09.2014, 10:08
Zu 2.
cmd (als Abkürzung für command) ist eine komplexe Variable vom Typ behaviour_command_t, der im Programm als struct so definiert ist, dass cmd aus einem "Satz" von Variablen besteht, die zusammen den "Befehl" (und gleichzeitig auch den Status) für die Bewegungen darstellen. Da drin sind move und rotate Einzelbits (flags).
Da das ganze Programm recht schnell durchlaufen wird, kommt es an die Abfrage "if(!(cmd->move || cmd->rotate))" öfter, bevor die Bewegung abgeschlossen ist. Damit ist diese Abfrage natürlich erforderlich, damit nicht VOR Ablauf einer move oder rotate Bewegung ein anderer Fahrbefehl (moveAtSpeed) oder eine Änderung der Bewegungsrichtung (changeDirection) erlaubt wird.
Letztlich wird danach erst dann, wenn die move/rotate Bewegung abgeschlossen ist (isMovementComplete()), das move- und rotate- Flag im cmd struct gelöscht.
Danach sind dann auch wieder Änderungen der Bewegungsrichtung oder Geradeausfahrten möglich.

StGla90
14.09.2014, 10:36
ok also das mit dem "if(!(cmd->move || cmd->rotate))" verstehe ich.

aber bei cmd:
wenn cmd eine Variable ist muss die doch noch irgendwo deklariert werden oder?
danke

- - - Aktualisiert - - -

Mir sind noch 2 Sachen eingefallen:

1. Für was ist der bump_Counter?

2. Bei der Structur:

typedef struct {
uint8_t speed_left;
uint8_t speed_right;
unsigned dir:2;
unsigned move:1;
unsigned rotate:1;
uint16_t move_value;
uint8_t state;
} behaviour_command_t;

für was ist :2 hinter dir und hinter move/rotate :1?

Danke

Dirk
14.09.2014, 10:46
Sorry, cmd ist der Übergabeparameter der Funktion.
Deshalb nicht dekariert.

Die :1 hinter move/rotate bedeuten: Das ist nur 1 Bit.
Die :2 hinter dir: Das sind 2 Bit.

StGla90
14.09.2014, 18:28
Ok das Programm habe ich jetzt soweit schon mal verstanden. Habe jetzt auch beim Programmieren festgestellt wie sich das Programm durch blocking bei true/false ändert.
Jetzt habe ich nochmal ne frage zu IRCOMM:
in der Anleitung steht: Achtung! schalten sie niemals den Pin des IRCOMM dauerhaft an! (Strom Aufnahme zu hoch, darf nur eine Millisekunde am stück an sein )
durch was für einen Befehl kann das passieren das der Pin dauerhaft an ist? Möchte das gerne vorm Programmieren wissen, nicht das durch einen Programmierfehler etwas kaputt geht.

Und eine Frage zu Task_ADC:
wird nach dem aufrufen dieser Funktion der Motorstrom automatisch durch die LIB überwacht und der RP6 bei zu hohem Strom abgeschalten oder muss man selber ein Programm dafür schreiben?
Danke.

Dirk
14.09.2014, 19:51
Hi,

Ok das Programm habe ich jetzt soweit schon mal verstanden.
Gut! ;)


Jetzt habe ich nochmal ne frage zu IRCOMM:
in der Anleitung steht: Achtung! schalten sie niemals den Pin des IRCOMM dauerhaft an! (Strom Aufnahme zu hoch, darf nur eine Millisekunde am stück an sein )
Man darf den Portpin PD7 nicht dauerhaft einschalten.
Ausschalten kann man den IRCOMM-Sender so: IRCOMM_OFF();


Und eine Frage zu Task_ADC:
wird nach dem aufrufen dieser Funktion der Motorstrom automatisch durch die LIB überwacht und der RP6 bei zu hohem Strom abgeschalten oder muss man selber ein Programm dafür schreiben?
Nein, die task_ADC mißt u.a. den Motorstrom (Variablen: adcMotorCurrentLeft, adcMotorCurrentRight) und muß daher auch beim Herumfahren des RP6 regelmäßig aufgerufen werden. Meist wird dazu die task_RP6System benutzt, denn ...

... sie ruft auch noch die task_motionControl auf, in der u.a. bewertet wird, ob es sich um ein Überstrom-Ereignis handelt.

Also:
Mit task_RP6System in der Hauptschleife (läuft permanent ohne Pausen alle paar ms durch) deines Programms bist du immer auf der sicheren Seite.

StGla90
14.09.2014, 21:39
Aber um Daten zu senden muss doch IRCOMM ON sein oder? Also müsste nach dem senden IRCOMM sofort auf OFF gestellt werden?

Sisor
15.09.2014, 01:09
Aber um Daten zu senden muss doch IRCOMM ON sein oder? Also müsste nach dem senden IRCOMM sofort auf OFF gestellt werden?

Stell dir vor du hättest eine sehr starke Taschenlampe.
Wenn du sie zu lange anlässt, überhitzt sie und brennt sie durch.
Du benutzt sie zum Morsen, d.h. du sendest kurze Lichtsignale in definierten zeitlichen Abständen.
Dabei wird sie nicht allzu heiß.

Dirk
15.09.2014, 19:05
Hi,

Aber um Daten zu senden muss doch IRCOMM ON sein oder?
Du must dich darum gar nicht kümmern.
Wenn du zum IR Senden nur die Library Funktion IRCOMM_sendRC5() benutzt, macht die alles automatisch.

StGla90
19.09.2014, 17:51
Eine Frage nochmal zu Move_04/05 was für einen sinn macht der pump_count? Wird hier der Winkel/ Weg geändert?