PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Tasterproblem!



maxfrie
02.04.2010, 14:03
Hallo liebe Community,

ich wollte ein Programm für meinen ASURO schreiben, dass ein Hindernis mit Hilfe der Taster erkennt und diesem Ausweicht.
Jetzt stehe ich aber vor einem Problem mit den Tastern!


#include "asuro.h"
#include "myasuro.h"

#define SPEED 0xC8

void Drehung(int speed_left, int speed_right);

int main(void)
{
unsigned char t1, t2;
Init();

while(1)
{
StatusLED(GREEN);
FrontLED(ON);
BackLED(OFF, OFF);
MotorDir(FWD, FWD);
MotorSpeed(SPEED, SPEED);

StartSwitch();
while(!switched);

t1 = PollSwitch(); t2 = PollSwitch();
if(t1 < K4 && t2 < K4) Drehung(0x00, SPEED);
else if(t1 > K3 && t2 > K3) Drehung(SPEED, 0x00);

switched = FALSE;
}
return 0;
}

void Drehung(int speed_left, int speed_right)
{
MotorDir(BREAK, BREAK);
StatusLED(YELLOW);
Msleep(500);
FrontLED(OFF);
MotorDir(RWD, RWD);
MotorSpeed(SPEED, SPEED);
int i;
for(i=0; i < 4; i++)
{
BackLED(OFF, ON);
Msleep(200);
BackLED(ON,OFF);
Msleep(200);
}
BackLED(ON, ON);
MotorSpeed(speed_left, speed_right);
Msleep(500);
MotorDir(FREE, FREE);
Msleep(500);
}

Das Programm funktioniert solange korrekt, bis ein erstes Mal die Taster betätigt werden. Danach denkt der Asuro es werden permanent weiter Taster gedrückt.
Das Problem muss allerdings an dem Aufruf der Funktion "Drehen" liegen, da ich als Test diese durch einen einfachen Farbentausch der StatusLED ersetzt habe und dies funktionierte dann auch korrekt...

Mir ist bewusst, das der ASURO sehr empfindlich auf die Taster reagiert, wenn die Motoren dabei ins Spiel kommen. Aber wie ihr sehen könnt habe ich mit der variable "switched" und zweifacher Abfrage von PollSwitch() gearbeitet. Somit müsste doch eigentlich ein Fehler vermieden werden, oder?

Ich freue mich auf jede Antowert,

Max

Rabenauge
02.04.2010, 14:43
Hm, ich bin mit dem Asuro nicht wirklich fit, aber wie ich das sehe, gibt es keinen Grund, die Drehungen je wieder zu beenden: er dreht einfach endlos weiter.
Dort würde ich im einfachsten Falle ein delay() nach die Drehung schreiben, damit sie nur eine bestimmte Zeit ausgeführt wird, und dann erstmal wieder nachgesehen wird, ob der Taster überhaupt noch betätigt wird.
Das zusammen kannst du in eine Schleife packen, die beendet wird, wenn die Taster nicht mehr betätigt werden, also ungefähr so:

Endlosschleife{

Wenn Taster{
drehen;
nach 1/10Sekunde;
stop mit drehen;
}
geradeaus fahren;
}

So muss der entsprechende Taster alle 1/10s abgefragt werden(ob er überhaupt noch gedrückt ist), in deinem Programm wohl nicht, wie es scheint.

maxfrie
02.04.2010, 14:54
Also wenn ich deine Antwort richtig verstanden habe, denkst du, dass der Taster nur einmal Abgefragt wird und danach nicht mehr...

Das Programm ist aber so geschrieben, das durch StartSwitch() ein Interrupt Befehl eingeleitet wird, der, sobald ein Taster gedrückt wird, die variable switched auf True stellt. Somit fängt sich der Asuro in der while(!switched); Schleife, bis ein Taster gedrückt wurde und fragt danach nurnoch mit PollSwitch() ab auf welcher Seite die Taster gedrückt worden sind, um entsprechend auszuweichen.

Bevor er sich in der while(!switched) Schleife fängt wird jedoch mit MotorDir und MotorSpeed die Drehrichtung auf vorraus gestellt.
Der Motor fährt dann auch kurz geradeaus aber dann will er wieder ausweichen, obwohl kein Taster betätigt wurde.

Rabenauge
02.04.2010, 15:00
Das Programm ist aber so geschrieben, das durch StartSwitch() ein Interrupt Befehl eingeleitet wird, der, sobald ein Taster gedrückt wird, die variable switched auf True stellt. Somit fängt sich der Asuro in der while(!switched); Schleife, bis ein Taster gedrückt wurde und fragt danach nurnoch mit PollSwitch() ab auf welcher Seite die Taster gedrückt worden sind, um entsprechend auszuweichen.

Ja. Aber wird auch ein Interrupt ausgelöst, wenn ich die Taste LOSlasse?
Wenn nicht, kann der Roboter gar nicht merken, dass man los lässt, weil er im drehen fest hängt.
Sprich: es gibt nirgendwo was, wo er auf "nicht gedrückt" wieder reagieren kann,w enn er mal mit drehen anfängt.

maxfrie
02.04.2010, 15:11
Aber wieso denn nach dem Funktionsaufruf von Drehung() wird switched = FALSE gesetzt - sprich es ist keine Taste gedrückt - die main schleife beginnt wieder von vorne und es wird der Interrupt Befehl neu eingeleitet, der erneut Prüft ob eine Taste gedrückt wird.

In der Funktion Drehung selbst soll nicht geprüft werden, ob er kollidiert.

