www.mikrocontroller.net

Forum: Mikrocontroller und Elektronik Hilferuf - RC5 - kurzer / langer Tastendruck


Autor: Alex (Gast)
Datum:

Liebe Fachleute!

mittels der RC5 Routine von P. Dannegger lese ich die IR Kommandos einer
Fernbedienung. Nun möchte ich gern unterschiedliche Aktionen bei kurzem
Tastendruck oder bei langem Tastendruck starten. Das Problem bei meier
FB ist, dass auch bei einem kurzen Druck mehrere Sequenzen (mit
konstantem toggle bit) gesendet werden.
Mir schwebt folgendes vor:
wird die Taste auf der FB gedrückt und innerhalb 1 sec wieder
losgelassen, führe Aktion für kurzen Tastendruck durch. Ist die Taste
nach 1 sec. immer noch gedrückt, führe zyklisch die "Langzeitaktion"
aus, bis Taste losgelassen wird.
Meine Projekt: Atmega8, AVR Studio mit gcc...

Möglicherweise ist die Lösung trivial, aber ich habe da irgendwie ein
Brett vor dem Kopf. Gibt es dafür evtl. Beispielcode? Ich habe bisher
leider nichts finden können. Bin dankbar für jede Hilfe.
Autor: Stefan B. (stefan) Benutzerseite
Datum:

Wieviele Sequenzen kommen typisch bei einem kurzen Tastendruck und
wieviele typisch bei einem langen Tastendruck? Haben die Sequenzen einen
bestimmten zeitlichen Abstand, so dass man sagen kann, "genug Sequenzen
für einen kurzen Tastendruck sind da, warten wir mal etwas, ob jetzt
Sequenzen kommen, die ein langer Tastendruck schickt".
Autor: Alex (Gast)
Datum:

Ein kurzer Tastendruck erzeugt 1-3 Wiederholsequenzen. Ein langer
Tastendruck erzeugt Wiederholsequenzen solange die Taste gedrückt ist.
Die Auswertung ist wie folgt geplant:
Auswertung eines kurzen Tastendrucks -> einmaliges Ein/Ausschalt
Kommando über USART erzeugen
Langer Tastendruck -> Wiederholte Kommandosequenzen über USART schicken
(z.B. Dimme 5% heller) solange die Wiederholsequenzen von der IR FB
eintreffen
Das ganze soll ein IR Umsetzer für ein Hausbussystem werden...
Autor: Stefan B. (stefan) Benutzerseite
Datum:

Wenn mehr als Sequenzen mit gleichem Togglebit innerhalb einer gewissen
Zeit, die für mehr als 3 Sequenzen reicht, kommen, hättest du eine lange
Sequenz.

Wenn bloß 1-3 Sequenzen innerhalb einer gewissen Zeit, die für mehr als
3 Sequenzen reicht, kommen (oder wenn nach einer Sequenz das Togglebit
wechselt), hast du eine kurzen Tastendruck (gehabt).

Wieviel "eine gewissen Zeit" in der Praxis bedeutet, würde ich durch
Versuche ermitteln. Wie lang muss das sein, um sauber kurz/lang zu
trennen und wie kurz darf das sein, um ein geschmeidiges Feedback zu
haben.

BTW. Hat deine FB nur eine Taste? Warum nicht verschiedene Tasten und
Kommandos benutzen?
Autor: Alex (Gast)
Datum:

Stefan B. schrieb:
> BTW. Hat deine FB nur eine Taste? Warum nicht verschiedene Tasten und
> Kommandos benutzen?

Ja, ich kann natürlich auch verschiedene Tasten der FB nutzen. Ich
wollte halt auf der FB das Verhalten von 1-Flächenbedienung bei
Hausbustastern nachempfinden. Jede Taste der FB sollte dabei einer
Lampe, Steckdose oder einem Rollo zugeordnet werden.
Also z.B. Taste 1: kurzer Tatsendruck Lampe 1 ein/aus abh. vom letzten
Zustand. Langer Druck: Dimme heller/dunkler abh. von letzter
Dimmrichtung.
Ich habe mir jetzt folgenden Codeschnipsel zurechtgedacht. Muss ich aber
erst noch heute abend ausprobieren...
for(;;){        // main loop
      cli();
      i = rc5_data;// in rc5_data ist immer die letzte IR-Sequenz decodiert
                   // ... wird in ISR ermittelt
      rc5_data = 0;
      sei();
    
    if(i){
      _delay_ms(400);
      if(i != rc5_data) { //nach Wartezeit keine neue IR-Sequenz oder andere als vor Wartezeit  
      sendcmd(i); // führe hier Einzelkommando aus
      }
      else{
        while(i==rc5_data){ //aktueller IR-Code wie vor Wartezeit
        cli();
        i=rc5_data;
        rc5_data=0;
        sei();
        sendcmd(i);// führe hier Wiederholkommando aus
        _delay_ms(120); //Zeit lassen für das Eintreffen einer Wiederholsequenz
                        //eine IR Sequenz wird periodisch nach ca. 114 ms wiederholt
        }
      }
    }
  }
Autor: Stefan B. (stefan) Benutzerseite
Datum:

Die Delays gefallen mir nicht. Du hast doch in der RC5 einen
durchlaufenden Timer, nutze den. Man könnte z.B. die RC5-Funktion so
aufbohren, dass die ISR zu jedem rc5_data auch eine Art rc5_time
liefert.

