====== Raspberry Pi - IR Remote ON/OFF ====== ===== Anforderungen ===== Ob wirklich alle Anforderungen umgesetzt werden können steht noch nicht fest. * Stromversorgung für den Raspberry Pi muss Ein- und Ausschaltbar sein. * Steuerung über Fernbedienung und Taster. * Das IR-Signal muss auch an den Raspberry Pi übertragen werden (Media-Center Steuerung). * Wenn der Raspberry Pi heruntergefahren wird sollte, wenn er heruntergefahren ist, die Stromversorgung ausgeschaltet werden. * Kleiner Aufbau! Wenn möglich IR-Empfänger und Taster über Kabel und Stiftleiste anschließbar. * Art der IR-Signal Codierung und IR-Code einstellbar (RCA / RC5). * LED zur Anzeige ob An/Aus. ==== zu Beachten / Nice to have ==== * Verwendung des PIC12F683 (vorhanden, klein, unter Linux Programmierbar) * Programmierung des PIC in C, nicht in Assembler (Einarbeitung für größere Projekte) * Ausschließliche Verwendung von OpenSource Software * gputils (gpasm, gplink) * sdcc (small device c compiler) * piklab (IDE für PICs unter Linux) * kicad (Schaltplan und Layout Software) * Stromverbrauch der Schaltung sollte gering sein (sleep nutzen) * Übertragungsfehler im IR-Signal sollten erkannt werden. * Automatische Erkennung von RCA und RC5 * Die IR-Codes (Tasten) sollten ohne den PIC neu zu Programmieren änderbar sein. * RCA und RC5 Codes zum Ein-/Ausschalten im EEProm sichern * Updates der Codes wenn z.B. der Taster > 8s betätigt wurde. * - Taster >8s --> IR-Code aufnehmen. * - 1. "STOP"-Taste * - 2. "SELECT"-Taste * - 3. "POWER"-Taste * - [4. "ANZAHL der STOP-Codes" (STOP so oft betätigen wie es zum einschalten genutzt werden soll) (Default: 2 (z.B. bei "Skip"))] ((eventuelle Erweiterung)) * - [5. "ANZAHL der STOP-Codes" (STOP so oft betätigen wie es zum ausschalten genutzt werden soll) (Default: 4 (z.B. bei "Skip"))] ((eventuelle Erweiterung)) * - [6. "ANZAHL der POWER-Codes" (POWER so oft betätigen wie es zum Ein-/Ausschalten genutzt werden soll) (Default: 1 (z.B. bei "Skip"))] ((eventuelle Erweiterung)) * Entscheidung ob RCA oder RC5 gespeichert wird innerhalb des PICs treffen * Wenn ein Code nicht gespeichert werden soll (z.B. keine "POWER"-Taste vorhanden) sollte dieser Abschnitt durch ein kurzes betätigen des Tasters übersprungen werden können. * Anzeige über LED ob CODE richtig entgegen genommen wurde. * und durch Blinken anzeigen welcher Code gerade eingegeben werden soll. (1-3 mal Blinken, dann ca. 3 Sekunden Pause) * Automatischer Abbruch der Aufzeichnung wenn länger als 2 Minuten keine Befehle empfangen wurden. * Taster > 20 Sekunden betätigt --> RESET der IR-Codes auf "Standard" Werte! * PIC-Code und Schaltplan/Layout in Subversion verwalten. * Zum Einschalten sollte der Taster länger als 500ms Sekunden betätigt werden und beim Ausschalter sicherheitshalber länger als 4 Sekunden! * Über die Fernbedienung sollten "Kombinationen" zum Ein/Ausschalten verwendet werden, z.B.: * 2x STOP, dann SELECT --> Einschalten * 4x STOP, dann SELECT --> Ausschalten * Aber auch das Ein-/Ausschalten über eine "POWER"-Taste auf der Fernbedienung sollte möglich sein. ===== Timing Diagramme von Fernbedienungen ===== Folgende Fernbedienungen sollten unterstützt werden (da Sie bei mir //über// sind): ==== XBox 1 DVD-Fernbedienung ==== Codierung der "Stop-Taste" auf der XBox DVD-Fernbedienung (RCA - Format) {{svg>private:rasperry_pi_ir-onoff:timing_XBox_Stop_Button}} \\ Die nachfolgenden Zeiten wurden mit dem Oszilloskop ermittelt und stimmen fast 100%ig mit den Zeiten auf [[http://www.sbprojects.com/knowledge/ir/rca.php|SB-Projects]] überein. | **Timings** ^ t_low ^ t_high ^ t_puls ^ __t_soll__ ^ ^ Start | 1.6ms | 6.5ms | 8.1ms | 8.0ms | ^ "0" | 0.6ms | 0.85ms | 1.45ms | 1.5ms | ^ "1" | 0.65ms | 1.85ms | 2.5ms | 2.5ms | ^ repeat ((Zeit zwischen letzter steigender Flanke und erster fallender)) | - - | 8ms | - - | ?? | === Mögliche "Dekodierung" === * Timer auf 1.6ms * Interrupt-On-Change (also bei fallender und steigender Flanke) * Start-Erkennung: * Int-Change: Timer-An * Int-Timer: IR-Data muss noch low sein * --> Start erkannt wenn zwischenzeitlich kein Int-On-Change eingetreten ist! * Jetzt müssen 6.5ms/1.6ms (**4**) Timer-Interrupts auftreten. * --> wenn mehr dann Fehler! Warten bis mehr als 8ms/1.6ms (**5**) Timer aufgetreten sind Timer-Reset bei jedem On-Change-Interrupt! * BitCounter auf 0 setzen * Bit-Erkennung: * Timer Reset wenn IR-Data = "0" bei On-Change-Interrupt * Bei Timer-Interrupt: * eine "1" an die empfangenen Daten anhängen * und BitCounter incrementieren * Bei On-Change-Interrupt: * Wenn Bit für "1" nicht gesetzt ist: * eine "0" an die empfangenen Daten anhängen * und BitCounter incrementieren * Timer-Reset * Bit setzen das "1" Empfangen wurde * ansonsten: * Timer-Reset * Bit löschen das "1" Empfangen wurde === Andere Möglichkeit === * Timer auf 8.2ms * Bei fallenden Flanke (On-Change-Interrupt IR-Data=0) den Timer-Wert vergleichen * Wenn <= 1.5ms --> 0 Empfangen * Wenn > 1.5ms und <= 2.5ms --> 1 Empfangen * Wenn > 2.5ms und <= 8.0ms --> Start-Bit * Wenn > 8.0ms (Timer-Interrupt) --> Pause zwischen den Telegrammen === Weitere Möglichkeit === Muss nochmal überdacht werden, war ein kurzfristiger Einfall der nicht zu Ende gedacht wurde! Wenn keine Logik hinter diesem erkannt werden kann, einfach diesen Punkt entfernen und nicht weiter drüber nachdenken! * Timer auf 1.6ms * Interrupt-On-Change (also bei fallender und steigender Flanke) * Start-Erkennung: * Int-Change: Timer-An * Int-Timer: IR-Data muss noch low sein * --> Start erkannt wenn zwischenzeitlich kein Int-On-Change eingetreten ist! * Jetzt müssen 6.5ms/1.6ms (**4**) Timer-Interrupts auftreten. * --> wenn mehr dann Fehler! Warten bis mehr als 8ms/1.6ms (**5**) Timer aufgetreten sind Timer-Reset bei jedem On-Change-Interrupt! * BitCounter auf 0 setzen * Bit-Erkennung: * Timer Reset wenn IR-Data = "0" bei On-Change-Interrupt * Bei Timer-Interrupt: * eine "1" an die empfangenen Daten anhängen * BitCounter incrementieren * Bit setzen das "1" Empfangen wurde * Bei On-Change-Interrupt: * Wenn IR-Data = "0" * Timer-Reset * eine "0" an die empfangenen Daten anhängen * BitCounter incrementieren * Wenn IR-Data = "1" * sollte eigentlich nicht vorkommen * Wenn Bit für "1" nicht gesetzt ist: * eine "0" an die empfangenen Daten anhängen * und BitCounter incrementieren * Timer-Reset * * ansonsten: * Timer-Reset * Bit löschen das "1" Empfangen wurde Während der gesamten Erkennung der Daten Bits darf der Timer-Interrupt nicht 2 mal nacheinander auftreten! Dies bedeutet ein Fehler und es muss auf insgesamt 5 (inklusive der 2 bereits empfangenen) Timer-Interrupts gewartet werden (Neue IR-Daten). Wenn mehr als 10 Timer-Interrupts aufgetreten sind, werden keine Daten mehr Empfangen und der Timer kann deaktiviert werden. Aktivierung bei nächsten On-Change-Interrupt. Außerdem kann in diesem Fall in den "Sleep"-Mode übergegangen werden, ein Erwachen findet dann bei dem nächsten On-Change-Interrupt statt. ==== Technisat DigiPal 2 - DBV-T Fernbedienung ==== Codierung der einer Taste auf der DigiPal 2 (ohne 'e') Fernbedienung (RC5 - Format) {{svg>private:rasperry_pi_ir-onoff:timing_digipal_remote}} Dieses Timing ist für das RC5 Format, im Nachhinein wurde festgestellt das einige Tasten ein "extended" RC5 Format übertragen. Bei diesem ist die START Codierung anders ('10' statt '11 -> somit low-Pegel für 1,8ms). Dadurch überschneidet sich die Zeitmessung mit dem RCA Format. Außerdem gibt es Probleme beim "fehlerfreien" Empfang des RCA Formats: - Das Start-Bit ist, bei direkter Richtung der Fernbedienung auf den IR-Empänger, nicht 4ms lang sondern schwankt zwischen 0.8ms und 4ms. Teilweise werden auch mehrere Pulse erkannt! - Die Logitech Harmony wird besser erkannt als die Original MS XBox Fernbedienung. - Die nachfolgenden Zeiten wurden mit dem Oszilloskop ermittelt. | **Timings** ^ t_low ^ t_high ^ t_puls ^ __t_soll__ ^ ^ Start | 0.9ms | 0.9ms | 1.8ms | x.y ms | ^ "0" | 0.9ms | 0.9ms | 1.8ms | x.y ms | ^ "1" | 0.9ms | 0.9ms | 1.8ms | x.y ms | ===== Ablaufdiagramm ===== "IR Active" --> if "IR-Code" then -left-> [RCA] "Decode RCA" --> "IR Decoded" else -right-> [RC5] "Decode RC5" --> "IR Decoded" endif --> if "Power On" then --> if "Power Off" then ->[true] "Turn Power Off" else --> "Sleep and\nwait for next IR" endif else ->[true] "Turn Power On" endif ===== Umsetzung ===== ==== Verwendete Module ==== * TIMER0: Increment alle 32µs (Bei 4MHz --> Prescaler 1:32), Overflow bei 8,192ms * Zur Zeitmessung des IR-Data-Signals * TIMER1: Increment alle 8µs (Bei 4MHz --> Prescaler 1:8), Overflow bei 524,288ms * Zur Erkennung von Button-Presses und Zeitmessungen für Sleep/CMD-Ende * ==== Schaltplan ==== ==== Layout ====