senden_und_empfangen_von_infrarot-signalen
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
senden_und_empfangen_von_infrarot-signalen [2025/03/05 12:34] – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | senden_und_empfangen_von_infrarot-signalen [2025/03/05 20:27] (aktuell) – torsten.roehl | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== Senden und empfangen von Infrarot-Signalen. ====== | ||
+ | // | ||
+ | ====== Voraussetzungen ====== | ||
+ | Für die Signalübertragung per Infrarot wird hier das **NEC-Protokoll** verwendet. | ||
+ | <note important> | ||
+ | Das NEC-Protokoll überträgt insgesamt **4 Byte (32 Bit)**. Wie diese Daten in binärer, dezimaler oder hexadezimaler Form dargestellt werden können, __muss__ ebenfalls bekannt sein, um die Inhalte dieser Abschnitte zu verstehen. | ||
+ | |||
+ | |||
+ | ====== Hardware ====== | ||
+ | Es gibt zahlreiche Empfänger- und Sender-Module, | ||
+ | * **2x** Arduino Nano (Clone) | ||
+ | *** HALJIA Digital <color # | ||
+ | *R-Empfänger Sensor-Modul** | ||
+ | |||
+ | <WRAP center round info 90%>Die von uns verwendeten Sender haben leider nur eine **geringe Reichweite**. Berücksichtigen Sie dies beim Testen. | ||
+ | </ | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | <WRAP center round tip 90%> | ||
+ | ☛Sender und Empfänger haben eine <color # | ||
+ | </ | ||
+ | |||
+ | |Anschluss des IR-Sendemoduls/ | ||
+ | |{{ : | ||
+ | |< | ||
+ | * **VCC** → an **5V** des Arduino | ||
+ | * **GND** → an **GND** des Arduino | ||
+ | * **Signal (S oder IN)** → hier an **Pin 7** des Arduino | ||
+ | </ | ||
+ | |||
+ | ====== Infrarot mit Arduino-Bibliothek ====== | ||
+ | ===== Empfangen von Infrarot-Signalen ===== | ||
+ | Dieser Arduino-Code empfängt Infrarot-Signale über **Pin 7** und nutzt die `IRremote`-Bibliothek (**IRremote - Joachimsmeyer 4.4.1**). Die empfangenen Signale, beispielsweise von einer Infrarot-Fernbedienung, | ||
+ | |||
+ | === Quellcode (engl. Sourcecode) === | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <Code c linenums:1 | Listing 1: | ||
+ | #include < | ||
+ | |||
+ | int IR_RECEIVE_PIN=7; | ||
+ | void setup(){ | ||
+ | Serial.begin(9600); | ||
+ | IrReceiver.begin(IR_RECEIVE_PIN, | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | if (IrReceiver.decode()) { | ||
+ | Serial.println(" | ||
+ | // Print " | ||
+ | Serial.print(" | ||
+ | Serial.println(IrReceiver.decodedIRData.decodedRawData, | ||
+ | // Print command | ||
+ | uint16_t cmd = IrReceiver.decodedIRData.command; | ||
+ | uint16_t add = IrReceiver.decodedIRData.address; | ||
+ | Serial.print(" | ||
+ | Serial.println(cmd, | ||
+ | | ||
+ | Serial.println(add, | ||
+ | // | ||
+ | Serial.println(" | ||
+ | // Print complete received data in one line | ||
+ | IrReceiver.printIRResultShort(& | ||
+ | Serial.println(" | ||
+ | IrReceiver.printIRSendUsage(& | ||
+ | IrReceiver.resume(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Beispiel: Makeblock Fernbedienung === | ||
+ | Der Code '' | ||
+ | < | ||
+ | === RECEIVING DATA === | ||
+ | RawData: BA45FF00 | ||
+ | command: 45 | ||
+ | address: 0 | ||
+ | Info... | ||
+ | Protocol=NEC Address=0x0 Command=0x45 Raw-Data=0xBA45FF00 32 bits LSB first | ||
+ | more Info... | ||
+ | Send with: IrSender.sendNEC(0x0, | ||
+ | |||
+ | </ | ||
+ | ===== Senden von Infrarot-Signalen ===== | ||
+ | Dieser Arduino-Code sendet Infrarot-Signale über **Pin 7** und nutzt die IRremote-Bibliothek (**IRremote - Joachimsmeyer 4.4.1**). Die gesendeten Signale, hier das Signal ' | ||
+ | |||
+ | Lässt man diesen Code auf einem Arduino Nano laufen und den weiter oben stehenden Code ('' | ||
+ | |||
+ | <Code c linenums:1 | Listing 1: | ||
+ | #include < | ||
+ | |||
+ | int IR_SEND_PIN = 7; | ||
+ | IRsend irsend(IR_SEND_PIN); | ||
+ | uint16_t address = 0; | ||
+ | uint8_t cmd = 0x45; // Makeblock Code Button_A! | ||
+ | uint32_t rawData = 0xBA45FF00; // Makeblock Signal ' | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | Serial.print(" | ||
+ | Serial.print(rawData, | ||
+ | irsend.sendNECRaw(rawData, | ||
+ | delay(5000); | ||
+ | |||
+ | Serial.print(" | ||
+ | irsend.sendNEC(address, | ||
+ | delay(5000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ====== Infrarot-Signale ohne Bibliothek empfangen ====== | ||
+ | |||
+ | ++++ Infrarot-Signale ohne Bibliothek empfangen | | ||
+ | Dieser Code empfängt und dekodiert **NEC-IR-Signale** __ohne externe Bibliothek__. | ||
+ | Er dient dazu, das Prinzip der **Pulslängen-Modulation** zu veranschaulichen und das Verständnis der Infrarot-Signalübertragung zu vertiefen. | | ||
+ | |||
+ | * **Erfassung: | ||
+ | * **Anzeige: | ||
+ | * **Dekodierung: | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <WRAP center round tip 90%> | ||
+ | **Messprinzip** | ||
+ | |||
+ | Die **Zeiterfassung** erfolgt mit '' | ||
+ | Das Signal wird erfasst, indem '' | ||
+ | Ein **Timeout (60 ms)** verhindert endlose Messungen. | ||
+ | |||
+ | Zur **Identifikation eines NEC-Signals**: | ||
+ | * **Startbit**: | ||
+ | * **Datenbits** (32 Stück): | ||
+ | * **Bit 1** → HIGH > 1000 µs. | ||
+ | * **Bit 0** → HIGH ≤ 1000 µs. | ||
+ | </ | ||
+ | |||
+ | ==== Quellcode (engl. Sourcecode) ==== | ||
+ | |||
+ | <Code c linenums:1 | Listing 1: infraredreceiver.ino> | ||
+ | / | ||
+ | | ||
+ | |||
+ | - Erfasst Pulse (LOW/HIGH) mit micros(). | ||
+ | - Zeigt eine formatierte Pulstabelle mit Bit-Spalte. | ||
+ | - Dekodiert NEC-Signale auf zwei Arten: | ||
+ | 1) decodeRawNEC | ||
+ | 2) decodeBitReverseNEC (LSB-first) | ||
+ | | ||
+ | |||
+ | #define IR_PIN 7 // Pin für den IR-Empfänger | ||
+ | #define MAX_PULSES 70 // Max. Anzahl erfassbarer Pulse-Paare | ||
+ | #define TIMEOUT_US 60000UL | ||
+ | #define HIGH_PAUSE 10000UL | ||
+ | bool USE_REGISTER = true; // true = direkten Registerzugriff! | ||
+ | |||
+ | unsigned long pulseArray[MAX_PULSES][2]; | ||
+ | int pulseIndex = 0; // Anzahl erfasster Pulse-Paare | ||
+ | bool capturing = false; | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(115200); | ||
+ | pinMode(IR_PIN, | ||
+ | Serial.println(" | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | |||
+ | // Messung starten? | ||
+ | if (!capturing && isIrSignalDetected()) { | ||
+ | | ||
+ | capturing = true; | ||
+ | pulseIndex = 0; | ||
+ | |||
+ | capturePulses(); | ||
+ | printPulses(); | ||
+ | decodeRawNEC(); | ||
+ | decodeBitReverseNEC(); | ||
+ | |||
+ | capturing = false; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // --------------------------------------------------------------------- | ||
+ | // Erfasst abwechselnd LOW- und HIGH-Dauer, bis eine lange HIGH-Pause | ||
+ | // (HIGH_PAUSE) oder das Array voll ist. | ||
+ | // --------------------------------------------------------------------- | ||
+ | void capturePulses() { | ||
+ | while (pulseIndex < MAX_PULSES) { | ||
+ | unsigned long lowDuration | ||
+ | unsigned long highDuration = measurePulse(HIGH); | ||
+ | |||
+ | pulseArray[pulseIndex][0] = lowDuration; | ||
+ | pulseArray[pulseIndex][1] = highDuration; | ||
+ | pulseIndex++; | ||
+ | |||
+ | if (highDuration > HIGH_PAUSE) { | ||
+ | break; // Ende des Signals | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | bool isIrSignalDetected() { | ||
+ | if (USE_REGISTER) | ||
+ | return !(PIND & (1 << IR_PIN)); | ||
+ | |||
+ | return digitalRead(IR_PIN) == LOW; | ||
+ | } | ||
+ | |||
+ | // --------------------------------------------------------------------- | ||
+ | // Misst, wie lange der Pin im angegebenen Zustand (LOW/HIGH) bleibt, | ||
+ | // bricht nach TIMEOUT_US ab (z.B. 60 ms). | ||
+ | // --------------------------------------------------------------------- | ||
+ | unsigned long measurePulse(bool state) { | ||
+ | bool checkState = (state == LOW); | ||
+ | | ||
+ | unsigned long startTime = micros(); | ||
+ | while (isIrSignalDetected() == checkState) { | ||
+ | if (micros() - startTime > TIMEOUT_US) { | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | return micros() - startTime; | ||
+ | } | ||
+ | |||
+ | // --------------------------------------------------------------------- | ||
+ | // Gibt die aufgenommenen Pulse als Tabelle im Serial Monitor aus. | ||
+ | // Spalten: | Label | LOW(µs) | HIGH(µs) | Bit | | ||
+ | // Startbit = Zeile 0, Bits 1..32, danach Stopbit? | ||
+ | // Zur Bit-Bestimmung wird ein simpler Schwellwert (HIGH > 1000 µs) genutzt. | ||
+ | // --------------------------------------------------------------------- | ||
+ | void printPulses() { | ||
+ | Serial.println(" | ||
+ | Serial.println("" | ||
+ | Serial.println(" | ||
+ | Serial.println(" | ||
+ | |||
+ | for (int i = 0; i < pulseIndex; i++) { | ||
+ | String label; | ||
+ | if (i == 0) { | ||
+ | label = " | ||
+ | } else if (i <= 32) { | ||
+ | label = "Bit " + String(i); | ||
+ | } else { | ||
+ | label = " | ||
+ | } | ||
+ | |||
+ | char bitVal = ' | ||
+ | if (i >= 1 && i <= 32) { | ||
+ | if (pulseArray[i][1] > 1000) { | ||
+ | bitVal = ' | ||
+ | } else { | ||
+ | bitVal = ' | ||
+ | } | ||
+ | } | ||
+ | |||
+ | char lineBuffer[80]; | ||
+ | sprintf( | ||
+ | lineBuffer, | ||
+ | "| %-10s | %8lu | %8lu | %c |", | ||
+ | label.c_str(), | ||
+ | pulseArray[i][0], | ||
+ | pulseArray[i][1], | ||
+ | bitVal | ||
+ | ); | ||
+ | Serial.println(lineBuffer); | ||
+ | } | ||
+ | Serial.println(); | ||
+ | } | ||
+ | |||
+ | // --------------------------------------------------------------------- | ||
+ | // Dekodiert das Signal MSB-first | ||
+ | // (klassischer Ansatz: data << 1, dann Bit rein). | ||
+ | // --------------------------------------------------------------------- | ||
+ | void decodeRawNEC() { | ||
+ | if (pulseIndex < 34) { | ||
+ | Serial.println(" | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | unsigned long startLow | ||
+ | unsigned long startHigh = pulseArray[0][1]; | ||
+ | if (startLow < 8000 || startLow > 10000 || | ||
+ | startHigh < 4000 || startHigh > 5500) { | ||
+ | Serial.println(" | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | uint32_t data = 0; | ||
+ | for (int i = 1; i <= 32; i++) { | ||
+ | unsigned long highDur = pulseArray[i][1]; | ||
+ | if (highDur > 1000) { | ||
+ | data = (data << 1) | 1; // Bit 1 | ||
+ | } else { | ||
+ | data = (data << 1); // Bit 0 | ||
+ | } | ||
+ | } | ||
+ | |||
+ | Serial.println(" | ||
+ | printHex32(data); | ||
+ | printNECBytes(data); | ||
+ | Serial.println("" | ||
+ | } | ||
+ | |||
+ | // --------------------------------------------------------------------- | ||
+ | // Dekodiert das Signal LSB-first | ||
+ | // (bitweises Umkehren durch data >> 1 | (bit << 31)). | ||
+ | // --------------------------------------------------------------------- | ||
+ | void decodeBitReverseNEC() { | ||
+ | if (pulseIndex < 34) { | ||
+ | Serial.println(" | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | unsigned long startLow | ||
+ | unsigned long startHigh = pulseArray[0][1]; | ||
+ | if (startLow < 8000 || startLow > 10000 || | ||
+ | startHigh < 4000 || startHigh > 5500) { | ||
+ | Serial.println(" | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | uint32_t data = 0; | ||
+ | for (int i = 1; i <= 32; i++) { | ||
+ | unsigned long highDur = pulseArray[i][1]; | ||
+ | int bitVal = (highDur > 1000) ? 1 : 0; | ||
+ | data = (data >> 1) | ((uint32_t)bitVal << 31); | ||
+ | } | ||
+ | |||
+ | Serial.println(" | ||
+ | printHex32(data); | ||
+ | printNECBytes(data); | ||
+ | Serial.println("" | ||
+ | } | ||
+ | |||
+ | // --------------------------------------------------------------------- | ||
+ | // Gibt den 32-Bit-Wert stets als achtstellige HEX-Zahl aus (mit 0ern). | ||
+ | // --------------------------------------------------------------------- | ||
+ | void printHex32(uint32_t val) { | ||
+ | char buf[9]; | ||
+ | for (int i = 7; i >= 0; i--) { | ||
+ | uint8_t nibble = val & 0xF; | ||
+ | val >>= 4; | ||
+ | buf[i] = (nibble < 10) | ||
+ | ? (char)(' | ||
+ | : (char)(' | ||
+ | } | ||
+ | buf[8] = ' | ||
+ | Serial.print(" | ||
+ | Serial.println(buf); | ||
+ | } | ||
+ | |||
+ | // --------------------------------------------------------------------- | ||
+ | // Zerlegt die 32-Bit-Daten in 4 Bytes (Addr, ~Addr, Cmd, ~Cmd) | ||
+ | // und gibt sie aus. Prüfung, ob ~Addr und ~Cmd jeweils Inversionen sind. | ||
+ | // --------------------------------------------------------------------- | ||
+ | void printNECBytes(uint32_t data) { | ||
+ | uint8_t addr = (data >> 24) & 0xFF; | ||
+ | uint8_t addrInv = (data >> 16) & 0xFF; | ||
+ | uint8_t cmd = (data >> | ||
+ | uint8_t cmdInv | ||
+ | |||
+ | Serial.print(" | ||
+ | Serial.print(addr, | ||
+ | Serial.print(", | ||
+ | Serial.print(addrInv, | ||
+ | Serial.print(", | ||
+ | Serial.print(cmd, | ||
+ | Serial.print(", | ||
+ | Serial.println(cmdInv, | ||
+ | |||
+ | bool verify = ((uint8_t)(addr ^ addrInv) == 0xFF) && | ||
+ | if (!verify) { | ||
+ | Serial.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | ==== Erklärungen zum Quellcode ==== | ||
+ | |||
+ | <color #ff7f27> | ||
+ | ** loop** - Hauptprogrammschleife</ | ||
+ | |||
+ | |||
+ | Sobald ein IR-Signal erkannt wird ('' | ||
+ | - **'' | ||
+ | - **'' | ||
+ | - **'' | ||
+ | - **'' | ||
+ | | ||
+ | Danach wird '' | ||
+ | |||
+ | |||
+ | ** | ||
+ | <color # | ||
+ | |||
+ | '' | ||
+ | *'' | ||
+ | * '' | ||
+ | |||
+ | Jeder Eintrag '' | ||
+ | |||
+ | ** | ||
+ | <color # | ||
+ | |||
+ | * **Prüft das Startbit** (ca. **9000 µs LOW** + **4500 µs HIGH**). | ||
+ | * Liest die folgenden 32 Datenbits: | ||
+ | - **Bit 1**, wenn HIGH-Dauer > 1000 µs. | ||
+ | - **Bit 0**, wenn HIGH-Dauer ≤ 1000 µs. | ||
+ | - Speichert das Bit von **links nach rechts** in '' | ||
+ | * '' | ||
+ | * Gibt das **32-Bit-Ergebnis als HEX-Wert** und die **Einzelbytes (Adresse, Kommando)** aus. | ||
+ | ** | ||
+ | <color # | ||
+ | |||
+ | * Identisch zu '' | ||
+ | * '' | ||
+ | * Das Ergebnis entspricht einer **spiegelbildlichen Darstellung** der Binärdaten. | ||
+ | |||
+ | |||
+ | |||
+ | ==== Beispiel: Makeblock Fernbedienung ==== | ||
+ | Der Code '' | ||
+ | < | ||
+ | Infrarot Signal empfangen: | ||
+ | |||
+ | | Label | LOW(µs) | HIGH(µs) | Bit | | ||
+ | |------------|---------: | ||
+ | | Startbit | ||
+ | | Bit 1 | 624 | 524 | 0 | | ||
+ | | Bit 2 | 596 | 524 | 0 | | ||
+ | | Bit 3 | 596 | 520 | 0 | | ||
+ | | Bit 4 | 596 | 524 | 0 | | ||
+ | | Bit 5 | 572 | 548 | 0 | | ||
+ | | Bit 6 | 596 | 520 | 0 | | ||
+ | | Bit 7 | 600 | 516 | 0 | | ||
+ | | Bit 8 | 600 | 524 | 0 | | ||
+ | | Bit 9 | 592 | 1624 | 1 | | ||
+ | | Bit 10 | ||
+ | | Bit 11 | ||
+ | | Bit 12 | ||
+ | | Bit 13 | ||
+ | | Bit 14 | ||
+ | | Bit 15 | ||
+ | | Bit 16 | ||
+ | | Bit 17 | ||
+ | | Bit 18 | ||
+ | | Bit 19 | ||
+ | | Bit 20 | ||
+ | | Bit 21 | ||
+ | | Bit 22 | ||
+ | | Bit 23 | ||
+ | | Bit 24 | ||
+ | | Bit 25 | ||
+ | | Bit 26 | ||
+ | | Bit 27 | ||
+ | | Bit 28 | ||
+ | | Bit 29 | ||
+ | | Bit 30 | ||
+ | | Bit 31 | ||
+ | | Bit 32 | ||
+ | | Stopbit | ||
+ | |||
+ | [decodeRawNEC] Ergebnis (MSB-first): | ||
+ | 32-Bit Hex: 0x00FFA25D | ||
+ | Addr = 0x0, ~Addr = 0xFF, Cmd = 0xA2, ~Cmd = 0x5D | ||
+ | |||
+ | [decodeBitReverseNEC] Ergebnis (LSB-first): | ||
+ | 32-Bit Hex: 0xBA45FF00 | ||
+ | Addr = 0xBA, ~Addr = 0x45, Cmd = 0xFF, ~Cmd = 0x0 | ||
+ | |||
+ | </ | ||
+ | |||
+ | === Analyse === | ||
+ | Die Verwendung der'' | ||
+ | |||
+ | |||
+ | ^ Abschnitt | ||
+ | | **Startbit LOW** | **9000** | ||
+ | | **Startbit HIGH** | ||
+ | | **Bit 0 LOW** | **560** | ||
+ | | **Bit 0 HIGH** | ||
+ | | **Bit 1 LOW** | **560** | ||
+ | | **Bit 1 HIGH** | ||
+ | | **Stopbit LOW** | **560** | ||
+ | | **Stopbit HIGH** | ||
+ | |||
+ | |||
+ | * **Das Startbit** liegt **sehr nahe** an den Sollwerten (~9000 µs LOW und ~4500 µs HIGH) mit einer minimalen Abweichung von **+1.3 % (LOW) und -1.6 % (HIGH)**. | ||
+ | * **Die Datenbits** weichen typischerweise **um 5–12 %** ab, wobei die LOW-Phasen tendenziell **etwas länger** und die HIGH-Phasen für " | ||
+ | * **Beim Stopbit** wird ein **kurzer LOW-Puls (~624 µs)** erfasst, der leicht über dem erwarteten Wert von 560 µs liegt (**+11.4 % Abweichung**). Danach folgt eine lange **HIGH-Phase (~60008 µs)**, was das typische **Signalende** des NEC-Protokolls anzeigt. | ||
+ | |||
+ | **→ Fazit:** Das Signal wird **präzise erkannt und dekodiert**, | ||
+ | ++++ | ||
+ | |||
+ | |||
+ | |||
+ | ++++ Exkurs: MSB (Most Significant Bit) & LSB (Least Significant Bit)| | ||
+ | |||
+ | <WRAP center round tip 98%> | ||
+ | MSB (**Most Significant Bit**) ist das **höchstwertige Bit** einer Zahl, während LSB (**Least Significant Bit**) das **niederwertigste Bit** ist. | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | Beim Speichern oder Übertragen von Daten gibt es zwei mögliche Reihenfolgen: | ||
+ | |||
+ | * **MSB-first**: | ||
+ | * **LSB-first**: | ||
+ | |||
+ | Je nach Protokoll kann eine der beiden Darstellungen verwendet werden, weshalb eine **Umwandlung zwischen MSB-first und LSB-first** manchmal erforderlich ist. | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Was macht decodeBitReverseNEC() genau? ===== | ||
+ | |||
+ | Die Funktion '' | ||
+ | |||
+ | * Jedes empfangene Bit wird **von rechts nach links gespeichert**. | ||
+ | * Am Ende ist das gesamte **32-Bit-Wort bitweise umgekehrt** – nicht nur die Reihenfolge der Bytes. | ||
+ | |||
+ | ==== Beispiel ==== | ||
+ | === Original (MSB-first) Empfang === | ||
+ | Angenommen, das empfangene Signal besteht aus **32 Bits**: | ||
+ | |||
+ | < | ||
+ | |||
+ | Hexadezimal als **MSB-first**: | ||
+ | '' | ||
+ | |||
+ | === Bitweise Spiegelung für LSB-first === | ||
+ | Wenn wir **LSB-first** dekodieren, wird nicht nur die **Reihenfolge der Bytes umgedreht**, | ||
+ | |||
+ | ^ **MSB-first Byte** ^ **LSB-first umgekehrt** ^ | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | Das ergibt Hexadezimal als **LSB-first**: | ||
+ | '' | ||
+ | |||
+ | === Warum werden nicht nur die Bytes, sondern auch die Bits umgedreht? === | ||
+ | |||
+ | In '' | ||
+ | |||
+ | < | ||
+ | uint32_t data = 0; | ||
+ | |||
+ | for (int i = 1; i <= 32; i++) { | ||
+ | unsigned long highDur = pulseArray[i][1]; | ||
+ | int bitVal = (highDur > 1000) ? 1 : 0; | ||
+ | data = (data >> 1) | ((uint32_t)bitVal << 31); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | **Erklärung: | ||
+ | - '' | ||
+ | - **A**: Das neue Bit wird an die höchste Position (''<< | ||
+ | - **B**: Der Rest der bereits gespeicherten Bits wird um eine Position nach rechts verschoben (''>> | ||
+ | - Beide Ausdrücke (**A** und **B**) werden '' | ||
+ | |||
+ | Das bedeutet: | ||
+ | * Das **erste empfangene Bit** (MSB in der Originaldatenfolge) landet **ganz rechts**. | ||
+ | * Das **letzte empfangene Bit** (LSB in der Originaldatenfolge) landet **ganz links**. | ||
+ | |||
+ | **Ergebnis: | ||
+ | * Die Bitfolge wird vollständig umgekehrt. | ||
+ | * Die Bytes erscheinen dabei ebenfalls in umgekehrter Reihenfolge. | ||
+ | |||
+ | ++++ | ||
+ | |||
+ | ====== Signaldarstellung am Oszilloskop ====== | ||
+ | ++++ Signaldarstellung am Oszilloskop | ||
+ | ===== Analyse der empfangenen Infrarotsignale mit dem Oszilloskop ===== | ||
+ | |||
+ | Mit dem Oszilloskop (**DSO1104**) werden nun die empfangenen Infrarotsignale näher untersucht. Dabei konzentrieren wir uns darauf, das **digitale Ausgangssignal** zu analysieren, | ||
+ | |||
+ | |||
+ | <WRAP center round tip 95%> | ||
+ | Der **HALJIA Digital 38 kHz Infrarot-Empfänger** ist ein **demodulierender IR-Empfänger**: | ||
+ | |||
+ | * ✅ Empfängt modulierte Infrarot-Signale mit einer Trägerfrequenz von 38 kHz. | ||
+ | * ✅ Entfernt die 38-kHz-Trägerfrequenz und gibt nur das **demodulierte digitale Signal** aus. | ||
+ | |||
+ | ☛ Die 38-kHz-Trägerfrequenz selbst ist **nicht sichtbar** und damit **nicht direkt messbar**, da sie demoduliert wird. | ||
+ | </ | ||
+ | |||
+ | === Was soll untersucht werden ? === | ||
+ | {{ : | ||
+ | * ✅ **Digitales Ausgangssignal (HIGH/ | ||
+ | * HIGH (5V) im Ruhezustand, | ||
+ | * LOW (0V), wenn ein 38-kHz-IR-Signal empfangen wird. | ||
+ | * ✅ **IR-Fernbedienungssignale analysieren** | ||
+ | * **Startsignal: | ||
+ | * **Datenbits: | ||
+ | * **Oszilloskop zur Messung der exakten Pulsbreiten nutzen.** | ||
+ | * ✅ **Empfang von IR-Signalen überprüfen** | ||
+ | * ✅ **Empfang eines gedrückten Tasters der Fernbedienung untersuchen** | ||
+ | |||
+ | ==== Oszilloskop Rigol 1104==== | ||
+ | |||
+ | ==== 🔌 Anschließen des Empfängers ==== | ||
+ | * **VCC (Pin 1)** → **+5V der Spannungsquelle** | ||
+ | * **GND (Pin 2)** → **Masse der Spannungsquelle**. | ||
+ | * **OUT (Pin 3)** → **Oszilloskop-Tastkopf (Signal-Messspitze an OUT, Masse an GND).** | ||
+ | |||
+ | **Masse** des Oszilloskop (Tastkopf) und die **Masse** der Spannungsquelle __müssen__ verbunden sein! | ||
+ | |||
+ | ==== ⚙️ Einstellungen am Oszilloskop ==== | ||
+ | * **Zeitskala: | ||
+ | * **Spannungsskala: | ||
+ | * **Trigger: | ||
+ | * **Eingangsmodus: | ||
+ | |||
+ | ==== Test & Analyse ==== | ||
+ | <WRAP center round tip 95%> | ||
+ | **IR-Empfang testen** | ||
+ | |||
+ | → Beim Drücken einer Taste sollte eine Abfolge von HIGH/ | ||
+ | </ | ||
+ | ^Übersichtsgraph: | ||
+ | |{{ : | ||
+ | |Dargestellt ist der Empfang (Makeblock-Fernbedienung) beim Drücken des Buchstabens **A**. Im oberen Bildausschnitt ist auch noch der // | ||
+ | === Analyse MakeBlock-Fernbedienung ' | ||
+ | < | ||
+ | === Analyse des Wiederholungssignals (gedrückte Taste) === | ||
+ | < | ||
+ | ++++ | ||
+ | ====== Quellen | ||
+ | * Verwendung der neuen Version: https:// | ||
+ | * Analyse der Signale https:// | ||
+ | * Analyse der Signale https:// | ||