Merke dir beim Eintreffen der ersten Sequenz eine Startzeit und berechne
eine Endzeit für >3 Sequenzen. Wie geschrieben kann man durch
Bedienversuche herausfinden wie groß diese Erkennzeitspanne
optimalerweise ist.

Dann zählst du eintreffende Sequenzen und vergleichst die aktuelle Zeit
mit der berechneten Endzeit.

Wenn >3 Sequenzen gezählt werden und die Endzeit noch nicht erreicht
ist, hast du einen langen Tastendruck.

Wenn <=3 Sequenzen gezählt sind und die Endzeit überschritten ist, hast
du einen kurzen Tastendruck.

Im zweiten Schritt würde ich über das Togglebit nachdenken. Wenn sich
beim Zählen der Sequenzen das Togglebit ändert, wurde die Taste
losgelassen und neu gedrückt. Man kann das unterschiedlich behandeln.
Ich tendiere dazu es als kurzen Tastendruck zu behandeln mit EIN
Funktion plus normale Auswertung für die jetzt gedrückte Taste.
Autor: Alex (Gast)
Datum:

Du hast Recht, die delays sind alles andere als elegant.
Dein Tip war goldrichtig! Ich habe jetzt die ISR so erweitert, dass
sowohl ein Wiederholungszähler als auch eine Pausenerkennung drin ist.
Wielen Dank für den Hinweis. Nun funktioniert es.

Die ISR sieht nun so aus:
#define RC5TIME   1.778e-3    // 1.778msec
#define PULSE_MIN  (uchar)(F_CPU / 512 * RC5TIME * 0.4 + 0.5)
#define PULSE_1_2  (uchar)(F_CPU / 512 * RC5TIME * 0.8 + 0.5)
#define PULSE_MAX  (uchar)(F_CPU / 512 * RC5TIME * 1.2 + 0.5)

#define PAUSETIME (60 * RC5TIME) // Wiederholsequenzen nach 50 bit
                // hier 10 bit bzw. 17.88 ms Reserve

#define PAUSE_MIN   (uint)(F_CPU / 512 * PAUSETIME) //Mind. ISR Durchläufe f. Pausenlänge

uchar  rc5_bit;        // bit value
uchar  rc5_time;        // count bit time
uint  rc5_tmp;        // shift bits in
uint  rc5_data;        // store result
uint    pause_ticks;      // Anzahl ISR Runden ohne IR Flanken    
uchar   rc5_pause;    //Pause nach letztem decodierten RC5_data erkannt
uint rc5_data_old;
uchar repeat_counter;

SIGNAL (SIG_OVERFLOW0)
{
  uint tmp = rc5_tmp;        // for faster access

  TCNT0 = -2;          // 2 * 256 = 512 cycle

  if( ++rc5_time > PULSE_MAX ){      // count pulse time
    if( !(tmp & 0x4000) && tmp & 0x2000 ){  // only if 14 bits received
    rc5_data = tmp;
  pause_ticks = 0;
    if(rc5_data==rc5_data_old){repeat_counter++;
    if(repeat_counter>50){repeat_counter=50;}//Überlauf verhindern
  }
  else{
    rc5_data_old=rc5_data;
    repeat_counter=0;  
  }
  }
  tmp = 0;
  }

  if( (rc5_bit ^ xRC5_IN) & 1<<xRC5 ){    // change detect
    rc5_bit = ~rc5_bit;            // 0x00 -> 0xFF -> 0x00
  pause_ticks =0;             // Pausenzähler zurücksetzen
    if( rc5_time < PULSE_MIN )        // to short
      tmp = 0;

    if( !tmp || rc5_time > PULSE_1_2 ){    // start or long pulse time
      if( !(tmp & 0x4000) )          // not to many bits
        tmp <<= 1;              // shift
      if( !(rc5_bit & 1<<xRC5) )      // inverted bit
        tmp |= 1;              // insert new bit
      rc5_time = 0;              // count next pulse time
    }
  }
  if(++pause_ticks > PAUSE_MIN){    // Zeit für Wiederholsequenz überschritten
    rc5_pause = 1;            // pause erkannt
  pause_ticks = PAUSE_MIN+1;       // Überlauf verhindern
  }
  else rc5_pause=0;
  
  rc5_tmp = tmp;
}

und in der Hauptschleifewerte ich dass dannso aus:
for(;;){        // main loop
  cli();
  i = rc5_data;// in rc5_data ist immer die letzte IR-Sequenz decodiert
  sei();
  if(i && rc5_pause){
     do_cmd(i,0); //kurzer Tastendruck
     rc5_data=0;
  }
    
  if(i && (repeat_counter>4)){
     do_cmd(i,1); // Langer Tastendruck
     rc5_data=0;
  }
}
Autor: Christian T. (shuzz)
Datum:

Noch ein Hinweis: Viele der billigen China-Universalfernbedienungen
implementieren das RC5-Protokoll leider nicht richtig, d.h. sie wechseln
bei jeder gesendeten Sequenz das Togglebit, unabhängig davon ob die
Taste nun losgelassen wurde oder nicht.

btw, das Verhalten Deiner Fernbedienung ist vollkommen normal und
richtig so.
Sie muss das Kommando öfter senden, schliesslich muss ja sichergestellt
sein dass es auch ankommt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net