PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Nibobee Liniensensoren kalibrieren



Tuxi-Halle
01.02.2010, 02:40
Die Kalibrierung wird mit schwarzem und mit weissem Untergrund durchgeführt, die Messung wird moduliert durchgeführt. Als Ergebnis erhält man 0 für schwarz und 1024 für weiss.
Diese Anmerkung ist zwar nun schon ein Vierteljahr alt, hab sie aber erst heute gelesen.
Deshalb meine Frage: Ist das wirklich so? 1024 (400h) nach dem Weissabgleich bei weissem Untergrund? Bei mir sieht das nach dem Kalibrieren so aus, wenn die Bee auf einem weißen Blatt steht - auf genau dem Blatt, mit dem auch kalibriert wurde!
http://img191.imageshack.us/img191/4773/nibobeeanalog.jpg

Auf dem schwarzen Blatt, mit dem kalibriert wurde, sind alle Werte 0 - reproduzierbar!
Sind bei Dir die Weiß-Werte nach dem Kalibrieren tatsächlich alle 400h??? Dann wäre bei meiner Bee irgendwas noch nicht in Ordnung :-( Für ganz unmöglich halte ich das nicht, da ich bisher noch keine wirklich vernünftige Linienverfolgung hinbekommen habe :?:
Mir scheint (aufgeschrieben habe ich es leider nicht), daß die Weiß-Werte etwas besser und gleichmäßiger geworden sind, nach dem ich kürzlich die Fototransistoren mit etwas Schrumpfschlauch versehen hatte.
http://img94.imageshack.us/img94/1779/nibobeesensoren.jpg
Kann aber auch Einbildung sein.

Rabenauge
01.02.2010, 13:29
Probier doch mal das von workwind gepostete Programm (weiter oben hier (https://www.roboternetz.de/phpBB2/viewtopic.php?p=468645#468645)) aus, das funktioniert auf nem "normalen" Parcours wirklich gut.
Schafft keine allzu engen Kurven oder ähnliches, aber z.b. die hier im Forum herumschwirrende Testunterlage dürfte kein Problem darstellen (wobei es bei der 8 innen natürlich an Logik fehlt).

Allerdings hatte auch ich mitunter etwas, nun, merkwürdige Ergebnisse, ich habe den Eindruck, da gibt es irgendwo eine Art "Drift", ab und an zeigen die Sensoren Werte, die sie nicht haben können (ich hab meine Nase auch abgeschirmt).
Leider hat meine Biene (noch...) kein Display, und mir die Werte mittels der vier LED`s ausgeben zu lassen würde doch in echte Forschungsarbeit ausarten..

Tuxi-Halle
01.02.2010, 15:45
Probier doch mal das von workwind gepostete Programm (weiter oben hier) aus, das funktioniert auf nem "normalen" Parcours wirklich gut.
Schafft keine allzu engen Kurven oder ähnliches, aber z.b. die hier im Forum herumschwirrende Testunterlage dürfte kein Problem darstellen ...
Genau das habe ich getan - sowohl in der völlig unveränderten Fassung von "workwind" als auch mit eigenen Experimenten und zusätzlichen Ausgaben auf das Display - der Effekt ist immer gleich: nach der ersten Kurve (egal ob links oder rechts) haut die Biene ab :-( Ich verwende die originale "Test-Arena", die hier irgendwo zum Download angeboten wurde. Die Kurven sind freilich etwas eng und die Bee ist ganz schön schnell unterwegs, aber wenn das bei allen anderen Leuten klappt, dann sollte meine das auch auch können, oder? Vielleicht sind die Linien der "Arena" auch etwas schmal - bei mir sind das 6mm. Wie breit sind die Linien bei Euch?

Rabenauge
01.02.2010, 18:35
Meine Linien sind zwischen 2mm (nur ein kurzes, relativ gerades Stück) und ca. 12mm breit.

Ich hab eben mal das Isolierband, was _ich_ hier habe (k.A ob es unterschiedliche Breiten gibt?) gemessen, das ist sogar 17mm breit.
Da man damit eh keine allzu engen Kurven kleben kann, ist das dann relativ leicht zu packen.

Besser klappt workwind`s Programm übrigens, wenn man das Tempo etwas drosselt, dann können die Kurvenradien auch ein bisschen enger werden oder die Linien etwas schmaler.

Ich denke aber, wenn es richtig gut werden soll, wird man um ein nachkalibrieren zur Laufzeit nicht drumherum kommen, es sei denn, man probiert es im dunklen Keller bei immer den selben Lichtverhältnissen.
Die Methode habe ich schon beim RCx vor Jahren benutzt, damit kriegt man dann auch schonmal rote Linien auf blauem Untergrund noch gelöst..

Wollen wir mal für die Geschichte nen extra Thread aufmachen?

Rabenauge
01.02.2010, 21:15
So, _ein_ Mysterium dürfte geklärt sein:

Ich habe eben ein wenig mit den Lichtsensoren gespielt.
Zustand Biene: Akku eher leer als voll (ich hatte vorher die Motoren für Tests etwas gequält), Maske drauf, wie immer.
Herumprobiert habe ich mit dem Liniensensoren-Programm aus dem Tutorial zur Biene, es zeigt Helligkeitsschwankungen durch aufleuchten verschiedener LED`s an.
Ich habe dort eine Weile mit den Werten gespielt, und auf einmal fiel mir auf, dass ich die Werte plötzlich immer weiter herunterdrehen musste, bis die Biene noch "wenigstens etwas hell" registriert, obwohl sie auf weissem Zeichenkarton stand.
Wie kann das denn sein??
Als mir einfiel, dass ich vorher mit den Motoren gespielt hatte, hab ich mal eben die Biene ein Weilchen (wenige Minuten) zum laden geschickt und oh Wunder, alle LED`s fanden wieder Helligkeit.
Also das unveränderte Program wieder laufen lassen und einfach mal nen Kaffe getrunken und zugesehen.
Schwupps, fing die erste LED an zu blinken, ging aus, ein Weilchen später die nächste...
Das war vor ca. 10 Minuten, inzwischen leuchtet noch eine, die erst bei einem Wert UNTER 70 "dunkel" anzeigen wird.

Während ich weiter getippt habe, ist nun auch die letzte LED aus, das heisst, die Lichtsensoren liefern nur noch Werte unter 70, und das auf weissem Zeichenkarton.

Alles klar, wenn ich jetzt die Biene wieder auflade, weiss ich, was passieren wird.
Die Sensoren liefern abhängig von der Bordspannung unterschiedliche Werte....damit ist auch das Kalibrieren etwas tricky: wenn ich das bei halbvollen Akkus mache, stimmen die Werte bei richtig geladenen nicht mehr und umgedreht. :roll:
Morgen probiere ich mal, wie lange man das Spiel mit vollen Akkus treiben kann, ehe sich spürbar was ändert, man kann es dann ja bei der Programmierung berücksichtigen.

radbruch
01.02.2010, 21:15
Hallo

Nein, bei einem weisen Blatt wird nicht auf 1023 kallibriert. Wie das genau funktioniert habe ich aber auch noch nicht durchschaut und wohl deshalb den Nutzen auch noch nicht erkannt. Meine bee "schielt" mit dem linken Sensor etwas, deshalb ist sein Wert auch immer geringer. Von Links nach Rechts: Von der Linienlib berechneter Wert, Wert ohne IR-LED, Wert mit IR-LED:

http://radbruch.bplaced.net/robot/nibobee/lcd/wertederliniensensoren.jpg

Direkt nach dem Kalibrieren wird bei allen Sensoren weis mit ca. 900 angezeigt, schwarz mit Werten <10, aber sobald ich die bee etwas drehe ist alles vorbei :(

Die Idee mit den drei Sensoren ist ja recht nett, aber mässig gut umgesetzt. Viel besser wären drei LEDs (warum eigentlich IR-LEDs?) gewesen, in Fahrtrichtung jeweils vor dem Sensor angeordnet.


// nibobee: LCD 20x4 (LMC-SSC4A20) an Port C 28.12.2009 mic

#include <nibobee/iodefs.h>
#include <nibobee/base.h>
#include <nibobee/analog.h>
#include <nibobee/motpwm.h>
#include <nibobee/line.h>
#include <nibobee/delay.h>
#include <nibobee/led.h>
#include <stdlib.h>
#include "lcd_lib.h"

void Msleep(uint16_t pause_ms) // für LCD-LIB
{
delay(pause_ms);
}

void do_blink(uint8_t mask)
{
uint8_t i;
for (i=0; i<5; ++i)
{
led_set(LED_L_RD, mask&0x01);
led_set(LED_R_RD, mask&0x01);
led_set(LED_L_YE, mask&0x02);
led_set(LED_R_YE, mask&0x02);
delay(200);
led_set(LED_L_RD, 0);
led_set(LED_R_RD, 0);
led_set(LED_L_YE, 0);
led_set(LED_R_YE, 0);
delay(200);
}
}
void liniensensoren_kalibrieren(void)
{
lcd_cls(); // lcd Inhalt löschen
lcd_locate(2,0);
lcd_writeString("Kalibrieren");
lcd_locate(2,3);
lcd_writeString("Abbruch Sav sw ws");
line_readPersistent();

while(lcd_getkeys()<7)
{
if (lcd_getkeys()==1)
{
while (lcd_getkeys()==1) delay(1);
line_calibrateWhite();
do_blink(2);
}
if (lcd_getkeys()==2)
{
while (lcd_getkeys()==2) delay(1);
line_calibrateBlack();
do_blink(1);
}

set_output_groupbitval(IO_LEDS, L_YE, line_get(LINE_L)>160);
set_output_groupbitval(IO_LEDS, L_RD, line_get(LINE_L)>240);
set_output_groupbitval(IO_LEDS, R_YE, line_get(LINE_R)>160);
set_output_groupbitval(IO_LEDS, R_RD, line_get(LINE_R)>240);

if (lcd_getkeys()==4)
{
while (lcd_getkeys()==4)
{
delay(1);
}
line_writePersistent();
do_blink(3);
}
while(lcd_getkeys());
delay(100);
}
}
// https://www.roboternetz.de/phpBB2/viewtopic.php?t=51863
int Batterie(void)
{
unsigned char temp1,temp2;
uint16_t ADCresult;

while ((ADMUX & 0x07) != 0x04);

cli();

while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF

//Registerinhalte retten
temp1 = ADCSRA;
temp2 = ADMUX;

ADMUX = (1 << REFS0) | (1 << REFS1) | ANALOG_VOLT; //internal 2.56V reference with external capacitor

//ADCSRA löschen und neu setzen
ADCSRA = 0;
ADCSRA |= ((1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)); //ADC clock = Clock/128
ADCSRA |= (1 << ADEN); //Enable ADC (das aktiviert die 2.56V Referenz)

//Warten bis Kondensator an ARef = 2.56V hat
//Messung an ARef ergab 1,2msec
delay(6); // = ca. 5*Tau

//1. ADC Wandlung starten und Ergebnis ignorieren
ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF

//2. ADC Wandlung starten und Ergebnis übernehmen
ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF

ADCresult = ADCL + (ADCH << 8);

//Registerinhalte wiederherstellen
ADMUX = temp2;
ADCSRA = temp1 & ~(1 << ADSC);

//Warten bis Kondensator an ARef = AVcc hat
//Messung ergab sehr steile Flanke
delay(2); //nicht notwendig, nur zur Sicherheit

ADCSRA |= (1 << ADSC); // Start conversion

sei();

return ADCresult;
}

int main(void)
{
uint8_t i=0; // Hilfsvariable
analog_init(); // ist ätzend die Libteile einzubinden...
line_init();
motpwm_init();
enable_interrupts();
led_init();

lcd_init(); // lcd initialisieren
lcd_cls(); // lcd Inhalt löschen
lcd_locate(2,0);
lcd_writeString("NIBOBee mit LCD");
lcd_locate(4,2);
lcd_writeString("28.12.09 mic");
led_set(0,1);
delay(2000);
led_set(0,0);
lcd_locate(0,2);
lcd_writeString("Bitte Taste druecken");
while(!lcd_getkeys());
i=16;

while(1)
{
if(i & 8) led_set(0,1); else led_set(0,0);
if(i & 4) led_set(1,1); else led_set(1,0);
if(i & 2) led_set(2,1); else led_set(2,0);
if(i & 1) led_set(3,1); else led_set(3,0);
if(i & 16)
{
lcd_init();
while(lcd_getkeys());
delay(100);
while(!lcd_getkeys());
if(lcd_getkeys() & 8) liniensensoren_kalibrieren();
lcd_cls();
lcd_writeString("Liniensensoren");
while(lcd_getkeys());
lcd_locate(0,1);
lcd_writeString("L:");
lcd_locate(0,2);
lcd_writeString("C:");
lcd_locate(0,3);
lcd_writeString("R:");
i=0;
}

if(i & 1)
{
motpwm_setLeft(-1000);
motpwm_setRight(-1000);
}
else if(i & 2)
{
motpwm_setLeft(1000);
motpwm_setRight(1000);
}
else if(i & 4)
{
motpwm_setLeft(0);
motpwm_setRight(1000);
}
else if(i & 8)
{
motpwm_setLeft(1000);
motpwm_setRight(0);
}
else
{
motpwm_setLeft(0);
motpwm_setRight(0);
}

lcd_locate(15,0);
lcd_writeInteger(Batterie(),10);
lcd_locate(3,1);
lcd_writeInteger(line_get(LINE_L),10);
lcd_writeString(" ");
lcd_writeInteger(analog_getValue(ANALOG_L0),10);
lcd_writeString(" ");
lcd_writeInteger(analog_getValue(ANALOG_L1),10);
lcd_writeString(" ");
lcd_locate(3,2);
lcd_writeInteger(line_get(LINE_C),10);
lcd_writeString(" ");
lcd_writeInteger(analog_getValue(ANALOG_C0),10);
lcd_writeString(" ");
lcd_writeInteger(analog_getValue(ANALOG_C1),10);
lcd_writeString(" ");
lcd_locate(3,3);
lcd_writeInteger(line_get(LINE_R),10);
lcd_writeString(" ");
lcd_writeInteger(analog_getValue(ANALOG_R0),10);
lcd_writeString(" ");
lcd_writeInteger(analog_getValue(ANALOG_R1),10);
lcd_writeString(" ");
delay(100);
i=lcd_getkeys();
}
return 0;
}

Das Spannungsproblem dürfte mit meinen AAs nicht so dramatisch sein. Zur Darstellung der Werte ohne LCD: Lass dir die Werte doch blicken. Eine LED blinkt nacheinander die Ziffer der jeweiligen Stelle. Oder du "sendest" die Bits des Wertes in Nipples aufgeteilt nacheinender: 0123 4567 89. Zwischen den Nipples eine kurze Pause, zwischen den Werten jeweils eine ängere Pause: http://www.youtube.com/watch?v=TvZ_JJk_yJE

Gruß

mic

Tuxi-Halle
01.02.2010, 21:20
Wollen wir mal für die Geschichte nen extra Thread aufmachen?
Könne wir gerne machen ;-)
Inzwischen habe ich aber Fortschritte gemacht:
Das Verbreitern der Linien (mit einem schwarzen Colli-Marker) hat gar nichts gebracht, aber:
Einen Teil des Problems habe ich vermutlich gefunden! Ich hatte aus rein ästhetischen Gründen (andere Forums-User haben es genau so gemacht) statt der unteren "Halbsphäre" einen halbierten Tischtennisball angeklebt:

http://img13.imageshack.us/img13/7936/nibobeeshell1.jpg

Nun habe mal versuchsweise die originale durchsichtige Halbsphäre drübergestülpt, wodurch die Liniensensoren einen ganzen Zentimeter höher liegen als vorher - da waren sie nur 0,5 cm über dem Boden:

http://img718.imageshack.us/img718/5930/nibobeeshell2.jpg

Der Erfolg war verblüffend: die Bee schafft jetzt problemlos die innenliegende "8" der "Linientestarena" - bei den engeren Kurven des äußeren Parcours steigt sie aber immer noch regelmäßig aus.
Noch ein interessantes Ergebnis: durch Kalibrierung mit einer grauen Unterlage anstelle der weißen wurden die Ergebnisse noch besser, ohne daß ich jetzt genau verstehen würde, weshalb das so ist. Ich werde es mal genauer untersuchen.

Rabenauge
01.02.2010, 21:26
Was ein durcheinander hier... ich hoffe, ihr habe gelesen, was ich vorhin schrieb. Wahrscheinlich ist das Problem beim fahren sogar noch akuter, da die Motoren auch noch Strom fressen.

radbruch
01.02.2010, 21:51
Tja, wir sind schneller als twitter ;)

Die innere 8 konnte meine bee auch schon mit dem TT-Ball, allerdings nur im Halbdunkel: http://www.youtube.com/watch?v=WaxGDNcvVpo

Je heftiger die Regelung reagiert, umso größer wird die Stromaufnahme der Motoren. Ich werde mal Testen wie die Liniensensoren mit meinem Ballast und den AAs reagieren.

Meine Messung von oben zeigt auch die Batteriespannung an: 923
(Gemessen mit der Funktion von Skroete: https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=51863)
Das wäre vielleicht ein Ansatz für eine Kompensation der Spannungsschwankungen.

Gruß

mic

Rabenauge
03.02.2010, 12:14
Ich schätze, den Referenzwert (der sich ja "verstellt" wenn die Spannung sich ändert) brauchen wir gar nicht.
Das Programm von workwind beruht auf Vergleichen, es werden einfach die unterschiedlichen Werte der drei Sensoren benutzt.
Die Strategie kommt also völlig ohne irgendwelche Referenzwerte aus, wenn ich das richtig verstehe.

Ich hab mir ein ähnliches geschrieben, und es scheint bestens zu funktionieren, man muss nur etwas Unschärfe reinbringen, denke ich.
In eine Richtung (wieso das in die andere noch nicht klappt, ist mir derzeit schleierhaft) fährt die Biene mit der Nase Kurvenradien von 3-4cm noch problemlos ab.
Geht auch noch nach einer halben Stunde üben.
Das heisst, wie es aussieht, ist der schwankende (weil von der Spannung abhängige) Wert völlig nebensächlich, man braucht gar keine fixen Werte.
Es wird einfach immer der jeweils aktuelle Wert des interessanten Sensors als Referenz genommen und dann nur verglichen, ob der auf der anderen Seite heller oder dunkler sieht.
Sollte, um auch einer komplizierten Linie zu folgen, eigentlich reichen, auch wenn man (ich schalte immer nur einen Motor, weil sie erst ab ca. 300 in jeder Fahrsituation _sicher_ laufen) im Grunde immer zickzack fährt.
Aber das kann man noch ausbügeln, erst mal geht es mir darum, den Kurs zu schaffen, Eleganz und Tempo kommen später.

bantyy
08.02.2010, 08:48
Hallo zusammen,

vermutlich wird die Biene die beste Linienverfolgung erreichen, wenn die Original-Halbkugel unter die Biene gesetzt wird. Der halbe Tischtennisball verschlechtert das "Linienfinden".

Die Erklärung ist so einfach und trotzdem nicht naheliegend: Die IR-Dioden haben einen festen Abstrahlwinkel. Wenn die Original-Halbkugel verwendet wird, ist der Abstand so, dass die Dioden zwei Kreise auf dem Boden erhellen, die sich berühren und deren Ränder von allen Fototransistoren "gesehen" werden.

Wenn ein halbierter Tischtennisball benutzt wird, liegt die Biene tiefer - und damit sind auch die beiden erleuchteten Kreise kleiner. Sogar so klein, dass sie sich nicht einmal berühren. Also wird der Bereich direkt unter den Fototransistoren gar nicht mehr durch die IR-LEDs beleuchtet.

So wird auch klar, warum die Biene mit einem halben Tischtennisball mehr Probleme hat, die Linen zu finden. Klar sehen die Fototransistoren noch einen Teil des IR-Lichts, aber der Signal-Rausch-Abstand nimmt deutlich ab.

Mein erster Versuch ist, die beiden äußeren Fototransistoren ein wenig nach innen zu biegen, so dass diese mehr unter die beiden IR-LEDs schauen. Da ich auf der SW-Seite leider noch nicht so weit bin, kann ich noch nicht so genau über Erfolg oder Misserfolg berichten. Vielleicht hilft es euch aber weiter?

Übrigens: Die IR-Leuchtpunkte lassen sich sichtbar machen, indem man mit der Biene in einen abgedunkelten Raum (muss nicht stockdunkel sein) geht, sie auf einen weißen Untergrund stellt und eine Digitalkamera (Handy ist OK) auf die Fläche unter die IR-LEDs richtet. Digitalkameras sind - im Gegensatz zu unseren Augen - empfindlich gegenüber IR-Licht und stellen dass "hell" dar ;-)

Ich hoffe, ich konnte ein wenig helfen :-)

