PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Seltsamer Taster-Fehler



Tausendacht
16.08.2011, 16:49
Hallo

ich habe einen, für mich sehr mysteriösen, Fehler bei meinem Asuro. Damit ihr mir helfen könnt, muss ich aber wahrscheinlich ersteinmal mein kleines Programm erklären.

Main-Datei:
startet den Motor und soll anschließend nur noch auf Kollisionen reagieren.


int main(void)
{

Init();

MotorDir(FWD,FWD);
MotorSpeed(180,180);

while(1)
{
Kollisionskontrolle ();
Msleep(10);
}

}


Kollisionskontrolle:
überprüft zuerst ob eine Kollision vorliegt (5mal in for-Schleife, da sonst Fehler auftraten ( einzelne falsche Werte) )
anschließend wird je nachdem, welcher Schalter gedrückt ist eine andere Drehung durchgeführt



void Kollisionskontrolle (void)
{
char Zaehler = 0; // Zaehler für die Kontrolle der Taster
int i;

// Teste auf Kollision
for (i=0; i<5; i++)
{
if (PollSwitch() != 0) Zaehler++;

Msleep(1);
}

// Ist der Zahler größer als 1, so leigt eine Kollision vor
// In diesem Fall muss anhand des Pollswitch-Wertes, der auf Zaehler übergeben wird
// unterschieden werden wie zu reagieren ist.
if (Zaehler > 1)
{
Zaehler = PollSwitch();

// Stößt ganz links an - Asuro dreht 45° rechts
if (Zaehler == 32)
{
// K1 gedrückt - 45° nach rechts drehen
Drehung(45, 150);
}

// Stößt ganz rechts an - Asuro dreht 45° nach links
else if (Zaehler == 1)
{
// K6 gedrückt - 45° nach links drehen
Drehung(-45, 150);
}

// Stößt anders an - Asuro dreht 180°
else
{
// 90° Drehung
Drehung(180, 150);
}
}
}


Drehung:
Hier wird zuerst die aktuelle Geschwindkeit gespeichert. Anschließend der roboter ein Stück zurückgefahren und anschließend die Drehung durchgeführt. Zum Schluss fährt der Asuro mit der ursprünglichen Geschwindigkeit weiter.


