Custom Game Controller Using Pro Micro: Inputs Aren't Fast Enough?

I recently splurged and bought a bunch of new components and tools, among which were some Arduino Pro Micros. I wanted to test the key input system, so I edited the keyboard example in the IDE and emulated the original Super Mario Bros. (which I own, piracy is wrong!). The key input worked fine, but Mario was glitching around and accelerating very slowly. Unless he jumped, he could only reach half his normal max speed (when not sprinting). I believe that the problem is that the Micro just isn't fast enough to input data to the emulator. I am using FCEUX to emulate and I have mapped the "d" key as the right button. Here is my code:

#include "Keyboard.h"

const int buttonPin = 4;

void setup() {
  pinMode(buttonPin, INPUT);
  Keyboard.begin();
}

void loop() {
  int buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH){
    Keyboard.print("d");
  }
delay(.0001);
}

Thank you for reading, any feedback is useful!

No, the ProMicro is not slow.
delay(.0001); // delay() only takes integers

Never use a ProMicro, but I think this sketch could work (untested).
Leo..

#include "Keyboard.h"
const byte buttonPin = 4; // button between pin4 and ground, no resistor

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  Keyboard.begin();
}

void loop() {
  if (!digitalRead(buttonPin)) { // if buttonPin is LOW
    Keyboard.write('d');
    delay(20); // only delay after a press
  }
}

KingDubDub:
I believe that the problem is that the Micro just isn't fast enough to input data to the emulator. I am using FCEUX to emulate and I have mapped the "d" key as the right button.

Apart from the "delay(0)" nonsense, I would say that your emulator isn't fast enough for the Micro! :astonished:

Sounds like I was half right then... It was a timing issue, just on the part of my emulator. That also makes sense as I had it run with no delay with similar results, and even had it type "dddddddddddddddddddddddd" in to try to force more inputs in quicker.

No, the ProMicro is not slow.
delay(.0001); // delay() only takes integers

Side note: how do I incorporate decimal numbers into an integer-only argument? I know they are used for PWM delay timings but I never looked into exactly how it worked.

KingDubDub:
Side note: how do I incorporate decimal numbers into an integer-only argument?

You can't.

There is a delayMicroseconds() though.
Most of these commands are right at your fingertips in the IDE (Help>Reference).
Leo..

KingDubDub:
I know they are used for PWM delay timings but I never looked into exactly how it worked.

Umm, no!

No decimals in PWM. :astonished:

Well, I just tested Wawa's code, and it did the same thing my original code did (except the delay caused there to be almost no acceleration to Mario). Although the if statement in the code needs to check if the pin is HIGH, or if the button is pressed.

You can't.

There is a delayMicroseconds() though.
Most of these commands are right at your fingertips in the IDE (Help>Reference).
Leo..

Salt noted, which I deserve. I have taken a long C sabbatical to learn Python and I am trying to re-acclimate to having to put semicolons after everything :D. Thanks for the reminder!

I also tested this with other games, and I got the same results (although some games didn't register any movement whatsoever).

Don't use keyboard.write(). Use keyboard.press() and keyboard.release(). That will allow you to 'hold down' multiple keys at the same time as well as make the game behave properly.

Thank you very much MorganS! Those commands worked perfectly, thank you for saving me a lot of headache!

Here is the code I am using now:

//Connect a button to pin 4 and ground

#include "Keyboard.h"

void setup() {
  pinMode(4, INPUT_PULLUP);
  Keyboard.begin();
}

void loop() {
  if (digitalRead(4)== LOW){ //if pin 4 is grounded:
    Keyboard.press('d');
    delay(1);
  } else {
    Keyboard.release('d');
  }
}

I am hopefully going to implement a tilt sensor into this in order to create a game-control device, or I can use some sort of pull-trigger for the fingers (I would use flex sensors, but those are not cheap!). Thank you all for your help!

Well, I got the MPU working! And here is the code:

/* Tilt Control - King Dub Dub, 11/29/19

A tilt-controller script for USB-HID enabled Arduino boards with the MPU-6050 sensor.
Tilt to control the WASD controls and spacebar (JK I lied about the W, it presses [space]).
There is an additional fail-safe that keeps any keyboard data from being printed if pin 9
isn't grounded. Ground pin 9 with a switch/button when you want to send keyboard inputs.

MPU6050 - Arduino
VCC to 5V
GND to GND
SCL to A5 or SCL
SDA to A4 or SDA
ADO to GND
INT to digital pin 2
Pin 9 to button/switch to ground

*/

#include<Wire.h>
#include<Keyboard.h>

const int MPU_addr=0x68;
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; //sets up the accelerometer XYZ's, temperature, and gyro XYZ's
int minVal=265;
int maxVal=402;
double x,y,z;
int MPUFail = 0;

void setup(){
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);
  Serial.begin(9600);

  pinMode(9, INPUT_PULLUP); //pin 9 is a fail-safe switch
  Keyboard.begin();
}

void loop(){
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B); Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);
  AcX=Wire.read()<<8|Wire.read();
  AcY=Wire.read()<<8|Wire.read();
  AcZ=Wire.read()<<8|Wire.read();

  int xAng = map(AcX,minVal,maxVal,-90,90);
  int yAng = map(AcY,minVal,maxVal,-90,90);
  int zAng = map(AcZ,minVal,maxVal,-90,90);

  x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
  y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);
  z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);
  
  if ((AcX == -1) and (AcY == -1) and (AcZ == -1)){
    MPUFail = 1; //if the Arduino can't connect to the MPU, all raw values come out as -1,
  } else {       // so this is another fail-safe that stops it from pressing keys.            
    MPUFail = 0;
  }

  Serial.print("X= "); Serial.print("N/A"); //the X value doesn't work on our axis
  Serial.print(" Y= "); Serial.print(y);    //print the Y value
  Serial.print(" Z= "); Serial.print(z);    //print the Z value
  Serial.print("  Safety: ");
  if(digitalRead(9) == 0){ //prints if safety button is on
    Serial.print("Off");
  } else {
    Serial.print("On");
  }
  Serial.print("\n");                       //prints a new line

  if ((y >=130) and (digitalRead(9) == 0) and (MPUFail == 0)){ //if tilted left:
    Keyboard.press('a'); //"press" the [a] key
  } else {
    Keyboard.release('a'); //else, stop "pressing"  the [a] key
  }
  if ((z <=335) and (z >= 180) and (digitalRead(9) == 0) and (MPUFail == 0)){ //if tilted down:
    Keyboard.press('s');
    delay(10);
  } else {
    Keyboard.release('s');
  }
  if ((y<=60) and (digitalRead(9) == 0) and (MPUFail == 0)){ //if tilted right:
    Keyboard.press('d');
    delay(10);
  } else {
    Keyboard.release('d');
  }
  if ((z >= 35) and (z<=179) and (digitalRead(9) == 0) and (MPUFail == 0)){ //if tilted up:
    Keyboard.press(' '); //sends [spacebar] key
    delay(10);
  } else {
    Keyboard.release(' ');
  }
  delay(10);//keeps a regulated speed
}

Here's an image of the glove I constructed rather then spend Thanksgiving with my family:

It is a little finicky, but I am a fast learner, so I just need to get the hang of using it. I hope to get the fingers working so I can run, shoot fireballs, climb vines, and maybe code it for other games as well. I might make a new showcase post if this works out!