Ciao bantyy

Rabenauge
08.02.2010, 09:04
Meine Digicam "erkennt" schon nach einem halben Stündchen gerade noch die LED`s selbst als leuchtende Punkte, eine Helligkeit auf dem Untergrund schon nicht mehr (zugegeben, ich hab auch nicht lange mit ihr herumprobiert), offenbar sind die verwendeten IR-LED`s nicht besonders stark.

Inzwischen bin ich dabei, mir ein Programm zu schreiben, mit dem ich- ohne Display- die gemessenen Werte der Fototransistoren über die LED`s auf Wunsch ausgeben kann.
Allerdings habe ich einen Stolperstein: ich bin zu doof, aus dem gemessenen Wert (line_get(LINE_L)) eine vernünftige Zahl zu machen, die aber brauche ich um den Wert auf die vier LED`s aufteilen zu können.
Weise ich dem Wert eine Variable zu, bekomme ich Warnungen, und weiss somit nicht, ob die Ausgabe stimmen wird.
Direkt den Wert zerlegen klappt auch nicht, da wird der Compiler richtig böse.
Wie kriege ich den Wert in eine Form, die man mathematisch zerlegen kann?

Warum das Ganze? Meine Biene will bevorzugt in eine bestimmte Richtung drehen, und das darf sie nicht..

