Teensy as USB Keyboard Key Repeat Needed

Status
Not open for further replies.

clarkdv

Member
I'm building a Teensy based jog controller for my CNC. It will take the place of the arrow keys on the regular USB keyboard. Pressing the button once jogs the CNC one step, but holding the button down needs to continually move the CNC.

I have a prototype working kinda. It does what I want when a button is pressed, but I need for it to continue sending the button press when I hold the button down. Right now it's a one-shot deal. Holding down the button sends one command and one only.

How do I get the button press to send one command when I press and release, but to send a string of commands when I press and hold the button?

The code I'm using is this:


Code:
#include <Bounce.h>

/* Create Bounce objects for each button.  The Bounce object automatically deals with contact
   chatter or "bounce", and it makes detecting changes very simple.*/
Bounce button0 = Bounce(0, 10);  // 10 = 10 ms debounce time which is appropriate for most
Bounce button1 = Bounce(1, 10);  // mechanical pushbuttons. If a button is too sensitive to rapid touch
Bounce button2 = Bounce(2, 10);  // you can increase this time.
Bounce button3 = Bounce(3, 10);
Bounce button4 = Bounce(4, 10);
Bounce button5 = Bounce(5, 10);
/*
  Bounce button6 = Bounce(6, 10);
  Bounce button7 = Bounce(7, 10);
  Bounce button8 = Bounce(8, 10);
  Bounce button9 = Bounce(9, 10);
*/

void setup() {
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  /*
    pinMode(6, INPUT_PULLUP);
    pinMode(7, INPUT_PULLUP);
    pinMode(8, INPUT_PULLUP);
    pinMode(9, INPUT_PULLUP);
  */
  Keyboard.begin();
}

void loop() {
  /* Update all the buttons.  There should not be any long delays in loop(), so this runs
     repetitively at a rate faster than the buttons could be pressed and released.*/
  button0.update();
  button1.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  /*
    button6.update();
    button7.update();
    button8.update();
    button9.update();
  */

  // Check each button for "falling" edge.

  if (button0.fallingEdge()) {

    Keyboard.set_modifier(MODIFIERKEY_GUI);  //  Mac "Command" key press and hold
    Keyboard.send_now();

    Keyboard.set_key1(KEY_LEFT);   //  Press "Left Arrow" key   Moves X- (LEFT)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key1(0);
    Keyboard.send_now();
  }



  if (button1.fallingEdge()) {

    Keyboard.set_modifier(MODIFIERKEY_GUI);  //  Mac "Command" key press and hold
    Keyboard.send_now();

    Keyboard.set_key2(KEY_RIGHT);   //  Press "Right Arrow" key   Moves X+ (RIGHT)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key2(0);
    Keyboard.send_now();
  }



  if (button2.fallingEdge()) {

    Keyboard.set_modifier(MODIFIERKEY_GUI);  //  Mac "Command" key press and hold
    Keyboard.send_now();

    Keyboard.set_key3(KEY_DOWN);   //  Press "Down Arrow" key   Moves Y- (DOWN)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key3(0);
    Keyboard.send_now();
  }

  if (button3.fallingEdge()) {

    Keyboard.set_modifier(MODIFIERKEY_GUI);  //  Mac "Command" key press and hold
    Keyboard.send_now();

    Keyboard.set_key4(KEY_UP);   //  Press "Up Arrow" key   Moves Y+ (UP)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key4(0);
    Keyboard.send_now();
  }



  if (button4.fallingEdge()) {

    Keyboard.set_modifier(MODIFIERKEY_SHIFT);  //  Press and hold "Shift"
    Keyboard.send_now();

    Keyboard.set_modifier(MODIFIERKEY_SHIFT | MODIFIERKEY_GUI);  //  Press Mac "Command" while still holding "Shift"
    Keyboard.send_now();

    Keyboard.set_key5(KEY_DOWN);   //  Press "Down Arrow" key   Moves Z- (DOWN)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key5(0);
    Keyboard.send_now();
  }


  if (button5.fallingEdge()) {

    Keyboard.set_modifier(MODIFIERKEY_SHIFT);  //  Press and hold "Shift"
    Keyboard.send_now();

    Keyboard.set_modifier(MODIFIERKEY_SHIFT | MODIFIERKEY_GUI);  //  Press Mac "Command" while still holding "Shift"
    Keyboard.send_now();

    Keyboard.set_key6(KEY_UP);   //  Press "Up Arrow" key   Moves Z+ (UP)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key6(0);
    Keyboard.send_now();
  }


}
 
but to send a string of commands when I press and hold the button?

There are many possible ways. One of them would involve creating a boolean variable to remember if the key is up or down, and an elapsedMillis variable to remember how long. In the fallingEdge case, set the boolean to true and the elapsedMillis to zero. In the risingEdge case, set the boolean to false.

Then elsewhere in loop(), check if the boolean is true and if the elapsedMillis variable is greater than however long you wish to wait between keystrokes. If so, send the keystroke and set the elapsedMillis back to zero. As long as the boolean remains true, every time elapsedMillis again increments up to the threshold, your code will send another keystroke.

Hope that makes sense?
 
