Simulated Keyboard types only one time

Hello all,

I need some support, because I don't know what to do...

The following situation:
I have made my Arduino Uno keyboard-compatible according to these instructions (https://www.instructables.com/How-to-Make-a-Arduino-HID-Keyboard/).

Attached is a screenshot to possibly understand the whole thing better.
Instead of buttons, I use a toggle switch with 3 pins and an LED that indicates HIGH and LOW accordingly. (see screenshot - in the screenshot, the connections are reversed.)

Desired design:

  • If I push the toggle switch to the left (HIGH), the "W" key is pressed once. This is not held.
    If I move the toggle switch to the right (LOW), the "W" key should also be pressed once.

Current execution:

  • When I move the toggle switch from the right (LOW) to the left (HIGH), the "W" key is emitted several times (about 4 to 5 times) instead of only once.
    This is not held. But if I now move the toggle switch to the right (LOW), the "W" key is pressed and output only once. Here is the code for this:
uint8_t buf[8] = { 0 };   //Keyboard report buffer
int w_state = 0;

#define PIN_W 2 // Pin for w


void setup()
{
  Serial.begin(9600); // Setup Serial communication

  //Set pinmode of Input pins
  pinMode(PIN_W, INPUT);
  pinMode(A0, OUTPUT);
}

void loop()
{
  //When button representing W is pressed

    if (digitalRead(PIN_W) == HIGH)
    {
      w_state = 1;
      LEDRON();
      buf[2] = 26;   // W keycode
      Serial.write(buf, 8); // Send keypress
      releaseKey();
      while (digitalRead(PIN_W) == HIGH) { };
    }
    
    else if (digitalRead(PIN_W) == LOW)
    {
      w_state = 0;
      LEDRON();
      buf[2] = 26;   // W keycode
      Serial.write(buf, 8); // Send keypress
      releaseKey();
      while (digitalRead(PIN_W) == LOW) { };
    }
}
// Function for Key Release
void releaseKey()
{
  buf[0] = 0;
  buf[2] = 0;
  Serial.write(buf, 8); // Send Release key
}

void LEDRON()
{
  if (w_state == 1)
  {
    digitalWrite(A0, HIGH);
  }

  else
  {
    digitalWrite(A0, LOW);
  }
}

Functioning:

  • If I move the toggle switch to the left (HIGH), the "W" key is pressed once. This is not held.
    If I move the toggle switch to the right (LOW), nothing happens.
uint8_t buf[8] = { 0 };   //Keyboard report buffer
int w_state = 0;

#define PIN_W 2 // Pin for w


void setup()
{
  Serial.begin(9600); // Setup Serial communication

  //Set pinmode of Input pins
  pinMode(PIN_W, INPUT);
  pinMode(A0, OUTPUT);
}

void loop()
{
  //When button representing W is pressed

    if (digitalRead(PIN_W) == HIGH)
    {
      buf[2] = 26;   // W keycode
      Serial.write(buf, 8); // Send keypress
      releaseKey();
      w_state = 1;
      LEDRON();
      while (digitalRead(PIN_W) == HIGH) { };
    }
    
    else if (digitalRead(PIN_W) == LOW)
    {
      releaseKey();
      w_state = 0;
      LEDRON();
    }
}
// Function for Key Release
void releaseKey()
{
  buf[0] = 0;
  buf[2] = 0;
  Serial.write(buf, 8); // Send Release key
}

void LEDRON()
{
  if (w_state == 1)
  {
    digitalWrite(A0, HIGH);
  }

  else
  {
    digitalWrite(A0, LOW);
  }
}

I have already tried it with additional conditions, but unfortunately had no success with them.

I hope someone can help me. Thank you.

seems you have some bouncing going on.

read tutorials on buttons, there are tons

Do you have an example of debounce based on my code?

I am currently trying to understand debounce with an example. (https://www.arduino.cc/en/Tutorial/BuiltInExamples/Debounce)

your code at the moment does this

    if (digitalRead(PIN_W) == HIGH)
    {
      buf[2] = 26;   // W keycode
      Serial.write(buf, 8); // Send keypress
      releaseKey();
      w_state = 1;
      LEDRON();
      while (digitalRead(PIN_W) == HIGH) { };  // <<=======
    }

the last while await for the PIW to be released before continuing. The challenge is that if the button bounces, you'll get a "fake release signal" and it will be HIGH again soon thereafter

one way to deal with it is called the "poor's man anti-bounce" (because you can't afford a better code nor an external RC circuit to kill the bouncing in hardware ) and consist in adding a small delay to absorb the bounces before testing for release.

    if (digitalRead(PIN_W) == HIGH)
    {
      buf[2] = 26;   // W keycode
      Serial.write(buf, 8); // Send keypress
      releaseKey();
      w_state = 1;
      LEDRON();
      delay(20); // <=== poor's man anti-bounce
      while (digitalRead(PIN_W) == HIGH) { };  
    }

15 to 20ms are usually good enough

proper management would consist for example in remembering when was the last HIGH and if you get one too soon (a few ms) after then just ignore it or waiting for the signal to be stable for "long enough" before accepting the press.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.