radbruch
08.02.2010, 12:14
Hallo

Hier ein Beispiel wie man auf die Ziffern der einzelnen Stellen kommt:

// aus: https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=328394#328394
void PrintChar(unsigned int x)
{
char ergebnis[5] = {'0','0','0','0','0'};
while (x >=10000) { ergebnis[0]++; x -=10000; }
while (x >= 1000) { ergebnis[1]++; x -= 1000; }
while (x >= 100) { ergebnis[2]++; x -= 100; }
while (x >= 10) { ergebnis[3]++; x -= 10; }
ergebnis[4] +=x;
SerWrite(ergebnis,5);
}

In Ergebniss[0] bis [4] stehen dann die 10tsd, 1tsd, hunis, zehner und einer. Allerdings als ASCII-Code, weil der Startwert jeweils '0' (48 oder 0x30) war. Wenn man die Zuweisung der Startwerte in

char ergebnis[5] = {0, 0, 0, 0, 0};

ändert, enthält das Array nur noch die Werte 0 bis 9 für die jeweilige Ziffer.

Meinen TT-Ball habe ich oberhalb der Taile abgeschnitten, der Abstand meiner Liniensensoren entspricht deshalb eher dem Anstand mit der orginalen Halbkugel. Wenn ich die echten Werte mit eingeschalteten IR-Leds ausgeben lasse, habe ich mit diesem Abstand so ziemlich das Maximum erreicht (Werte für weises Blatt bei knapp 1000). Wenn ich die Sensoren anhebe oder senke werden die Werte kleiner. Die Lichtkegel der IR-LEDs werde ich heut abend mal anschauen.

