PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Einfache IR-Code Übertragung funktioniert nicht



R2D2 Bastler
24.01.2014, 20:38
Hallo zusammen,

Ich kämpfe zur Zeit mit den Tücken einer „Infrarot-Kanone“ für Modellflugzeuge (indoor).

Den Aufbau habe ich mir so vorgestellt:
Ein Attiny45 (da klein und leicht), eine IR Diode (LD 274-3) und ein IR Empfänger (TSOP34836), das ganze angeschlossen zwischen RC-Empfänger und Motor-Regler. Optional ein weiterer Anschluss zwischen RC-Empänger und Attiny für den Trigger (zunächst aber ohne Trigger, nur mit „Dauerfeuer“).

Wie soll das ganze funktionieren:
1. Im normalen Flug wird das RC-Throttle-Signal (Gas) durch den Attiny „durchgeschleift“.
2. Die IR-LED „feuert“ ständig. (Optional: Die IR-LED feuert erst, wenn an der Fernsteuerung ein Schalter/Taster betätigt wird).
3. Wird der IR-Empfänger von einem passenden Infrarot-Signal „getroffen“ soll der Motor für eine bestimmte Zeit ausgehen bzw. stottern (unterbrechen des bis dahin durchgeschleiften Gas-Kanals).

Ich habe bis jetzt noch nichts mit IR-Übertragungen gemacht (nur viel gelesen). Das RC5 Protokoll scheidet aber aus, da es viel zu lang ist. Mir schwebt im Moment ein sehr kurzes individuelles Protokoll vor. Meine Gedanken gehen in Richtung „3-Bit-Protokoll“. Ein Start-Bit und 2 Kommand-Bits. Damit sollten 4 verschiedene IR-Befehle übertragbar sein. Mit den unterschiedlichen Befehlen könnte man später mit mehreren Flugmodellen auf ein einzelnes Bodenziel schießen, mit anschließender Trefferauswertung. Auch ein „Team-Deathmatch“ z.B. zwei gegen zwei wäre denkbar, bei dem man sogar in der Software „friendly fire“ ausschließen könnte.

Im folgenden Code habe ich versucht, die IR-Übertragung zu realisieren. Leider klappt das nur mit mäßigem Erfolg. IR-LED und TSOP stehen sich gegenüber. Die Kontroll-LED sollte eigentlich durchgehend leuchten, flackert aber die ganze Zeit. Wird die optische Verbindung zwischen IR-LED und TSOP unterbrochen, geht die Kontroll-LED wie gewünscht aus.

Ich habe es nicht geschafft, eine halbwegs verlässliche Datenübertragung herzustellen.

Bin langsam am verzweifeln und für alle Ideen offen :cry:


mfg
Robert


Hier noch ein paar Infos, wo ich meine Inspiration her habe:
http://www.youtube.com/watch?v=TQp0mS8dtpg
oder einfach nach „20100117 IAC-ASO 52“ suchen.
Ab 1:36 geht’s los mit dem IR-Stuff, ab 2:51 Minuten sieht man „Luftkämpfe“
Meine Modelle werden allerdings etwas größer sein :-)



PS: Wenn ich die Sendepause im Code nicht ausklammere, leuchtet die Kontroll-LED gar nicht.



'================================================= ==============================
'IR Kanone V 01
'
'IR-LED an Pin 5 (PB0, OCR0A)
'TSOP34836 an Pin 7 (PB2, INT0)
'
'
'
'
'
'Pin 6 (PB1 Test-LED)
'================================================= ==============================

$regfile = "attiny45.dat"
$crystal = 8000000 'FuseBit CKDIV8 deaktivieren

$hwstack = 40
$swstack = 40
$framesize = 50


'-------------------------------------------------------------------------------------------------
'Timer konfigurieren
'-------------------------------------------------------------------------------------------------

Tccr1 = &B00000111 'Timer1 als Zeitbasis für Datenempfang starten (Prescale 64) (geht beim Attiny45 nicht mit "Config"!)
'Enable Timer1 (wird erst in der ISR enabled!!!)
On Timer1 Daten_sammeln



Config Timer0 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1 'Timer0 erzeugt 36kHz IR-Trägerfrequenz, Clear Timer setzt Timer bei Erreichen des Comparewertes auf 0 zurueck
Ocr0a = 110


'-------------------------------------------------------------------------------------------------
'Interrupt-Service-Routinen konfigurieren und freigeben
'-------------------------------------------------------------------------------------------------


Config Int0 = Rising 'bei steigende Flanke an PB2/INT0 (Ir_data_in) Int0 auslösen und in die Subroutine springen
Enable Int0
On Int0 Ir_data_start

Enable Interrupts


'-------------------------------------------------------------------------------------------------------------
'Variablen definieren
'-------------------------------------------------------------------------------------------------------------
Dim Ir_befehl As Byte 'es steht einer von 4 möglichen Sendebefehlen zur Verfügung
Dim Level As Byte
Dim Ir_data As Byte 'zusammensetzen des IR Befehl
Dim Ir_data_fertig As Byte 'fertig empfangener IR Befehl



'-------------------------------------------------------------------------------------------------------------
'Ein- und Ausgang festlegen
'-------------------------------------------------------------------------------------------------------------

Ddrb = &B00010011 'PB0, PB1 und PB4 werden Ausgänge, restlicher PortB bleibt Eingang



'================================================= =====
'Hauptprogramm
'================================================= =====

Do


Ir_befehl = &B00000101
' |||
' ||Zweites Befehlsbit
' ||
' |Erstes Befehlsbit
' |
' Startbit

'Alternative Befehle:
'Ir_befehl = &B00000100
'Ir_befehl = &B00000110
'Ir_befehl = &B00000111


'Startbit senden (immer 1)
Ddrb.0 = Ir_befehl.2 ' 36 kHz Carrier on
Waitus 500
Ddrb.0 = 0 ' 36 kHz Carrier off
Waitus 500

'Erstes Befehlsbit senden
Ddrb.0 = Ir_befehl.1
Waitus 500
Ddrb.0 = 0
Waitus 500

'Zweites Befehlsbit senden
Ddrb.0 = Ir_befehl.0
Waitus 500
Ddrb.0 = 0
Waitus 500
'(
'Sendepause einlegen
Ddrb.0 = 0
Waitus 2000
')


