[SOLVED]Arcade trackball to usb mouse help

Hello all.

I was wondering if there is a way to use an arduino leonardo as a way for me to get this golden tee trackball along with about 10 buttons working as a usb gamepad in my windows environment. How i see it is if someone here can help me with this then i can do the rest as long as it all works as a usb gamepad in windows. Like somehow make the trackball show up in the windows joystick window as an analog joystick like you would find on a playstation controller. In doing so the faster the trackball is moved the more acceleration there is. Any help with this? I have the Leonardo.

This all sounds feasible but you need to supply links/details to the trackball your wanting to use to confirm it can be interfaced with the Leonardo.
For some mad reason the HID library used on the Leonardo does not include joystick descriptions but there are posts outlining the changes needed to the core files to add a joystick that I have used and tested. I cannot remember how many buttons it supported though but can see no reason it should not support at least 8.

Riva:
This all sounds feasible but you need to supply links/details to the trackball your wanting to use to confirm it can be interfaced with the Leonardo.
For some mad reason the HID library used on the Leonardo does not include joystick descriptions but there are posts outlining the changes needed to the core files to add a joystick that I have used and tested. I cannot remember how many buttons it supported though but can see no reason it should not support at least 8.

link to the trackball

I cannot see a schematic on the pinout of the 6 pin connector but (in no particular order) is probably VCC, GND, Y-A, Y-B, X-A & X-B. The trackball output is just like the output from 2x encoders so as long as the voltage matches your Arduino it should be easy to interface.

There are loads of examples of different methods of reading encoders in the link above so just pick one that gives you a suitable feel or write your own code if you prefer.

Interfacing the push buttons to the Arduino is very simple and just requires an Arduino pin connected to ground through the button like below

I cannot find the thread on here that outlines the additions you need to apply to the Leonardo core files to give joystick support but maybe someone else can or you just grab a modified copy from someone/somewhere else.

Riva:
I cannot see a schematic on the pinout of the 6 pin connector but (in no particular order) is probably VCC, GND, Y-A, Y-B, X-A & X-B. The trackball output is just like the output from 2x encoders so as long as the voltage matches your Arduino it should be easy to interface.

There are loads of examples of different methods of reading encoders in the link above so just pick one that gives you a suitable feel or write your own code if you prefer.

Interfacing the push buttons to the Arduino is very simple and just requires an Arduino pin connected to ground through the button like below

I cannot find the thread on here that outlines the additions you need to apply to the Leonardo core files to give joystick support but maybe someone else can or you just grab a modified copy from someone/somewhere else.

The trackball uses two sets of two opts. I hooked it up to 5vdc and put a meter on one of the pins and found out that it spits out 5vdc (about) and 0 volts. It does this on both wires on both axis. So would I need to also come up with a voltage divider so I don't release the smoke from the arduino lol? Maybe to drop it down to 3.3 volts or so? I have the Leonardo joystick library on my Leonardo but I have no idea how to modify the code that is there. It shows up in windows as a joystick. It has 32 buttons, two POV hats, rudder, throttle and two analog joysticks. All the code does though is a test when pin A5 (I think) is shorted to ground. I'm not really sure how to modify the code or make even the buttons work lol. I'm really new to this but I know a lot about hardware and electronics.

If your you using a 3.3V Leonardo/ProMicro then try using 3.3V instead of 5v and see if the output still works. If your using a 5V Leonardo/ProMicro then no need of a voltage divider.
Please link to the site where you got the Joystick library from. The site should probably outline how to use the library or supply examples of its use with the library code.
The version I have has helpful info like...

// Joystick
//  Usage: Joystick.move(x, y, throttle, buttons)
//  x & y forward/left = 0, centre = 127, back/right = 255
//  throttle max = 0, min = 255
//  8 buttons packed into 1 byte

Link to the page.

I don't understand how to use the instructions or how to incorporate the track ball into that code.

From a quick look at the link I supplied in #3 a suitable library would probably be this as it allegedly works well with 2x encoders like you have in the trackball.
Get the trackball connected and working with the example sketch supplied printing results to the serial monitor and then try incorporating the Joystick element.

