[OT]Die erste Textfassung ging gründlich daneben - mitten im Bericht - Noteinsatz[/OT]
Mehrere Dinge habe ich bei meinen Tests mit der Sensorplatine (siehe posting vom 12.Feb.) mittlerweile festgestellt. Einschränkend muss ich sagen, dass diese Ergebnisse (vorerst) nur mit ein und demselben Satz 415/5110 gefahren wurden, ich werde (vielleicht) später meine restlichen Bausteine unter meinen Standardbedingungen testen und dann auch weitere, übliche Flächen anstrahlen. Vermutlich werde ich vorrangig noch eine "Dauer-irLeuchte" anbauen, um die deutliche Funktion der AGC zu beeinflussen und zu stabileren Ergebnissen bei unterschiedlichen Bedingungen zu kommen.
Die Geschichte hatte meine dünnen C-Kenntnisse bloßgestellt - und es war wirklich recht Cäh. Vermutlich, nein: sicherlich, ist der Code, der erschreckend kurz für die lange Programmierarbeit ist, nicht optimal. Aber es läuft recht ordentlich.
1) Übersprechen der SendeLED auf Receiver ist durch Schrumpfschlauch nicht zu verhindern
2) Übersprechen der SendeLED auf Receiver ist durch ein Messingrohr zu verhindern, es muss der LED-Fuß zusätzlich z.B: durch einen (dickwandigen) Schrumpfschlauch abgeblendet werden. Der blanke Boden der 415 stört eindeutig nicht.
3) Übersprechen der SendeLED auf Receiver ist beim Aufbau nach 2) ohne Rückenblende des Receivers abgesichert.
4) Übersprechen tritt wieder auf, wenn vor das MSRohr ein Schrumpfschlauch gezogen wird (übersteht).
5) Deutliche Unterschiede der Entfernungsmesswerte zwischen Tages- und Kunstlicht und Dunkelheit.
6) Deutliche Unterschiede der Entfernungsmesswerte je nach Messkörperabmessung und -oberfläche.
7) Es sind wohl nur Bereiche definierbar, wenn man unabhängig von Tageslicht und Oberfläche bleiben will : Nah- Mittel- und Fernbereich.
8 ) Praktisch gleiche Entfernungsmesswerte (unter sonst gleichen Bedingungen) bei PWM-Plateau von „unten“ : 1, 2 …. und „oben“ (ICR1-1, ICR1-2 …).
9) Der 5110 schaltet nur korrekt, wenn die bursts die in den Datenblättern geforderten mind. 6 Pulse aufweisen. Es ist sicherer, mit 7 Pulsen zu arbeiten. 4 Pulse führen eindeutig zu Fehlmessungen.
10) Eine erste Messung bei Tageslicht ist hier vorgestellt, es wurden jeweils ca. 15 Messpunkte für eine Distanz erfasst. Ein Messpunkt besteht aus 100 einzelnen Messungen, deren PWM-Werte für diesen Abstand dargestellt sind. Als Zielfläche diente ein Standard-Papiertaschentuch, eben auf eine Plexischeibe aufgespannt; Ziel der SFH415 war Mitte der Taschentuchs.
11) Zur Frequenz der SFH415 ein Auszug aus meinen Projektnotizen:
Grob ist festzustellen: bei Zimmerbeleuchtung „Essecke“ (alles an, Hängelampe gedimmt) ist ein guter Lauf bei 37,7 kHz festzustellen. 40 kHz gibt praktisch ab 2..3 cm nur „high“. 34 kHz ist ebenfalls recht schlecht. 36kHz ergibt einen eher gröberen Nahbereich bei ähnlichen Werten im Fernbereich wie 37,7. 37,0 kHz (mit irDME_mo1_x14-37.h; ICR1 ist 270) scheint die beste Wahl für feinen Nah- und grossen/fernen Fernbereich zu sein.
12) Die ursprünglich geplanten 6-7 Iterationen zur Bestimmung des Messwertes sind mit meinen C-Kenntnissen nicht machbar - ich musste auf ein stufenweises Hochzählen der Pulsbreite der LED-PWM zurückgreifen. Hier überlege ich noch . . . .
..................................Bild hier
Der Code. Wie gesagt - es war für mich als C-Anfänger schwer, zum Glück hat hier niemand meine anfängliche Stöpselarbeit gesehen. Es fehlte halt an allen Enden, z.B. wie funktionierte die while()-Abfrage ... Aber ich habe ein bißchen dazugelernt.
Code:
// =================================================================================
int ReDiM(void) // Relative Distanz Messung, Rückgabewert = Wert der PWM-Ansteuerung
{
uint8_t mpwm = 0; // mpwm ist der jeweis aktuelle "PWM-Stellwert" bzw. der
// endgültige Messwert
uint8_t tmp = 0; // temporärer Wert
tmp = PINB; // Test, ob ein Signal anliegt
mpwm = 1; // Sicherheitshalber PWM ganz klein
setSRV1(mpwm); // Ansteuerung der PWM auf
for(uint8_t n = 1; n <= 6; n = n + 1) //Es wird die LED auf n Pulse geprüft
// Warten, bis irLED dunkler/heller wird. Im Datenblatt des SFH5110 sind sechs Pulse
// je burst als Minimum gewünscht. Bei 36 kHz dann ca. 6*26 µs bis zum nächsten Test
{ // dies statt: // chk_irLED(); //Warte n Pulse der irLED ab
while (!(PINB & (1<<PINB1))); // Bit 1 (0..7) gelöscht? <==> irLED aus
while (PINB & (1<<PINB1)); // Prüfe, ob Bit 1 (0..7) gesetzt <==> irLED an
}
for (i = 128; i >= 2; i=i-1)
{
if (i > 6)
i = i-1;
if (i > 20)
i = i-2;
if (i > 40)
i = i-6;
mpwm = i;
setSRV1(mpwm); //PWM für irLED ansteuern
for(uint8_t n = 1; n <= 7; n = n + 1) //Es wird n Pulse lang geprüft
{ // dies statt: // chk_irLED(); //Warte n Pulse der irLED ab
while (!(PINB & (1<<PINB1))); // Bit 1 (0..7) gelöscht? <==> irLED aus
while (PINB & (1<<PINB1)); // Prüfe, ob Bit 1 (0..7) gesetzt <==> irLED an
}
tmp = PINB; //Der Empfänger müsste jetzt korrekt schalten
if (tmp & 0x08) //Bit 4 gesetzt? Input high? Freistrahl?
{ //Bit ist high = frei, PWM verstellen
break;
}
else // Bit ist low = bedämpft
{ }
}
return mpwm;
}
/* ============================================================================== */
/* ============================================================================== */
// Aufruf, z.B. aus main mit
mecho = ReDiM();
// ================================================================================
Der zweimalige Aufruf dieser LED-Puls-Zähl-Zeilen wird nicht als Unterprogramm gefahren, das spart etwa 15 % der immer noch unsinnig langen Laufzeit. Die Routine braucht bei (m)einem mega168/20MHz etwa 6 ms bis ein korrekter Wert da ist - das hängt naturgemäß vom Messwert ab: hohe Messwerte brauchen drastisch weniger Zeit. Ich habe keine Ahnung, wie ich den Programmablauf in C schneller machen kann, allerdings läuft der Compiler noch mit -O0. Sicher wäre das auch eine Möglichkeit für Assembler, aber ich bin ja in die µC-Technik, bzw. embedded computing, eingestiegen, weil ich schon lange C lernen wollte.
Die Timerinitialisierung und PWM-Ansteuerung erfolgt so:
Code:
/* ============================================================================== */
/* == PWM-Routinen zur IRLED-ansteuerung auf OC1A/PB1 ======================= */
void TC1SRV_init(void) //Init Timer/Counter 1, PWM-Signal für Servo hin-her
{ // normale PWM aktivieren (nicht invertiert)
TCCR1A |= (1<<COM1A1); //Clear/set OC1A on Compare Match, doc S132.
// also Port PB3, vgl. auch PWM-routine unten
TCCR1B |= (1<<CS10); // cs10 <=> clk/1 => no prescaling doc S 134
TCCR1B |= (1<<WGM13); // PWM, Phase+Frequency correct doc S 134
ICR1 = 270; // =>PWM-Frequenz 20MHz/(2*nn) => 37,0kHz/
TIMSK1 &= ~(1<<OCIE1A)|(1<<OCIE1B); // Tmr/Cntr1 Oput CompA/B Mtch intrrpt disab
TIMSK1 &= ~(1<<TOIE1); // Tmr/Cntr1 Overflow interrupt disabled
}
/* ============================================================================== */
void setSRV1(uint16_t speed1) //Relative Pulslänge auf OC1A/PB1
{OCR1A = speed1;} // z.B. für SFH5110 oder Servo
/* ============================================================================== */
Für beide Abschnitte nehme ich Verbesserungen des Codes gerne an , wie gesagt ....
Variablen, die hier nicht deklariert erscheinen, sind in meiner COMMON-h enthalten. Diese ist hier nicht vorgestellt.
Nachtrag 23:28 Uhr: Diagramm aktualisiert mit "Kunstlicht"
Lesezeichen