-1

I put together a NES controller connected to a Arduino mini pro (3.3v) and a Bluetooth HID module (similar to the rn-42 BlueSmirf). I can get it connected to my Macbook and it sends keystrokes.

However, it acts like the key is being repeatedly pressed instead of a key being held down. I need it to act exactly like a keyboard, but right now it presses a key every time it goes through the loop (50ms). Thanks for the help in advance!

Arduino Code:

const int buttonA = 2;//Button: A
const int buttonB = 3;//Button: B
const int buttonC = 4;//Button: Start
const int buttonD = 5;//Button: Select
const int buttonE = 6;//Button: Up
const int buttonF = 7;//Button: Down
const int buttonG = 8;//Button: Left
const int buttonH = 9;//Button: Right

...

void loop()
{
  if (digitalRead(buttonA) == LOW)      //pin is HIGH until a button is pressed
  {Serial.write('A');}
  if (digitalRead(buttonB) == LOW) 
  {Serial.write('B');}
  if (digitalRead(buttonC) == LOW) 
  {Serial.write('1');}
  if (digitalRead(buttonD) == LOW) 
  {Serial.write('2');}
  if (digitalRead(buttonE) == LOW) 
  {Serial.write('U');}
  if (digitalRead(buttonF) == LOW) 
  {Serial.write('D');}
  if (digitalRead(buttonG) == LOW) 
  {Serial.write('L');}
  if (digitalRead(buttonH) == LOW) 
  {Serial.write('R');}
  delay(50);
}
user2238127
  • 63
  • 1
  • 5

2 Answers2

0

To get you started: your program is doing exactly what you told it to. Here's what's happening: every time through the loop the program asks: is the button pressed? If yes, then it sends a keystroke.

What you need to do is store the state of each button (i.e. whether the button is pressed or not), perhaps in an array. Then read each button, check if the state of that button changed from what you stored, and only if it did, send something to the Bluetooth. In that case you'll need to update the state to the new state of the button.

If the button state has not changed, send nothing (for that button). That will have the behavior you want.

angelatlarge
  • 4,086
  • 2
  • 19
  • 36
0

Like @angelatlarge says, your code is doing exactly as what you ask it to (see his response for why).

Your first step should probably be to implement @angelatlarge's proposal: store the state of the button, and only send the character if it is not previously pressed and it is now. For one button, it would look something like this*:

const int buttonA = 2;
boolean wasAPressed = false;
boolean isAPressed  = false;

// ...

loop() {

    isAPressed = (digitalRead(buttonA) == LOW);
    if(!wasAPressed && isAPressed) {
        wasAPressed = true;
        Serial.write('A');
    } else if(wasPressed && !isAPressed){
        wasAPressed = false;
    }

    // ...
}

The logic is basically simple. We have two boolean variables, giving you four possible options. If the button wasn't pressed and it is now, save the state (wasAPressed = true) and send the character. If it was previously pressed, but it isn't now, save the state (wasAPressed = false). In the remaining two cases, don't change anything.

Note however, that this will simply send a single 'A' every time you press button A. If you want to simulate a long press, you have to add additional logic on both sides. Here for example, I've established that 'Ad' means that the A button was pushed (d**own), while 'Au' means the *A button was released (*u**p).

// ...

isAPressed = (digitalRead(buttonA) == LOW);
if(!wasAPressed && isAPressed) {
    wasAPressed = true;
    Serial.write('Ad');
} else if(wasAPressed && !isAPressed){
    wasAPressed = false;
    Serial.write('Au');
}

// ...

Your receiving code on your computer will then read the first character to know who we're talking about, and the second to know if it is a press or a release action. Finally, you must find the code required to simulate a key press and a key release individually.

Philippe Signoret
  • 13,299
  • 1
  • 40
  • 58