I'm not convinced how well a trackball will work as a joystick but each to there own.

Riva:
From a quick look at the link I supplied in #3 a suitable library would probably be this as it allegedly works well with 2x encoders like you have in the trackball.
Get the trackball connected and working with the example sketch supplied printing results to the serial monitor and then try incorporating the Joystick element.

I'm not convinced how well a trackball will work as a joystick but each to there own.

Well if the encoders show up in windows as four buttons then I should be able to use a key mapper program to take those four buttons and turn them into the mouse on the PC. I will try what you supplied when I get home, in at work right now. Oddly enough I work at a vending company and I'm in charge of the amusement machines as a tech lol. This is where I originally got the track ball from :slight_smile: I get a lot of strange parts from old machines and such. I actually have another post in the displays section of this forum for a 1x16 vfd star burst display but no one has answered it yet. Would you maybe mind going over there and taking a look at it and see if you could sort it out for me?

hydrolisk1792:
Well if the encoders show up in windows as four buttons then I should be able to use a key mapper program to take those four buttons and turn them into the mouse on the PC.

Does this mean you really want to use the trackball as a mouse and not some sort of joystick as you posted in your OP. Maybe you should explain exactly what your hoping to achieve (mouse, joystick or something else).
Converting the trackball output to a mouse should be a lot easier.

I need it to show up in windows as a gamepad. From there i can also have the other ten buttons. from there i can set everyrhing up with xpadder for the trackball as the mouse, three buttons for the mouse and the other seven buttons as hotkeys like media controls and such. this is for an embeded project.

Okay I used that link you suggested and seen it in the serial monitor. So it does see the trackball. Now how would i make this code work as a gamepad with the buttons and such? My apologizes for so many questions. I'm new to this arduino programming thing. thank you for all your help so far.

You will need to decide how your going to setup the trackball as a mouse but one way might be to note the time difference in readings between each encoder change to determine how fast it is being moved and then map this to a value between -127 and 127 to pass to the joystick axis.
From the joystick and encoder sketches you should be able to glean the correct calls needed to adjust the a joystick axis and do button presses but I have attached a totally untested example below that might start you in the right direction.

#include <Encoder.h>
#include <Joystick.h>

// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 9;
  
Encoder axisX(0, 1);
Encoder axisY(2, 3);

void setup() {
  // Initialize 4 Button Pins
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);

  // Initialize Joystick Library
  Joystick.begin(false);
}

void loop() {
  Joystick.setXAxis(0);               // Center joystick X
  int newX = axisX.read();            // Read X encoder
  if (newX > 0)                       // Has the value increased since last read
  {
    Joystick.setXAxis(127);           // Set joystick X hard over to right
    axisX.write(0);                   // Zero encoder count for next time
 }
  if (newX < 0)                       // Has encoder decreased since last read
  {
    Joystick.setXAxis(-127);          // Set joystick hard left
    axisX.write(0);                   // Zero encoder count
  }
  
  Joystick.setYAxis(0);               // Center joystick Y
  int newY = axisY.read();
  if (newY > 0) 
  {
    Joystick.setYAxis(127);
    axisY.write(0);
  }
  if (newY < 0) 
  {
    Joystick.setYAxis(-127);
    axisY.write(0);
  }

  // Read button pin values
  for (byte index = 0; index < 4; index++)
  {
    byte currentButtonState = !digitalRead(index + pinToButtonMap); // Read button state
    Joystick.setButton(index, currentButtonState);                  // Set state in joystick
  }

  Joystick.sendState();               // Send the joystick data
  delay(50);                          // Wait a bit
}

Riva:
You will need to decide how your going to setup the trackball as a mouse but one way might be to note the time difference in readings between each encoder change to determine how fast it is being moved and then map this to a value between -127 and 127 to pass to the joystick axis.
From the joystick and encoder sketches you should be able to glean the correct calls needed to adjust the a joystick axis and do button presses but I have attached a totally untested example below that might start you in the right direction.

#include <Encoder.h>

#include <Joystick.h>

// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 9;
 
Encoder axisX(0, 1);
Encoder axisY(2, 3);