If Ir_data_fertig = &B00000101 Then 'Test LED soll leuchten, wenn der richtige Code empfangen wurde
Portb.1 = 1
Else
Portb.1 = 0
End If


Loop

End



'-------------------------------------------------------------------------------------------------------------
'ISR IR Daten empfangen
'-------------------------------------------------------------------------------------------------------------

Ir_data_start:
Ir_data = &B00000001
Timer1 = 155 ' nach rund 808 us den Timer Interrupt auslösen
Enable Timer1
Disable Int0 ' weiter Interrupts durch INT0 unterbinden

Return



Daten_sammeln:
Shift Ir_data , Left
Level = Not Pinb.2 'TSOP gibt invertierte Daten aus, deshalb nochmal inventieren
Ir_data = Ir_data + Level 'eben gelesenes Bit zugeben
Timer1 = 131 ' nach rund 1000us den Timer Interrupt auslösen '
If Ir_data < &B00000100 Then
nop
Else
Disable Timer1 'weitere Interrupts durch Timer1 unterbinden
Set Gifr.intf0 'Interruptflag vom INT0 löschen
Enable Int0
Ir_data_fertig = Ir_data
End If

Return

RoboHolIC
25.01.2014, 00:31
Schau ganz genau im Datenblatt nach: Viele dieser Empfängerbausteine sind nicht für Dauer-Ein spezifiziert sondern brauchen Sendepausen. Das hat irgendwie mit ihrer AGC (automatic gain control) / Arbeitspunkt der Filterschaltung für die Fremdlichtunterdrückung zu tun.

R2D2 Bastler
25.01.2014, 09:46
Hallo RoboHolIC,

das Datenblatt hab ich mir unzählige male durchgeschaut und auch einige Testprogramme probiert, um die "Grenzen" des TSOP auszuloten.
Im Datenblatt steht u.a. "Minimum burst length: 10 cycles/burst" und "After each burst of length a minimum gap time is required of: 10 to 70 cycles, ≥ 10 cycles". Bei einer Trägerfequenz von 36kHz dauert ein cycle rund 27,8 us. Bei meinen angegebenen 500 us komme ich damit auf 18 cycles/burst und liege damit absolut im grünen Bereich.

Beim folgenden Testprogramm macht die Kontroll-LED genau das gleiche, wie die IR-LED (außer natürlich, wenn die optische Verbindung unterbrochen wird, dann bleibt sie aus).



'================================================= ==============================
'IR Kanone V 01
'
'IR-LED an Pin 5 (PB0, OCR0A)
'TSOP34836 an Pin 7 (PB2, INT0)
'
'Pin 6 (PB1 Test-LED)
'================================================= ==============================

$regfile = "attiny45.dat"
$crystal = 8000000 'FuseBit CKDIV8 deaktivieren

$hwstack = 40
$swstack = 40
$framesize = 50


'-------------------------------------------------------------------------------------------------
'Timer konfigurieren
'-------------------------------------------------------------------------------------------------

Config Timer0 = Timer , Prescale = 1 , Compare A = Toggle , Clear Timer = 1 'Timer0 erzeugt 36kHz IR-Trägerfrequenz, Clear Timer setzt Timer bei Erreichen des Comparewertes auf 0 zurueck
Ocr0a = 110


'-------------------------------------------------------------------------------------------------
'Interrupt-Service-Routinen konfigurieren und freigeben
'-------------------------------------------------------------------------------------------------

Config Int0 = Change 'beim Flankenwechsel an PB2/INT0 (Ir_data_in) Int0 auslösen und in die Subroutine springen
Enable Int0
On Int0 Ir_data_in

Enable Interrupts


'-------------------------------------------------------------------------------------------------------------
'Ein- und Ausgang festlegen
'-------------------------------------------------------------------------------------------------------------

Ddrb = &B00010011 'PB0, PB1 und PB4 werden Ausgänge, restlicher PortB bleibt Eingang


'================================================= =====
'Hauptprogramm
'================================================= =====

Do

Ddrb.0 = 1 ' 36 kHz Carrier on
Waitus 500
Ddrb.0 = 0 ' 36 kHz Carrier off
Waitus 500


'Sendepause einlegen
Ddrb.0 = 0
Wait 2


Loop

End


'-------------------------------------------------------------------------------------------------------------
'ISR IR Daten empfangen
'-------------------------------------------------------------------------------------------------------------

Ir_data_in:
If Pinb.2 = 0 Then
Portb.1 = 1
Else
Portb.1 = 0
End If

Return

Die Zahlen habe ich in einem weiten Bereich getestet. Alles über 300 us wird problemlos übertragen (300 us entspricht ca. 10 cycles/burst und deckt sich somit perfekt mit dem Datenblatt). Auch die Sendepause habe ich von 0 (null) bis mehreren Sekunden getestet. Im Code sind 2 sec angegeben, d.h. die Kontroll-LED blitzt alle 2 sec kurz auf.

Ich bin mir daher sicher, dass es nicht am TSOP oder dem gesendeten IR-Signal liegt, da diese Übertragung problemlos klappt. Es scheitert offensichtlich an der Signalauswertung im Programmcode :(

mfg
Robert

Searcher
25.01.2014, 10:33
Hai ;),





'-------------------------------------------------------------------------------------------------------------
'ISR IR Daten empfangen
'-------------------------------------------------------------------------------------------------------------

Ir_data_start:
Ir_data = &B00000001
Timer1 = 155 ' nach rund 808 us den Timer Interrupt auslösen
Enable Timer1
Disable Int0 ' weiter Interrupts durch INT0 unterbinden

Return


Könnte ein Bug hier versteckt liegen?
Zum Zeitpunkt des Ansprungs der "Ir_data_start:" könnte das TOV1 Interruptflag schon gesetzt sein, da der Timer1 läuft. Durch das "Enable Timer1" springt AVR deshalb SOFORT nach Beendigung von "Ir_data_start:" in die "Daten_sammeln:"
Abhilfetest: Nach "Timer1 = 155" ein "set tifr.tov1" (vorsorglich anstehendes TOV1 Flag löschen) einfügen?

Gruß
Searcher

oberallgeier
25.01.2014, 10:39
Hi Robert,

