RE: Infrarot Fernbedienung für Arduino

#1 von MobaNils , 16.10.2020 20:14

Hallo,

mit Arduinos lassen sich (wie in diesem Forum und im Internet allgemein sehr gut dokumentiert ist), vielerlei schöne Dinge für die Modelleisenbahn realisieren. Oftmals reicht es uns dann aber nicht einen ewigen loop auf dem Arduino laufen zu lassen, sondern wir wollen ihn auch mit weiteren Befehlen steuern können. Dafür kann man den Arduino beibringen die Digitalsignale der Zentrale zu verstehen. Ich persönlich mag lieber direkt mit dem kleinen Ding sprechen können und möchte nicht über die Digitalzentrale gehen. Das geht ganz einfach über eine Fernbedienung und da ich im Forum keinen Beitrag in der Richtung gefunden habe, möchte ich an dieser Stelle meine bisherigen Experimente dazu vorstellen und vielleicht den einen oder anderen inspirieren.

Wir brauchen nur zwei Dinge zu unserem Arduino: Einen Infrarotempfänger und eine Fernbedienung. Dabei muss es keine dieser kleinen Nerventöter sein, wie auf dem Bild, sondern irgendeine Fernbedienung, die gerade so rumliegt. Denn fast jede Fernbedienung, die man so in die Finger bekommt, arbeitet ja mit Infrarot. Der Empfänger benötigt vom Arduino Strom (große Überraschung, ich weiß und einen Pin zur Datenübertragung.



Zur Programmierung gibt es die IRremote Bibliothek, die uns das Leben einfach macht. Jeder Druck auf der Fernbedienung wird in einen Zahlencode umgewandelt. Der ist (kann) von Fernbedienung zu Fernbedienung unterschiedlich sein. Das heißt meine '3' ist nicht unbedingt deine '3'. Man muss am Anfang also eine Fernbedienung erstmal "einlesen". Dafür habe ich das folgende kleine Programm geschrieben.

[spoiler title=Programm zum Einlesen]
Funktionsweise:
Jede Eingabe wird über eine Debug-Ausgabe im Seriellen Monitor als Zahlencode angezeigt.
Diese Codes kann man in die check-Funktion unten eintragen. Dann wird im seriellen Monitor auch noch angezeigt welche Taste gedrückt wurde.
Die Codes in der check-Funktion sind aktuelle die Beispieldaten meiner kleinen Fernbedienung, aber das Prinzip sollte klar sein.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
 
/*
* Infrarot-Einlesen <1.0>
* MobaNils - 10.2020
*/
 
#include<IRremote.h>
 
int PIN_IR = 9; // Pin zum Datenempfang vom IR-Sensor
 
IRrecv irrecv(PIN_IR); // Instanz der IR-Empfangs Klasse
 
decode_results input; // Empfangene Daten landen in input
 
// ----------------------
 
void setup(){
Serial.begin(9600);

irrecv.enableIRIn(); // Empfang über den IR-Sensor wird initialisiert
Serial.println("IR-Setup gestartet.");
}
 
// ----------------------
 
void loop(){
if (irrecv.decode(&input)) { // Wenn Daten empfangen wurden:
if(input.value != 4294967295){ // "Fehlerwert" der auftaucht, wenn eine Taste zu lange gedrückt wird, wird hier einfach herausgefiltert
Serial.println(input.value,DEC); // Debug Ausgabe
check(input.value);
}
irrecv.resume(); // Der nächste Wert soll vom IR-Empfänger eingelesen werden
}
}
 
// ----------------------
 
void check(unsigned long in){
switch(in){
case 16753245:
Serial.println(1);
break;
case 16736925:
Serial.println(2);
break;
case 16769565:
Serial.println(3);
break;
case 16720605:
Serial.println(4);
break;
case 16712445:
Serial.println(5);
break;
case 16761405:
Serial.println(6);
break;
case 16769055:
Serial.println(7);
break;
case 16754775:
Serial.println(8);
break;
case 16748655:
Serial.println(9);
break;
case 16750695:
Serial.println(0);
break;
case 16738455:
Serial.println("*");
break;
case 16756815:
Serial.println("#");
break;
case 16726215:
Serial.println("OK");
break;
case 16718055:
Serial.println("^");
break;
case 16734885:
Serial.println(">");
break;
case 16716015:
Serial.println("<");
break;
case 16730805:
Serial.println("v");
break;
default:
Serial.println("Taste nicht erkannt");
}
}
 

[/spoiler]

Wenn man nun weiß welche Taste wie beim Arduino ankommt, kann man sich daran machen die Eingaben zu nutzen. Dabei sind der Kreativität keine Grenzen gesetzt. Zum Beispiel bei einer digitalen Werbetafel zum Durchwechseln der angezeigten Bilder oder einer entsprechenden Direktwahl oder bei einer Bahnsteigsanzeige (Dafür gibt es im Forum ein sehr schönes Thema: viewtopic.php?f=21&t=131472) zur Anwahl des nächsten Zuges. Fürs Erste habe ich ein kleines Programm geschrieben mit welchem man einen dreistelligen Zahlencode empfangen kann.

[spoiler title= Programm zur Eingabe eines dreistelligen Zahlencodes]
Funktionsweise:
Alle Tastencodes aus dem Einleseprogramm sind nun oben im Quelltext per #define angeben, so kann man schnell die Codes ändern, ohne das ganze Programm durchgehen zu müssen. Insbesondere bei den Befehlstasten zum Starten, abbrechen, usw. einer Codeeingabe nützlich. Die angegeben Daten sind wieder die meiner Testfernbedienung.
Mit einer Starttaste wird die Codeeingabe begonnen. Dann können nacheinander drei Zahlen eingegeben werden, eine Eingabe kann korrigiert werden oder ganz abgebrochen werden. Eine Eingabe muss bestätigt werden.
Alle Eingaben und Ereignisse werden wieder auf dem Seriellen Monitor ausgegeben.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
 
/*
* Infrarot-Empfang <1.0>
* MobaNils - 10.2020
*/
 
#include<IRremote.h>
 
int PIN_IR = 9; // Pin zum Datenempfang vom IR-Sensor
 
IRrecv irrecv(PIN_IR); // Instanz der IR-Empfangs Klasse
 
decode_results input; // Empfangene Daten landen in input
 
//Definition von Funktionstasten
#define Button_Start 16738455
#define Button_Cancel 16756815
#define Button_Okay 16726215
#define Button_Undo 16716015
 
//Definition von Zahlentasten
#define Button_One 16753245
#define Button_Two 16736925
#define Button_Three 16769565
#define Button_Four 16720605
#define Button_Five 16712445
#define Button_Six 16761405
#define Button_Seven 16769055
#define Button_Eight 16754775
#define Button_Nine 16748655
#define Button_Zero 16750695
 
//Zahlencode
unsigned int n = 3; //n muss die gleiche Zahl sein wie in den eckigen Klammern hinter x
typedef struct code{unsigned int x[3];
bool success;
} code;
 
code revcode;

// ----------------------
 
void setup(){
Serial.begin(9600);

irrecv.enableIRIn(); // Empfang über den IR-Sensor wird initialisiert
Serial.println("IR-Eingabe gestartet.");
}
 
// ----------------------
 
void loop(){
if (irrecv.decode(&input)) { // Wenn Daten empfangen wurden:
if(input.value != 4294967295){ // "Fehlerwert" der auftaucht, wenn eine Taste zu lange gedrückt wird, wird hier einfach herausgefiltert
//Serial.println(input.value,DEC); // Debug Ausgabe
if(input.value == Button_Start){ //Wenn die Starttaste gedrückt wird, erhalte einen Zahlencode
irrecv.resume();
revcode = getInputCode();
if(revcode.success){ //Mache etwas mit dem erhaltenen Datencode, falls die Eingabe nicht abgebrochen wurde
Serial.print("Code erhalten: ");
for(unsigned int j=0; j<n; j++){
Serial.print(revcode.x[j]);
Serial.print(" ");
}
Serial.println("");
}
}else{
Serial.println("Keine Befehlstaste gedrückt.");
}
}
irrecv.resume();
}
}
 
// ----------------------
 
unsigned int getDigit(unsigned long in){
switch(in){
case Button_One:
return 1;
case Button_Two:
return 2;
case Button_Three:
return 3;
case Button_Four:
return 4;
case Button_Five:
return 5;
case Button_Six:
return 6;
case Button_Seven:
return 7;
case Button_Eight:
return 8;
case Button_Nine:
return 9;
case Button_Zero:
return 0;
default:
return 99; //Fehlerwert, falls keine Zahlentaste gedrückt wurde
}
}
 
code getInputCode(){
code revcode;
unsigned int i=0;
unsigned int c;
 
Serial.print("Codeeingabe gestartet. Bitte ");
Serial.print(n);
Serial.println(" Dezimalzahlen eingeben");
 
while(true){
if (irrecv.decode(&input)) {
if(input.value == Button_Cancel){ //beim Cancel Button, Fehlschlag dokumentieren und beenden
revcode.success = false;
irrecv.resume();
Serial.println("--Abbruch.");
return revcode;
}
if(i == n && input.value == Button_Okay){ //bei vollständiger Eingabe und Bestätigung, Erfolg dokumentieren und beenden
revcode.success = true;
irrecv.resume();
Serial.println("");
return revcode;
}
if(i > 0 && input.value == Button_Undo){ //bei Korrektur Zähler zurücksetzen, sodass der letzte gelesene Wert überschrieben wird
i --;
Serial.println("--Korrektur.");
for(unsigned int j=0; j<i; j++){
Serial.print(revcode.x[j]);
Serial.print(" ");
}
}
if(i < n){ //weitere Eingabe möglich
c = getDigit(input.value);
if(c != 99){ //Dezimalzahl empfangen und nicht den Fehlerwert
revcode.x[i] = c;
i++;
Serial.print(c);
Serial.print(" ");
}
}
irrecv.resume();
}
}


}
 


[/spoiler]

Zu guter Letzt noch das Folgende: Der Empfänger tut auch hinter einer dickeren Plastikschicht, an dieser Stelle eine Preiser-Verpackung zu Testzwecken, ohne Einschränkungen seinen Dienst. Also könnte man den Empfänger ohne Probleme in einem Haus auf der Anlage, hinter einem ordentlichen Fenster, verstecken.



Ich hoffe euch hat mein Beitrag gefallen. Viele Grüße,
MobaNils


MobaNils  
MobaNils
Regionalbahn (RB)
Beiträge: 45
Registriert am: 16.09.2020
Spurweite H0
Stromart DC, Digital


   


  • Ähnliche Themen
    Antworten
    Zugriffe
    Letzter Beitrag
Xobor Einfach ein eigenes Forum erstellen
Datenschutz