Gruß

mic

bantyy
08.02.2010, 12:21
Hallo,


Meine Digicam "erkennt" schon nach einem halben Stündchen gerade noch die LED`s selbst als leuchtende Punkte, eine Helligkeit auf dem Untergrund schon nicht mehr (zugegeben, ich hab auch nicht lange mit ihr herumprobiert), offenbar sind die verwendeten IR-LED`s nicht besonders stark.

Das mit der halben Stunde verstehe ich nicht?!? Die LEDs sind "stark" genug, ich sehe da sehr deutlich die zwei Leuchtpunkte. Das Umgebungslicht sollte allerdings nicht zu hell sein, wenn die Kamera schon hell sieht, können die IR-LEDs das nicht noch heller werden lassen ;-)

Wenn Du wissen willst, was die IR-Transistoren sehen, müsstest Du einen Filter vor die Kamera setzen, der nur noch IR durchlässt.

Im übrigen haben die meisten höherwertigen Kameras einen IR-Filter eingebaut, so dass dort nicht die volle IR-Intensität zu sehen ist. Ein ganz billiges Handy mit Kamera zeigt da oft mehr - weil dort kein IR-Filter eingebaut ist ;-)


Allerdings habe ich einen Stolperstein: ich bin zu doof, aus dem gemessenen Wert (line_get(LINE_L)) eine vernünftige Zahl zu machen, die aber brauche ich um den Wert auf die vier LED`s aufteilen zu können.

Mit den vier LEDs kannst Du nur 16 Werte anzeigen. Entweder Du gibst die Zahl als HEX-Wert aus, dann kannst Du immer ein Nibble zusammenfassen (4 Bit) und das an den LEDs ausgeben oder Du gibst sie als BCD-Code aus.

Du kannst nur Ziffernweise vorgehen, deswegen musst Du Dir ein eindeutiges "Pausensignal" und "Zahlstart" usw einfallen lassen.

Ich hoffe, dass hilft ein wenig?

Ciao bantyy

radbruch
08.02.2010, 12:55
Du gibst sie als BCD-Code aus.Das erscheint mir am einfachsten. Jede Ziffer belegt dann 4 Bit die man direkt mit den 4 LEDs ausgeben kann:
- Alle Leds einmal an ist Start linker Sensor (15 ist keine BCD-Ziffer!)
- kurze Pause
- nacheinander jeweils die Bitmuster der Einer, Zehner, ...-Stelle anzeigen. (0 als 14?)
- Dazwischen immer kurze Pause zum Notieren der Ziffern ;)
- zweimal mit allen LEDs blinken für Start mittlerer Sensor
- Ziffern nacheinander anzeigen und notieren
- dreimal alle blinken...

So würde ich das angehen. Wie lange man die jeweiligen Ziffern darstellt hängt davon ab, wie schnell man die Bitmuster erkennen und in Ziffern umrechnen kann ;)

Gruß

mic

Ich hab's mal wie oben beschrieben umgesetzt:

#include <nibobee/iodefs.h>
#include <nibobee/delay.h>
#include <nibobee/led.h>

void ausgabe_BCD(uint8_t startsignal, uint16_t wert)
{
uint8_t ziffer=4;
char ergebnis[5] = {0,0,0,0,0}; // Speicher für 5 Ziffern bereitstellen
while (wert >=10000) { ergebnis[0]++; wert -=10000; }
while (wert >= 1000) { ergebnis[1]++; wert -= 1000; }
while (wert >= 100) { ergebnis[2]++; wert -= 100; }
while (wert >= 10) { ergebnis[3]++; wert -= 10; }
ergebnis[4] +=wert;

// Die LEDs hängen an PB0-PB3 und werden direkt angesteuert. BCD-Bit0 ist LED0:
while(startsignal--) // Blinken als Kennung des Wertes
{
PORTB |= 15; // alle LEDs an bedeutet Start eines neuen Wertes
delay(1000);
PORTB &= ~15; // alle LEDs aus
delay(1000);
}
do // die Ziffern nacheinander anzeigen (Einer zuerst)
{
if(ergebnis[ziffer] == 0) ergebnis[ziffer]=14; // '0' darstellbar machen
PORTB |= ergebnis[ziffer]; // Bitmuster anzeigen
delay(1000);
PORTB &= ~15; // und wieder löschen
delay(1000);
}while(ziffer--);
delay(1000);
}
int main(void)
{
led_init();

while(1)
{
ausgabe_BCD(1, 12345);
ausgabe_BCD(2, 321);
ausgabe_BCD(3, 1357);
ausgabe_BCD(4, 8642);
}
return(0);
}

Rabenauge
08.02.2010, 14:40
Ich merk schon, ich muss wohl noch ein bisschen Pauken. ;)
Zwar verstehe ich euere Ausführungen ansatzweise, aber eben nur das...

Ich bin leider in C noch nicht so fit, wie ichs gerne wäre, den RCX hab ich nur in NQC (da gibts bedeutende Einschränkungen, aber es ist auch viel leichter) programmiert..aber dazu hab ich ja die Biene, um auch das zu lernen.

@bantyy: das mit der halben Stunde ist pro Akkuladung gemeint, da man bei der Biene nie weiss, wie voll die Akkus nun wirklich sind, lassen sie dann unter Umständen schon hübsch nach, und es klappt nicht mehr so gut.

Und nun üb ich ein bisschen C... ;)
Zwischendurch werde ich mir mal ein neues Linienfolgeprogramm schreiben (mein jetztiges funktioniert ganz gut, aber sieht weder schön aus, noch ist die Biene schnell und stromsparend ist die pausenlose Pendelei gleich gar nicht), ich hab da einen recht interessanten Ansatz im Kopf.

Rabenauge
11.02.2010, 19:46
So, etwas tippen geübt, eine Packung Zigaretten und einige Liter Kaffe später:

Das Messprogramm ist soweit fertig.
Man kann die Biene auf eine beliebige Unterlage stellen und dann mit einem der Fühler (antippen) die drei Liniensensoren messen lassen.
Im angefügten Programm (dürfte gut genug dokumentiert sein, hoffe ich?) ist eine Variable enthalten, die man nach Lust und Laune ändern kann: es wird im derzeitigen Zustand zehnmal gemessen und ein Durchschnittswert gebildet. Wenn man die Variable ändert, ändert man die anzahl der Messungen.

Das Ergebnis wird dann der Reihe nach ausgegeben, und zwar über die LED`s und im Klartext: die linke (gelb) LED gibt die Tausender, die linke (rot) die Hunderter, und so weiter. Mann muss nur mitzählen.
So werden der Reihe nach (genaueres steht im Kommentar am Programmanfang) alle drei Sensorwerte ausgegeben.