genau wegen der regelmässigen Pflichtpause der TSOPs habe ich die noch nicht verwendet (hab also keine Erfahrung damit), habe aber schon Fernsteuerungen mit ähnlichen, kurzen Sendeprotokollen mit den OSRAM-Empfängern betrieben (Beispiel hier) (https://www.roboternetz.de/community/threads/55430-IR-Fernsteuerung-für-NIKON-Spiegelreflex-(ML-L3-Clone)?highlight=nikon).


... Datenblatt steht ... Bei meinen angegebenen 500 us ... 18 cycles/burst ... im grünen Bereich ...Deine Rechnung kapier ich nicht. Du nennst ein minimales Protokoll von drei Bit, daraus rechne ich mal : drei Pulse (=: Modulation ist on, bursts) zu je min 10 cycles => dreissig cycles, dazwischen zwei Pausen (=: Modulation ist off) zu je min 14 cycles *) => 28 cycles, insgesamt schlappe sechzig cycles von 36 kHz, macht bei mir 1,66666 ms für ein komplettes Telegramm/Kommando. Das ist nahe an 1,8 ms, also meiner Meinung nach schon etwas grenzwertig **). Daher würde ICH das geforderte Gap von 4*60cycles => 6,7 ms nach einem Telegramm einschieben. Keinesfalls aber Dein oben erwähntes:
... (zunächst aber ohne Trigger, nur mit „Dauerfeuer“).... aber das "Dauerfeuer" hast Du ja offenbar schon abgelegt. Allerdings finde ich eben weder Deine 500 ms, noch Deine 18 cycles/burst *grübel*. Vielleicht könntest Du mal ne Skizze machen ?

Zur Theorie der IR-Fernsteuerungen hat übrigens San Bergmans eine prächtige Dokumentation online (http://www.sbprojects.com/knowledge/ir/index.php).



*)
... • After each burst which is between 10 cycles and 70 cycles a gap time of at least 14 cycles is necessary. ...
**)
... • For each burst which is longer than 1.8 ms a corresponding gap time is necessary at some time in the data stream. This gap time should be at least 4 times longer than the burst. ...

R2D2 Bastler
25.01.2014, 12:49
Hallo zusammen,



Abhilfetest: Nach "Timer1 = 155" ein "set tifr.tov1" (vorsorglich anstehendes TOV1 Flag löschen) einfügen?

Du wirst lachen, genau das hatte ich auch schon im Code, allerdings blieb die Kontroll-LED dann aus :-k





aber das "Dauerfeuer" hast Du ja offenbar schon abgelegt.

Hier habe ich mich vermutlich etwas ungeschickt ausgedrückt. "Dauerfeuer" bezog sich lediglich auf die (noch) nicht vorhandene Möglichkeit, das Senden der IR-LED durch die RC-Fernbedienung (die das Flugmodell mittels Funk steuert) zu beinflussen (wenn ich z.B. 1-2 Minuten einfach so durch die Halle fliege und dann beschließe, durch Umlegen eines Schalters an der RC-Fernbedienung, mit meinem "Bordgeschütz" zu feuern). Es bezog sich nicht auf die vom TSOP geforderten Sendepausen.





Vielleicht könntest Du mal ne Skizze machen ?

Gerne. Im Bild sieht man das Signal, welches die IR-Diode sendet, wenn der Code 101 ausgegeben werden soll. Im Anschluß folgt dann noch eine längere Sendepause, aber selbst ohne diese währe nach meinem Wissen der TSOP nicht überfordert (oder habe ich etwas komplett missverstanden :-k)

27323






... • After each burst which is between 10 cycles and 70 cycles a gap time of at least 14 cycles is necessary. ...


Also, die Sätze habe ich in meinem Datenblatt nicht gefunden, benutze dieses hier:
https://www.it-wns.de/data/datenblatt_0000168_1.pdf

Aber auch dann: Ich habe doch bei meinem Code immer mindestens 18 cycles Pause vor dem nächsten Senden. Daran dürfte es nicht liegen.


Ich bin, wie bereits anfangs erwähnt, nicht total auf "meinen" Code fixiert. Ich nehme auch gern jede andere Möglichkeit der Codegestaltung/Übertragung/Auswertung in Kauf. Es sollen lediglich 4 verschiedene Befehle übertragen werden können und keine Wait-Befehle in einer ISR beinhalten, da ich sonst beim weiteren Ausbau des Codes (RC-Signale einlesen etc) Schwierigkeiten bekomme.

mfg
Robert

oberallgeier
25.01.2014, 13:44
... die Sätze habe ich in meinem Datenblatt nicht gefunden, benutze dieses hier ...Gut, beide sind vom Hersteller. Bei Vishay läuft offenbar die Zeit rückwärts. Das Datenblatt bei mir (http://www.farnell.com/datasheets/30492.pdf) ist Rev. 5, 23-Jun-03 - immerhin sieben Seiten, das Datenblatt bei Dir ist Rev. 1.3, 29-Jan-09 - sechs Seiten.

Achtung: Deine logische "1" ist mir nicht logisch (wohl eher falsch). Der Photodetektor geht üblicherweise bei Empfang einiger Modulationspeaks auf low - also ist eine (im Datenblatt definierte) Serie von Peaks eine logische Null - siehe "mein" Datenblatt, Seite 3, links oben. ERST der Wechsel von logisch Eins (Modulation wird erkannt) auf Null in einem bestimmten Zeitraum lässt sich als "Eins" definieren - z.B. beim Manchestercode. Du scheinst da etwas noch zu verwechseln. Schau mal bei den Infos von SB nach (Link ist oben).

R2D2 Bastler
25.01.2014, 14:59
Hallo nochmal,

mit Logisch 1 und 0 , sowie dem Diagramm im Bild meinte ich das, was die IR-LED sendet.
Das mit dem inventierten Signal beim TSOP hab ich gesehen. Deshalb schrieb ich im Programm die erste 1 auch manuell in die Variable "Ir_data"


Ir_data_start:
Ir_data = &B00000001
'Timer1 = 155 ' nach rund 808 us den Timer Interrupt auslösen
Timer1 = 180 ' nach rund 608 us den Timer Interrupt auslösen

Mit unterschiedlichen Timerwerten versuchte ich dann, die zeitliche Abfrage des TSOP so zu timen, dass er sich sicher in einem definierten Zustand befindet (es geht ja auch Zeit für das Springen in die ISRs verloren). Da ein gesendetes high (logisch 1) beim TSOP dann als low ausgegeben wird, habe ich diese Abfrage mit "Not" wieder inventiert, siehe hier


Level = Not Pinb.2


Hier nochmal mein gedankliche Ablauf, wann was passieren "müsste"

27325


Wenn also die IR-LED eine logische 1 sendet, sollte in der Variable "Ir_data" auch eine 1 landen.

Beim Zeichnen des Bildes kam mir allerdings ein Gedanke: Was passiert, wenn der TSOP erst die zweite 1 bemerkt. Dann wäre meine ganze Auswertung im Eimer.
Mann, das "bisschen" IR-Übertragen bringt mich bald ins Grab... :MistPC


mfg
Robert

Searcher
25.01.2014, 17:52
Hallo,

Mann, das "bisschen" IR-Übertrtragen bringt mich bald ins Grab... :MistPC

:-) Hier noch ein Sargnagel :twisted:

