IR-Decoder - universell

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • IR-Decoder - universell

      Bezunehmen möchte ich auf einen anderen Thread - ist zwar schon ein paar Tage alt, aber es passt nahtlos: Für
      den Einsatz diverser IR-FB‘s baue ich gerade an einem (relativ) universellen Decoder. Von diesen „Technik-Leichen“ habe ich einige (20?) rumliegen...

      Ziel ist es, mit ein paar Bytes Anpassung weitere Protokolle hinzuzufügen und das Ganze auch für einfache 433MHz Module einzusetzen.
      Wenn es halbwegs als Alpha-Version fertig ist stelle ich es hier ein.Verwendet wird ein Timer (läuft durch) und ein Pin Change Interrupt, an dem der TSOP hängt. Implementiert habe ich den ersten Teil als State Machine, weil der IR-Sensor massig Störungeneinsammelt - vor allem von Leuchtstoffröhren (alte Tischleuchte).Gedimmte LED-Streifen (ca. 2kHz) stören dagegen wenig.
      Der ganze Kram soll in eine Datei gepackt werden, mit mäßigemSpeicherkonsum (ca. 50Byte RAM und <2kB ROM) auskommen und den
      Programmablauf in der Main Loop wenig stören - die ISR braucht bei 8MHzunter 15 Mikrosekunden.

      Muss noch viel optimiert und entwanzt werden.

      Wollte das Ganze für die indirekte Beleuchtung mit Dimmer einsetzen, die meisten unserer FB‘s können mehrere Geräte ansprechen (DVD, BR,
      Videorecorder, ...).

      Das zugeschnittene Code-Schnippseln ist mir zu umständlich geworden...

      Hier ein Zwischenstand - Mitgeschnitten an der seriellen Ausgabe (zum Debuggen), dabei ist die Ausgabe der 1. Zeile so zu Lesen:
      P2 = Protokoll Nr.2 (NEC)
      77 = Messwert 1. Bitphase (Licht)
      59 = Messwert 2. Bitphase (Dunkel)
      53 = untere Messtoleranz für den letzten Messwert
      67 = obere Messtoleranz für den letzten Messwert
      32 = Anzahl Bits
      010111... ist das dekodierte Signal ohne Deutung

      Die Idee ist, dass übliche Formate (IR-Sender, 433 MHz Funk) erkannt werden - also Signale mit Synchronimpuls, Manchester codierte, Bitstrom.
      Dazu werden Angaben als Liste im EPROM hinterlegt, inkl. Anzahl zu erkennender Bits und Messtoleranzen.
      Mit der "kleinen Lösung" kann ich dann unabhängig von den im Netz kursierenden (und meist in C geschriebenen) Lösungen die vorhandenen Tiny's und uralten AT90S-Typen verbauen (hab' noch viele ;( ).
      Dateien
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Und wenn im Protokoll eine 2 auftaucht, dann ist es ein Bitfehler und die Messung wird verworfen.

      Gebaut habe ich das Ganze als (Pseudo-) State-Machine, wobei in der ISR nix passiert außer Messwert lesen, der Rest danach. Bei gängigen MC's bei 8-16 MHz liegt zwischen den Pulsen eine Zeit von 100-1.000 μs. Da geht schon einiges zwischendurch zu erledigen.

      Zum Auslösen wird ein maskierter Pin Change Interrupt bemüht. Die Besonderheiten bei der Interrupt-Priorisierung möge jeder selbst in seinen Projekten beachten.
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Das „Pseudo“ habe ich davor gepackt, weil ich mir nicht sicher bin ob tatsächlich alle Zustände vorhersehbar und implementiert sind. Die Grundzüge sind jedenfalls da... Und offenbar ist es für Dich @Mitch keine Neuigkeit (Vermutung).

      Den Schnipsel stelle ich ein sobald ich wieder daheim bin, versprochen.

      Es ist halt so, dass der Manchester Teil noch reingepfriemelt werden muss, und das dauert noch. Mehrere Baustellen offen zu haben ist nicht meins. Im Beispiel sind auch noch nicht alle Variablen bereinigt und einheitlich mit Namen versehen.

      Refactoring mache ich nach der Alpha-Version.

      Aber vielleicht macht das sogar Sinn alles so „roh“ reinzuschmeißen , weil dann die vielen Köpfe optimieren und eigene Wege beschreiten können...
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • monkye schrieb:

      Das „Pseudo“ habe ich davor gepackt, weil ich mir nicht sicher bin ob tatsächlich alle Zustände vorhersehbar und implementiert sind.
      Was meinst du mit vorhersehbar?

      Bei einer Statemachine legst du ja selbst die möglichen Zustände fest. Der Controller kann dann immer nur in einem dieser definierten Zustände sein. Unvorhergesehene Zustände kann es da nicht geben.

      Oder meinst du, dass du vielleicht noch zusätzliche Zustände benötigst, die bisher noch nicht definiert sind?
      Oft entscheidet sich beim Programmieren, ob ein zusätzlicher Zustand sinnvoll ist oder nicht.

      Pseude-Statemachinen kann es nicht geben. Genauso wenig kann man ein bischen schwanger sein. Entweder man ist es oder eben nicht.

      Also es ist entweder eine Statemachine (selbst wenn noch nicht alle Zustände festgelegt sind), oder eben nicht.

      Bin auf dein Codeschnipsel gespannt.
      Kaum macht man es richtig - und schon geht's!
    • Hallo monkye,
      interessante Aufgabe, die du dir da vorgenommen hast.
      Habe ich auch schon mal drüber nachgedacht, aber bis jetzt immer zurückgestellt.

      Wenn du wirklich einen universellen Empfänger machen willst, dann wäre es meiner Meinung nach wichtig, dass dein Programm möglichst einfach auf die jeweilige Hardware angepasst werden kann.
      Sprich verschiedene Controller und Frequenzen. Häufig ist es nämlich recht aufwendig, solche Codes auf eine andere Quarzfrequenz unzupassen. Das wäre auch so, wenn du die Längen der Impulse im EEPROM abspeicherst. Wenn man dann den Quarz ändert, müssten entweder alle Werte angepasst werden oder die Timerkonfiguration ensprechend angepasst werden, was aber nur in Grenzen möglich ist.
      Kannst du ja mal überlegen, ob du das implementieren kannst/willst.

      Ich würde natürlich auch gerne mithelfen, wenn ich von deiner Arbeit partizipieren kann.
    • Spielversion 1:
      - Protokoll-Def.:
      1. Umrechnung Ticks bei "IrProtocol" Daten noch nicht berücksichtigt
      2. Struktur noch nicht für Pre-Bit, Stop-Bit, 4-Phasen-Bit angepasst
      - Manchester fehlt
      - Variablen noch nicht einheitlich
      - nicht optimiert für Speicherverbrauch

      Dazu ein Stück Code zum Aufzeichnen der Impulsfolgen (Measurement). Das Ergebnis des Empfangs habe ich mit HyperTerm aufgezeichnet (Menüpunkt Transfer-->Capture Text...).
      Dateien
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • In der Mainloop gibt es einen IF-THEN Block, der prüft auf das Status-Word. IRStatusH enthält die Zustände:
      - Messung gestartet
      - 1 Impulsphase erkannt
      - 2 Impulsphase erkannt
      - 3 Protokoll erkannt

      Und IRStatusL enthält den Bitphasenzähler, also aktuell maximal 128 Bit. Da über den Sensoranschluss klar ist ob das Signal H/L aktiv ist, lässt sich jede Phase erkennen/messen. Die Polarität sollte auch noch mit rein, aber erst wenn das Konstrukt zufriedenstellend läuft.

      Ach ja, die ISR ist noch die ungekürzte Version, das geht noch ein bissel schneller (nicht unbedingt kürzer).
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Ich muss dir recht geben, ist doch keine Statemachine.

      In einer Statemachine gibt es eine Variable, die den Zustand des Automaten enthält.
      Zustände werden definiert z.B. mit Constanten.

      Der Zustand muss irgendwo gesetzt werden (Zustand = neuer Zustand) und dann auf abgefragt werden, um abhängig davon Code auszuführen.

      Was du hast ist ein Statusbyte des Empfängers, der dich über etwas Informiert.
      Das ist nicht das gleiche wie ein Zustand eines Automat.

      Lese dir mal den Eintrag im Lexikon durch "Statemachine" durch.
      Dann wird dir der Unterschied bestimmt klar sein.

      An deinem Programmierstyle erkenne ich dass Potenzial in dir steckt.
      Mit dem Verständnis der Statemachine lassen sich noch ganz andere Projekte realisieren.
      Kaum macht man es richtig - und schon geht's!
    • Mitch64 schrieb:

      Der Zustand muss irgendwo gesetzt werden (Zustand = neuer Zustand) und dann auf abgefragt werden, um abhängig davon Code auszuführen.

      Was du hast ist ein Statusbyte des Empfängers, der dich über etwas Informiert.
      Das ist nicht das gleiche wie ein Zustand eines Automat.
      Der Zustand wird ja klar benannt, im Status-Word (Stichwort Speicher sparen, Performance). Das macht ja den Geschwindigkeitsvorteil aus:
      Wenn ich den Zustand "Protokoll erkannt" (IRStatusH.6 = 1) erreicht habe, dann müssen danach die Bits gelesen werden. In welchem Fertigstellungsgrad das Einlesen der Nachricht ist, beinhaltet IRStatusL - da gibt es nur eine Richtung (Bit 0, 1, 2, ... Bit n) und endet mit dem Zustand "IR-Code gültig". Genauso führt ein ungültiges Messergebnis eines Bits klar zum Verwerfen der Nachricht und der Rückkehr in den Ausgangszustand.

      Der Code Ausschnitt zeigt die Flussrichtung und die Zustandsänderung:

      BASCOM-Quellcode

      1. ' Protokoll erkannt
      2. IF PPointer1 = PPointer2 THEN
      3. IRStatusH.6 = 1
      4. IRStatusH = IRStatusH OR PPointer1
      5. ' Anzahl Bits lesen
      6. bTmp = 7
      7. CALL GetProtocol(PPointer1,bTmp)
      8. END IF
      9. IcpIdx = 0
      10. ELSE
      11. ' SYNC abgeschlossen - Biterkennung
      12. IF IRStatusH.6 = 1 THEN
      Alles anzeigen
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Ein Zustand wird nicht bitweise interpretiert. Was du hast ist ein Statusbyte.

      In deinem Programm kannst du das zwar verwenden, om den Empfang zu steuern.
      Es ist aber kein automat.

      In einem Automat wäre dein Statusbyte des Empfängers eher ein Ereignis oder Kriterium, den Zustand deines Automaten zu wechseln.

      Schau dir mal die Programmstruktur an von einer Statemachine (Lexikon).

      BASCOM-Quellcode

      1. Dim ZustandDesAutomaten as Byte ' Variablem de den Zustand des Automaten aufnimmt.
      2. Const ZUSTAND_A=0
      3. Const ZUSTAND_B=1
      4. Const ZUSTAND_C=2
      5. ZustandDesAutomaten=ZUSTAND_A ' Ein Automat beginnt immer mit einem definierten Zustand
      6. Do
      7. Select Case ZustandDesAutomaten
      8. Case ZUSTAND_A
      9. ' Hier ist Code, der bei ZUSTAND_A ausgeführt wird
      10. ' Prüfen auf Ereignisse, die den Zustand ändern
      11. If Enpfang.0=1 then ZustandDesAutomaten=ZUSTAND_B
      12. Case ZUSTAND_B
      13. ' Hier ist Code, der bei ZUSTAND_B ausgeführt wird
      14. Case ZUSTAND_C
      15. ' Hier ist Code, der bei ZUSTAND_C ausgeführt wird
      16. End Select
      17. Loop
      Alles anzeigen
      So sieht die Struktur eines Automaten aus.

      Deine Abfrage des Empfangsstasus-Byte wären Ereignisse (Bedingungen bzw. Kriterien), den Zustand zu wechseln.

      Unterschied verstanden?
      Kaum macht man es richtig - und schon geht's!
    • Meinst Du das so:

      Quellcode

      1. IRStatus_Messung_Gestartet = 128 ;
      2. IRStatus_Messung_Synchron_1 = 130 ;
      3. IRStatus_Messung_Synchron_2 = 131 ;
      4. IRStatus_Messung_Protokoll_Erkannt = 195 ;
      5. IRStatus_Messung_Protokoll_Benannt = 197 ;
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Nein so meine ich das nicht.

      Wenn ich das als Statemachine machen wollte würde ich Zustände definieren wie

      BASCOM-Quellcode

      1. ' Etwa so
      2. Const ST_WARTE_AUF_SIGNAL = 0
      3. Const ST_SIGNAL_EMPFANG = 1
      4. Const ST_EMPFANG_KOMPLETT = 2
      Dein Statusbyte sagt nur aus, in welchen Zustand dann zu wechseln ist.

      In den unterschiedlichen Zuständen wird dann unterschiedlicher Code ausgeführt.

      Bei Zustand Werte_auf_Signal prüfst du nur, ob etwas kommt, und wenn ja, dann wechselst du in Zustand Signal_Empfang. Dort kannst du z.b. ein LED einschalten um Empfang anzuzeigen.

      Da prüfst du, ob der Empfang fertig ist, wenn ja, dann wird in Empfang_Komplett gewechselt.
      Dort wird dann was mit dem Empfangenen Daten angestellt. Ist das Erledigt, wird wieder in Zustand Warte_auf_Signal gewechselt.

      Aber das macht in deinem IR-Dingens keinen wirklichen Sinn, weil da groß nichts getan werden muss.

      Anders sieht es aus, wenn deine Steuerung komplex wird.

      Nimm ein Getränkeautomat, den stellst du dir in dein Zimmer.
      Deine Freunde müssen Geld einwerfen, wenn die was zu Trinken rauslassen wollen.

      Da du aber die Formware für das Teil selbst geschrieben hast (vielleicht irgend wann mal), hast du einen IR-Empfänger eingebaut. Über den kannst du ein Getränk ohne Geldeinwurf auswählen und raus lassen.

      Dann sind einige der Zustände des Automaten (Geldautomat)
      Warten auf Geldeinwurf
      Wenn genug Geld eingeworfen wurde kann Getränk ausgewählt werden.
      Wenn Getränk ausgegeben wurde, geht Automat wieder in Warte auf Geldeinwurf.

      Es fehlen natürlich noch Zustände für Geldrückgabe bei Abbruch, Wechselgeltausgabe, Fehlerbehandung etc.

      Mit Fernbedienung kannst du nun von Warten auf Geldeinwurd direkt nach Getränkeauswahl wechseln und per Fernbedienung das Getränk wählen.

      Oder du könntest die Preise der Getränke ändern.

      Damit ist dein Statusbyte des IR-Empfängers nichts weiter als ein Ereignis, auf den der Automat reagiert.
      Es ist also nicht der Zustand des Automaten.

      War das verständlich?
      Kaum macht man es richtig - und schon geht's!
    • Mitch64 schrieb:

      Dein Statusbyte sagt nur aus, in welchen Zustand dann zu wechseln ist.
      Tut mir Leid, dann bin ich halt an der Stelle unterbelichtet... Aus meiner Sicht habe ich nur keine Konstanten im Kopfbereich definiert und zwei Sachen vermischt. Die Protokollnr. kann ich ja noch "entsorgen" aus dem Status - dann kann man aus dem Status ganz klar den Zustand ableiten.

      So im Nachgang betrachtet spart das vielleicht ein paar Byte, aber im Nachgang muss ich Logik-Operationen anwenden die wieder Speicher fressen...
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Wenn dein Code läuft lass es wie es ist.
      Don't touch a running system!

      Für eines deiner nächsten Projekte solltest du mal im Lexikon den Zustandsautomat (Statemachine) studieren.

      Es ist nicht schwer. Man muss nur bissel umdenken.

      Damit eröffnet sich aber eine neue Welt an Möglichkeiten.

      In deinem Programm macht es wirklich keinen Sinn, das als Statemachine umzuschreiben.

      Das ist wie beim Hausflurschalter. Da lohnt der Aufwand nicht für eine Statemachine.
      Taster drücken, licht geht an. Taster wieder drücken, licht geht aus.

      Wenn du mal ein Projekt vor hast, lasse es mich wissen.

      Ich gebe dir gerne ein paar Tips. Dann wird es klar für dich.
      Kaum macht man es richtig - und schon geht's!