Rabenauge
02.04.2010, 20:09
Ja, ich blicke das Programm (hab keinen Asuro) nicht ganz, aber es wäre gut, wenn der eine oder andere Kommentar drinnen wäre und vor allem: wenn was nicht klappt, wirft man erstmal sämtliches unnötige heraus. Der arme Asuro hat ja mehr mit warten und blinken zu tun, als er fährt.
Gewöhn dir bitte an, erst die eigentliche Programmaufgabe zu lösen, solche Spielereien wie das ganze Geblinke (ich mag das auch, keine Sorge) baut man ein, wenn das Grundprogramm läuft.

Aufgefallen ist mir: du hast zwei Unterprogramme "Drehen" definiert?
Einmal bereits vor main(), dort aber leer und unten nochmal, wozu das?
Um die Compiler-Warnung auszutricksen?

Ausserdem wird das eigentliche Drehen-Unterprogramm nie richtig beendet da fehlt das return() am Schluss.
Gut möglich, dass das gesamte Programm deswegen an der Stelle hängen bleibt.
Dann wird die Funktion nie beendet und somit der switched nie =false.

maxfrie
03.04.2010, 13:37
Ich danke dir Rabenauge für die Hilfe bis jetzt...

Ich konnte den Fehler weiter eingrenzen und habe nun eine stark abgespeckte Version des Quellcodes.
Der Fehler muss an der Kombination von StartSwitch ( Tasterabfrage im Interrupbetrieb) und PollSwitch ( Tasterabfrage im Polling-Betrieb) liegen. Sobald PollSwitch() nach StartSwitch() aufgerufen wird, um zu prüfen welcher Taster gedrückt wurde, funktioniert StartSwitch() nach dem ersten Aufruf nicht mehr. Selbst wenn ich switched = false setze.

Hier die zwei Codeschnippsel mit erläuterung, die eindeutig beweisen, dass der Fehler an der Kombination der beiden Funktionen liegt:



#include "asuro.h"
#include "myasuro.h"

#define SPEED 200

int main(void)
{
Init();

while(1)
{
MotorDir(FWD, FWD);
MotorSpeed(SPEED, SPEED);

StartSwitch();
while(!switched);
MotorDir(RWD, RWD);
Msleep(1000);
switched = FALSE;
}
return 0;
}

Hier funktioniert der Code einwandfrei: Der Asuro fährt unendlich lange geradeaus, bis irgendein Taster berührt wird. Dann fährt er 1 sek. zurück, um dann einfach wieder geradeaus zu fahren. Das ganze wiederhohlt sich und er reagiert auch immer wieder auf einen Tastendruck.

Hier der fehlerhafte Code:


#include "asuro.h"
#include "myasuro.h"

#define SPEED 200

int main(void)
{
unsigned char t1;
Init();

while(1)
{
MotorDir(FWD, FWD);
MotorSpeed(SPEED, SPEED);

StartSwitch();
while(!switched);
t1 = PollSwitch();
MotorDir(RWD, RWD);
Msleep(1000);
switched = FALSE;
}
return 0;
}

Dies ist fast der selbe Code, bis auf einen Funktionsaufruf von PollSwitch() nach StartSwitch(), dessen Rückgabewert nur zu Testzwecken in t1 hinterlegt wird. Mit dem Wert an sich wird nicht gemacht. Aber:

Asuro fährt hier solange geradeaus, bis irgentein Taster gedrückt wird. Dann fährt er zurück. Aber nicht wie es sein soll für 1 sek, um dann wieder egradeaus zu fahren, sondern er fährt unendlich lange zurück. Das kann also nur Passieren, wenn StartSwitch() wieder switched = TRUE setzt. Aber halt ohne das ein Taster gedrüclt worden ist.

Und dies übersteigt nun meine fähigkeiten in der Microcontrollerprogrammierung, da sich die beiden Funktionen StartSwitch() und PollSwitch() in der LOW-Level programmierung anscheinend stören. Vielleicht liegt auch ein fehler in der lib vor...

Natürlich könnte ich auf StartSwitch() verzichten. Jedoch müsste ich dann mit wohlmöglich 3 abfragen von PollSwitch() arbeiten, um ein richtiges Tasterergebnis zu bekommen und das macht den Quellcode dann natürlich unschön. Auf die Kombination von beiden muss ich dann bei einer genauen Abfrage verzichten.

Ich fände es jedoch sehr interessant, wenn einer das Problem kennt und es mir schildern könnte.

Ansonsten funktioniert jetzt mein Kollisionsprogramm ohne Probleme.

Danke für die Hilfe,
Max

Valen
03.04.2010, 14:29
Ich denke Rabenauge hat recht. Diesen 'return 0;' fehler muss erst korrigiert werden. Dan versuch es mal wieder zu testen. Vergesse aber nicht die änderung zu speichern. Das haupt program sieht gut aus. Das mit switched und herauskommen und wieder eingehen in dem while-schleife. Ich kan kein logik fehler bemerken.

Nur das in dem if regeln, die beider tastermessungen nicht mit einander verglichen werden dammit sie ubereinstimmen. Auf diesen stelle sind die beide motoren noch immer in 'voller gas' modus, aber ist er gegen einer object angestosen und das wird höhe motorstrom verursachen. Mit ebenso grossere störungen vermutte ich.

Und in das unwarscheinliche fall das t1 und t2 gleich nul sind (keiner taster mehr angeprellt, dann ist Pollswitch gleich 0) nach einem interupt anruf, wurde Asuro doch ruckfähren und nach links drehen. Weil 0 auch kleiner ist als K4.