Leonard USB Keyboard - Two outputs from one key press

I’m scratching my head a little on this but I’m sure I’m over thinking it.

I looking to have two different button presses on an input to output two different keystrokes via USB.

eg.

normal key press = x
hold key press = y

My code in the loop is:

if (digitalRead(8)==LOW){
    Keyboard.print("9");
    delay(200);}

I was thinking something along the lines of if (digitalRead(8)==LOW) then using a counter to somehow count the button press but im not sure if that will work

But it doesn’t work. Any ideas?

you can do this:

if (digitalRead(8)==LOW)
{
  delay(100);
     if(digitalRead(8)==LOW)
      {
        //hold key press
       }
      else
       {
         //short key press
        }
   
}

But this wud create a delay of 100ms for every keystroke... is that fine or not for you project? There must be a method without this delay, im thinking over it...

normal key press = x hold key press = y

Can you please quantify how long the keypress needs to be before it is considered to be held ?

The code in this Thread has a neat way of dealing with different button presses,

...R

Thank you everyone for you responses.

UKHeliBob: I would say 1000ms would be classed as button hold.

Robin2: Thanks for that I will have a look into it.

That code worked a charm thanks Robin2.

I've made some headway with this.....

and its working except I have all the inputs setup up to write their key in ASCII using Keyboard.write()

so when I hold a button it will print all the BUTTON PRESS keys or all the BUTTON HOLD keys depending on the button state.

eg.

void clickEvent() {
  
   //if the button is pressed
   if(digitalRead(0)==LOW){
    //Send the ASCII Key [0]
    Keyboard.write(48);
    delay(200);}
   
    if (digitalRead(1)==LOW){
    //Send the ASCII Key [1]
    Keyboard.write(49);
    delay(200);}

// HOLDEvents to trigger

void holdEvent() {
   //if the button is pressed
   if(digitalRead(0)==LOW){
    //Send the ASCII Key [k]
    Keyboard.write(107);
    delay(200);}
   
   if (digitalRead(1)==LOW){
    //Send the ASCII Key [l]
    Keyboard.write(108);
    delay(200);}

The output I'm getting is CLICK = 01 and HOLD = kl

How would I get it to only print the single input per button press

Tip: try not to use delay() it is a blocking function that means the Arduino will sit there and do nothing for the defined time. Check out Robin2 thread for more information. forum.arduino.cc/index.php?topic=223286.0

Here is my code.

I’ve got it so it will type on HOLD Pin( 8 ) only… :frowning:

void setup() 
{
   //Build in delay for testing!!!
   //delay(20000);


  // Initize inputs for wired USB interface
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
   Keyboard.begin();
   
}

void loop() 
{

   // Get button event and act accordingly
   int b = checkButton();
   if (b == 1) clickEvent();
   //if (b == 2) doubleClickEvent();
   if (b == 3) holdEvent();
   //if (b == 4) longHoldEvent();

}

   //=================================================
// CLICK Events to trigger

void clickEvent() {
   
  

    if(digitalRead(8)==LOW){
    //Send the message
    Keyboard.print("9");
    delay(200);}
   
    if (digitalRead(9)==LOW){
    //Send the message
    Keyboard.print("0");
    delay(200);}

    if(digitalRead(10)==LOW){
    //Send the message
    Keyboard.print("q");
    delay(200);}
   

    if (digitalRead(11)==LOW){
    //Send the message
    Keyboard.print("w");
    delay(200);}

 
}

//=================================================
// HOLDEvents to trigger

void holdEvent() {
 

    if(digitalRead(8)==LOW){
    //Send the message
    Keyboard.print("l");
    delay(200);}
   
    if (digitalRead(9)==LOW){
    //Send the message
    Keyboard.print("z");
    delay(200);}

    if(digitalRead(10)==LOW){
    //Send the message
    Keyboard.print("x");
    delay(200);}
   

    if (digitalRead(11)==LOW){
    //Send the message
    Keyboard.print("c");
    delay(200);}

    
}

//=================================================
//  MULTI-CLICK:  One Button, Multiple Events

// Button timing variables
int debounce = 0;          // Default = 20ms. ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 200;            // Default = 250ms. max ms between clicks for a double click event
int holdTime = 1000;        // ms hold period: how long to wait for press+hold event
int longHoldTime = 3000;    // ms long hold period: how long to wait for press+hold event
    
// Button variables
boolean buttonVal = HIGH;   // value read from button
boolean buttonLast = HIGH;  // buffered value of the button's previous state
boolean DCwaiting = false;  // whether we're waiting for a double click (down)
boolean DConUp = false;     // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true;    // whether it's OK to do a single click
long downTime = -1;         // time the button was pressed down
long upTime = -1;           // time the button was released
boolean ignoreUp = false;   // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false;        // when held, whether to wait for the up event
boolean holdEventPast = false;    // whether or not the hold event happened already
boolean longHoldEventPast = false;// whether or not the long hold event happened already
    
int checkButton() {   
   int event = 0;
   buttonVal = digitalRead(8);
   // Button pressed down
   if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce)
   {
       downTime = millis();
       ignoreUp = false;
       waitForUp = false;
       singleOK = true;
       holdEventPast = false;
       longHoldEventPast = false;
       if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true)  DConUp = true;
       else  DConUp = false;
       DCwaiting = false;
   }
   // Button released
   else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce)
   {       
       if (not ignoreUp)
       {
           upTime = millis();
           if (DConUp == false) DCwaiting = true;
           else
           {
               event = 2;
               DConUp = false;
               DCwaiting = false;
               singleOK = false;
           }
       }
   }
   // Test for normal click event: DCgap expired
   if ( buttonVal == HIGH && (millis()-upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true && event != 2)
   {
       event = 1;
       DCwaiting = false;
   }
   // Test for hold
   if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
       // Trigger "normal" hold
       if (not holdEventPast)
       {
           event = 3;
           waitForUp = true;
           ignoreUp = true;
           DConUp = false;
           DCwaiting = false;
           //downTime = millis();
           holdEventPast = true;
       }
       // Trigger "long" hold
       if ((millis() - downTime) >= longHoldTime)
       {
           if (not longHoldEventPast)
           {
               event = 4;
               longHoldEventPast = true;
           }
       }
   }
   buttonLast = buttonVal;
   return event;
}

Any feedback is greatly appreciated as I’m currently pulling my hair out yet enjoying my arduino.

Maestr0: I've got it so it will type on HOLD Pin( 8 ) only........ :(

Does that mean you want the same behaviour for several buttons.

I had assumed from your Original Post "I looking to have two different button presses on an input to output two different keystrokes" that you only wanted to use one button.

I suspect that if you want to have multiple actions on multiple buttons you will need to sit back with a cup of coffee (or 5) and figure out how to abstract the essence of the code so it can apply to (say) an array of pins. (Each pin relating to one button).

I would also spend time (perhaps 2 cups of coffee) thinking seriously whether you actually require what you think you require.

Tell us what you are trying to achieve rather then how you think it might be done

...R

Look this

But dont work with my Compiler.