Hallo!
Ich habe einen TSOP1736 an einen Atmega32 am externen Interrupt
angeschlossen. Ich möchte nun das Signal mit dem µC auswerten. Doch das
klappt irgendwie bei mir nicht. Kann mir bitte irgendjemand helfen und
sagen was ich falsch mache, ich bin hier schon am verzweifeln :(
lg
Vali
Ja Interrupt wird ausgelöst, aber der Code wird irgendwie nicht richtig
eingelesen. Ich habe die Vermutung das irgendetwas mit dem Timing nicht
stimmt, aber ich weiß echt nicht mehr weiter :(
lg
Versuche mal mit eigenen Worten zu beschreiben, was das Programm machen
soll. Dann kann man feststellen, ob die Logik dahinter richtig ist und
dann prüfen, ob es richtig umgesetzt wurde.
Z.B.
Interrupt wird bei fallender Flanke ausgelöst. Oder Interrupt wird bei
Level LOW ausgelöst und dann gesperrt.
Wenn ein Interrupt ausgelöst wurde, wird x Millisekunden lang alle y
Millisekunden (gesteuert durch Timer) der Pinzustand gepollt.
Aus dem gepollten Pinzustand wird abgeleitet, ob ein Bit 1 oder ein Bit
0 empfangen wurde.
Wenn nach x Millisekunden kein Levelwechsel am Pin stattgefunden hat,
wird das vermeintliche Bit oder die Bitfolge bisher verworfen.
Wenn 14 Bits eingelesen wurden ist, wird das Kommando abgeschlossen.
Ok gg
Also sobald am INT0 eingang eine negative flanke erkannt wird wird der
Timer gestartet und der externe Interrupt deaktiviert. Der Timer
arbeitet ohne Vorteiler bei 1MHz, also meiner Meinung nach löst er mit
dem Vorladewert 128, alle 127µs einen Timer Overflow Interrupt aus.
Als ersten wert für das Code Array wird 1 eingelesen da dieser wert
sowieso immer 1 ist. Danach wird 889µs gewartet (sprich 7x Timer
Overflow) und der nächste Wert eingelesen. Danach wird 1778µs
(Periodendauer) gewartet um den nächsten Wert einzulesen. Sobald der
Code fertig eingelesen ist, geht das Programm weiter zur Auswertung.
Hier werden die einzelnen Werte in den Arrays in eine einzige Variable
(code) vom typ unsigned integer geschrieben.
Danach wird der Wert dieser Variable noch aufs LCD ausgegebn.
Hier wird der externe Interrupt wieder aktiviert. Und das ganze beginnt
wieder von vorne.
lg
Vali H. wrote:
> Also sobald am INT0 eingang eine negative flanke erkannt wird wird der> Timer gestartet und der externe Interrupt deaktiviert.
Dann bist du in der 2. Hälfte des 1. Startbits.
> Der Timer> arbeitet ohne Vorteiler bei 1MHz, also meiner Meinung nach löst er mit> dem Vorladewert 128, alle 127µs einen Timer Overflow Interrupt aus.
Ok.
> Als ersten wert für das Code Array wird 1 eingelesen da dieser wert> sowieso immer 1 ist.> Danach wird 889µs gewartet (sprich 7x Timer> Overflow)
Also die 2. Hälfte vom 1. Bit.
> und der nächste Wert eingelesen.
Das wäre das 2. Startbit
> Danach wird 1778µs> (Periodendauer) gewartet um den nächsten Wert einzulesen.> Sobald der> Code fertig eingelesen ist,
Das entscheidet was? 14 Bits insgesamt gelesen?
> geht das Programm weiter zur Auswertung.> Hier werden die einzelnen Werte in den Arrays in eine einzige Variable> (code) vom typ unsigned integer geschrieben.> Danach wird der Wert dieser Variable noch aufs LCD ausgegebn.> Hier wird der externe Interrupt wieder aktiviert. Und das ganze beginnt> wieder von vorne.
Die Idee ist so OK. Die Idee kann ich im Sourcecode so aber nicht
nachvollziehen. Die einzelnen Schritte kommen mir dort etwas konfus vor.
Aus dem Bauch raus würde ich sowas erwarten (ungestestet!)
Danke für deine Bemühungen :)
Dein Source sieht schon mal viel übersichtlicher als meiner aus. gg
Habe das ganze jetzt mal ander Hardware getestet. Aber da wird bei mir
wenn ich "1" auf der Fernbedienung drücke am Display 25484 angezeigt.
Was einem Wert von 110001110001100b entspricht. Laut Oszilloskop müsste
aber ein Wert von 11000000000001b rauskommen (oszi-bild im anhang). Ich
weiß aber nicht wo der Fehler liegt. Der Source von stefan sieht meiner
meinung nach richtig aus.
lg
Das Pollen ist derzeit ja zu Beginn des zweiten Halbbits und zwar sehr
knapp an der Flanke in der Mitte des Bits. Und die Bits kommen in natura
vielleicht nicht so exakt...
Du könntest mehr in der Mitte des zweiten Halbbits pollen. Dazu könntest
du die Zeit nach dem INT0 etwas verlängern, also z.B. statt wartezeit=7
wartezeit=4 in der INT0 ISR benutzen und damit den nächsten
Pollzeitpunkt um 3 * 127µs weiter Richtung die Mitte des zweiten
Halbbits verschieben.
Oder mehrfach im zweiten Halbbit pollen und den mehrfach vorkommenden
Wert nehmen.
Ich habe das mit dem pollen weiter in der halbbit mitte probiert. Führt
leider irgendwie nicht zum gewünschten ergebnis. Aber ich hab noch eine
frage wieso wird in dem Block
1
if(wartezeit>=13)// 1 Bit = 14 * 127 µs gewartet?
2
{
3
anzahl_bits++;
4
code_B[anzahl_bits]=(PIND&(1<<PD2));// Bit pollen
5
wartezeit=0;// nächste Wartezeit beginnt
6
}
die wartezeit auf größer gleich 13 abgefragt und nicht 14?
Weil sobald wartezeit den wert 1 erreicht sind 127µs vergangen, bei 2
127µs usw. also folglich bei 14 sind es 1778µs oder bin ich mit dieser
Annahme falsch unterwegs?
lg
Hmm, hast Recht! Das Ergebnis vom Einlesen und das Oszibild passt auch
zu dem Fehler.
wartezeit startet bei 0. Wenn die Timer ISR 1x gelaufen ist, hat
wartezeit den Wert 1. Wenn wartezeit 2x gelaufen ist, hat wartezeit den
Wert 2... Wenn wartezeit 14x gelaufen ist, hat wartezeit den Wert 14!
Kontrolle des anderen Zählers anzahl_bits. Wenn zwei Bits gespeichert
wurden, hat anzahl_bits den Wert 1, Wenn 3 Bits gespeichert wurden 2...
wenn 14 Bits gespeichert wurden 13.
Ich würde aber trotzdem eher in der Mitte Pollen.
Also ich habe jetzt versucht eher in der Mitte des zweiten Halbbits
abzufragen. Daher habe ich wartezeit mal auf 6 gesetzt ( bedeutet ja um
127µs weiter in der mitte). Die Abfrage zum einlesen des Port Status
wird nun erst nach 14 Timer Overflows ausgelöst. Nun ist mir aufgefallen
das sich im Code Bereich die beiden letzten beiden Bits (Bit 13 und
Bit14), egal welche Taste gedrückt wird, nicht ändern. Dies würde ja
bedeuten dass die gesamte Routine zu lange dauert und Bit 13 und 14 das
Idle Signal des Tsop enthalten. Irgendetwas stimmt bei den ganzen Zeiten
nicht. Aber ich weiß einfach nicht was falsch sein soll ?!
mfg
Wenn du magst, schau dir meine Änderungen an.
Ich habe da weitergemacht, weil mich deine Rechenvorschrift (1. INT dann
2. Pollen über Timer) interessiert hat.
Nicht erschrecken, wenn du anfangs nur noch wenig wiedererkennst ;-) Die
Änderungen sind:
1/ Umstellung von Atmega32 auf Attiny2313
Weil ich letzteren derzeit im Pollin Funk AVR Board habe. Anschluss TSOP
auch an PD2 siehe auch
http://www.mikrocontroller.net/articles/Pollin_Funk-AVR-Evaluationsboard#RC5_Empf.C3.A4nger
Den Atmega32 Code habe ich mitgeführt und fehlerfrei kompiliert aber
nicht auf einem Atmega32 getestet.
Das 14 Byte Array ist Verschwendung auf einem µC. Man kann das (und
würde in der Praxis bestimmt auch) durch eine 16-Bitvariable ersetzen
und gleich die gepollten Bits reinodern. Ich habe das Array drin
gelassen, um nicht zuviel zu ändern.
2/ Änderung wo gepollt wird
Das Pollen habe ich in die Timer ISR geschafft. Das Pollen ist
"zeitkritisch" und hat - vom Bauch her - im Userprogramm nichts zu
suchen.
3/ Änderung des Timer Modus
Das manuelle Nachladen von TCNT0 habe ich ersetzt. Dazu eignet sicg der
CTC Modus, weil der automatisch nachlädt.
4/ Änderung der Ausgabe
Ich habe derzeit kein LCD angeschlossen. Die bequemste Ausgabe ist für
mich UART. Mein Attiny2313 hat 8 MHz extern und ich kann 9600/8N1
ausgeben. Für den 1 MHz Atmega32 bin ich mit der Baudrate auf 2400
runter - hoffentlich klappt das ohne Quarz,
5/ Einführung eines DEBUG Modus
Klingt mehr als es ist - es sind einfach 2 Outputpins (PD5 und PD6).
Einer wird beim Eintreten der Timer ISR getoggelt und einer wird kurz
HIGH gezogen, wenn der PD3 gepollt wird. Damit sieht man im
Logikanalysator, wann gepollt wird (3 Spuren: PD2, PD5 und PD6). Wenn es
nicht klar wird, kann ich einen Screenshot machen.
6/ Löschen des INTF0 Flags vorm Enable des INT0
Es scheint so, dass das dieses Flag nicht automatisch gelöscht wird,
wenn INT0 in seiner ISR disabled wird. Vielleicht weiss da jemand
genaueres? Ich wollte da noch nachsehen, bin aber noch nicht dazu
gekommen.
Vielen herzlichen Dank für deine Bemühungen :)
Der Code wird nun richtig angezeigt. Aber ein Problem ist nun
aufgetreten, welches bei mir zu hause nicht war. Da ich das ganze jetzt
in der Schule ausprobiert habe ist mir aufgefallen das dass Programm
auch auf irgendwelche Störeinflüsse aus der Umgebung reagiert und
dadurch irgendwelchen nonsense ausgibt. Jetzt müsste ich noch eine
Funktion einbauen die überprüft ob es sich wirklich um RC5 handelt. Wie
realisier ich so etwas am besten?
lg
Genau das ist ein Knackpunkt an der einfachen Rechenvorschrift ;-)
Irgendwas triggert INT0 und dann werden timergesteuert "stur" 14-Bits
gepollt und das soll dann ein RC5 Datagramm sein.
Bei dieser Rechenvorschrift (es gibt andere) kann man mehrere Sachen
machen, um das empfangene Datagramm gültig/ungültig zu markieren
z.B. prüfen, ob die Halbbits korrekt kommen. RC5 ist biphasig, d.h. ein
Bit wird durch zwei Pegel definiert. Statt wie jetzt ein Halbbit (das
erste) für das Gesamtbit zu pollen, kann man beide Halbbits pollen und
nur wenn ein Wechsel stattgefunden hat dann das Bit und damit die
14-Bitfolge gültig erklären.
Technisch könnte man das so machen, dass jetzt zusätzlich im 2. Halbbit
gepollt wird (wartezeit == 7 => Halbbit-2, wartezeit == 14 =>
Halbbit-1). steckt man das Polling bitweise in Variablen, kann man nach
14-Bits die beiden Pollwerte miteinander exklusiv verodern und wenn
dabei 0 sind die Wechsel OK.
Ok vielen Dank. Werde das bei nächster gelegenheit mal ändern.
Vielen Dank für die ganze Hilfe hat mir wirklich sehr geholfen. Ich wäre
da wohl noch einige Stunden gesessen.
lg