Du hattest doch zuletzt ein Programm zum Einlesen und Ausgeben von Servo Signalen auf Tiny45 gemacht. Das hab ich hergenommen und ASM der EmpfangsISR angepaßt und Codeschnipsel für eine IR-Empfangsprogramm draus gemacht. Ging besser als viel Text zu schreiben.

Im Grunde werden Länge von IR Signalpause und IR Signalimpuls vom TSOP gemessen. Die Länge auf Gültigkeit geprüft und einer Auswerteroutine übergeben. Hoffe ist verständlich und es bleibt noch einige Arbeit ...

Wie damit Sender UND Empfänger auf einem µC untergebracht werden ??? Irgendwie einen Timer doppelt verwenden. Geht erstmal nur ums Prinzip.


'================================================= =====
'ISR
'================================================= =====


Rc_eingang_1: 'ISR mit NOSAVE anspringen
$asm
push r17 'Register auf Stack sichern
sbis pinb , 2 'Skip next Instr if PINB.2 = 1
rjmp Puls_ende1 'Springe Puls_ende
in r17 , tcnt1 'Timer1 Wert holen
sts {Rc_signal_1_start} , r17 'Speichere Timer1 nach Rc_signal_1_start

'##### für IR Bitlängenmessung
ldi r17 , 1
sts {Rc_signal_1_start_flag} , r17 'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
'#####

rjmp ende1 'Springe zum Ende
Puls_ende1:
in r17 , tcnt1 'Timer1 Wert holen
sts {Rc_signal_1_stop} , r17 'Speichere Timer1 nach Rc_signal_1_stop
ldi r17 , 1
sts {Rc_signal_1_stop_flag} , r17 'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife
Ende1:
pop r17 'Register vom Stack zurückholen
$end Asm
Return




do '#### Haupschleifenausführung darf nicht länger als eine gültige Bitlänge dauern

If Rc_signal_1_start_flag = 1 Then 'Bearbeitung nur, wenn ISR Pulsanfang gefunden hat
Pausen_laenge_1 = Rc_signal_1_stop - Rc_signal_1_start
Rc_signal_1_start_flag = 0
if Pausen_laenge > 400µs and pausen_laenge < 600µs then 'vorsicht pseudocode
received_bit = 0
received_bit_flag = 1 'Anzeige eines Emfangs eines gültigen Bits
end if
End If

If Rc_signal_1_stop_flag = 1 Then 'Bearbeitung nur, wenn ISR Pulsende gefunden hat
Impuls_laenge_1 = Rc_signal_1_stop - Rc_signal_1_start
Rc_signal_1_stop_flag = 0
if Impuls_laenge > 400µs and Impuls_laenge < 600µs then 'vorsicht pseudocode
received_bit = 1
received_bit_flag = 1 'Anzeige eines Emfangs eines gültigen Bits
end if
End If


if received_bit_flag = 1 then

'### Empfangene Bits (die von "received_bit") aufreihen und auf gültiges bitmuster scannen

received_bit_flag = 0
end if

loop


Gruß
Searcher

oberallgeier
25.01.2014, 18:23
... es geht ja auch Zeit für das Springen in die ISRs verloren ...Das ist jetzt nicht Dein Ernst? Wie langsam tickert denn Dein Controller? Ist das ein tiny13 mit dem internen 128 kHz-Oszillator? Oder noch langsamer?

Im Ernst: bei dem burst von 500 µs (und ohne sonstige Interrupts oder Interrupt-long-run-Kunststücke) kannst Du die Zeit vom Eintritt des Ereignisses bis zum Beginn der ISR bei Takten über 1 Mhz beruhigt erstmal vergessen.

Ich bin nicht sicher, dass Dir klar ist, was am Eingang des Controllers - also am Anschluss des SigOut des TSOP passiert - wenn die irLED mit 36 kHz zum Blinken beginnt - - und wieder aufhört.

a) irLED blinkt nicht (aus, kein irLicht wird abgegeben, die LED ist wirklich dauerdunkel)
....TSOP empfängt nix => SigOut-TSOP ist high

b) irLED blinkt seit drei bis vier 36-kHz-Pulsen
....TSOP empfängt nix => SigOut-TSOP ist high

c) irLED hat zehn oder mehr 36-kHz-Pulse abgeschickt
....Der TSOP hat gemerkt, dass ihm jemand etwas mit der "richtigen" Frequenz zublinkt
....Der TSOP-SigOut geht auf low

d) Die irLED blinkt weiter, sagen wir mal so zehn bis 20 36-kHz-Pulse
....Der TSOP-SigOut bleibt auf low

e) Die irLED ist AUS (blinkt nicht, ist wirklich dauerdunkel) seit drei bis vier 36-kHz-Pulsen
....TSOP empfängt nix => SigOut-TSOP ist trotzdem/noch immer (ein bisschen *gg*) low

f) Die irLED ist weiter aus, sagen wir mal so zehn bis 20 36-kHz-Pulse
....Der TSOP-SigOut geht auf high, weil er längere Zeit keine 36-kHz-Pulse empfängt.

Wenn Dein Programm (ich programmiere C, kann kein Bascom) das berücksichtigt, dann ists ok. Du brauchst nicht unbedingt das/Dein Datenprotokoll einzuhalten, das Du vermutlich bei irgendeinem Code zur Manchesterdekodierung abgeguckt hast!


