mikrocontroller.net

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


Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:

Bewertung
0 lesenswert
nicht lesenswert
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:

Bewertung
0 lesenswert
nicht lesenswert
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:

Bewertung
0 lesenswert
nicht lesenswert
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:

Bewertung
0 lesenswert
nicht lesenswert
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:

Bewertung
0 lesenswert
nicht lesenswert
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:

Bewertung
0 lesenswert
nicht lesenswert
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:

Bewertung
0 lesenswert
nicht lesenswert
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
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
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 bestätigst du, die Nutzungsbedingungen anzuerkennen.