IR-Fernbedienung zur PIN-Eingabe

Moin zusammen,
ich bin noch ziemlicher Anfänger und versuche mich momentan an einem Projekt, das meine aktuellen Fähigkeiten etwas übersteigt, weshalb ich hoffe, dass mir hier vielleicht jemand helfen kann.

Mein Ziel ist, mithilfe einer handelsüblichen TV-Fernbedienung eine PIN einzugeben und so bei korrekter Eingabe ein Relais zu schalten. Dabei stellen sich mir jedoch zwei Probleme:

  1. Wie kann ich eine wiederholte Eingabe der gleichen Ziffer durch die Fernbedienung unterbinden? Diese sendet ihr Signal bei gedrückter Taste in einer schnellen Folge, wodurch es auch bei kurzem Drücken der Taste dazu kommt, dass die Eingabe mehrfach erkannt wird und so der PIN-Abgleich fehlschlägt.

  2. Wie kann ich das PIN-Array permanent mit den eingegebenen Ziffern abgleichen, sodass man die PIN-Eingabe nicht bestätigen muss?

Ich benutze die IRremote-Library von shirriff.

Würde mich sehr freuen, könnte mir jemand etwas auf die Sprünge helfen, falls sich die Umsetzung nicht als zu aufwendig erweisen sollte.

Hallo,

Zeig uns doch mal Dein Programm. (in Codetages </>)

Bei vielen Fernbienungen wird der Code und dann nur noch #FFFFFF gesendet. Hast Du schon die Codes aus Deiner Fernbedienung ausgelesen, teste doch mal was passiert wenn Du am selben Knopf brauchst.

Eigentlich ist es egal was gesendet wird, dass musst Du so wie beim Taster Entprellen machen. Ohne Code ist alles nur spekulation.

Grüße,
Donny

Fresco00:
.....
Würde mich sehr freuen, könnte mir jemand etwas auf die Sprünge helfen, falls sich die Umsetzung nicht als zu aufwendig erweisen sollte.

Du musst nur den empfangenen Code vergleichen und wenn nach einer festgelegten Zeit ein anderer Code kommt, diesen wieder vergleichen. Ob das nun für dich zu aufwändig wird, kann ich nicht sagen.
Umsetzbar ist das jedenfalls.

Du merkst dir mit jedem empfangenen Tastendruck die Zeit (aktmillis=millis()). Gleichzeitig vergleichst du die Zeit des letzten Tastendrucks mit der des aktuellen. Wenn z.B. mehr als eine halbe Sekunde dazwischen liegt, ist das ein neuer Tastendruck. Das ist ähnlich wie Zeitsteuerungen mit millis() und Intervallen.

Zum Codevergleich: Beispiel 4stellige Pin: Du speicherst die letzten 4Tastendrücke in einem Array. Bei jedem Tastendruck wird der erste Platz neu besetzt und die anderen rücken eins weiter nach hinten, so dass der hinterste Tastendruck auf Platz4 rausfällt.
Deine Pin hast du auch in einem Array. Nach jedem Tastendruck vergleichst du beide Arrays.

Im NEC Protokoll gibt es einen REPEAT Code, der statt der zu wiederholenden Taste gesendet wird. Für Dein Problem reicht es, genau diesen Code zu ignorieren.

Vielen Dank schon mal für die ganzen Antworten,
den Repeat-Code, auf den , taucht bei den von mir genutzten Fernbedienungen seltsamerweise nicht auf. Liegt das vielleicht an der Bibliothek, die ich verwende? Wandelt die den repeat-Code möglicherweise schon von selbst in den zu Beginn empfangenen Code um? Die meisten Fernbedienungen sendeten augenscheinlich bei gedrückter Taste durchgehend den selben Code, wenn man diese los lies und nochmals drückte war es ein zweiter, anderer Code, damit das empfangende Gerät mehrere Betätigungen der gleichen Taste unterscheiden kann. Ansonsten probier ich's mal mit millis().

Theseus:
Zum Codevergleich: Beispiel 4stellige Pin: Du speicherst die letzten 4Tastendrücke in einem Array. Bei jedem Tastendruck wird der erste Platz neu besetzt und die anderen rücken eins weiter nach hinten, so dass der hinterste Tastendruck auf Platz4 rausfällt.
Deine Pin hast du auch in einem Array. Nach jedem Tastendruck vergleichst du beide Arrays.

So hatte ich mir das vorgestellt, nur mit der Verwendung von Arrays muss ich mich noch etwas auseinander setzen, dann werde ich mich mal an einer Implementierung versuchen.

Bei Infrarot-Fernbedienungen gibt es verschiedene "Protokolle" und wie mit länger gedrückten bzw. wiederholt gedrückten Tasten umgegangen wird.