... Hier nochmal mein gedankliche Ablauf, wann was passieren "müsste" ...
Hier nochmal mein gedankliche Ablauf, wann was passieren "müsste"

Na ja, schon schon, aber ich finde, dass hier Ursache und Wirkung nicht übersichtlich genug dargestellt wird. Passt dieses Diagramm zur obigen Abfolge a) bis f) ?????

PS: bist Du die Theorie der IR-Fernsteuerung schon durchgegangen?

Searcher
25.01.2014, 23:21
Ich bin, wie bereits anfangs erwähnt, nicht total auf "meinen" Code fixiert. Ich nehme auch gern jede andere Möglichkeit der Codegestaltung/Übertragung/Auswertung in Kauf. Es sollen lediglich 4 verschiedene Befehle übertragen werden können und keine Wait-Befehle in einer ISR beinhalten, da ich sonst beim weiteren Ausbau des Codes (RC-Signale einlesen etc) Schwierigkeiten bekomme.

Hallo,
noch ein Sendecodeschnipsel zu der weiter oben erwähnten Zeitmeßmethode und ein "Übertragungscode". Kann aber nicht absehen, ob Dein weiterer Ausbau des Codes im Empfänger nicht die Hauptschleifenlaufzeit zu lang macht:confused:

Startbit ist immer 400µs lang und wird mit Burst übertragen
Ein LOW Datenbit wird mit 600µs Länge übertragen
Ein HIGH Datenbit wird mit 800µs Länge übertragen
Ob Datenbit mit Burst oder Pause übertragen wird, hängt von seiner Stelle in der Sendereihenfolge ab.
Das erste, dritte, also alle ungeraden Datenbits (wenn mit eins zu zählen begonnen wird), wird mit Pause (Gap) übertragen.
Die geraden Datenbits werden mit Burst übertragen.
Bei einer geraden Anzahl zu übertragender Datenbits ist der Carrier zum Schluß also abgeschaltet.
Mit dem Startbit kann synchronisiert werden.
Maximale Rahmenzeit ist incl. Sicherheitszeit zwischen zwei Rahmen 2400µs, min. ist 2000µs

Habe nicht genau ins Datenblatt geschaut bzw nicht getestet; falls die Erholungszeiten und Ansprechzeiten des TSOP nicht eingehalten werden, kann man an den Zeiten natürlich noch was drehen.

Bleibt "nur" noch die Auswerteroutine im Empfänger anzupassen und fehlerhafte Berechnungen der Impulse/Pausen ausschließen, wenn sich lange nichts tut (verstrichene Zeit ist größer 255 Timerticks).



do

Waitus 400 'Sicherheitszeit zwischen zwei Commands

'Startbit (Ir_befehl.2) senden (immer 1)
Ddrb.0 = 1 'carrier on, burst begin
Waitus 400 'Startbit soll 400µs lang sein
Ddrb.0 = 0 'carrier off, burst ende

'erstes Datenbit
Select Case Ir_befehl.1
Case 0 : Waitus 600 'für erstes datenbit=0 bleibt carrier für 600µs off
Case 1 : Waitus 800 'für erstes datenbit=1 bleibt carrier für 800µs off
End Select

'zweites Datenbit
Ddrb.0 = 1 'carrier on, burst begin
Select Case Ir_befehl.0
Case 0 : Waitus 600 'ist zweites datenbit=0 ist carrier für 600µs on
Case 1 : Waitus 800 'ist zweites datenbit=1 ist carrier für 800µs on
End Select
Ddrb.0 = 0 'carrier zum Schluß wieder off, burst ende

loop


Alles noch halbgar:cool:
Gruß
Searcher

oberallgeier
26.01.2014, 00:23
... „Infrarot-Kanone“ für Modellflugzeuge ... Ein Start-Bit und 2 Kommand-Bits ...Mach Dich vielleicht von solchen Formalismen frei. EIN Burst - bei 400 µs Dauer ists ne eins, bei 700 eine zwei, bei tausend ne drei und bei ... Ohne Start, ohne irgendetwas. Small is beautiful (und klein/simpel/schnell ist eine Steigerungsart von sophisticated).

Da Du eh einen GANZEN 45er nimmst, hast Du einen Pinn für die LED, einen für den TSOP und drei für die AUSGABEcode: 0, 1, 2 ... 0 - keine Funktion, 1 bis 4 der Befehlscode, 5 6 nc, 7 Fehlercode. Bleiben Vcc, GND und 1 Pinn als Reserve. Unverschlüsselt gings nicht wirklich, weil Du den /RES nur in Ausnahmefällen als Ausgabepin nutzen wirst (aber mit dem gings natürlich total unverschlüsselt mit vier Ausgabezuständen).

Searcher
26.01.2014, 12:48
Hallo,
habe Dein ursprüngliches Programm nochmal unter die Lupe genommen.



https://www.roboternetz.de/community/images/misc/quote_icon.png Zitat von Searcher https://www.roboternetz.de/community/images/buttons/viewpost-right.png (https://www.roboternetz.de/community/showthread.php?p=593397#post593397)
Abhilfetest: Nach "Timer1 = 155" ein "set tifr.tov1" (vorsorglich anstehendes TOV1 Flag löschen) einfügen?

Du wirst lachen, genau das hatte ich auch schon im Code, allerdings blieb die Kontroll-LED dann aus :-k


Ist auch richtig und muß drinbleiben UND der INT0 Interrupt in der "Daten_sammeln:" ISR wird zu früh enabled. Es könnte je nach übertragenem Bit noch ein rising edge auftreten, da ja in der Mitte eines Bits gepollt wird.

Also das Enable INT0 aus der ISR rausnehmen und in der Sendepause einfügen, wenn sich sicher nichts mehr an INT0 tut. Außerdem sollte das "Ir_data" initialisiert werden. Habe es mit dieser Sendepause mal getestet, allerdings nicht sehr ausgiebig. Geht.


'Sendepause einlegen
Ddrb.0 = 0
Waitus 2000
Set Gifr.intf0
Ir_data = 0
Enable Int0

R2D2 Bastler
26.01.2014, 13:18
Hallo oberallgeier