Wers probieren will ein Tipp: lasst nach erfolgter Messung die Biene mal stehen, und messt unter den selben Bedingungen nach einer Stunde erneut, was wird wohl passieren... ;)

Übrigens habe ich es auf meiner Testunterlage (jaha, die selbe, mit der ich das Kalibrierungsprogramm ausgeführt habe) nie Werte über 600 auf weiss gemessen...;)


/*Messprogramm für NIBOBee (by Rabenauge)
Beim betätigen des linken Fühlers nach hinten werden die drei
Liniensensoren der Reihe nach mehrmals abgefragt und Durchschnittswerte ermittelt. Die An-
zahl der Messungen wird mit der Variable iv eingestellt. Während des Messvorganges blinken die
roten LED für jede Messung kurz auf, während der Zeit sollte der Roboter nicht bewegt werden.
Nach der Messung werden die Ergebnisse mittels den LED ausgegeben: jede LED steht für eine
Stelle, das heisst, links gelb blinkt die Tausender aus, links rot die Hunderter, rechts rot
die Zehner und rechts gelb die Einer.
Bevor die Ausgabe beginnt, leuchten kurz alle vier LED, um das Ende der Messung anzuzeigen.
Danach werden der Reihe nach alle drei Messwerte ausgegeben, vor der Ausgabe wird das je-
weils durch die roten LED (leuchten anderthalb Sekunden) visualisiert: leuchtet die Linke,
wird anschliessend der Wert des linken Sensors ausgegeben, leuchten beide, der Wert des mitt-
leren, leuchtet die rechte dann...

Indem man den linken Fühler nach vorne betätigt, kann das Messergebnis gelöscht werden, um eine
neue Messung vorzunehmen.

*/