void setup() {
 // Initialize 4 Button Pins
 pinMode(9, INPUT_PULLUP);
 pinMode(10, INPUT_PULLUP);
 pinMode(11, INPUT_PULLUP);
 pinMode(12, INPUT_PULLUP);

// Initialize Joystick Library
 Joystick.begin(false);
}

void loop() {
 Joystick.setXAxis(0);               // Center joystick X
 int newX = axisX.read();            // Read X encoder
 if (newX > 0)                       // Has the value increased since last read
 {
   Joystick.setXAxis(127);           // Set joystick X hard over to right
   axisX.write(0);                   // Zero encoder count for next time
}
 if (newX < 0)                       // Has encoder decreased since last read
 {
   Joystick.setXAxis(-127);          // Set joystick hard left
   axisX.write(0);                   // Zero encoder count
 }
 
 Joystick.setYAxis(0);               // Center joystick Y
 int newY = axisY.read();
 if (newY > 0)
 {
   Joystick.setYAxis(127);
   axisY.write(0);
 }
 if (newY < 0)
 {
   Joystick.setYAxis(-127);
   axisY.write(0);
 }

// Read button pin values
 for (byte index = 0; index < 4; index++)
 {
   byte currentButtonState = !digitalRead(index + pinToButtonMap); // Read button state
   Joystick.setButton(index, currentButtonState);                  // Set state in joystick
 }

Joystick.sendState();               // Send the joystick data
 delay(50);                          // Wait a bit
}

Okay so I don’t know if this matters or not but I have the Pro Micro, but it shows up in the Arduino IDE as a Leonardo… I tried to add more buttons and such to the code and I’m getting some funny things happening and the track ball is hooked up to A0-A3 (I assume from the code) but it isn’t doing anything… Furthermore in windows game controller properties it shows 32 buttons, a stick, rudder, throttle, POV Hat, and x/y axis. Is this supposed to happen? Also some of the buttons show as pressed and I have nothing hooked up to the other pins on the Micro… The pins are very strange on my board compared to an UNO or something else. The pin numbers skip around, I assume that all the numbered pins are just the digital pins and the “A” pins are the analog pins? As you will see in the code I assumed that all the digital pins could be used as buttons? What does this part of the code mean:

"
// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 9;
"

I’ll post the modified code:

#include <Encoder.h>
#include <Joystick.h>

// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 9;
  
Encoder axisX(0, 1);
Encoder axisY(2, 3);

void setup() {
  // Initialize 4 Button Pins
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);
  
  // Initialize Joystick Library
  Joystick.begin(false);
}

void loop() {
  Joystick.setXAxis(0);               // Center joystick X
  int newX = axisX.read();            // Read X encoder
  if (newX > 0)                       // Has the value increased since last read
  {
    Joystick.setXAxis(127);           // Set joystick X hard over to right
    axisX.write(0);                   // Zero encoder count for next time
 }
  if (newX < 0)                       // Has encoder decreased since last read
  {
    Joystick.setXAxis(-127);          // Set joystick hard left
    axisX.write(0);                   // Zero encoder count
  }
  
  Joystick.setYAxis(0);               // Center joystick Y
  int newY = axisY.read();
  if (newY > 0) 
  {
    Joystick.setYAxis(127);
    axisY.write(0);
  }
  if (newY < 0) 
  {
    Joystick.setYAxis(-127);
    axisY.write(0);
  }

  // Read button pin values
  for (byte index = 0; index < 12; index++)
  {
    byte currentButtonState = !digitalRead(index + pinToButtonMap); // Read button state
    Joystick.setButton(index, currentButtonState);                  // Set state in joystick
  }

  Joystick.sendState();               // Send the joystick data
  delay(50);                          // Wait a bit
}

I have uploaded a picture of the Properties Window as well so you can take a look.

I also tried the first library I downloaded and tried to modify it with your example and got the same result. Here is the code from that attempt as well. The axis don’t move when I move the trackball around and some of the buttons are stuck on.

// Simple example application that shows how to read four Arduino
// digital pins and map them to the USB Joystick library.
//
// The digital pins 9, 10, 11, and 12 are grounded when they are pressed.
//
// NOTE: This sketch file is for use with Arduino Leonardo and
//       Arduino Micro only.
//
// by Matthew Heironimus
// 2015-11-20
//--------------------------------------------------------------------