Danke für Deine ausführliche Darstellung des TSOP Verhaltens. So in etwa habe ich mir es gedacht (auch wenn ich es bei weitem nicht so klar formulieren hätte können) :D
Ich wusste allerdings nicht, dass der TSOP auch nach dem Abschalten des IR-Signals noch einige Zeit auf low bleibt (habe keine Gerätschaften, um das rauszumessen). Bedeutet das also, wenn ich meine IR-Led z.B. 1000us lang senden lasse (≙ 36cycles), dann wird der TSOP auch 1000us auf low gehen (zeitverschoben um die paar cycles, um die der TSOP verspätet dran ist?



Das ist jetzt nicht Dein Ernst? Wie langsam tickert denn Dein Controller? Ist das ein tiny13 mit dem internen 128 kHz-Oszillator? Oder noch langsamer?

Ich habe vor kurzem an einer RC-Baggersteuerung gearbeitet, bei der RC-Signale (1-2ms) eingelesen, bearbeitet und ausgegeben wurden. Hier wurde die "ISR-Register-Speicher-Orgie" von Bascom zum Hauptproblem. Nur mit viel Hilfe aus diesem Forum und ASM konnte es in den Griff bekommen werden (PS: der Attiny lief dort auch mit 8Mhz). Im jetzigen Projekt kommt der RC-Anteil später noch dazu.



Da Du eh einen GANZEN 45er nimmst, hast Du einen Pinn für die LED, einen für den TSOP und drei für die AUSGABEcode: 0, 1, 2 ... 0 - keine Funktion, 1 bis 4 der Befehlscode, 5 6 nc, 7 Fehlercode. Bleiben Vcc, GND und 1 Pinn als Reserve.

Versteh ich jetzt nicht wirklich :confused:
Wie ich bereits zu Beginn geschreiben habe, soll das Teil im Modellflugzeug verbaut werden. Dazu wird der Attiny wie folgt verdrahtet:

1x IR-LED
1x TSOP
1x RC Signal Gas (vom RC-Empfänger) rein
1x RC Signal Gas (zum Motorregler) raus
1x Optional RC Signal (feuern) rein

Damit sind alle Pins (außer VCC, GND und Reset) belegt



@Searcher
Deinen neuen Code muss ich mir noch ein paar mal durchlesen, Du weißt ja, ich "liebe" ASM :---)



Ich werde aber in jede Richtung weiter experimentieren und wieder berichten :cheesy:


mfg
Robert


PS: Die Theorie der IR-Fernsteuerung bin ich durchgegangen, aber es scheiter wohl an der praktischen Umsetzung beim Programmieren :oops:

oberallgeier
26.01.2014, 14:10
... wenn ... IR-Led z.B. 1000us lang senden lasse ... der TSOP auch 1000us auf low gehen ...Klar. MUSS ja so sein, sonst könnte ich nicht die verschieden(st)en Protokolle mit ihren unterschiedlichen high-low-Zyklen verarbeiten.


... aber in jede Richtung weiter experimentieren und wieder berichten ...NEIN, um alles in der Welt nein. Es reicht wenn Du NUR die sinnvollen Richtungen weiter verfolgst. Die Wahrscheinlichkeit dass eine sinnlos erscheindende Richtung das Optiumum oder auch nur einigermassen sinnvoll wird, ist sehr gering, glaub mir.


... RC-Baggersteuerung ... wurde ... "ISR-Register-Speicher-Orgie" von Bascom zum Hauptproblem ...Mal nur so als kurzen Denkansatz: ICH dekodiere meine Codes, vorzugsweise RC-5, NICHT (ääähhhh nur zum Teil) mit einer eigenen ISR. Ich habe in meinen Controllern praktisch immer einen 50 µs-Heartbeat - und die Controller laufen praktisch immer mit 20 MHz (kann doch der 45er tiny auch: DAtenblatt: – ATtiny25/45/85: 0 - 10 MHz @ 2.7 - 5.5V, 0 - 20 MHz @ 4.5 - 5.5V); von dem abgeleitet zeigt mein 1-sek-LED-Toggle korrekt an, dass zumindest diese ISR noch läuft. Eine sehr praktische Funktionsanzeige. DANEBEN nutze ich diesen 20 kHz-Timer als Zeitmesser - - und hole mir IN dieser ISR manchen Pinzustand im Polling. Meine zugehörigen Zeitscheiben heissen tupsi - Timer Unit Per Sensor Interrupt, wurde irgendwann so eingeführt und seither beibehalten.

