Pushbutton Keyboard.write continuously running.

Before I start, I know I should be using an Uno or something other than an esplora. But since my Uno refuses to let me upload code to it. (Pretty sure I accidentally killed the bootloader last year messing with some LED strips.) The esplora was all that radioshack had in stock anymore.

Now to my problem. I'm attempting to set up a simple control panel to input keypresses with a SPST Momentary switch, And for every button press an LED will toggle either on or off to indicate it's activated. I've got the LED working with the button just fine (after a few hours) but I can't for the life of me get it to output a keyboard command without it spamming them one after the other until i reset the board. I've omitted all my attempts to get it to work. It's probably something super simple i'm missing but it's going right over my head.

It just needs to send a single keystroke to the computer. "u". It always gives me "uuuuuuuuuuuuu" to infinity and beyond..

#include <Keyboard.h>
#include <Esplora.h>
  const int pinButton = 8;
  const int ledPin = 7;
  int state = LOW;
  int reading;
  int previous = LOW;
  long time = 0;
  long debounce = 200;

void setup() {
  // There's nothing to set up for this sketch
  pinMode(ledPin, OUTPUT);
  pinMode(pinButton, INPUT_PULLUP);
  Keyboard.begin();
  
}

void loop()
{
  reading = digitalRead(pinButton);
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    if (state == HIGH)
    state = LOW;
    else
    state = HIGH;

    time = millis();
   }

   digitalWrite(ledPin, state);
   
   previous = reading;
}

The control panel will eventually only have 3 inputs and 3 outputs. If that's of any importance. Any help here would be greatly appreciated!

  pinMode(pinButton, [color=red]INPUT_PULLUP[/color]);
...
 reading = digitalRead(pinButton);
  if (reading == [color=red]HIGH[/color] && previous == LOW...

--> with an INPUT_PULLUP your button is expected to be active LOW (connected to GND). How is this button wired?

Oh, Forgot I changed that. It does the same if it's set to pinMode(pinButton, INPUT); though.

Button is wired to a 10k ohm Resistor and pin 8. Other end of button is to ground.

OK if you wired to ground then you need to use the input pullup and you code will trigger upon button release, not button push

sorry if this is obvious but you are aware that you do digitalWrite(ledPin, state); always (at every spin of the loop()) and not just at time of state change, right? so if this is where you've put your code to send the letter, then no surprise you send it all the time

if you want to do it only once you need to have the digitalWrite as part of the state change test

(I also fixed the type of your variables to better match what's good practice or required for the timing to work fine over a long period (unsigned long versus long))

const byte pinButton = 8;
const byte ledPin = 13;
byte state = LOW;
byte reading;
byte previous = LOW;
unsigned long time = 0; // important to use unsigned long not just long or you'll have a problem in 25 days or so
unsigned long debounce = 200;

void setup() {
  // There's nothing to set up for this sketch
  pinMode(ledPin, OUTPUT);
  pinMode(pinButton, INPUT_PULLUP);
}

void loop()
{
  reading = digitalRead(pinButton);
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
   // THIS IS WHERE YOU NEED TO DO STUFF REQUIRED ONLY IN CASE OF STATE CHANGE
    if (state == HIGH) {
      state = LOW;
      // do what's required when going to LOW
    } else {
      state = HIGH;
      // do what's required when going to HIGH
    }
    digitalWrite(ledPin, state);
    time = millis();
  }
  previous = reading;
}

That has done the trick! After realizing I also needed to put Keyboard.write('u'); before state= LOW;

As for the digitalWrite(ledPin, state); I was following a tutorial that was supposed to give me the desired effect. I tried it first only with LED to get that right. Then came the keypress repeat. However old code could be useful for some sort of spam bot. :slight_smile: I had tried to put the keypress code in many places.

Hopefully later today I can get into 3D printing my enclosure and see about adding the extra 2 inputs without too much hassle. Can't thank you enough J-M-L!

This is currently how It's set up.

/*

 */
 
#include <Keyboard.h>
#include <Esplora.h>
const byte pinButton = 8;
const byte ledPin = 7;
byte state = LOW;
byte reading;
byte previous = LOW;
unsigned long time = 0; // important to use unsigned long not just long or you'll have a problem in 25 days or so
unsigned long debounce = 200;

void setup() {
  // There's nothing to set up for this sketch
  pinMode(ledPin, OUTPUT);
  pinMode(pinButton, INPUT_PULLUP);
  Keyboard.begin();
}

void loop()
{
  reading = digitalRead(pinButton);
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
   // THIS IS WHERE YOU NEED TO DO STUFF REQUIRED ONLY IN CASE OF STATE CHANGE
    if (state == HIGH) {
      Keyboard.write('u');
      state = LOW;
      // do what's required when going to LOW
    } else {
      Keyboard.write('u');
      state = HIGH;
      // do what's required when going to HIGH
    }
    digitalWrite(ledPin, state);
    time = millis();
  }
  previous = reading;
}