void Drehung (int Grad,unsigned char Geschwindigkeit)
{
int Faktor = 4; // spezifischer Faktor - Je nach Reibung einzustellen damit Drehung etwa stimmt
unsigned char Left_Speed;
unsigned char Right_Speed;

// Ursprüngliche Geschwindigkeit übernehmen
Left_Speed = OCR1A;
Right_Speed = OCR1B;


// Kurz zurücksetzen
MotorDir(RWD,RWD);
MotorSpeed(120,120);
Msleep(200);
MotorSpeed(0,0);

// Unterscheide Links und Rechtsdrehung
if(Grad >0) // Rechtsdrehung
{
MotorDir(FWD,RWD);
MotorSpeed(Geschwindigkeit,-Geschwindigkeit);
Msleep(Grad * Faktor);
}
else
{
MotorDir(RWD,FWD);
MotorSpeed(-Geschwindigkeit,Geschwindigkeit);
Msleep(-Grad * Faktor);
}



MotorDir(FWD,FWD);
MotorSpeed(Left_Speed,Right_Speed);



Hat soweit bei meinen ersten Versuchen auch wunderbar funktioniert. Stell ich die Geschwindigkeit aber höher als ca. 150 macht der Asuro was er möchte. Teilweiße dreht er sich mehrfach, bzw die ganze Zeit. Eigentlich immer beginnt er sogar nicht mit vorwärtsfahren, bis ein Hindernis kommt, sondern beginnt direkt mit einer 180° Drehung.

Ich habe mit einem kleinen Programm die Funktion der Taster getestet (auch bei laufendem Motor in verschiedenen Geschwindigkeiten). Dabei habe ich bis auf ganz wenige einzelne Fehler fast nur richtige Werte bekommen.
Das Programm sah in etwa so aus:



if (PollSwitch() != 0) UartPutc ('1');

else UartPutc('0');

Msleep(1);


Ich habe mittlerweile alles mögliche ausprobiert und konnte auch im Quelltext keinen Fehler entdecken. Ich stehe etwas ratlos vor dem Problem. Deshalb hoffe ich, dass sich hier jemand die Mühe macht sich das mal genauer anzusehen.

Vielen Dank
Tausendacht

radbruch
16.08.2011, 17:10
Entprellung der Taster, einer von unzähligen Threads zu diesem Thema:
http://www.arexx.com/forum/viewtopic.php?f=19&t=1544

[Edit]
Zu: "Dabei habe ich bis auf ganz wenige einzelne Fehler fast nur richtige Werte bekommen."


// Teste auf Kollision
for (i=0; i<5; i++)
{
if (PollSwitch() != 0) Zaehler++;

Msleep(1);
}

// Ist der Zaehler größer als 1, so liegt eine Kollision vor
// In diesem Fall muss anhand des Pollswitch-Wertes, der auf Zaehler übergeben wird
// unterschieden werden wie zu reagieren ist.
if (Zaehler > 1)
{
Zaehler = PollSwitch();

Jeder PollSwitch()-Fehler in der zaehler++ -Schleife würde dazu führen, dass die If-Bedingung erfüllt wird. Anschließend wird bei Zaehler = PollSwitch(); wieder der viel häufigere richtige Wert der Tasten eingelesen. Ist dieser dann nicht 1 oder 32 landet deine if-else-Kette hier:


else
{
// 90° Drehung
Drehung(180, 150);
}

Tausendacht
16.08.2011, 19:27
Hallo Radbruch

Vielen Dank (schon wieder) für deine schnelle Antwort.

Die Sache mit der Entprellung muss ich mir Morgen oder nacher noch genauer durchlesen. Ich versuche mich noch in die Materie einzuarbeiten und brauche deshalb für Alles etwas länger.


Jeder PollSwitch()-Fehler in der zaehler++ -Schleife würde dazu führen, dass die If-Bedingung erfüllt wird. Anschließend wird bei Zaehler = PollSwitch(); wieder der viel häufigere richtige Wert der Tasten eingelesen. Ist dieser dann nicht 1 oder 32 landet deine if-else-Kette hier:

Die if-Bedingung (Zaehler>1) wäre nur dann erfüllt, wenn (mindestens) 2 Fehler innerhalb von 5 Durchläufen (5ms) auftreten.
Mit dem oben beschriebenem Progrämmchen hab ich dies überprüft und hatte nie 2 Fehler hintereinander, maximal jeder 2000. übermittelte Wert war ein falscher. Deshalb denke ich, dass hier kein Fehler liegen dürfte, oder verstehe ich Dich falsch?

Tausendacht
16.08.2011, 22:32
Ich hab mir Deinen Link durchgelesen und den Taster-Test aus der Library durchgeführt. Alle Taster liefern exakt den richtigen Wert. Nur wenn mindestens 4 Taster gedrückt sind kann es sein, dass der Wert um 1 abweicht.

Ich hab also weiterhin keien Ahnung was da falsch läuft...

radbruch
16.08.2011, 22:45
Zeig doch bitte mal eine komplette und komplierfähige Version von deinem Kollision-Programm.

Tausendacht
16.08.2011, 22:59
Normalerweiße auf 3 Dateien verteilt, hier der Einfachheit halber in einer:


#include "asuro.h"

// Prototypen
void Kollisionskontrolle (void);
void Drehung (int Grad,unsigned char Geschwindigkeit);

int main(void)
{

Init();

MotorDir(FWD,FWD);
MotorSpeed(210,210);

while(1)
{
Kollisionskontrolle ();
Msleep(5);
}


return 0;
}






void Kollisionskontrolle (void)
{
char Zaehler = 0; // Zaehler für die Kontrolle der Taster
int i;

// Teste auf Kollision
for (i=0; i<5; i++)
{
if (PollSwitch() != 0) Zaehler++;

Msleep(1);
}

// Ist der Zahler größer als 1, so leigt eine Kollision vor
// In diesem Fall muss anhand des Pollswitch-Wertes, der auf Zaehler übergeben wird
// unterschieden werden wie zu reagieren ist.
if (Zaehler > 1)
{
Zaehler = PollSwitch();

// Unterschiedliche Reaktionen

// Stößt ganz links an - Asuro dreht 45° rechts
if (Zaehler == 32)
{
// K1 gedrückt - 45° nach rechts
Drehung(45, 150);
}

// Stößt ganz rechts an - Asuro dreht 45° nach links
else if (Zaehler == 1)
{
// K6 gedrückt - 45° nach links
Drehung(-45, 150);
}

// Stößt anders an - Asuro dreht 180°
else
{
// 90° Drehung
Drehung(180, 150);
}
}
}



void Drehung (int Grad,unsigned char Geschwindigkeit)
{
int Faktor = 4;
unsigned char Left_Speed;
unsigned char Right_Speed;

// Ursprüngliche Geschwindigkeit übernehmen
Left_Speed = OCR1A;
Right_Speed = OCR1B;


// Sicherheitshalber kurz zurücksetzen
MotorDir(RWD,RWD);
MotorSpeed(120,120);
Msleep(200);
MotorSpeed(0,0);

// Unterscheide Links und Rechtsdrehung
if (Grad >0) // Rechtsdrehung
{
MotorDir(FWD,RWD);
MotorSpeed(Geschwindigkeit,-Geschwindigkeit);
Msleep(Grad * Faktor);
}
else // Linksdrehung
{
MotorDir(RWD,FWD);
MotorSpeed(-Geschwindigkeit,Geschwindigkeit);
Msleep(-Grad * Faktor);
}



MotorDir(FWD,FWD);
MotorSpeed(Left_Speed,Right_Speed);

}

radbruch
16.08.2011, 23:33
So vielleicht:

void Kollisionskontrolle (void)
{
char Zaehler = 0; // Zaehler für die Kontrolle der Taster
char sw[5]; // Speicher für 5 Tastenwerte
int i;

// Teste auf Kollision
for (i=0; i<5; i++)
{
sw[i]=PollSwitch(); // Tastenwert speichern
if (sw[i] != 0) Zaehler++; // Wenn eine Taste erkannt wird Zähler erhöht

Msleep(1);
}

// Wurde fünf mal die selbe Taste erkannt?
if ((Zaehler == 5) && (sw[0]==sw[1]) && (sw[0]==sw[2]) && (sw[0]==sw[3]) && (sw[0]==sw[4]))
{
//Zaehler = PollSwitch();
Zaehler=sw[0];

// Unterschiedliche Reaktionen
...

Tausendacht
17.08.2011, 11:26
Guten morgen

Ich habe deine Änderung vorgenommen und den Asuro geflasht. Momentan dreht er sich bei einem Aufprall zumindestens nicht mehrfach.
Dafür kommt es vor, dass er nachdem er gegen einen Schrank oder Ähnliches fährt anschließend nur noch rückwärts fährt.
Manchmal verändert er nach einer normaler Drehung auch die Geschwindigkeit, was wohl die Geschwindigkeit beim Drehen ist, jedoch nicht die ursprüngliche.
Ein weiterer Fehler ist, dass er sich manchmal nach einem aufprall endlos dreht. Manchmal beginnen während der Fehler auch LEDs zu leuchten...

Alle Versuche die ich unternommen hab um nach einem System hinter dem Fehler zu suchen laufen ins leere... der kleine hat wohl nen widerspenstiges Eigenleben entwickelt.

radbruch
17.08.2011, 12:29
Hallo

Wenn die LEDs blinken gabs einen Reset oder eine "VL"-Meldung. Beides könnte von schwachen/leeren Akkus kommen, z.B. nach längerer Fahrtdauer, oder von den Erschütterungen beim Aufprall.

Grundsätzlich muss man bedenken, dass jede Kollision den asuro komplett erschüttert. Die Taster sind fast schon am Ende des Betätigungswegs, wenn der Kontakt durchschaltet. Und sie werden dann bis zum Anschlag gedrückt, weil der asuro nicht schnell genug bremsen kann. Dadurch ist die mechanische Belastung an der Platine recht hoch. Schlechte Lötstellen, Kontaktprobleme im Batteriehalter oder am Schalter, Blockierströme der Antriebe, und was weiß ich noch alles, könnte stören.

int main(void)
{
int i;

Init();

for(i=1; i<10; i++) // Reseterkennung
{
StatusLED(i & 3);
Msleep(200);
}
StatusLED(GREEN);

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

Kollisionskontrolle ();

Msleep(5);
}
return 0;
}


Zusätzlich könntest du die Tastenwerte zur Kontrolle an ein Terminal senden:
https://www.roboternetz.de/community/threads/38537-Asuro-dauernd-kollision
https://www.roboternetz.de/community/threads/30118-K6-sagt-nix?p=284529&viewfull=1#post284529
https://www.roboternetz.de/community/threads/9093-ASURO-ADC-für-Taster-direkt-auslesen?
https://www.roboternetz.de/community/threads/26283-gelöst-Asuro-Schalter-K1-K6-per-Software-korrigieren?

Gruß

mic