Teensy 3.1 analog sticks to generate keyboard input

Status
Not open for further replies.

Mundm28

Member
Hi guys,
at the moment im building a gameboy casemod similar to this: http://www.xodustech.com/projects/ra...gameboy-pocket .
For the keypresses im using my teensy to act as a usb keyboard and mouse controller just as the guy on this website did it, but i want to include two psp replacement analog sticks in my project so i have better ps1 emulation control.
I want them to behave as keyboard keys just like the other buttons so they arent actually analog because i think this is the best way to include them in the teensyduino code provided by the website (and here: https://github.com/WarriorRocker/pi-pocket), as i dont have to specify another input mode for them then.
I did not find someone doing it that way and this is my first time using a c language instead of python.
so i edited the code to include the analog sticks but as im on vacation i cant try it out. so my question is does the approach i chose work at all?
(i dont want you to painstakingly look for syntax mistakes etc, but just ask you to give it a look and see if youre experienced if its complete shit or might work)
Thanks
 

Attachments

  • gamepad_edited.ino
    7.4 KB · Views: 171
  • gamepad.ino
    4 KB · Views: 148
Keyboard.set:key4
Should be
Keyboard.set_key4

But otherwise it looks okay

EDIT -
Oh wait no it doesn't. Take for example:
Code:
if (analogRead(A3) >= 400 && analogRead(A3)<= 600  && rhorival != 2){
      Keyboard.set_key3(0);
When this stick is in the middle key3 will always be zero.

As there is this code later on:
Code:
if (bB.fallingEdge()) {
      Keyboard.set_key3(KEY_L);
      Keyboard.send_now();
    }

When bB is pressed it will pulse KEY_L for one iteration and then the top chunk of code will stop L from being held down
 
Last edited:
my idea was to set the right-horizontal-value (rhorival) to 2 so the script knows the stick is alredy in the middle and wont set this to 0 again as there are 2 requirements to execute the code and they are only met when the variable is for example 1 or 3 when the stick is moved
Code:
    else if (analogRead(A3) >= 400 && analogRead(A3)<= 600  && rhorival != 2){
      Keyboard.set:key3(0);
      Keyboard.send_now();
      rhorival = 2;}

and for the later part i thought as the usb protocol only can send 6 keys plus modifiers at one time i set it up that way as you dont move the right stick and press one of these buttons at the same time. you would have to really hold the controller in a weird way to do this i think
 
Last edited:
Yep, that'll do it!

You may find if you're floating around the 400 value it turns it on and off rapidly. Consider looking into fuzzy logic if that happens to be the case
 
Last edited:
dude youre quick...
yeah maybe ill implement something like this:

Code:
int data =0;
for (int i=0; i<3;i++) {
    data = data + analogRead(A0);
}
data = data / 3;

to make measurements more consistent and also do something to limit the times the keys are checked per second a bit so you dont really feel it but the teensy doesnt run it like crazy.

But thanks a lot you really helped me!
 
dude you're quick...
I'm at work and I've been waiting on the hardware guys to finish a prototype for a few weeks now ;)
I've pretty much exhausted all I can do without it

Smoothing can help take out any spikes but obviously at the cost of responsiveness. A running/moving average might work out better for you

In terms of stopping it toggling you can introduce a kind of fuzzy state. More commonly known in the joystick world as a deadspace... I think

Code:
#define DS 50 //Deadspace

if (analogRead(A3) > 600 && rhoritval != 3){
      Keyboard.set:key3(KEY_B);
      Keyboard.send_now();
      rhorival = 3;}
    else if (analogRead(A3) < 400 && rhorival != 1){
      Keyboard.set:key3(KEY_M);
      Keyboard.send_now();
      rhorival = 1;}
    else if (analogRead(A3) >= 400+DS && analogRead(A3)<= 600-DS  && rhorival != 2){
      Keyboard.set:key3(0);
      Keyboard.send_now();
      rhorival = 2;}

This means that between 400-450 and 550-600 the state won't change and the state remains at it's previous state. This means if you move the stick to 400 and wiggle it a little it'll just set KEY_M once and won't keep toggling. This helps to keep your controller as responsive as possible.

I guess if you put a cat in a box who moved the analogue stick to 425 the key would be both KEY_B and 0
 
Last edited:
yes its called a deadzone ..its a span for the 'rest' position .... using it in combination with hysterisis is what zeno has suggested (averaging is a good idea too), and it will get you all the way home. I do hysterisis a little differently from zeno ... Here is some code (from memory, untested, no compiler) I use it for an analog slider controlling a motor... effectively loosing resolution (I have an idea to improve resolution but I don't think you need it)
Code:
//global
bool zero=false;
int currentread;
int prevread = 512;

//loop()
currentread = analogRead(A3);

if ((prevread + 3) < currentread) {prevread=currentread;}
else if ((prevread - 3) > currentread) {prevread=currentread;}
else currentread = prevread;

if (currentread < 600 && currentread > 400) { if (zero=false) {Keyboard.set:key3(0); Keyboard.send_now(); zero = true;}}
else if(currentread >= 600 {Keyboard.set:key3(KEY_B);
      Keyboard.send_now(); zero=false;}
else  {Keyboard.set:key3(KEY_M);
      Keyboard.send_now(); zero=false;}
 
Last edited:
Finally finished

there is the joystick usb type, which is good for analog sticks / gamepads ....
yeah for games only would be better but i want to control xmbc and cli music players and stuff with it too

So its been a while and i finally tested everything.
Thanks to you guys i only had to make very little changes so here is a pic of my test setup with only one stick attached (was alredy disassembling when i thought i could make a picture)
and the final version of the code will be attached below so guys searching for similar things can get it! 20160220010803.jpg
but beware.... there are 4 variables with non selfdocumenting names, but im to tired to change them before uploading.

btw. is it possible or common to mark a thread as closed in this forum?
 

Attachments

  • gb.ino
    7.7 KB · Views: 153
Status
Not open for further replies.
Back
Top