Yes, what you say I need to do is clear, but how to do it....:(

I do most Arduino code by taking an example and tweaking it to fit my needs. I have no idea how to go about doing what you say I need to do. I thought surely I could find online someone else's examples of how they did this, because making a button repeat a command surely is a common practice I'd think.

Thanks for your input, I'll keep digging.
 
but how to do it....:(

Maybe this can help you get going?

Code:
#include <Bounce.h>

/* Create Bounce objects for each button.  The Bounce object automatically deals with contact
   chatter or "bounce", and it makes detecting changes very simple.*/
Bounce button0 = Bounce(0, 10);  // 10 = 10 ms debounce time which is appropriate for most
Bounce button1 = Bounce(1, 10);  // mechanical pushbuttons. If a button is too sensitive to rapid touch
Bounce button2 = Bounce(2, 10);  // you can increase this time.
Bounce button3 = Bounce(3, 10);
Bounce button4 = Bounce(4, 10);
Bounce button5 = Bounce(5, 10);
/*
  Bounce button6 = Bounce(6, 10);
  Bounce button7 = Bounce(7, 10);
  Bounce button8 = Bounce(8, 10);
  Bounce button9 = Bounce(9, 10);
*/

bool button0down = false;
elapsedMillis button0elapsed;

void setup() {
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  /*
    pinMode(6, INPUT_PULLUP);
    pinMode(7, INPUT_PULLUP);
    pinMode(8, INPUT_PULLUP);
    pinMode(9, INPUT_PULLUP);
  */
  Keyboard.begin();
}

void loop() {
  /* Update all the buttons.  There should not be any long delays in loop(), so this runs
     repetitively at a rate faster than the buttons could be pressed and released.*/
  button0.update();
  button1.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  /*
    button6.update();
    button7.update();
    button8.update();
    button9.update();
  */

  // Check each button for "falling" edge.

  if (button0.fallingEdge()) {

    button0down = true;
    button0elapsed = 0;

    Keyboard.set_modifier(MODIFIERKEY_GUI);  //  Mac "Command" key press and hold
    Keyboard.send_now();

    Keyboard.set_key1(KEY_LEFT);   //  Press "Left Arrow" key   Moves X- (LEFT)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key1(0);
    Keyboard.send_now();
  }

  if (button0.risingEdge()) {
    button0down = false;
  }

  if (button0down && button0elapsed > 500) {
    button0elapsed = 0;
    Keyboard.press(KEY_LEFT);
    Keyboard.release(KEY_LEFT);
  }

  if (button1.fallingEdge()) {

    Keyboard.set_modifier(MODIFIERKEY_GUI);  //  Mac "Command" key press and hold
    Keyboard.send_now();

    Keyboard.set_key2(KEY_RIGHT);   //  Press "Right Arrow" key   Moves X+ (RIGHT)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key2(0);
    Keyboard.send_now();
  }



  if (button2.fallingEdge()) {

    Keyboard.set_modifier(MODIFIERKEY_GUI);  //  Mac "Command" key press and hold
    Keyboard.send_now();

    Keyboard.set_key3(KEY_DOWN);   //  Press "Down Arrow" key   Moves Y- (DOWN)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key3(0);
    Keyboard.send_now();
  }

  if (button3.fallingEdge()) {

    Keyboard.set_modifier(MODIFIERKEY_GUI);  //  Mac "Command" key press and hold
    Keyboard.send_now();

    Keyboard.set_key4(KEY_UP);   //  Press "Up Arrow" key   Moves Y+ (UP)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key4(0);
    Keyboard.send_now();
  }



  if (button4.fallingEdge()) {

    Keyboard.set_modifier(MODIFIERKEY_SHIFT);  //  Press and hold "Shift"
    Keyboard.send_now();

    Keyboard.set_modifier(MODIFIERKEY_SHIFT | MODIFIERKEY_GUI);  //  Press Mac "Command" while still holding "Shift"
    Keyboard.send_now();

    Keyboard.set_key5(KEY_DOWN);   //  Press "Down Arrow" key   Moves Z- (DOWN)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key5(0);
    Keyboard.send_now();
  }


  if (button5.fallingEdge()) {

    Keyboard.set_modifier(MODIFIERKEY_SHIFT);  //  Press and hold "Shift"
    Keyboard.send_now();

    Keyboard.set_modifier(MODIFIERKEY_SHIFT | MODIFIERKEY_GUI);  //  Press Mac "Command" while still holding "Shift"
    Keyboard.send_now();

    Keyboard.set_key6(KEY_UP);   //  Press "Up Arrow" key   Moves Z+ (UP)
    Keyboard.send_now();

    // release all the keys at the same instant
    Keyboard.set_modifier(0);
    Keyboard.set_key6(0);
    Keyboard.send_now();
  }


}
 
Paul, you're awesome! It works when I test it replacing KEY_LEFT with KEY_A (so I can test it in a text editor)

However, when I set it back to KEY_LEFT and test it with my CNC the Key Left function works, it moves the gantry to the Left, but it only does it as a one-shot, holding the button is ignored.

Is it possible that when I hold the button that only the KEY_LEFT command is being sent, without the MODIFIERKEY_GUI command?

Thanks!
 
Last edited:
OK, crap, I just needed to replace the Keyboard.press and Keyboard.release with the Keyboard.set_modifier and Keyboard.send_now commands and it now works when I hold the button.

Now the thing is, holding the button sends the command at the same speed as if I were just manually pressing the button over and over myself. Any way to speed that up?

Thanks!
 
And another in a line of "I should have tried something before posting a question" :rolleyes:

I changed the if (button0down && button0elapsed > 500) from 500 to 100. That worked but it was bouncing so I increased it to 200 and it seems to be stable and noise free now.

Thanks again!
 
Status
Not open for further replies.
Back
Top