0

So, I made this code (I'm rather new to this). The only thing that the Arduino should do, is when I press the button on pin 2, turn on the LED on pin 4 and emulate CTRL + R on the keyboard for the computer. Then, if the LED is on and I hit the button again, turn it off and hit the spacebar on my computer. But as soon as I hit the button for the first time, it does indeed press CTRL + R and the LED turns on, but after the delay, it immediately skips checking if I am pressing the button and assumes that I am pressing the button. Thereby it only sees that the LED is on and it turns it off while hitting the spacebar. Any suggestions?

#include <Keyboard.h> int buttonPin = 2; int ledPin = 4; int val = 0; void setup() { // put your setup code here, to run once: pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT_PULLUP); Keyboard.begin(); } void loop() { val = digitalRead(buttonPin); // check if the pushbutton is pressed. If it is, the buttonState is HIGH: if ((val == LOW) && (digitalRead(ledPin) == LOW)) { // turn LED on: digitalWrite(ledPin, HIGH); Keyboard.press(KEY_LEFT_CTRL); Keyboard.press('r'); delay(100); Keyboard.release(KEY_LEFT_CTRL); Keyboard.release('r'); delay(500); } if ((val == LOW) && (digitalRead(ledPin) == HIGH)) { digitalWrite(ledPin, LOW); Keyboard.write(32); } if ((val == HIGH) && (digitalRead(ledPin) == LOW)) { digitalWrite(ledPin, LOW); } if ((val == HIGH) && (digitalRead(ledPin) == HIGH)) { digitalWrite(ledPin, HIGH); } }

2
  • think about what is the sequence of button states when you press the button twice ... are you checking for all of the states?
    – jsotola
    Apr 13, 2020 at 3:57
  • You declared ledPin as output, then in the loop you check its status with digitalRead(ledPin). This is not going to work as you intend doing. How is a pin meant to source current, read its own voltage? For that purpose you need a flag representing its state, not the electric state. Sep 19, 2021 at 12:20

2 Answers 2

1

Try something like this.

The code does not use button states in its decision making.

Instead, it looks for the transition between button states, so holding the button does not generate events.

void loop() {

  val = digitalRead(buttonPin);

  if (val != oldButtonState) {      // button state transition
    oldButtonState = val;
    if (val == LOW) {               // transition from "released" to "pressed"
      buttonClicked = true;         // set click flag
    }
  }



  if ( buttonClicked ) {

    buttonClicked = false;                // clear click flag

    if (digitalRead(ledPin) == LOW) {
      digitalWrite(ledPin, HIGH);         // turn LED on
      Keyboard.press(KEY_LEFT_CTRL);      // send CTRL-R
      Keyboard.press('r');
      delay(100);
      Keyboard.release(KEY_LEFT_CTRL);
      Keyboard.release('r');
      delay(500);
    }

    else {
      digitalWrite(ledPin, LOW);          // turn LED off
      Keyboard.write(32);                 // send space
    }
  }
}
0

Your code isn't checking for a button. It's checking the value in val. That only gets updated once per loop. Let's say the code enters the first if statement because the val is LOW and the LED is also LOW. This sets the LED to HIGH. Now the next if statement, val is still LOW and now LED is HIGH so that one is true as well.

I think what you want is to use "else if" so it will skip the rest once it finds a true one.

void loop() {
  val = digitalRead(buttonPin);
  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if ((val == LOW) && (digitalRead(ledPin) == LOW)) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    Keyboard.press(KEY_LEFT_CTRL);
    Keyboard.press('r');
    delay(100);
    Keyboard.release(KEY_LEFT_CTRL);
    Keyboard.release('r');
    delay(500);
  }
  else if ((val == LOW) && (digitalRead(ledPin) == HIGH)) {
    digitalWrite(ledPin, LOW);
    Keyboard.write(32);
  }
  else if ((val == HIGH) && (digitalRead(ledPin) == LOW)) {
    digitalWrite(ledPin, LOW);
  }
  else if ((val == HIGH) && (digitalRead(ledPin) == HIGH)) {
    digitalWrite(ledPin, HIGH);  
  }
}
3
  • Hmm, if I try this, the LED does stay solid after the first press and it doesn't hit my spacebar yet. But when I hit the button a second time, it performes both CTRL + R and the spacebar and the LED stays solid. I think we're on the right trace but there's still some problems.
    – Hendriks3D
    Apr 13, 2020 at 7:57
  • Well there's no delay or anything after the action in that second if statement like there is on the first one. My bet is that the loop comes back around and sees that the button is still pressed and catches the first if again. Look at the State Change Example in the IDE for some inspiration on how to respond to the change in state of the button and not just the fact that it is held down. Detect the edges. Only react once per press.
    – Delta_G
    Apr 13, 2020 at 22:54
  • You got me on the right track. I now used press counts. After it its CTRL + R it sets the button press count to 2, and if the value becomes 3 (ie hitting the button a 2nd actual time) it hits space bar, turns off the LED and sets the press count back to 0. Works fllawlessly. THANK U very much!
    – Hendriks3D
    Apr 14, 2020 at 0:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.