Benötigte Komponenten
- Arduino UNO R3 kompatibles Board
- Breadboard
- 11 Jumperkabel
- 1x IR Fernbedienung
- 1x IR Empfänger
- 6x 220 Ohm Widerstand
- 6x LED
Übersicht
In Dieser Anleitung zeigen wir Ihnen, wie sie den Infrarotempfänger und die Infrarotfernbedienung mit Ihrem Arduino UNO kompatiblen Board verwenden.
IR-Fernbedienungen senden binäre Impulse als Signal im unsichtbaren Infrarotbereich aus. Um Störsignale von anderen Quellen zu vermeiden, werden die Signale vormoduliert und erst dann mit Hilfe einer IR-LED in einer bestimmten Frequenz gesendet.
Der IR-Empfänger besitzt in der Regel eine IR-Fotodiode, die Signale auf einer bestimmten Frequenz empfängt und Störungen von anderen Lichtquellen filtert. Hinter der IR-Fotodiode befindet sich dann meistens ein Signalverstärker und Demodulator, um das Signal weiterverarbeiten zu können.
Funktionsweise
Der IR-Empfänger wandelt das Lichtsignal, welches von der IR-LED gesendet wird, in ein schwaches, elektronisches Signal um. Dieses Signal wird dann durch einen IC verstärkt, automatisch gefiltert, geglättet und demoduliert, bis das ursprüngliche Signal der Fernbedienung wiederhergestellt ist. Dieses Signal wird dann an den Output-Pin des IR-Empfängers gesendet.
Verschlüsselung mit NEC-Protokoll
Wenn Sie die Signale einer IR-Fernbedienung auslesen wollen, müssen Sie zuerst wissen, wie sie verschlüsselt sind. Die Verschlüsselung in unserem Beispiel ist das NEC-Protokoll.
Technische Daten des NEC-Protokolls
- 8-bit Adressen und 8-bit Befehlslängen.
- Adresse und Befehl werden zur Verlässlichkeit immer wiederholt.
- Puls Distance Modulation (PDM)
- Frequenz von 38 Khz
- Bit time von 1.125 ms oder 2.25 ms
Definition von 0 und 1 im NEC-Protokoll
Signalübertragung bei Knopfdruck auf der Fernbedienung
Diese Abbildung zeigt eine typische Impulsfolge des NEC-Protokolls. Bei diesem Protokoll wird das LSB (Least Significant Bit) zuerst übertragen. In diesem Fall wird die Adresse $59 und der Befehl $16 übertragen. Eine Nachricht wird durch einen 9 ms AGC-Burst eingeleitet, der bei den früheren IR-Empfängern zur Einstellung der Verstärkung verwendet wurde. AGC steht kurz für engl. „automatic gain control“ und dient dazu, den Ausgangspegel eines Verstärkers konstant zu halten.
Auf diesen AGC-Burst folgt ein 4,5 ms langes Leerzeichen, auf das die Adresse und der Befehl folgen. Adresse und Befehl werden zwei Mal übertragen, um die Fehlerquote zu verringern. Beim zweiten Übertragen sind alle Bits invertiert und können zur Überprüfung der empfangenen Nachricht verwendet werden. Die Gesamtübertragungszeit ist konstant, da jedes Bit mit seiner invertierten Länge wiederholt wird. Wenn Sie an diese Zuverlässigkeit nicht benötigen, können Sie die invertierten Werte auch ignorieren, oder die Adresse und den Befehl auf jeweils 16 Bit erweitern!
Ein Impuls wird gesendet, wenn eine Taste gedrückt und nach einer bestimmten Zeit losgelassen wird.
Ein Befehl wird nur einmal übertragen, auch wenn die Taste der Fernbedienung gedrückt bleibt. Alle 110ms wird ein Wiederholungscode gesendet, solange die Taste gedrückt bleibt. Dieser Wiederholungscode ist einfach ein 9ms AGC-Burst, gefolgt von einer 2,25ms Pause und einem 560µs Burst.
Wenn der Impuls im Empfänger eintrifft, findet eine Dekodierung, Signalverstärkung und Wellenglättung statt. Sie müssen als sicherstellen, dass der Ausgangspegel genau das Gegenteil von dem des sendenden Signals ist. Das heißt, wenn kein Infrarotsignal vorhanden ist, ist der Ausgangspegel hoch; Wenn ein Infrarotsignal vorhanden ist, ist der Ausgangspegel low. Sie können das Signal des Empfängers mit einem Oszilloskop untersuchen, um das Signal besser zu verstehen.
Anschlussplan
Den VOUT-Pin vom IR-Empfänger schließen wir auf Pin 11 an. Die LEDs mit den Widerständen kommen an die Pins 2, 3, 4, 5, 6, 7. Die Spannungsversorgung erfolgt über den BUS des Breadboards, verbunden mit GND und 5V vom Arduino.
Code
Für den Code wird die IRremote Bibliothek verwendet. Das Programm dekodiert das verschlüsselte Signal der IR-Fernbedienung. So können Sie im seriellen Monitor der Arduino IDE die Signale der Fernbedienung auslesen. Mit diesen Signalen können wir dann unsere Anwendung steuern, in diesem Beispiel die 6 LEDs.
Die Codes können je nach Fernbedienung und Charge variieren. Wenn Sie z. B. die Tastenbelegung zum Einschalten der ersten LED ändern möchten, müssen Sie folgende Zeile anpassen:
long on1 = 0x00FFA25D;
Diese Zeile passen wir an, um die erste LED einzuschalten. Wie wir im seriellen Monitor erkennen können, entspricht FFA25D unserer ersten Taste der Fernbedienung.
Nun können Sie den angepassten Sketch erneut hochladen und die LEDs mit Hilfe der Taste anschalten. So können Sie nach der Reihe alle LEDs den Tasten zuweisen.
#include <IRremote.h>
int RECV_PIN = 11; // Pin vom IR-Empfänger
int LED1 = 2; // LED Pin
int LED2 = 3; // LED Pin
int LED3 = 4; // LED Pin
int LED4 = 5; // LED Pin
int LED5 = 6; // LED Pin
int LED6 = 7; // LED Pin
// Ab hier können Sie die Tastenbelegung anpassen
long on1 = 0x00FFA25D;
long off1 = 0x00FFE01F;
long on2 = 0x00FF629D;
long off2 = 0x00FFA857;
long on3 = 0x00FFE21D;
long off3 = 0x00FF906F;
long on4 = 0x00FF22DD;
long off4 = 0x00FF6897;
long on5 = 0x00FF02FD;
long off5 = 0x00FF9867;
long on6 = 0x00FFC23D;
long off6 = 0x00FFB04F;
IRrecv irrecv(RECV_PIN);
decode_results results;
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
// decode_results *results = (decode_results *)v
void dump(decode_results *results) {
int count = results->rawlen;
if (results->decode_type == UNKNOWN)
{
Serial.println("Could not decode message");
}
else
{
if (results->decode_type == NEC)
{
Serial.print("Decoded NEC: ");
}
else if (results->decode_type == SONY)
{
Serial.print("Decoded SONY: ");
}
else if (results->decode_type == RC5)
{
Serial.print("Decoded RC5: ");
}
else if (results->decode_type == RC6)
{
Serial.print("Decoded RC6: ");
}
Serial.print(results->value, HEX);
Serial.print(" (");
Serial.print(results->bits, DEC);
Serial.println(" bits)");
}
Serial.print("Raw (");
Serial.print(count, DEC);
Serial.print("): ");
for (int i = 0; i < count; i++)
{
if ((i % 2) == 1) {
Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
}
else
{
Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
}
Serial.print(" ");
}
Serial.println("");
}
void setup()
{
pinMode(RECV_PIN, INPUT);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
pinMode(LED5, OUTPUT);
pinMode(LED6, OUTPUT);
pinMode(13, OUTPUT);
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
int on = 0;
unsigned long last = millis();
void loop()
{
if (irrecv.decode(&results))
{
// If it's been at least 1/4 second since the last
// IR received, toggle the relay
if (millis() - last > 250)
{
on = !on;
// digitalWrite(8, on ? HIGH : LOW);
digitalWrite(13, on ? HIGH : LOW);
dump(&results);
}
if (results.value == on1 )
digitalWrite(LED1, HIGH);
if (results.value == off1 )
digitalWrite(LED1, LOW);
if (results.value == on2 )
digitalWrite(LED2, HIGH);
if (results.value == off2 )
digitalWrite(LED2, LOW);
if (results.value == on3 )
digitalWrite(LED3, HIGH);
if (results.value == off3 )
digitalWrite(LED3, LOW);
if (results.value == on4 )
digitalWrite(LED4, HIGH);
if (results.value == off4 )
digitalWrite(LED4, LOW);
if (results.value == on5 )
digitalWrite(LED5, HIGH);
if (results.value == off5 )
digitalWrite(LED5, LOW);
if (results.value == on6 )
digitalWrite(LED6, HIGH);
if (results.value == off6 )
digitalWrite(LED6, LOW);
last = millis();
irrecv.resume(); // Receive the next value
}
}