So as you send the same letter 'u' at every press - your if can become just this:

if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    Keyboard.write('u');
    digitalWrite(ledPin, state = !state); // a bit dirty coding :)
    time = millis();
  }

Note that 200ms for a debounce is considered high. usually a value between 15 and 50 is enough for most buttons.

Good job!

have fun

Okay, So upon adding the extra buttons, and another few hours of debugging I've run into another problem. I've recorded a video to help explain what's going on now. All buttons are wired up the same way with the exception of the Toggle Switch and red button. I really don't mind how that one works. I'd prefer the use of the toggle switch anyway, So ignore that one. The problem is with the second button.

The order the physical buttons are in the code, from top to bottom is pinButton2 - pinButton3 - pinButton1

pinButton3 doesn't do anything. Here's the video.

And here's my current code. It's messy, but for the most part it works.

/*

 */
 
#include <Keyboard.h>
#include <Esplora.h>
const byte pinButton1 = 0;
const byte ledPin1 = 8;
const byte pinButton2 = 7;
const byte ledPin2 = 16;
const byte pinButton3 = 15;
const byte ledPin3 = 14;
byte state1 = LOW;
byte state2 = LOW;
byte state3 = LOW;
byte reading1;
byte reading2;
byte reading3;
byte previous1 = LOW;
byte previous2 = LOW;
byte previous3 = LOW;
unsigned long time = 0; // important to use unsigned long not just long or you'll have a problem in 25 days or so
unsigned long debounce = 25;

void setup() {
  // Setting up the LEDs, Buttons and Keyboard.
  pinMode(ledPin1, OUTPUT);
  pinMode(pinButton1, INPUT_PULLUP);
  pinMode(ledPin2, OUTPUT);
  pinMode(pinButton2, INPUT_PULLUP);
  pinMode(ledPin3, OUTPUT);
  pinMode(pinButton3, INPUT_PULLUP);
  Keyboard.begin();
}

void loop()
{
  reading1 = digitalRead(pinButton1);
  if (reading1 == HIGH && previous1 == LOW && millis() - time > debounce) {
    Keyboard.write('u');
    digitalWrite(ledPin1, state1 = !state1); // a bit dirty coding :)
    time = millis();
  }
{
  previous1 = reading1;
  {
  reading2 = digitalRead(pinButton2);
  if (reading2 == HIGH && previous2 == LOW && millis() - time > debounce) {
    Keyboard.write('a');
    digitalWrite(ledPin2, state2 = !state2); // a bit dirty coding :)
    time = millis();
  }
  }
  {
  previous2 = reading2;
{
  reading3 = digitalRead(pinButton3);
  if (reading3 == HIGH && previous3 == LOW && millis() - time > debounce) {
    Keyboard.write('l');
    digitalWrite(ledPin3, state3 = !state3); // a bit dirty coding :)
    time = millis();
  }
  previous3 = reading3;
}
  }
}
}

Again, Probably a super simple fix, but it's going right over my head..

what's going on with all the {{{{ }}}}}} ???

this should be enough brackets

void loop()
{
  reading1 = digitalRead(pinButton1);
  if (reading1 == HIGH && previous1 == LOW && millis() - time > debounce) {
    Keyboard.write('u');
    digitalWrite(ledPin1, state1 = !state1); // a bit dirty coding :)
    time = millis();
  }
  previous1 = reading1;
  
  reading2 = digitalRead(pinButton2);
  if (reading2 == HIGH && previous2 == LOW && millis() - time > debounce) {
    Keyboard.write('a');
    digitalWrite(ledPin2, state2 = !state2); // a bit dirty coding :)
    time = millis();
  }
  previous2 = reading2;
  
  reading3 = digitalRead(pinButton3);
  if (reading3 == HIGH && previous3 == LOW && millis() - time > debounce) {
    Keyboard.write('l');
    digitalWrite(ledPin3, state3 = !state3); // a bit dirty coding :)
    time = millis();
  }
  previous3 = reading3;
}

now your problem is that you have only one time variable shared across the 3 buttons so depending how you press them (2 at the same time) that will get you in trouble

only one button will be pressed at a time, I tried adding more time variables but pinButton3 still refuses to do what it should. It's wired as it should be but completely unresponsive.

*EDIT

Nevermind! The button is just a bit more sensitive to the rest. I got mad at it and pushed it too hard and it worked as intended. Who knew getting angry helps. :wink: Thanks so much for all the help!

Doesn't the esplora have built in buttons? Why don't you use those? The pins you use have other functions too, pin 15 is PCINT1 not sure if this is not used by your keyboard library