PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Stopp am Abgrund



Andrew7
23.01.2007, 19:52
Hi

Nachdem ich das Programm "Stop am Abgrund" vom Asuro Buch begriffen hatte, versuchte ich ein eigenes Programm zu schreiben.
Zuerst; das Programm vom Buch funktionierte einwandfrei.
Nachdem ich mein Programm geladen hatte kroch asuro nur anstelle einer Geschwindigkeit von 200 und reagierte auch nicht auf die Ergebnisse.
Sieht jemand den Fehler?

damaltor
23.01.2007, 21:31
ich verstehe dein programm nicht so wirklich. könntest du es etwas kommentieren? einfacher wäre es auch, wenn du mit dem [code]button postest.

radbruch
23.01.2007, 22:51
Hallo

ich habe das Buch nicht und kenne deshalb auch das Programm nicht, dass zur Vorlage diente.

So auf den ersten Blick würde ich mal hier den Wert vergrössern:

if(diff>5)

Das ist der Schwellwert der zwischen Anhalten oder Weiterfahren entscheidet. Wenn dieser Wert zu klein ist (weil die eingelesenen Werte schwanken) wird laufend schnell zwischen Fahren und Stoppen umgeschaltet und das Ergebnisse dürfte ein dahinschleichen sein.

Aber Achtung! Bei zu großem Wert werden kleine echte Änderungen "ausgefiltert" und nicht als Abgrund erkannt!

Das "Spielfeld" sollte bei dieser einfachen Funktion möglichst gleichmässig ausgeleuchtet sein, dann ist der Wertesprung am Abgrund besser zu erkennen. Übrigens kann man auch einen ebenen Hell/Dunkel-Übergang zum Testen verwenden, z.b. verschiedenfarbiges Papier/Karton.

Gruß

mic

Andrew7
24.01.2007, 18:56
Hier nochmal mein Code

Mein Programm sollte als erstes die Werte der Fotodioden einlesen, diese Werte speichern und später in der while Schleife wieder Einlesen. Somit bekommt man zwei Werte. Diese Werte sollen verglichen werden und der kleinere Wert vom grösseren Abziehen.
Ist die Differenz grösser als der Eingestellte Wert, soll er stehen bleiben. Was bedeuten würde, dass sich der Untergrund geändert hat.
Am Schluss wird der erste Eingelesene Wert aktualisiert.

Den Einstellwert habe ich nochmals angepasst. Nun fährt er jedoch, reagiert aber nicht mehr auf die Ergebnisse.




#include "asuro.h"


int main (void)
{
unsigned int lineData[2];
unsigned int erg,erg2;
unsigned char diff;

Init();
LineData(lineData);
erg=lineData[0]+lineData[1];
FrontLED(ON);
while (1)
{

LineData(lineData);
erg2=lineData[0]+lineData[1];
if (erg>erg2)
{
diff=erg-erg2;
}
else
{
diff=erg2-erg;
}
if(diff>10)
{
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);
StatusLED(RED);
}
else
{
MotorDir(FWD,FWD);
MotorSpeed(200,200);
StatusLED(YELLOW);
}
erg=erg2;
}
}

radbruch
24.01.2007, 20:04
Hallo

Ist doch schon mal prima wenn er jetzt fährt. Nun hast du folgendes Problem:

Nach diesem Befehl

erg=erg2;

ganz am Ende der Schleife "vergisst" der asuro den Abgrund der sich vor im auftut. Er startet denn nächsten Schleifendurchlauf mit dem soeben eingelesenen und abgespeicherten Helligkeitswert des Abgrunds und vergleicht diesen mit dem nächsten Wert bis er unten aufschlägt.

Eine Lösung wäre eine Endlosschleife im Stopp-Teil der Abfrage (oder eine Variable die das Ereigniss speichert oder eine Flucht...):

...
{
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);
StatusLED(RED);
while(1); // stehenbleiben und auf Hilfe warten
}
...

Wenn du das jetzt änderst wird er vermutlich überhaupt nicht mehr losfahren wegen:

Init();
LineData(lineData);
erg=lineData[0]+lineData[1];
FrontLED(ON);

Der allererste Wert wird mit ausgeschalteter FrontLED eingelesen. Der nächste Wert, der dann in der Schleife mit eingeschalteter FrontLED eingelesen wird, könnte als Abgrund interpretiert werden. Genau weis ich es nicht, bin zu faul zum Testen. *gg*

Gruß

mic

Andrew7
25.01.2007, 17:47
Danke für deine Hilfe
funktioniert jetzt einwandfrei und zuverlässig :cheesy:

