www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik V-USB: HIDKeys ignoriert ersten Tastendruck


Autor: Patrick (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen!

Ich habe einen USB-Taster entwickelt, der am PC als USB-Tastatur erkannt 
wird, und der bei einem Tastendruck die Kombination alt+n sendet. Dafür 
habe ich das HIDKeys-Projekt verwendet:
http://www.obdev.at/products/vusb/hidkeys.html

Nun wird aber immer nach dem Anschluss an den PC der erste Tastendruck 
ignoriert. Ich muss immer zweimal drücken, bis alt+n beim PC ankommt.

Hat jemand Erfahrung mit HIDKeys? Wo ist das Problem? Ich hab Euch mal 
die main.c angehängt.

Danke für Eure Hilfe!

Autor: Ernestus Pastell (malzeit) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie kurz/lang ist dein Tastenimpuls. Sehr kurze Impulse (ein paar µs) 
können von der Software übersehen werden, wenn ich es auf die schnelle 
richtig überschaut habe.

Edit: Du benutzt auch Pull-up, und nicht Pull-down?

Autor: Patrick (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Danke für Deine Antwort.

Ich habs eben ausprobiert. Es spielt keine Rolle, wie lange der erste 
Tastendruck ist (einige ms bis mehrere s). Er wird einfach nicht 
ausgeführt.

Mein Taster ist mit der Schaltung im Anhang am AVR dran (zwischen P1 und 
P2).

Autor: Ernestus Pastell (malzeit) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast dich eigentlich recht an die Vorgabe gehalten. Das etwas 
wesentliches herausgekürzt wurde kann ich nicht erkennen.

Jetzt kannst du noch deine einzigen direkten Änderungen falsifizieren. 
Da du nur einen Eingang benutzt ändere die Tastenabfrage etwa so ab.

        if( (lastKey != key) && keyDidChange == 0){ // erst altes 
abarbeiten
            if(key == 1) { // nur zwei Zustaende
              lastkey = 1;
            } else {
              lastkey = 0;
            }
            // lastKey = key;
            keyDidChange = 1;
        }


BTW: Kondensatoren parallel zu Schaltern sind nicht gesund.

Autor: Kai W. (kai-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine Lösung kann ich Dir leider auch nicht anbieten, aber mein 
HIDKeys-Projekt verhält sich genauso, unabhängig ob ich die Eingänge mit 
Tastern, Relais oder einem anderen Controller ansteuere.

Gruß Kai

Autor: Mario M. (mariom)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier ebenfalls!

Der erste Tastendruck nach einer Weile Nichtbenutzung wird nicht 
erzeugt. Der "Befehl" kommt von einem Barcode-Scanner, dessen erstes 
Zeichen dann jeweils nicht angezeigt wird...

Lg
Mario

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für Eure Hilfe. Ich habs jetzt so gelöst:
buildReport(lastKey);
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));

  for(;;){  /* main event loop */
Vor der Endlosschleife sende ich gleich, dass kein Taster gedrückt ist. 
Damit funktioniert es bei mir. Vielleicht hilft das den anderen auch.

Autor: Ernestus Pastell (malzeit) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick schrieb:
> Vor der Endlosschleife sende ich gleich, dass kein Taster gedrückt ist.
> Damit funktioniert es bei mir. Vielleicht hilft das den anderen auch.

Klänge irgendwo plausibel, da das Betriebssystem erstmal von der 
Tastatur hören will, das keine Taste gedrückt ist.

Mario M. schrieb:
> Der erste Tastendruck nach einer Weile Nichtbenutzung wird nicht
> erzeugt. Der "Befehl" kommt von einem Barcode-Scanner, dessen erstes
> Zeichen dann jeweils nicht angezeigt wird...

Vielleicht wäre es dann auch sinnvoll immer vor dem Senden eines 
Tastendrucks ein "keine Taste gedrückt" Signal zum senden. Könnte ja 
sein das der Hack mit V-USB doch zu sehr vom Standard abweicht und 
irgendwelche Timeouts verletzt.

Autor: Kai W. (kai-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Tipp - ich werd's bei Gelegenheit mal ausprobieren (hab' 
das Projekt grade nicht zur Hand)

Autor: Ernestus Pastell (malzeit) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok eigentlich sollte der folgende Abschnitt im main.c das schon 
erledigen. Komisch aber, das Patrick seine Behelfslösung dann 
funktioniert.

        if(TIFR & (1<<TOV0)){   /* 22 ms timer */
            TIFR = 1<<TOV0;
            if(idleRate != 0){
                if(idleCounter > 4){
                    idleCounter -= 5;   /* 22 ms in units of 4 ms */
                }else{
                    idleCounter = idleRate;
                    keyDidChange = 1;
                }
            }

        }

Autor: Ernestus Pastell (malzeit) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Windows setzt die idleRate wohl auf Null und daher läuft kein idle-Timer

http://proyectosfie.com/html/usb/libro/capitulo13.pdf

> if(idleRate != 0){

Mit einer if-Verzweigung könnte man im Fall ohne idle-Timer vor dem 
Senden eines "Taste gedrückt" immer ein "keine Taste gedrückt" senden 
und hoffen, das man sich damit keine weiteren Probleme einhandelt.

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kommentare ein wenig unpassend ?
PORTC = 0x01;   /* disable pull-up for PC0 */

Alle Pins außer PC0 als Ausgang und in Kombination mit obiger Zeile Low:
DDRC = 0xfe;    /* PC0 as input */

keyPressed() scannt Pins von 0-6 und wird PC1 als gedrückt erkennen, da 
Low.

Rückgabewert = 2, damit wird key zu 2, woraus hier:
*(int *)reportBuffer = pgm_read_word(keyReport[key]);

ein Zufriff auf die 3. Progmem-Zelle erfolgt, obwohl hier mit NUM_KEYS = 
1 nur 2 definiert wurden:
static const uchar  keyReport[NUM_KEYS + 1][2] PROGMEM

Damit wird ständig eine unvorhersehbare Kombination geschickt und es ist 
eigentlich verwunderlich, daß es so überhaupt geht.

Autor: Om Pf (ompf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MWS schrieb:

> Damit wird ständig eine unvorhersehbare Kombination geschickt und es ist
> eigentlich verwunderlich, daß es so überhaupt geht.

Das mag wohl sein, hat aber nichts mit dem eigentlichen Problem des OP 
zu tun. Den gleichen Effekt habe ich auch bei diesem Projekt beobachtet:
http://www.schatenseite.de/dulcimer.html Der Bug bzw das Feature scheint 
aber schon in der Musterlösung von OBDev drinzustecken.

Wenn man die Tastatur eine Weile liegenlässt, wird der erste Tastendruck 
ignoriert und erst der zweite übertragen.

Ausserdem passiert es ab und zu, dass die zuletzt gedrückte Taste als 
Dauerfeuer gesendet wird. Der unerwünschte Repeat hört erst auf, wenn 
man eine andere Taste drückt.

Ich habe den usbdrv Release 2009-08-22 verwendet, der atmega324p läuft 
mit 12MHz.


Patrick

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick S. schrieb:
> Das mag wohl sein, hat aber nichts mit dem eigentlichen Problem des OP
> zu tun.

Da Du auch nicht erklären kannst, worin der Fehler denn nun genau 
besteht, halte ich's für gewagt zu behaupten daß so ein grober Schnitzer 
nichts damit zu tun hat. Aber selbst wenn's so wär', bevor man sich an 
die unerklärlichen Fehler wagt, schaltet man erst mal die erklärlichen 
ab.

Patrick S. schrieb:
> Wenn man die Tastatur eine Weile liegenlässt, wird der erste Tastendruck
> ignoriert und erst der zweite übertragen.

Was steht dem entgegen, wie bereits von Pastell angesprochen, einen 
Null-Tastencode zu senden, und in Abständen kleiner als die 
"Liegenlasszeit" dies zyklisch zu wiederholen ?

Autor: neanderthaler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick S. schrieb:
> Der Bug bzw das Feature scheint
> aber schon in der Musterlösung von OBDev drinzustecken.

Jo, ist bei meinem HID-Keys auch so. ATmega8 auf Lochraster, genau nach 
dem Vorschlag von Obdev.
Es wird nach dem Einschalten immer genau der erste Tastendruck 
verschluckt, das Terminal und xev zeigen dabei garnix an. Dann klappts 
aber problemlos, ohne Hänger o.ä., auch nach laaanger Pause (>12 
Stunden).

Gruß,
Jörn

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anstelle des Sendens for der Endlosschleife, kann man auch die Variable 
keyDidChange mit 1 initialisieren. Dann wird einmal der Teil ausgeführt:
if(keyDidChange && usbInterruptIsReady()){
            keyDidChange = 0;
            /* use last key and not current key status in order to avoid lost
               changes in key status. */
            buildReport(lastKey);
            usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
      }
Da lastKey am Anfang 0 ist, wird auch hier ein "keine Tasten gedrückt" 
gesendet. Ich hab das noch nicht ausprobiert, aber es müsste eigentlich 
funktionieren.

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.