Zum Beispiel:

  • Es wird der "Tastencode" nur einmal gesendet und danach ein einheitlicher Wiederholungscode (NEC)
  • Für jede Taste gibt es 2 Codes, die abwechselnd gesendet werden - so kann erkannt werden, ob eine Taste länger gedrückt gehalten wird oder mehrmals hintereinander gedrückt wird (RC-5 und RC-6).
  • Es wird derselbe Code immer wieder gesendet (SONY).

Details siehe hier: Fernsehsteuerung - #8 by uxomm - Deutsch - Arduino Forum

Du müsstest zuerst herausfinden welches "System" deine Fernbedienung verwendet.
Dazu gibt es einen Beispielsketch zur Library.

uxomm:
Bei Infrarot-Fernbedienungen gibt es verschiedene "Protokolle" und wie mit länger gedrückten bzw. wiederholt gedrückten Tasten umgegangen wird.

Danke für die Info, hatte zufällig noch ne Universalfernbedienung rumliegen, die sich auf einen Hersteller, der das NEC-Protokoll verwendet, einstellen ließ. Somit wäre diesen Problem erstmal gelöst.

Fresco00:
Liegt das vielleicht an der Bibliothek, die ich verwende? Wandelt die den repeat-Code möglicherweise schon von selbst in den zu Beginn empfangenen Code um?

Nein, nein.

Ein kurzer, nicht repräsentativer Test in meinem Haushalt ergibt folgendes Bild: IR-Fernbedienungen für Licht senden einen Wiederholungscode, andere für Fernsehen, Video oder Sat wiederholen den selben Code.

Für eine IR-Fernbedienung (Grundig) mit wiederholendem Code habe ich mal was geschrieben:

#include <IRremote.h>
int recvPin = 6;
IRrecv irrecv(recvPin);
const uint16_t TASTE1 = 0xC11, TASTE2 = 0xC10; // Codes an die Tastatur anpassen!
const uint32_t SCHWELLE = 130;
uint32_t aktMillis, codeMillis;

void  setup ( )
{
  Serial.begin(9600);   // Status message will be sent to PC at 9600 baud
  irrecv.enableIRIn();  // Start the receiver
  Serial.println("Programmanfang");
  Serial.print("USECPERTICK: ");
  Serial.println(USECPERTICK, DEC);
}

void  loop ( )
{
  aktMillis = millis();
  decode_results  results;        // Somewhere to store the results

  if (irrecv.decode(&results)) {  // Grab an IR code
    Serial.print("Code      : ");
    Serial.print(results.value, HEX);
    Serial.print('\t');
    Serial.print(aktMillis - codeMillis);
    Serial.println();
    if (aktMillis - codeMillis > SCHWELLE)
    {
      switch (results.value)
      {
        case TASTE1:
          Serial.println("Taste 1");
          break;
        case TASTE2:
          Serial.println("Taste 2");
          break;
      }
    }
    codeMillis = aktMillis;
    irrecv.resume();              // Prepare for the next value
  }
}

Das sollte für Dich verwendbar sein, wenn Du eine entsprechende Tastatur nutzt.

Zu spät, schade :frowning:

Fresco00:
Danke für die Info, hatte zufällig noch ne Universalfernbedienung rumliegen, die sich auf einen Hersteller, der das NEC-Protokoll verwendet, einstellen ließ. Somit wäre diesen Problem erstmal gelöst.

Ja, mit dem NEC Protokoll lässt sich deine Aufgabenstellung am einfachsten lösen.

agmue:
Zu spät, schade :frowning:

Wow, nichtsdestotrotz vielen Dank für diesen sehr ausführlich Lösungsansatz!
Nachdem ich den Schwellenwert und natürlich die Codes angepasst habe, funktioniert auch mit der anderen Fernbedienung alles wunderbar.
Solche praktisch angewandten Codes nachzuvollziehen ist mir sowieso immer eine große Hilfe um mich generell mit der Funktionsweise von Sketchen vertrauter zu machen.

Fresco00:
Wow, nichtsdestotrotz vielen Dank für diesen sehr ausführlich Lösungsansatz!

Bitte gerne :slight_smile:

So, ich habe mich jetzt nach längerer Zeit mal wieder mit meinem Projekt beschäftigt und nach einiger Nachforschung versucht, etwas funktionierenden Code zu schreiben. So ganz wie geplant läuft der jedoch noch nicht.

#include <IRremote.h>
int recvPin = 11;
IRrecv irrecv(recvPin);
const uint32_t TASTE1 = 0x401, TASTE1_1 = 0x10401, TASTE2 = 0x10402, TASTE2_1 = 0x402, TASTE3 = 0x403, TASTE3_1 = 0x10403; // jede Taste hat zwei Codes
const uint16_t SCHWELLE = 140;
uint32_t aktMillis, codeMillis;
int PINx[]={0,0,0}; // Array für die Eingabe
int PIN[]={1,2,3}; // Array für die korrekte PIN
#define lock 8