#include <Encoder.h>
#include <Joystick.h>

Encoder axisX(0, 1);
Encoder axisY(2, 3);

void setup() {
  // Initialize Button Pins
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);

  // Initialize Joystick Library
  Joystick.begin(true);
}

// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 9;

// Last state of the button
int lastButtonState[12] = {0,0,0,0,0,0,0,0,0,0,0,0};

void loop() 

  Joystick.setXAxis(0);               // Center joystick X
  int newX = axisX.read();            // Read X encoder
  if (newX > 0)                       // Has the value increased since last read
  {
    Joystick.setXAxis(255);           // Set joystick X hard over to right
    axisX.write(0);                   // Zero encoder count for next time
 }
  if (newX < 0)                       // Has encoder decreased since last read
  {
    Joystick.setXAxis(-255);          // Set joystick hard left
    axisX.write(0);                   // Zero encoder count
  }
  
  Joystick.setYAxis(0);               // Center joystick Y
  int newY = axisY.read();
  if (newY > 0) 
  {
    Joystick.setYAxis(255);
    axisY.write(0);
  }
  if (newY < 0) 
  {
    Joystick.setYAxis(-255);
    axisY.write(0);
  }

{

  // Read pin values
  for (int index = 0; index < 12; index++)
  {
    int currentButtonState = !digitalRead(index + pinToButtonMap);
    if (currentButtonState != lastButtonState[index])
    {
      Joystick.setButton(index, currentButtonState);
      lastButtonState[index] = currentButtonState;
    }
  }

  delay(50);
}

hydrolisk1792:
Okay so I don't know if this matters or not but I have the Pro Micro, but it shows up in the Arduino IDE as a Leonardo...
Does not matter for this.

I tried to add more buttons and such to the code and I'm getting some funny things happening and the track ball is hooked up to A0-A3 (I assume from the code) but it isn't doing anything...
Try getting the code working with the 4 buttons first (on the pins specified) and then start to expand on that if it works. The encoders are connected to digital pins 0-3 not analogue pins A0-A3 as the pins 0-3 are external interrupt pins and give the best results with the encoders (read the blurb on the page I had linked the library to).

Furthermore in windows game controller properties it shows 32 buttons, a stick, rudder, throttle, POV Hat, and x/y axis. Is this supposed to happen?
Yes. The Joystick library defines the maximum number of axis/buttons usable but you don't need to use them all.

Also some of the buttons show as pressed and I have nothing hooked up to the other pins on the Micro...
This is probably because you have altered the code and have the encoders connected to the wrong pins.

The pins are very strange on my board compared to an UNO or something else. The pin numbers skip around, I assume that all the numbered pins are just the digital pins and the "A" pins are the analog pins? As you will see in the code I assumed that all the digital pins could be used as buttons?
Yes the pin numbers do jump around a bit but if you get the pin map from Sparkfun you will see where they all fit. Analogue pins can also be used for digital signals but digital pins cannot be used for analogue.

What does this part of the code mean:
// Constant that maps the phyical pin to the joystick button.
const int pinToButtonMap = 9;

It is the base pin number from where the buttons are defined.

I'm not understanding what the base pin number is for and why it is needed. I did hook up the trackball to the other pins after reading this and am now getting button presses in the windows properties instead of the joystick moving around in the properties window. :confused:

hydrolisk1792:
I'm not understanding what the base pin number is for and why it is needed. I did hook up the trackball to the other pins after reading this and am now getting button presses in the windows properties instead of the joystick moving around in the properties window. :confused:

What pins did you connect the trackball to?

what pins did you connect the trackball to?

A0 - A3

Assuming you have a genuine (or standard clone) of the Sparkfun Pro Micro then the pinout for it is here and the pins you should be using for the encoders are pins 0-3 NOT A0-A3.
I see from this pinout there is no pins 11-12 on the pro micro so you should also have 4 buttons that connect GND to pins 4-7 and alter the sketch line to

const int pinToButtonMap = 4;

and

 // Initialize 4 Button Pins
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);