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.
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?
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.
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
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
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.
Code:#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; } }
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
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Danke für deine Hilfe
funktioniert jetzt einwandfrei und zuverlässig
vielleicht auch mit diesem Programm:
mfGPHP-Code:
#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);
}
[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:
(ungetestet)PHP-Code:
#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);
}
Ich hoffe, ich habe nichts übersehen.
Geändert von radbruch (09.03.2011 um 22:43 Uhr)
while (!asleep()) sheep++;
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
while (!asleep()) sheep++;
@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
PHP-Code:
#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
Grüße,
Harri
könntest du das vielleicht auch für mich einmal im ganzen Programm posten?
danke
mfG
while (!asleep()) sheep++;
Lesezeichen