Auch der Zustand des RC-5-Pinns wird in der Timerroutine abgefragt - und die Zeit für eine "Zustandsperiode" festgehalten. Daneben wird in einer ISR zu einem externen Interrupt (im untenstehenden Code PCINT) der Pinzustand abgefragt, weil ich auf JEDE Zustandsänderung/Flanke triggere. Erfahrungsnachweis: immerhin starte ich mit dieser Routine z.B. in meiner Getränkedose MiniD0 (https://www.roboternetz.de/community/threads/36121-Autonom-in-kleinen-Dosen-R2_D03-Nachfolger-R3D01/page24?p=503279&viewfull=1#post503279) und in meinem WALL R (https://www.roboternetz.de/community/threads/40453-WALL-R-l%C3%A4uft-%28autonomes-Fahrzeug%29?p=385717&viewfull=1#post385717)bestimmte Tasks - im WALL R auch eine Wegfahrsperre !!, in meinem ArchieKopf (http://www.youtube.com/watch?v=Kt4UiEaTicc) ebenfalls Tasks und auch einzelne Funktionsparameter (schneller, langsamer etc).

Langer Rede kurzer Sinn . . . steht im Codebeispiel. Vielleicht kannst Du etwas damit anfangen.


// ================================================== ============================ =
// === Nicht unterbrechbare ISR für timer2, Kanal B !! 20 kHz / 50 µs
ISR(TIMER2_COMPB_vect) // Vektor 11 Progr.addr. $0014
{ //
// SetBit (PORTD, 7);
// - - - - - - - - - - - - - - -
if (Izeit_b) Izeit_b --; //Interrupt-Timer = 1 ... 20 000 ... (1 sec blink)
else Izeit_b = Izthrznt; // in if (Izeit_1 <= Izthrznt)
// - - Ende der eigentlichen Timer2-ISR

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - Zeiten für RC-5-Analyse setzen, RC-5-Analyse in ~mot~/(PCINT2_vect)
if (IsBitSet (RC5prt, RC5pin)) // WENN RC5-pinn high; Encoder empfängt nichts
{ // => zähle Vorstartcounter hoch
// Vorstartcounter wird in IRS(INT2_vect) genullt
RCvorsc ++; // RC-5-Vor-Sequenz-Counter bis 100 hochzählen
if (RCvorsc > 1000) RCvorsc = 1000; // RCvorsc max 1000 tupsi / 50 ms
} // Ende if (RC5prt & (1<<RC5pin))

// - - - - - - - - - - - - - - -
RCbit_zt ++; // Zeit für 1 Codebit 1,778ms, in tupsi 33 .. 38
RCzeit1 ++; // Tupsicounter uint16_t für RC-5-Decoding
RCges_zt ++;
if (RCges_zt >= 490 && RCDECO) // Endemarkierung RC-5-Deco 27Nov2012-15:22
{ // Endeerkennung: Zeitablauf und RCDECO != 0
RCBB = RCDECO; // Datum wird übernommen
RCDCO2 = RCDECO; // Datum sichern zum Dekodieren
RCTold = RCTGGB; // Toggelbit für nächses Lesen sichern
RCTGGB = IsBitSet (RCDECO, 1<<10); // Togglebit lesen + sichern
if ( RCTGGB == RCTold ) RCTums = 0;
else RCTums = 1;
RCDECO = 0; // RCDECOdierungsbyte leeren
} //
if ( RCzeit1 > 2000) // "Reset" Dekodierung bei einer zehntel Sekunde
{ //
// RC5roff = 1; // RC5-read-off, 0 <=> Lesen ist an, 1 <=> aus
RCzeit1 = 0; //
} //

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
return; //
} // Ende ISR(TIMER2_COMPB_vect)
// ================================================== ============================ =


// ================================================== ============================ =
// === INT20/Pin PC4 zum Dekodieren von RC-5 nach folgendem Arbeitsablauf
// - In ~tmr~/ISR(TIMER2.. wird der Vorstartcounter RCvorsc bis 100 hochgetickt
// - Hier wird zuerst das Startbit abgefragt
//
ISR (PCINT2_vect) // ISR für INT20 auf Pin PC4 zum Dekodieren von RC-5
{ //
// - - - - - - - - - - - - - - - -
// Start RC5-Decoding: Level (RC5prt & (1<<RC5pin)) ist low <=> IR-Empfang aktiv !!
// ===== RC-5-DECOding-Byte (RCDECO) ist Null
// RCvorsc >= 99 -- nur dann ist "vorher" länger high
if ((!(RC5prt & (1<<RC5pin))) && (!RCDECO) && (RCvorsc > 99)) //
{ //
RCvorsc = 0; // Vorstartcounter nullen 07. Nov. 2013 11h42
RCges_zt = 18; // ?? Gesamtzeit in tupsi f EINEN kplt CodeSATZ
// hier ein offset, weil ja 1/2 Bit vorbei ist
RCBptr = 13; // RC-5-Code: Bitpointer (0..13) f RC-5-Code-Word
// - - - - - - - - - - - - - - - -
// Hauptaufgabe: Schreibe Bit ins Target
RCDECO |= ((uint16_t)1<<13 ); // Hier wird nur Bit 13 {13..0} gesetzt
RCBptr = 12; // ... und pointer auf nächstes Bit
RCbit_zt = 0; // Zeit für 1 Codebit 1,778ms, in tupsi 33 .. 38
} //
// - - - - - - - - - - - - - - - -
if (RCBptr >= 0) // war : if ((32 < RCbit_zt) && (RCbit_zt < 39))
{ //
if ((RCbit_zt>26) && (RCbit_zt < 60)) // <<## gute Funktion, so bleibts
{ // Ist ein gültiges Bit erkannt worden ?
if (!(RC5prt & (1<<RC5pin))) // High oder low level ?
{ //
RCDECO |= ((uint16_t)1<<RCBptr ); // Bei LOW schreib "1" weg
} // Ende if (!(RC5prt & (1<<RC5pin))) : High oder low
RCBptr -- ; // ... und pointer auf nächstes Bit
RCbit_zt = 0; // Zeit für 1 Codebit 1,778ms, in tupsi 33 .. 38
} // Ende if ((RCbit_zt>26) && (RCbit_zt < 48))
} // Ende if (RCBptr >= 0)
// - - - - - - - - - - - - - - - -
// TESTWEISE Ausgabe Codewort und Zeitbedarf
if ((RCBptr < 0) && (RCges_zt < 1000))
{ //
RCBptr = 0; // doppelte Ausgabe verhindern
} // Ende if (RCBptr < 0)
// - - - - - - - - - - - - - - - -
} // Ende ISR (PCINT2_vect)
// ================================================== ============================ =

ABER - wie schon oben geschrieben - ich vermute dass Du mit der Abfrage der Pulslänge Deines DEKODIERTEN IR-Pulses alleine Deine Steuerung erfüllen könntest.


1x IR-LED
1x TSOP
1x RC Signal Gas (vom RC-Empfänger) rein
1x RC Signal Gas (zum Motorregler) raus
1x Optional RC Signal (feuern) rein

Jaaaaa - so eine Tabelle ist SEHR aussagekräftig. Danke. Dir reicht also eigentlich a) das Durchschleifen des RC-Gas-rein zum RC-Gas-raus UND die Analyse des RC-Signals (und ich denke für eine erste Funktion brauchst Du NUR die Existenz dieses Signals nachzuweisen, ohne Codecontrolle). Und wenn dieses Signal erreicht wird, dann wird eben das RC-Gas-raus für ne bestimmte Zeit auf "wenig Gas" gesetzt. Oder ?!

R2D2 Bastler
26.01.2014, 14:55
@oberallgeier

mit "in jede Richtung" meinte ich natürlich nur sinvolle :mrgreen:

Kann der Attiny 20MHz OHNE Quarz, also intern? Hab persönlich noch nie was darüber gelesen :-k

Ansonsten, Du weißt schon, dass Du programmiertechnisch in Spheren über mir schwebst (ich kann nur sehr begrenzt Bascom, kein C oder ähnliches :oops:)