Herbert A.
09.03.2011, 13:44
vielleicht auch mit diesem Programm:


#include "asuro.h"

#define STOP 1

int main(void)

{

unsigned int lineData[2];

unsigned int erst[2];

int x;

int i;

Init();

LineData(erst);

for(i = 0; x< 100000000; i++){

for(i = 0; i< 3; i++){


FrontLED(ON);

MotorDir (FWD,FWD);

MotorSpeed(120,120);

LineData(lineData);

if ((lineData[0]- erst[0] < STOP ) && (lineData[1] - erst[1] < STOP)) {

MotorSpeed(120,120);

MotorDir(RWD,RWD);

for(i = 0; i< 200; i++){

Sleep(255);

}

MotorSpeed(140,0);

MotorDir(RWD,BREAK);

BackLED(ON,ON);

for(i = 0; i< 400; i++){

Sleep(255);

}

BackLED(OFF,OFF);

}

else;

{

MotorSpeed(100,100);

MotorDir(FWD,FWD);

}

}

}

while (1);

return (0);

}

mfG

[Edit von radbruch]
Hast du das Programm selbst mal ausprobiert? Mir ist nicht ganz klar wie das funktioniert:

if ((lineData[0]- erst[0] < STOP )...

Wenn ( der immer wieder mit Beleuchtung neu eingelesene Linienwert links) minus ( der beim Start ohne Beleuchtung eingelesene Linienwert links) insgesamt kleiner als STOP ist...

Wäre nicht ein || sinnvoller als das && ? Wenn der Abgrund von einem Liniensensor erkannt wird würde dann gestoppt.

Der else-Zwieg endet direkt nach dem ; hinter else, alles was danach kommt wird unabhängig von der if-Bedingung ausgeführt.

Verschachtelte For-Schleifen dürfen nicht dieselbe Variable verwenden, i wird nie größer als 401. Maxwert einer Integervariable ist 32.767, 100000000 wird deshalb sowieso nie erreicht:

for(i = 0; x< 100000000; i++){
for(i = 0; i< 3; i++){
...
for(i = 0; i< 200; i++)
...
for(i = 0; i< 400; i++)

Etwas umformatiert und mit allen Änderung sieht dein Programm dann so aus:

#include "asuro.h"

#define STOP 1

int main(void)
{
unsigned int i, lineData[2], erst[2];

Init();
LineData(erst); // die erste Lesung ist immer Schrott!
LineData(erst);
FrontLED(ON);
Sleep(10);
MotorDir (FWD,FWD); // vorwärts fahren
MotorSpeed(120,120);

while(1)
{
LineData(lineData);
if ((lineData[0]- erst[0] < STOP ) && (lineData[1] - erst[1] < STOP))
{
MotorSpeed(120,120); // zurückstoßen
MotorDir(RWD,RWD);
for(i = 0; i< 200; i++)
Sleep(255);

MotorSpeed(140,0); // drehen
MotorDir(RWD,BREAK);
BackLED(ON,ON);
for(i = 0; i< 400; i++)
Sleep(255);
BackLED(OFF,OFF);
}
else
{
MotorDir (FWD,FWD); // vorwärts fahren
MotorSpeed(120,120);
}
}
return (0);
}(ungetestet)

Ich hoffe, ich habe nichts übersehen.

Herbert A.
10.03.2011, 19:22
danke für die Korrektur.
hat irgendjemand eine Idee, wie man den Wert der Liniensensoren einlesen und den
dann 5(z.B.) mal hintereinander mit dem aktuellen Wert vergleichen kann?
mfG

harry3
11.03.2011, 14:37
@Herbert: Mach ein Array, also int links[5] und int rechts[5].
Dann schiebst du die Werte jeweils eins nach hinten, bevor du ganz vorne den aktuellsten Wert reintust.
Du hast dann eine schöne Zeitreihe in den Arrays, wobei [0] das aktuellste, und [4] der älteste Wert ist. Das Rauschen der Sensoren lässt sich hiermit ganz gut eliminieren, wenn du z.B. die ersten beiden Werte addierst sowie die letzten beide Werte addierst, und dann schaust, wie die Differenz der beiden ist (ist eine Minimalversion eines Tiefpasses!).


Hab vor Jahren mal ein Programm für die Kantenerkennung geschrieben, wobei die erste Funktion zum initialisieren aufgerufen wird, und die zweite um zu erkennen ob man über eine Kante gefahren ist(1==>Kante, 0==>keine Kante).
Ich mach es allerdings auf die einfache Art und Weise, also aktuellsten mit dem vorherigen Wert vergleichen.
Eleganter wäre es, eine längere Zeitspanne zu verwenden um das Rauschen auszugleichen(Tiefpass)==>siehe oben!

hs_abgrund.h

#ifndef HSASURO
#define HSASURO
/*Helligkeitsunterschied bei dem eine Kante erkannt wird*/
#define ABGRUND_DIFF 20


/*Variablen für Abgrunderkennung*/
int abgrund_ldata_ref[2];




/*Muss aufgerufen werden,
bevor die Funktion fkt_abgrund_erkennung verwendet wird.*/
void fkt_init_abgrund_erkennung(void);

/*Erkennt Kanten(z.B. beim Tisch). Am besten funktioniert die Erkennung
mit einer Vorwärtsgeschwindigkeit von 100.*/
unsigned char fkt_abgrund_erkennung(void);




unsigned char fkt_abgrund_erkennung(void)
{
int ldata[2],diff_l=0,diff_r=0,schnitt_l=0,schnitt_r=0;
unsigned char c=0;

for(c=0;c<10;c++)
{
LineData(ldata);
schnitt_l=schnitt_l+ldata[0];
schnitt_r=schnitt_r+ldata[1];
}
schnitt_l=schnitt_l/10;
schnitt_r=schnitt_r/10;

diff_l=abs(schnitt_l-abgrund_ldata_ref[0]);
diff_r=abs(schnitt_r-abgrund_ldata_ref[1]);

if(diff_l>ABGRUND_DIFF || diff_r>ABGRUND_DIFF)
{
FrontLED(OFF);
return 1;
}

return 0;

}


void fkt_init_abgrund_erkennung(void)
{
unsigned char c=0;
int schnitt_l=0,schnitt_r=0;

FrontLED(ON);
for(c=0;c<10;c++)
{
LineData(abgrund_ldata_ref);
schnitt_l=schnitt_l+abgrund_ldata_ref[0];
schnitt_r=schnitt_r+abgrund_ldata_ref[1];
}
abgrund_ldata_ref[0]=schnitt_l/10;
abgrund_ldata_ref[1]=schnitt_r/10;
}


#endif

Herbert A.
11.03.2011, 16:41
könntest du das vielleicht auch für mich einmal im ganzen Programm posten?
danke
mfG

harry3
11.03.2011, 18:14
könntest du das vielleicht auch für mich einmal im ganzen Programm posten?
danke
mfG

Hab ich nicht. Ist ja nicht schwer zum einbauen.
Meinen Quelltext in eine Header Datei reinkopieren, diese dann in der Source Datei (C Datei) inkludieren.
Dann erstmal fkt_init_abgrund_erkennung aufrufen.
Und in einer Schleife dann fkt_abgrund_erkennung abfragen:

-----Pseudocode-----------
#include "abgrunderkennung.h"

fkt_init_abgrund_erkennung()
while(fkt_abgrund_erkennung()==0)
{
Vorwärts fahren
}
Sofort Stoppen
---------------------------

Herbert A.
12.03.2011, 09:24
sorry ,ich weiß leider nicht wie das geht,aber wenn das so einfach ist, könntest du das vielleicht für mich machen???
mfG

harry3
12.03.2011, 13:49
Es bringt doch nichts alles vorgekaut zu bekommen.
Mehr als ein paar Grundlagen in C braucht man nicht, um das hinzubekommen.
Beschäftige dich also mal mit C, danach wirst du dir viel leichter tun in Sachen Asuro programmieren!
Hier ein super Online Tutorial für C:
http://www2.fh-augsburg.de/informatik/vorlesungen/XX/c_cplus/tutorial/cyris/ckmain.htm (https://www2.fh-augsburg.de/informatik/vorlesungen/XX/c_cplus/tutorial/cyris/ckmain.htm)

Valen
12.03.2011, 15:35
Es bringt doch nichts alles vorgekaut zu bekommen.
Mehr als ein paar Grundlagen in C braucht man nicht, um das hinzubekommen.
Beschäftige dich also mal mit C, danach wirst du dir viel leichter tun in Sachen Asuro programmieren!
Hier ein super Online Tutorial für C:
https://www2.fh-augsburg.de/informatik/vorlesungen/XX/c_cplus/tutorial/cyris/ckmain.htmKannst du die https:// ändern in http:// ? (also nur die 's' wegnehmen!) Sonnst bekommt man ein Frage von dem Browser ob es das Zertifikat akzeptieren soll? SSL Verschlüsselung ist aber keines Wegs nötig.

P.S. Dazu gibbt es hier auch noch ein C-tutorial:

http://www.rn-wissen.de/index.php/C-Tutorial