====== Senden und empfangen von Infrarot-Signalen. ======
//Infrarot-Signale werden häufig für die drahtlose Kommunikation zwischen Geräten verwendet, etwa bei Fernbedienungen. In diesem Artikel wird gezeigt, wie man mit einem **Arduino-Nano** Infrarot-Signale **senden** und **empfangen** kann. Dabei kommt das **NEC-Protokoll** zum Einsatz, ein weit verbreitetes Standardprotokoll für IR-Übertragungen. Grundlagen zur Signalstruktur werden am **Oszilloskop** untersucht. Praktische Beispiele helfen, die Funktionsweise zu verstehen und eigene Projekte umzusetzen. Zudem wird der grundsätzliche Umgang mit der **Arduino-Bibliothek** ''IRremote'' erklärt. Für ein vertieftes Verständnis wird außerdem gezeigt, wie **Signale ohne Bibliothek empfangen werden können**.//
====== Voraussetzungen ======
Für die Signalübertragung per Infrarot wird hier das **NEC-Protokoll** verwendet. Insbesondere das Beispiel mit dem Oszilloskop setzt Kenntnisse über das Protokoll voraus.
Informieren Sie sich im Internet, wie das NEC-Protokoll aufgebaut ist und wie die Signalübertragung mit Infrarot grundsätzlich funktioniert.
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, die verwendet werden können. Hier wird folgende Hardware genutzt:
* **2x** Arduino Nano (Clone)
*** HALJIA Digital 38 kHz Infrarot-I
*R-Empfänger Sensor-Modul**
Die von uns verwendeten Sender haben leider nur eine **geringe Reichweite**. Berücksichtigen Sie dies beim Testen.
{{ :inf:msr:infrarot_sr.png?400 |}}
☛Sender und Empfänger haben eine **rote LED**, die anzeigt, ob ein Signal gesendet bzw. empfangen wurde. Dies ist für das Debuggen hilfreich.
|Anschluss des IR-Sendemoduls/IR-Empfängermoduls|
|{{ :inf:msr:bauplan-ir.png?400 |}}|
|
* **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, werden auf der seriellen Schnittstelle ausgegeben.
=== Quellcode (engl. Sourcecode) ===
#include
int IR_RECEIVE_PIN=7;
void setup(){
Serial.begin(9600);
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
}
void loop() {
if (IrReceiver.decode()) {
Serial.println("=== RECEIVING DATA ===");
// Print "old" raw data
Serial.print("RawData: ");
Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);
// Print command
uint16_t cmd = IrReceiver.decodedIRData.command;
uint16_t add = IrReceiver.decodedIRData.address;
Serial.print("command: ");
Serial.println(cmd,HEX);
Serial.print("address: ");
Serial.println(add,HEX);
//decode_type_t p = IrReceiver.decodedIRData.protocol;
Serial.println("Info...");
// Print complete received data in one line
IrReceiver.printIRResultShort(&Serial);
Serial.println("more Info...");
IrReceiver.printIRSendUsage(&Serial);
IrReceiver.resume(); // Enable receiving of the next value
}
}
=== Beispiel: Makeblock Fernbedienung ===
Der Code ''receiver.ino'' erzeugt die folgende Ausgabe, wenn ‚A‘ mit der Makeblock-Fernbedienung gesendet wird. Diese wird von einem Arduino Nano über die serielle Schnittstelle ausgegeben.
=== 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, 0x45, );
===== 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 'A' von einer Makeblock-Fernbedienung, werden **zur Demonstration auf zwei verschiedene Arten** übertragen.
Lässt man diesen Code auf einem Arduino Nano laufen und den weiter oben stehenden Code (''receiver.ino'') auf einem anderen Arduino, kann man beim Empfänger über die serielle Schnittstelle die Ausgabe betrachten.
#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 'A'!
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.print("Sending NEC signal with rawData: ");
Serial.print(rawData, HEX);
irsend.sendNECRaw(rawData, 1);
delay(5000);
Serial.print("Sending NEC signal with command: ");
irsend.sendNEC(address, cmd, 1);
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:** Misst LOW-/HIGH-Pulse mit ''micros()'' und speichert sie in ''pulseArray''.
* **Anzeige:** Gibt eine Pulstabelle im **Serial Monitor** aus.
* **Dekodierung:**
* ''decodeRawNEC()'': **MSB-first**
* ''decodeBitReverseNEC()'': **LSB-first**
**Messprinzip**
Die **Zeiterfassung** erfolgt mit ''micros()'', das die Dauer von **LOW- und HIGH-Pulsen** misst (Pulslängen-Modulation).
Das Signal wird erfasst, indem ''measurePulse(state)'' die Zeit für jeden Zustand speichert.
Ein **Timeout (60 ms)** verhindert endlose Messungen.
Zur **Identifikation eines NEC-Signals**:
* **Startbit**: ~9000 µs LOW + ~4500 µs HIGH.
* **Datenbits** (32 Stück):
* **Bit 1** → HIGH > 1000 µs.
* **Bit 0** → HIGH ≤ 1000 µs.
==== Quellcode (engl. Sourcecode) ====
/**********************************************************************
IR-Decoder-Beispiel: NEC-Protokoll mit Pulstabelle
- Erfasst Pulse (LOW/HIGH) mit micros().
- Zeigt eine formatierte Pulstabelle mit Bit-Spalte.
- Dekodiert NEC-Signale auf zwei Arten:
1) decodeRawNEC (MSB-first)
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 // 60 ms Sicherheitszeit
#define HIGH_PAUSE 10000UL // 10 ms: Abbruchkriterium (Ende des IR-Signals)
bool USE_REGISTER = true; // true = direkten Registerzugriff!
unsigned long pulseArray[MAX_PULSES][2];
int pulseIndex = 0; // Anzahl erfasster Pulse-Paare
bool capturing = false; // Flag: Erfassung läuft?
void setup() {
Serial.begin(115200);
pinMode(IR_PIN, INPUT);
Serial.println("IR-Decoder gestartet.");
}
void loop() {
// Messung starten?
if (!capturing && isIrSignalDetected()) {
capturing = true;
pulseIndex = 0;
capturePulses(); // Pulse erfassen
printPulses(); // Tabelle ausgeben
decodeRawNEC(); // Dekodierung (MSB-first)
decodeBitReverseNEC(); // Dekodierung (LSB-first)
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 = measurePulse(LOW);
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("Infrarot Signal empfangen:");
Serial.println("");
Serial.println("| Label | LOW(µs) | HIGH(µs) | Bit |");
Serial.println("|------------|---------:|---------:|-----|");
for (int i = 0; i < pulseIndex; i++) {
String label;
if (i == 0) {
label = "Startbit";
} else if (i <= 32) {
label = "Bit " + String(i);
} else {
label = "Stopbit";
}
char bitVal = '-';
if (i >= 1 && i <= 32) {
if (pulseArray[i][1] > 1000) {
bitVal = '1';
} else {
bitVal = '0';
}
}
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("[decodeRawNEC] Zu wenige Pulse für NEC (mind. 34)!");
return;
}
unsigned long startLow = pulseArray[0][0];
unsigned long startHigh = pulseArray[0][1];
if (startLow < 8000 || startLow > 10000 ||
startHigh < 4000 || startHigh > 5500) {
Serial.println("[decodeRawNEC] Kein gültiges Startbit!");
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("[decodeRawNEC] Ergebnis (MSB-first):");
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("[decodeBitReverseNEC] Zu wenige Pulse für NEC (mind. 34)!");
return;
}
unsigned long startLow = pulseArray[0][0];
unsigned long startHigh = pulseArray[0][1];
if (startLow < 8000 || startLow > 10000 ||
startHigh < 4000 || startHigh > 5500) {
Serial.println("[decodeBitReverseNEC] Kein gültiges Startbit!");
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("[decodeBitReverseNEC] Ergebnis (LSB-first):");
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)('0' + nibble)
: (char)('A' + (nibble - 10));
}
buf[8] = '\0';
Serial.print("32-Bit Hex: 0x");
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 >> 8) & 0xFF;
uint8_t cmdInv = data & 0xFF;
Serial.print("Addr = 0x");
Serial.print(addr, HEX);
Serial.print(", ~Addr = 0x");
Serial.print(addrInv, HEX);
Serial.print(", Cmd = 0x");
Serial.print(cmd, HEX);
Serial.print(", ~Cmd = 0x");
Serial.println(cmdInv, HEX);
bool verify = ((uint8_t)(addr ^ addrInv) == 0xFF) && ((uint8_t)(cmd ^ cmdInv) == 0xFF);
if (!verify) {
Serial.println("→ WARNING: Keine typische Inversion!\n");
}
}
==== Erklärungen zum Quellcode ====
** loop** - Hauptprogrammschleife
Sobald ein IR-Signal erkannt wird (''isIrSignalDetected()''), startet die Verarbeitung:
- **''capturePulses()''**: Erfasst die LOW-/HIGH-Pulse und speichert sie.
- **''printPulses()''**: Gibt die erfasste Pulstabelle im Serial Monitor aus.
- **''decodeRawNEC()''**: Dekodiert das Signal im **MSB-first-Format**.
- **''decodeBitReverseNEC()''**: Dekodiert das Signal im **LSB-first-Format**.
Danach wird ''capturing'' zurückgesetzt, um neue Signale zu empfangen.
**
pulseArray - zweidimensionales Array**
''pulseArray'' ist ein zweidimensionales Array ''pulseArray[MAX_PULSES][2]'', das die gemessenen Dauerwerte eines empfangenen IR-Signals speichert.
*'' pulseArray[i][0]'' enthält die Dauer der **LOW-Phase** in Mikrosekunden.
* ''pulseArray[i][1]'' enthält die Dauer der **HIGH-Phase** in Mikrosekunden.
Jeder Eintrag ''i'' entspricht einem gemessenen Puls-Paar (**LOW/HIGH**), beginnend mit dem Startbit und gefolgt von den Datenbits des IR-Signals.
**
decodeRawNEC() – MSB-first Dekodierung**
* **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 ''data'':
* '' data = (data << 1) | bitVal;''
* Gibt das **32-Bit-Ergebnis als HEX-Wert** und die **Einzelbytes (Adresse, Kommando)** aus.
**
decodeBitReverseNEC() – LSB-first Dekodierung**
* Identisch zu ''decodeRawNEC()'', aber die Bits werden **umgekehrt gespeichert**:
* ''data = (data >> 1) | ((uint32_t)bitVal << 31);''
* Das Ergebnis entspricht einer **spiegelbildlichen Darstellung** der Binärdaten.
==== Beispiel: Makeblock Fernbedienung ====
Der Code ''infraredreceiver.ino'' erzeugt die folgende Ausgabe, wenn ‚A‘ mit der Makeblock-Fernbedienung gesendet wird. Diese wird von einem Arduino Nano über die serielle Schnittstelle ausgegeben.
Infrarot Signal empfangen:
| Label | LOW(µs) | HIGH(µs) | Bit |
|------------|---------:|---------:|-----|
| Startbit | 9116 | 4428 | - |
| 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 | 624 | 1620 | 1 |
| Bit 11 | 624 | 1624 | 1 |
| Bit 12 | 624 | 1620 | 1 |
| Bit 13 | 624 | 1624 | 1 |
| Bit 14 | 624 | 1620 | 1 |
| Bit 15 | 624 | 1624 | 1 |
| Bit 16 | 620 | 1620 | 1 |
| Bit 17 | 624 | 1624 | 1 |
| Bit 18 | 628 | 520 | 0 |
| Bit 19 | 596 | 1620 | 1 |
| Bit 20 | 624 | 524 | 0 |
| Bit 21 | 596 | 520 | 0 |
| Bit 22 | 592 | 524 | 0 |
| Bit 23 | 596 | 1616 | 1 |
| Bit 24 | 628 | 524 | 0 |
| Bit 25 | 596 | 520 | 0 |
| Bit 26 | 596 | 1624 | 1 |
| Bit 27 | 624 | 520 | 0 |
| Bit 28 | 596 | 1624 | 1 |
| Bit 29 | 620 | 1624 | 1 |
| Bit 30 | 624 | 1616 | 1 |
| Bit 31 | 620 | 524 | 0 |
| Bit 32 | 596 | 1620 | 1 |
| Stopbit | 624 | 60008 | - |
[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'' micros()''-Methode liefert präzisere und konsistentere Werte als beispielsweise eine auf** delay()**-basierten Messung, was zu einer zuverlässigeren Erfassung der IR-Signale führt.
^ Abschnitt ^ Erwartet (NEC) µs ^ Gemessen µs ^ Abweichung ^ Bewertung ^
| **Startbit LOW** | **9000** | **9116** | **+1.3%** | ✅ Sehr gut |
| **Startbit HIGH** | **4500** | **4428** | **-1.6%** | ✅ Sehr gut |
| **Bit 0 LOW** | **560** | **624** | **+11.4%** | ⚠ Leichte Abweichung |
| **Bit 0 HIGH** | **560** | **524** | **-6.4%** | ✅ Gut |
| **Bit 1 LOW** | **560** | **592-628** | **+5-12%** | ⚠ Leichte Abweichung |
| **Bit 1 HIGH** | **1690** | **1616-1624** | **-4.4%** | ✅ Sehr gut |
| **Stopbit LOW** | **560** | **624** | **+11.4%** | ⚠ Leichte Abweichung |
| **Stopbit HIGH** | **keine Angabe** | **60008** | **N/A** | 🚩 Typische HIGH-Pause (Signalende) |
* **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 "0" **leicht kürzer** als erwartet sind. Diese Abweichungen liegen im **akzeptablen Bereich** für IR-Signale.
* **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**, die Messergebnisse liegen im akzeptablen Toleranzbereich. 🚀
++++
++++ Exkurs: MSB (Most Significant Bit) & LSB (Least Significant Bit)|
MSB (**Most Significant Bit**) ist das **höchstwertige Bit** einer Zahl, während LSB (**Least Significant Bit**) das **niederwertigste Bit** ist.
{{ :inf:msr:msb-lsb.png?250 |}}
Beim Speichern oder Übertragen von Daten gibt es zwei mögliche Reihenfolgen:
* **MSB-first**: Das **höchstwertige Bit (MSB)** wird zuerst gesendet.
* **LSB-first**: Das **niederwertigste Bit (LSB)** wird zuerst gesendet.
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 ''decodeBitReverseNEC()'' dekodiert das NEC-Signal **LSB-first**, also das **niederwertigste Bit zuerst**. Das bedeutet:
* 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**:
MSB → 00000000 11111111 10100010 01011101 ← LSB
Hexadezimal als **MSB-first**:
'' 0x00FFA25D''
=== Bitweise Spiegelung für LSB-first ===
Wenn wir **LSB-first** dekodieren, wird nicht nur die **Reihenfolge der Bytes umgedreht**, sondern auch die **Bits in jedem Byte selbst**:
^ **MSB-first Byte** ^ **LSB-first umgekehrt** ^
| ''00000000'' ''(0x00)''↓ | ''00000000'' ''(0x00)'' |
| ''11111111'' ''(0xFF)'' | ''11111111'' ''(0xFF)'' |
| ''10100010'' ''(0xA2)'' | ''01000101'' ''(0x45)'' |
| ''01011101'' ''(0x5D)'' | ''10111010'' ''(0xBA)''↑ |
Das ergibt Hexadezimal als **LSB-first**:
'' 0xBA45FF00''
=== Warum werden nicht nur die Bytes, sondern auch die Bits umgedreht? ===
In ''decodeBitReverseNEC()'' passiert folgendes:
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:**
- ''bitVal'' wird als 0 oder 1 gesetzt, basierend auf der HIGH-Zeit.
- **A**: Das neue Bit wird an die höchste Position (''<< 31'') geschrieben.
- **B**: Der Rest der bereits gespeicherten Bits wird um eine Position nach rechts verschoben (''>> 1'').
- Beide Ausdrücke (**A** und **B**) werden ''oder'' verknüpft.
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 darstellen. |
===== 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, indem wir die **IR-Signale der Makeblock-Fernbedienung** untersuchen.
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 ? ===
{{ :inf:msr:ir-ossi.png?650 |}}
* ✅ **Digitales Ausgangssignal (HIGH/LOW-Pulse)**
* HIGH (5V) im Ruhezustand, wenn __kein__ IR-Signal erkannt wird.
* LOW (0V), wenn ein 38-kHz-IR-Signal empfangen wird.
* ✅ **IR-Fernbedienungssignale analysieren**
* **Startsignal:** 9 ms LOW, 4.5 ms HIGH (z. B. NEC-Protokoll).
* **Datenbits:** 560 µs Pulse mit variablen Abständen.
* **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:** 10-50 ms/div für IR-Signal-Pulse.
* **Spannungsskala:** 2V/div (abhängig von VCC).
* **Trigger:** Falling Edge (da das Signal beim Empfang LOW wird).
* **Eingangsmodus:** DC-Kopplung für volle Signaldarstellung.
==== Test & Analyse ====
**IR-Empfang testen**
→ Beim Drücken einer Taste sollte eine Abfolge von HIGH/LOW-Pulsen sichtbar sein.
^Übersichtsgraph: Infrarot-Signalmessung mit dem Rigol 1104^
|{{ :inf:msr:rigol_ir_01.png?500 |}}|
|Dargestellt ist der Empfang (Makeblock-Fernbedienung) beim Drücken des Buchstabens **A**. Im oberen Bildausschnitt ist auch noch der //Repeat-Code// zu erkennen. Im Folgenden soll dieses Signal genauer untersucht werden. Dabei sollen u. a. die Signalzeiten bestimmt und mit dem NEC-Protokoll verglichen werden. |
=== Analyse MakeBlock-Fernbedienung 'A' ===
TODO: Bilder einfügen + Beschreibung
=== Analyse des Wiederholungssignals (gedrückte Taste) ===
TODO: Bilder einfügen + Beschreibung
++++
====== Quellen ======
* Verwendung der neuen Version: https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#converting-your-2x-program-to-the-4x-version
* Analyse der Signale https://wolles-elektronikkiste.de/ir-fernbedienungen
* Analyse der Signale https://devxplained.eu/de/blog/infrarot-empfaenger