#include <nibobee/iodefs.h>
#include <nibobee/led.h>
#include <nibobee/sens.h>
#include <nibobee/delay.h>
#include <nibobee/line.h>

int main()
{
enable_interrupts();
led_init();
sens_init();
line_init();
while (1==1)
{

int mode=0; //Modus, per Eingabe
int i=0; //Zählervariable
int iv=10; //Variable Messwiederholung,
//ändern für mehr/weniger Messungen
int l_line=0; //Rückgabe Messergebnis Linie_links
int r_line=0; //Rückgabe Messergebnis Linie_rechts
int c_line=0; //Rückgabe Messergebnis Linie_mitte
int status_L =sens_getLeft(); //linker TastSensor

switch (status_L)
{
case -1: mode=1; //nach hinten =Messung starten
led_set(LED_L_RD,0);
led_set(LED_L_YE,1); //Auswahl zeigen
delay(1500);
led_set(LED_L_YE,0);
delay(500);
break ;

case +1: mode=2; //nach vorne =Messung zurücksetzen
led_set(LED_L_YE,0);
led_set(LED_L_RD,1); //Auswahl zeigen
delay(1500);
led_set(LED_L_RD,0);
delay(500);
break ;

default :led_set(LED_L_RD,0); //links Mitte
led_set(LED_L_YE,0);
break ;
}

if(mode!=0) //was soll es werden?
{
switch (mode)
{
case 1:
for (i=0; i<iv; i++) //Messchleife
{
led_set(LED_L_RD,1);
led_set(LED_R_RD,1);
delay(5);
l_line=(l_line + line_get(LINE_L)); //messen und addieren
r_line=(r_line + line_get(LINE_R));
c_line=(c_line + line_get(LINE_C));
led_set(LED_L_RD,0);
led_set(LED_R_RD,0);
delay(500);
}

l_line= (l_line/iv); //Ergebnis durch Anzahl Messungen
r_line= (r_line/iv);
c_line= (c_line/iv);
delay(500);
break;

case 2:
led_set(LED_L_RD,1); //Messergebnisse zurücksetzen
led_set(LED_R_RD,1);
delay(500);
led_set(LED_L_YE,1);
led_set(LED_R_YE,1);
delay(20);
l_line=0;
r_line=0;
c_line=0;
led_set(LED_L_RD,0);
led_set(LED_R_RD,0);
led_set(LED_L_YE,0);
led_set(LED_R_YE,0);
break;

default:
{line_get(0);
break;
}


}

delay(1000); //Anzeige der gemessenen Werte
led_set(LED_L_RD,1); //zuerst den linken Liniensensor
delay(1000);
led_set(LED_L_RD,0);
delay(1500);

if (l_line>1000) //Tausender?
{
led_set(LED_L_YE,1);
delay(300);
led_set(LED_L_YE,0);
delay(300);
l_line=(l_line-1000);
}
for(i=0; i<10; i++) //Hunderter?
{
if (l_line>100)
{
led_set(LED_L_RD,1);
delay(300);
led_set(LED_L_RD,0);
delay(300);
l_line=(l_line-100);
}
}

for(i=0; i<10; i++) //Zehner?
{
if (l_line>10)
{
led_set(LED_R_RD,1);
delay(300);
led_set(LED_R_RD,0);
delay(300);
l_line=(l_line-10);
}
}
for(i=0; i<10; i++) //Einer?
{
if (l_line>1)
{
led_set(LED_R_YE,1);
delay(300);
led_set(LED_R_YE,0);
delay(300);
l_line=(l_line-1);
}
} //linker Sensor fertig

delay(1000); //Anzeige der gemessenen Werte
led_set(LED_R_RD,1); //mittlerer Liniensensor
led_set(LED_L_RD,1);
delay(1000);
led_set(LED_R_RD,0);
led_set(LED_L_RD,0);
delay(1500);

if (c_line>1000) //Tausender?
{
led_set(LED_L_YE,1);
delay(300);
led_set(LED_L_YE,0);
delay(300);
c_line=(c_line-1000);
}
for(i=0; i<10; i++) //Hunderter?
{
if (c_line>100)
{
led_set(LED_L_RD,1);
delay(300);
led_set(LED_L_RD,0);
delay(300);
c_line=(c_line-100);
}
}

for(i=0; i<10; i++) //Zehner?
{
if (c_line>10)
{
led_set(LED_R_RD,1);
delay(300);
led_set(LED_R_RD,0);
delay(300);
c_line=(c_line-10);
}
}
for(i=0; i<10; i++) //Einer?
{
if (c_line>1)
{
led_set(LED_R_YE,1);
delay(300);
led_set(LED_R_YE,0);
delay(300);
c_line=(c_line-1);
}
} //mittlerer Sensor fertig

delay(1000); //Anzeige der gemessenen Werte
led_set(LED_R_RD,1); //rechter Liniensensor
delay(1000);
led_set(LED_R_RD,0);
delay(1500);

if (r_line>1000) //Tausender?
{
led_set(LED_L_YE,1);
delay(300);
led_set(LED_L_YE,0);
delay(300);
r_line=(r_line-1000);
}
for(i=0; i<10; i++) //Hunderter?
{
if (r_line>100)
{
led_set(LED_L_RD,1);
delay(300);
led_set(LED_L_RD,0);
delay(300);
r_line=(r_line-100);
}
}

for(i=0; i<10; i++) //Zehner?
{
if (r_line>10)
{
led_set(LED_R_RD,1);
delay(300);
led_set(LED_R_RD,0);
delay(300);
r_line=(r_line-10);
}
}
for(i=0; i<10; i++) //Einer?
{
if (r_line>1)
{
led_set(LED_R_YE,1);
delay(300);
led_set(LED_R_YE,0);
delay(300);
r_line=(r_line-1);
}
} //Ende Ausgabe
}

}

}


