PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Tastenkollision mit Linienverfolgung kombinieren



Y0yo
07.07.2014, 19:17
Hallo Community,

Ich soll für meine Seminararbeit ein Programm für meinen Asuro schreiben, bei dem er einer schwarzen Linie folgen soll an deren Ende ein Kasten steht, wenn der Asuro da dagegen stoßt soll er sofort stehen bleiben und die Status-LED grün aufleuchten.

Nun habe ich mithilfe des AsuroWiki es bereits geschafft ein funktionsfähiges Linienverfolgungsprogramm sowie ein Tastenkollisionsprogramm zu erstellen, aber ich schaffe es nicht beide zu kombinieren.
Wenn ich Asuro starte, fährt er gar nicht los sondern es leuchtet sofort die Status-LED grün. Das soll eigentlich nur passieren, wenn ein Taster betätigt wurde.
Wenn ich nun in der Unendlichschleife eine Sleep() Funktion einbaue klappt zwar das mit den Tastern, aber die Linienverfolgung nicht mehr, da der Asuro dann zu langsam reagiert.

Hier mein Programmcode, hoffe ihr könnt mir helfen.

#include "asuro.h"
#include <stdbool.h>

void wait(float seconds);

int main(void)
{
Init();
StatusLED(RED);
wait(1);
StatusLED(OFF);

unsigned int fototransdata[2];
unsigned int SpeedLeft= 120;
unsigned int SpeedRight= 130;

unsigned char j;
int Offset;

unsigned char T1,T2;
bool Stop= false; // Sobald ein Taster aktiviert wurde soll ASURO nichts mehr machen

FrontLED(ON);

for(j = 0; j < 0xFF; j++)
{
LineData(fototransdata);
}
Offset = fototransdata[0] - fototransdata[1];


MotorDir(FWD,FWD);
MotorSpeed(SpeedLeft,SpeedRight);


while (1)
{
T1= PollSwitch();
T2= PollSwitch();

if( (T1 > 0 && T2 > 0 && T1 == T2) || Stop == true)
{
MotorDir(BREAK,BREAK);
BackLED(OFF,OFF);
FrontLED(OFF);
StatusLED(GREEN);
Stop= true;
}
else
{
LineData(fototransdata);

int dif = (fototransdata[0] - fototransdata[1]);

if((dif - Offset) > 4)
{
StatusLED(OFF);
BackLED(ON,OFF);
if(SpeedLeft > 0 && SpeedLeft < 254)
{
SpeedLeft++;
}
}
else if((dif - Offset) < -4 )
{
StatusLED(OFF);
BackLED(OFF,ON);
if(SpeedRight > 0 && SpeedRight < 254)
{
SpeedRight++;
}
}
else
{
BackLED(OFF,OFF);
StatusLED(YELLOW);
SpeedLeft= 120;
SpeedRight= 130;
}

MotorSpeed(SpeedLeft,SpeedRight);
}

}
return 0;
}


void wait(float seconds)
{
int j;
int max= 1000 * seconds;

for(j=0;j<max;j++)
{
Sleep(72);
}
}

LG. Yoyo

markusj
07.07.2014, 21:05
Zur Fehlersuche könntest du dir Mal T1 und T2 via serieller Schnittstelle ausgeben lassen, wenn du in den Stop-Fall gerätst. Ich bin geneigt auf Schwankungen der Spannungsversorgung zu tippen, evtl. gepaart mit einem grenzwertigen Kalibrierfaktor für die Tasterauswertung.

Davon abgesehen solltest du dich demnächst Mal mit dem Thema Zustandsautomaten beschäftigen - Das wird nämlich erforderlich wenn das Verhalten noch komplexer werden soll.
Außerdem kannst du das Problem der Verlangsamung des Linienfolgers beheben in dem du statt einer Warteschleife (sleep) einfach mehrere Iterationen der Hauptschleife überspringst und nur bei jeder n-ten Iteration die Taster abfragst. Eine noch schönere Lösung wäre natürlich, wenn du Linienfolger und Tasterabfrage zeitgesteuert durchführen würdest, unter Verwendung einer festen Zeitbasis (Timer!)

mfG
Markus

radbruch
08.07.2014, 17:29
Hallo

Vielleicht bringt das eine Besserung:


T1= PollSwitch(); / erst den Tastenstatus einlesen...
MotorSpeed(SpeedLeft,SpeedRight); / ... und dann die Antriebe starten

while (1)
{
T2=T1; / alten Tastenstatus merken für Vergleich mit dem neuen Status
T1= PollSwitch(); / Tasten nur einmal pro Zyklus einlesen

if( ((T1 > 0) && (T1 == T2)) || (Stop == true) ) / klammern, wenn man die Rangfolge nicht auswendig kennt :)


Gruß

mic

Valen
08.07.2014, 18:09
Wie Markusj schon angegeben hat. PollSwitch kann falsche werten ausgeben. Eben andere wenn die Motoren angeschaltet sind. Erst testen ob es die richtige Werten gibt, oder kalibriert werden muss.

Wieso muss die Funktion wait ein Float wert bekommen? Und wie viel Sekunden Dauer verwendest du als Parameter für Endloss-schleife-verzögerung. Vielleicht entsteht hier mehr Verzögerung als gewünscht. Float-rechnerei kostet sehr viel Prozessorkraft (und Speicherplatz) für ein einfache Mikrocontroller als ein Atmega8. Du könntest es viel einfacher für Asuro machen wenn du es zu ein Msleep Funktion umbaut das nur mit integer werten arbeitet. Und ein ganz-Zahl von Millisekunden wartet.


void Msleep (int dauer)
{
int z;
for (z = 0; z < dauer; z++)
Sleep (72); // Warte ein Millisekunde ( mit Originale Asuro Lib!!)
}

Dazu wundere ich mich auch über dein Letzte Else-zweig:


...
else
{
BackLED(OFF,OFF);
StatusLED(YELLOW);
SpeedLeft= 120;
SpeedRight= 130;
}
...Wie arbeitet es wenn du SpeedLeft und SpeedRight nicht auf 120 und 130 einstellt (aber unverändert last) wenn die Linie im mitten der Sensor befindet (absoluten diff-offset weniger als 4). Dein Änderung auf diese niedriger Motorspeed werten macht das steuern vielleicht schlimmer.