@Searcher

Hab Deine Änderungen nun auch getestet. Funktioniert leider bei manchen Code-Kombinationen nicht immer.

Senden 100, empfangen 100 -> LED leuchtet ständig
Senden 110, empfangen 100 -> LED leuchtet wenn sie aus sein sollte und umgekehrt
Senden 101, empfangen 100 -> LED leuchtet wenn sie aus sein sollte und umgekehrt
Senden 111, empfangen 110 -> LED leuchtet oft kurz auf,wenn optische Verbindung unterbrochen oder wieder hergestellt wird
Senden 111, empfangen 101 -> LED leuchtet oft kurz auf,wenn optische Verbindung unterbrochen oder wieder hergestellt wird


Ich teste auch mal die Auswertung der Pulslängen, mal sehen, wie genau das wird (es müssen ja nur 4 verschiedene Längen erkannt werden)...

mfg
Robert

oberallgeier
26.01.2014, 16:32
... Kann der Attiny 20MHz OHNE Quarz, also intern ...Kann er nicht, stimmt. Aber da gibts irgendwelche Sonderheiten zu tiny15-Kompatibilität.

Sorry, dass ich Dir nur Hilfen in C gebe. Bascom kann ich nicht.

Searcher
28.01.2014, 13:53
Hallo,

Ich teste auch mal die Auswertung der Pulslängen, mal sehen, wie genau das wird (es müssen ja nur 4 verschiedene Längen erkannt werden)...
da habe ich auch mal exprimentiert und komme immer mehr zu dem Schluß, daß das nicht besonders gut ist:

Zwischenstand mit meinem verwendeten TSOP31236:
Fremdlicht kann erheblichen Einfluß auf die vom TSOP weitergegebenen Pulslängen haben.
Meine Schreibtischleuchtstofflampe hat definitiv erheblichen Einfluß auf die Pulslänge.
Teilweise abgeblendete IR-Sendediode verändert die Pulslänge auch.
Bei meinem noch nicht ganz ausgereiftem und schon kompliziert gewordenem Programm führt das zu Kommandofehlinterpretationen.

Werde jetzt mal versuchen mit Flankenzählung innerhalb einer gewissen Zeitspanne weiterzumachen. Problem finde ich bei der Erkennung von verfälschten Telegrammen - ob man die ganz aussortieren kann:confused:

Gruß
Searcher

RoboHolIC
28.01.2014, 16:40
Fremdlicht kann erheblichen Einfluß auf die vom TSOP weitergegebenen Pulslängen haben.
Meine Schreibtischleuchtstofflampe hat definitiv erheblichen Einfluß auf die Pulslänge.
Was ist denn die Zielsituation bzgl. Beleuchtung? Ein Hallenwettbewerb oder OpenAir? Das Produkt darf auf der Werkbank ruhig Fehlfunktionen haben - nur im realen Einsatzszenario eben nicht.

edit: Ooop, das wurde ja schon ganz am Anfang gesagt: Indoor, also Kunstlicht.


Teilweise abgeblendete IR-Sendediode verändert die Pulslänge auch.
. . . Werde jetzt mal versuchen mit Flankenzählung innerhalb einer gewissen Zeitspanne weiterzumachen.
Klingt erfolgversprechender.

oberallgeier
28.01.2014, 19:27
... TSOP31236 ... Fremdlicht kann erheblichen Einfluß auf die vom TSOP weitergegebenen Pulslängen haben ...Das wundert mich jetzt schon. Ich hatte bei meinen Anwendungen zwar nie TSOPs verwendet - aber soo unterschiedlich können die doch nicht zu den Osram-SFHs sein. Denn bei meinem RC-5-Dekoder ist die Datenübertragung ziemlich gut und sicher, es gibt sehr selten Ausfälle/Störungen. Und der Code ist ja auf relativ genaue Pulslängen angewiesen, sonst gibts sicherlich Fehlinterpretationen.

Ich hatte allerdings deutliche Störungen gefunden durch die LED-Beleuchtung von Bildschirmen (https://www.roboternetz.de/community/attachment.php?attachmentid=12693&d=1218730388) - da gings aber um eine eher "analoge" Auswertung der Photodetektoren - es wurde die Ansprechschwelle des Detektors auf reflektiertes IR-Licht einer gepulsten LED mit variablem duty-cycle bestimmt.


... Ich kämpfe zur Zeit mit den Tücken einer „Infrarot-Kanone“ für Modellflugzeuge (indoor) ...Meine autonomen Dosen und mein WALL R fahren fast nur indoor, da müsste ich bei massiven Einflüssen durch Kunstlicht doch auffällig viele Störungen feststellen. Wie geschrieben, Fehlfunktionen sind bei mir die Ausnahme - und das bei mittlerweile vielen verschiedenen Beleuchtungssituationen.

Searcher
28.01.2014, 20:50
Na ja, ausprobiert auf einem Steckbrett.
Spannung am µC (Tiny45) 5V aus stabilisiertem Steckernetzteil.
Am Ausgang des TSOPs (Beschaltung mit 100 Ohm von +5V nach VS und 100nF zwischen Vs und GND) ein Oszi.
Im Abstand von ca. 5cm eine IR LED mit 1 kOhm Vorwiderstand am µC Ausgang.

Gestern Abend mit Leuchtstoffbeleuchtung immer sporadische Fehler bei der Datenerkennung.
Heute morgen bei Tageslicht praktisch fehlerfrei. Lampe an - Fehler häuften sich.
Oszi zeigt selten aber doch in abwartbaren Abständen echte Einbrüche bei der Signaldauer - Sender taktet jede Sekunde 400µs Burst, 800µs Gap, 800µs Burst, Gap bis zur nächsten Serie. Vor allen Dingen der erste Burst wird verzerrt ausgewertet.

Vermute den AGC als Ursache. Habe dann noch mit Abdunkeln und "normalem" Fremdlicht gespielt. Ausreißer waren nicht gewollt reproduzierbar aber schon auf die Lichtspielereien zurückzuführen.

Mal sehen, was noch zu Tage tritt und ob die Fehler vernachlässigbar sind ... Dazu muß aber erstmal Ordnung ins Empfangsprogramm ...

Gruß
Searcher