Übrigens: ich _denke_ dass die Ausgaben stimmen, aber ich garantiere es natürlich nicht, schaut bitte mal über den Code, ob sich bei der Auflösung der Werte kein Fehler eingeschlichen hat!
Schlussendlich aber kommt es wohl kaum auf den exakten Wert an, wichtiger ist es, zu sehen, wie die Sensoren unterschiedliche (ich habe nie drei gleiche Werte bekommen, die liegen locker um 20 auseinander) Ergebnisse liefern.
Ausserdem kann man so bequem ermitteln, wie "dunkel" das Schwarz oder wie "hell" das Weiss wirklich ist.

radbruch
11.02.2010, 21:03
Hallo

Prima umgesetzt und gut kommentiert. Dafür erstmal ein Lob von mir. Nachdem ich der main() noch ein void als Parameter eingegeben hatte, konnte ich dein Programm warnungsfrei übersetzen. analog.c muß auch eingebunden sein. Die Werte meiner bee auf einem weißem Blatt:

0 4 4
0 21 24
0 1 0
0 19 20
0 17 21
...

???

Muß ich zuvor noch kalibrieren? Warum zeigst du nicht auch die echten Sensorwerte an?

Gruß

mic

Rabenauge
11.02.2010, 22:35
Das Programm sollte doch die echten Werte anzeigen?

Warnungen habe ich übrigens auch keine beim compilieren.
Liegt das irgendwie an den Einstellungen von AVR-Studio? Die nämlich blicke ich absolut nicht...ich benutze die im Tutorial angegebenen (buchstabengetreu, dafür muss ich die Datei immer erst als Nibobee.c speichern)..

Bei mir kommen Folgen heraus wie:
528
516
536

oder
524
513
533

Wobei man den Werten eigentlich noch eine Null voranstellen müsste (es ist ja auf nen Wertebereich jenseits der 1000 ausgelegt), aber die erste LED blinkt natürlich nichts, wenn der Wert unter 1000 ist.

In Anbetracht der Tatsache, dass die Biene bereits vor dem posten eine ganze Weile in Betrieb war (anfangs warfen die Werte noch so knapp bei 600), dürfte das eigentlich hinhauen. Inzwischen gibts keine Werte mehr (die Biene stand jetzt stundenlang eingeschalten da und ich hab sie immer mal messen lassen, man merkt, wie die Spannung abnimmt).

Aber wenn da Fehler drin sind, sag es ruhig, ich gehe dann nochmal drüber, das Programm kann man recht leicht für diverse andere Geschichten modifizieren.

Kalibriert habe ich das Bienchen vor einigen Tagen mal, aber da die Sensorwerte ja ohnehin mit der Akkuspannung schwanken, dürfte auch die Kalibrierung nicht sehr wirksam sein (oder wie funktioniert die?)

Rabenauge
19.02.2010, 19:15
Sodele.
Da meine Biene nun einen LiPo hat, habe ich mal wieder das Messprogramm bemüht.
Ergebnis: geht doch. =D>

Messwerte gegen 19.00:
auf "Weiss"
Links 474
Mitte 437
Rechts 470

auf "Schwarz"
Links 124
Mitte 041
Rechts 000

Danach habe ich die Biene ein Stündchen angelassen, und wieder gemessen:

"Weiss":
Links 465
Mitte 342
Rechts 467

"Schwarz"
Links 148
Mitte 038
Rechts 000

Man sieht deutlich, dass es kaum noch Schwankungen gibt, da der Akku in der Biene quasi nie nachlassen kann.
Interessant ist, dass ich die Biene vorher mit dem Calibrations-Programm auf dem selben Untergrund kalibriert hatte, und trotzdem nicht einmal die Hälfte der zu erwartenden Werte an der Tausend auf weiss erreiche..dafür kommt schwarz erstaunlich gut hin.

Wäre aber möglich, dass ich die Kalibrierung falsch bedient habe, ich hab nicht nachgeschlagen, wie es geht sondern aus dem Gedächtnis... nunja, ab 40 solls ja nachlassen. ;)