void  setup ( )
{
  Serial.begin(9600);   
  irrecv.enableIRIn();  
  Serial.println("Programmanfang");
  Serial.print("USECPERTICK: ");
  Serial.println(USECPERTICK, DEC);
  pinMode(8, OUTPUT);
}

void  loop ( )
{
  aktMillis = millis();
  decode_results  results;        
  if (irrecv.decode(&results))
     if (aktMillis - codeMillis > SCHWELLE){  
      switch (results.value)
      {
        case TASTE1:
        case TASTE1_1:
          PINx[0]=1;
          break;
        case TASTE2:
        case TASTE2_1:
          PINx[0]=2;
          break;
        case TASTE3:
        case TASTE3_1:
          PINx[0]=3;
          break;  
       }
      Serial.println(PINx[0]);    // zum gucken, ob's funktioniert. Hier hat sich die Ausgabe wiederholt.
      for (int k = sizeof(PINx) - 2; k >= 0; k--){
        PINx[k+1] = PINx[k];      // hier sollen die Einträge im Array einen Platz nach hinten verschoben werden
      }
    codeMillis = aktMillis;
    irrecv.resume();              
    }
  if (PINx == PIN){               // zum Schalten des Relais
    digitalWrite(lock, HIGH);   
    delay(500);
    digitalWrite(lock, LOW);
  }
}

Aus irgendeinem, womöglich sehr trivialen Grund, scheint der Code die Entprellung zu ignorieren, jedenfalls gibt er den gleichen Code mehrmals über den seriellen Monitor aus :confused: .

Kann mir sonst vielleicht auch jemand sagen, ob der Code theoretisch so in der Praxis funktionieren würde, wenngleich er wahrscheinlich noch fernab von perfekt ist? Ich hatte bisher noch nicht die Gelegenheit, das selbst zu testen.

Außerdem würde ich mich freuen, könnte mir jemand sagen, was hinter "USECPERTICK" steckt, das agmue in seinem Codevorschlag verwendet hat. Ich hab' das einfach mal so übernommen, ohne zu wissen, was da passiert :-\ .

Fresco00:
Außerdem würde ich mich freuen, könnte mir jemand sagen, was hinter "USECPERTICK" steckt, das agmue in seinem Codevorschlag verwendet hat. Ich hab' das einfach mal so übernommen, ohne zu wissen, was da passiert :-\ .

Das ist eine Konstante, die von der Bibliothek in IRremoteInt.h gesetzt wird:

// microseconds per clock interrupt tick
#define USECPERTICK    50

Hat keine Relevanz, kannst Du rausschmeißen.

Hat keine Relevanz, kannst Du rausschmeißen.

Ok, gut zu wissen.

Fresco00:

  1. Wie kann ich eine wiederholte Eingabe der gleichen Ziffer durch die Fernbedienung unterbinden? Diese sendet ihr Signal bei gedrückter Taste in einer schnellen Folge, wodurch es auch bei kurzem Drücken der Taste dazu kommt, dass die Eingabe mehrfach erkannt wird und so der PIN-Abgleich fehlschlägt.

Sicher? Eigentlich senden IR-Fernbedienungen den Origal-Code nur beim ersten Mal und danach nur noch Wiederholungs-Codes. Mit der Arduino-IRLib kann man das deutlich unterscheiden.

Im Sender werkelt ein Algorithmus, der bestimmt wann (mit welchem Abstand) bei gedrückter Taste der Tastencode (oder REPEAT) übertragen wird. Hat man nur einen ganz bestimmten Sender, so kann man dessen Parameter experimentell ermitteln und dann im Code des Empfängers passend berücksichtigen. Wobei mir REPEAT nur vom NEC Protokoll bekannt ist. RC4/5 (meine ich) senden stattdessen bei Wiederholungen abwechselnd zwei verschiedene Codes für die selbe Taste.

Wenn ich mich richtig erinnere, verhält sich meine (Panasonic) FB zB bei Zifferntasten anders als bei lauter/leiser. Es kommt jedenfalls bei langem Drücken was anderes als bei zweimal hintereinander dieselbe Taste.

Hmm, es macht natürliche einen Unterschied, ob eine Zifferntaste oder eine andere über längere Zeit gedrückt wird. Beim Computer kann Autorepeat auch auf Ziffern anwendbar sein, bei einer Fernbedienung eher nicht.

Anscheinend muß/sollte man bei jeder Fernbedienung erst einmal ausprobieren, was bei Autorepeat welcher Tasten gesendet wird.