Allerdings werde ich mir eventuell was einfallen lassen müssen, denn meine Biene wird nun konstant mit 5.07V versorgt, das ist deutlich weniger als mit vollen AAA-Zellen, und so dürften die IR-Dioden wohl noch schwächer funzeln nun.

Achja: Tischkanten sind mit den Liniensensoren absolut zuverlässig erkennbar, dann gibts nirgends Werte über Null...es genügt schon, die Nase etwas anzuheben und aus ists.
Mal schauen, ob es heute abend noch irgendwelche Erkenntnisse gibt, jetzt ist erstmal ein anderer Test dran: laufen die Motoren nun besser an?

bantyy
24.02.2010, 13:46
Hallo,


Allerdings werde ich mir eventuell was einfallen lassen müssen, denn meine Biene wird nun konstant mit 5.07V versorgt, das ist deutlich weniger als mit vollen AAA-Zellen, und so dürften die IR-Dioden wohl noch schwächer funzeln nun.

Häh? Anders ausgedrückt: Die Biene ist _nicht_ für Spannungen oberhalb von 5 V ausgelegt! Sie _darf_ nicht mit AAA-Primärzellen, sondern nur mit AAA-Akkus betrieben werden.

Nein, ich meinte nicht, dass Du Deine geregelte Energiequelle da nicht anschließen darfst, sondern dass das "Original" mit dem AAA-Batteriefach eben nur mit Akkus betrieben werden darf.

Die IR-Dioden werden mit genug Power betrieben. Wie ich schon geschrieben habe, "sehen" die IR-Transistoren unter Umständen die Leuchtkegel der IR-Dioden gar nicht vollständig.

Leider bin ich noch an anderen Stellen mit der Biene unterwegs, weswegen ich diesen Teil noch nicht ausgiebig getestet habe. Was ich aber schon gemerkt habe: Ein leichtes verbiegen der Dioden / Transistoren zueinander oder voneinander weg hat einen deutlichen Einfluss auf die Messergebnisse. Also nehmt das nicht auf die leichte Schulter! Ich sag nur: Digitalkameratest...

Viel Erfolg,
Ciao bantyy

Rabenauge
24.02.2010, 14:50
Vier voll geladene 1.2V NiMh-Akkus haben schon "deutlich" mehr als 5V. Ich habe was um die 5.6V Leerlauf gemessen, bevor ich sie raus operiert hatte. ;) Ich weiss: Leerlauf ist nicht Betrieb, aber trotzdem tritt anfangs sicherlich etwas mehr als 5V auf.

Das mit dem ausrichten stimmt allerdings, sie haben (klug gedacht) einen sehr schmalen Lichtkegel. Aber der kann auch alles verderben, siehe die Leute mit den TT-Bällen, da wird der Kegel schlichtweg zu klein.

Ich finde trotzdem, dass die Geschichte recht grenzwertig betrieben wird, wenn man die Nase auch nur 2-3cm höher anhebt, "sehen" die Sensoren gar nix mehr.
Mit mehr Leuchtkraft liesse sich das sicherlich beheben, der Lichtsensor meines RCX kann Hindernisse noch auf nen halben Meter gut detektieren.
Allerdings hat er zwei oder drei grosse IR-LED`s in der Nase, die reichen bei der PC-Verbindung etliche Meter weit.

Da 5cm Absätze der Biene beim runterfallen nichts tun, sollte die Reichweite wenigstens in der Gegend sein *find

Rabenauge
29.03.2010, 15:26
Sodele.
Meine Biene hat inzwischen ein I2C-Display, und als kleine Fingerübung habe ich mal ein Progrämmchen geschrieben, was die Werte der Lichtsensoren schön nebeneinander ausgibt, und zwar nicht in Hex, wie im erweiterten Testprogramm, sondern in Menschen-Zahlen... [-(

So kann man ohne langes fummeln, herumspielen, warten und Blinkzeichen zählen live die Werte direkt ablesen.

Einfach Biene auf den Untergrund, einschalten und schauen:


#include <nibobee/iodefs.h>
#include <nibobee/usart.h>
#include <nibobee/i2cmaster.h>
#include <nibobee/lcdi2c.h>
#include <nibobee/line.h>
#include <nibobee/delay.h>
#include <avr/eeprom.h>
#include <stdio.h>

void __eewr_block (const void *src, void *dst, size_t n) //muss rein wegen neuerer Bibliotheken
{ //----------oder so-------------------
eeprom_write_block(src,dst,n); //--ergibt sonst Probleme-------------
} //-------beim einbinden der-----------
void __eerd_block (void *dst, const void *src, size_t n) //---------line.h---------------------
{ //------------------------------------
eeprom_read_block(dst,src,n); //------------------------------------
} //------------------------------------

int main() {

usart_setbaudrate(9600);
usart_enable();
i2c_init();
lcd_init(0x27);
lcd_setBacklight(0);
printf(" Liniensensoren "); //Was sehn wir?
set_output_group(IO_SENS); // Pull-ups aktivieren
line_init();

uint16_t links = 0; //Wert linker LS
uint16_t mitte = 0; //--"-- mittlerer
uint16_t rechts= 0; //--"-- rechter

while(1) {
enable_interrupts();

links= line_get(LINE_L); //Linie links auslesen
mitte= line_get(LINE_C); //Linie mitte auslesen
rechts=line_get(LINE_R); //Linie rechts auslesen

lcd_setCursor(0,1); //Ausgabe Licht
printf(" %4d %4d %4d ", links, mitte,rechts);

delay(100);
}
return 0;
}



Funktioniert hervorragend, und gibt, da man sich Zettel, Stift und Geduld spart einige interessante Erkenntnisse.

Falls ihr es benutzt: passt auf, meine Biene hat das Display _richtigherum_ drauf, also oben=vorne, sonst sind die Seiten vertauscht und rechts=links.

Der obere Teil (mit der EEprom-Geschichte) musste rein, da ich vor einigen Tagen alles neu installiert habe hier, ohne läuft bei mir nix, sowie ich die Liniensensoren benutzen will, eventuell kann der Teil ansonsten noch weg.