[SOLVED]Arcade trackball to usb mouse help

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);

So that means that i hook trackball up to the teal coloured numbered pins on the sparkfun pinout and i can have all the other pins as buttons that activate when shorted to ground? So by hooki g trackball to the pins you specified it will manipulate the joystick portion of the windows properties window and the buttons will manipulate the buttons in the windows properties window?

hydrolisk1792:
So that means that i hook trackball up to the teal coloured numbered pins on the sparkfun pinout and i can have all the other pins as buttons that activate when shorted to ground? So by hooki g trackball to the pins you specified it will manipulate the joystick portion of the windows properties window and the buttons will manipulate the buttons in the windows properties window?

If your Teal is what the image legend names as 'Arduino' then you should get movement of the joystick X/Y axis when the trackball is rotated. The code is a simple test and should simulate the joystick being pushed hard over in the trackball direction of rotation. The same with the buttons on the pins 4-7.
This code is only a test that things are connected properly and will need changing to add extra buttons and adjust the trackball operation to suit your needs.

Riva:
If your Teal is what the image legend names as 'Arduino' then you should get movement of the joystick X/Y axis when the trackball is rotated. The code is a simple test and should simulate the joystick being pushed hard over in the trackball direction of rotation. The same with the buttons on the pins 4-7.
This code is only a test that things are connected properly and will need changing to add extra buttons and adjust the trackball operation to suit your needs.

Okay will do. Ill try that as soon as i get home. Thank you.

Okay, so I did as you stated and modified the code and got everything to work. How would I go about making the trackball a lot less sensitive and more like the joystick? I can already tell by my test that I will need to somehow make a dead zone so the computer will realize that if I'm rolling the ball Up it actually goes up and ignores the little fidgets from side to side for instance. Also I'm looking for a way to have the acceleration taken into account. Like the faster I roll it the more the joystick registers in that direction. Like when you push just a bit on an actual analog joystick it goes a little bit in that direction. It is all working how you stated it would though, so many thanks to you for all your help thus far and I gave you some good karma for putting up with me though all this. I know I can be a bit annoying with simple to answer questions and all. I'm new to this but am learning a lot from you and I thank you for that as well.

Furthermore, how would I go about adding one more actual rotary encoder to the sketch as the Z axis. I tried doing it and all I get is it fidgeting back and forth in the properties window. I took the X axis and copied it and changed all the values that had "X" and changed them to Z and reduced the numbers to 63 and -63 but that didn't seem to work the way I hoped. Also if you could get this working, is there a way to have it accelerate the faster I turn the knob is that direction? I did this on pins 4 & 5.

I'm also having trouble adding buttons above pin ten. I'm getting the same result as last time where some of the buttons are locked down like they are being pressed even though they aren't. I'll post my code.

EDIT: I went ahead and installed some 1K pullup resistors on pins 4 & 5 but that didn't seem to fix the problem. I was reading on a different forum that sometimes the rotary encoder needs theses resistors to operate properly, however that didn't seem to do the trick :frowning: Also should I be hooking the centre pin of the encoder to GND or 5VDC? I currently have it hooked to GND.

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

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

void setup() {
  // Initialize Buttons

  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  pinMode(19, INPUT_PULLUP);
  pinMode(20, INPUT_PULLUP);
  pinMode(21, 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);
  }

  Joystick.setZAxis(0);               // Center joystick Z
  int newZ = axisZ.read();
  if (newZ > 0) 
  {
    Joystick.setZAxis(63);
    delay(50);
    axisZ.write(0);
  }
  if (newZ < 0) 
  {
    Joystick.setZAxis(-63);
    delay(50);
    axisZ.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
}

A lot of questions...
Adding more encoders is possible but it may impact the performance of the first 2 encoders. From the encoder page I linked it...

Encoders have 2 signals, which must be connected to 2 pins. There are three options.
Best Performance: Both signals connect to interrupt pins.
Good Performance: First signal connects to an interrupt pin, second to a non-interrupt pin.
Low Performance: Both signals connect to non-interrupt pins, details below.

I would then suggest change to the 'good performance' model and have one encoder pin connected to an interrupt pin (pins 0-3) instead of the current two pins.

The button reading code was only for testing the joystick library worked as expected and is not really suitable for more buttons like this as it cannot cope well non contiguous pin numbers, as you have found.
I suggest putting the button pin numbers into an array and then using that array to configure the pins and read them.

A dead zone might not be so important if you can make the trackball act like an analogue joystick as the off axis values will be small when rolling in a single direction compared to the test code that makes any movement in any axis a full joystick axis move.
A possible way to do the acceleration is to count the number of changes in an axis within a fixed time interval as this will be higher the faster the encoder is rotated, you then map this change value to the amount of joystick movement.
I don't have the hardware to check what value you would get for this so you will need to work on this (with a bit of help).
I would start with loading the original encoder code posted on the library web page that prints the encoder changes to the Serial monitor and then modify it to suit your encoder pins and time interval, and run it.
Start turning the encoder at a fixed speed that sort of matches your minimum joystick movement so you get several results printed in the serial monitor and then do the same at the speed you would expect for full joystick movement. This should give an idea of the min/max values used for acceleration.
Once you have that the code can be altered to use it.
I will try to make time to change the code to suit more buttons and post it here but I'm working (or meant to be :slight_smile: so might not have time.

Try this sketch to test the encoder counts at different speeds.

#include <Encoder.h>

// Change these pin numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder knobLeft(0, 1);
Encoder knobRight(2, 3);
//   avoid using pins with LEDs attached

void setup() {
  Serial.begin(115200);
  Serial.println("TwoKnobs Encoder Test:");
}

void loop() {
  int newLeft, newRight;
  newLeft = knobLeft.read();
  newRight = knobRight.read();
  if (newLeft != 0 || newRight != 0) {
    Serial.print("Left = ");
    Serial.print(newLeft);
    Serial.print(", Right = ");
    Serial.print(newRight);
    Serial.println();
    knobLeft.write(0);
    knobRight.write(0);
  }
  delay(50);
}

And this sketch is your code modified to allow the reading of all buttons.

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

Encoder axisX(0, 1);
Encoder axisY(2, 3);
Encoder axisZ(4, 5);

const byte buttonArray[] = {6, 7, 8, 9, 10, 14, 15, 16, 18, 19, 20, 21};

void setup() {
  // Initialize Buttons
  for(byte x = 0; x < sizeof(buttonArray); x++)
  {
    pinMode(buttonArray[x], 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);
  }
  
  Joystick.setZAxis(0);               // Center joystick Z
  int newZ = axisZ.read();
  if (newZ > 0)
  {
    Joystick.setZAxis(63);
    delay(50);
    axisZ.write(0);
  }
  if (newZ < 0)
  {
    Joystick.setZAxis(-63);
    delay(50);
    axisZ.write(0);
  }
  
  // Read button pin values
  for(byte x = 0; x < sizeof(buttonArray); x++)
  {
    byte currentButtonState = !digitalRead(buttonArray[x]);   // Read button state
    Joystick.setButton(x, currentButtonState);                // Set state in joystick
  }
  
  Joystick.sendState();               // Send the joystick data
  delay(50);                          // Wait a bit
}

Riva:
And this sketch is your code modified to allow the reading of all buttons.

#include <Encoder.h>

#include <Joystick.h>

Encoder axisX(0, 1);
Encoder axisY(2, 3);
Encoder axisZ(4, 5);

const byte buttonArray[] = {6, 7, 8, 9, 10, 14, 15, 16, 18, 19, 20, 21};

void setup() {
  // Initialize Buttons
  for(byte x = 0; x < sizeof(buttonArray); x++)
  {
    pinMode(buttonArray[x], 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);
  }
 
  Joystick.setZAxis(0);              // Center joystick Z
  int newZ = axisZ.read();
  if (newZ > 0)
  {
    Joystick.setZAxis(63);
    delay(50);
    axisZ.write(0);
  }
  if (newZ < 0)
  {
    Joystick.setZAxis(-63);
    delay(50);
    axisZ.write(0);
  }
 
  // Read button pin values
  for(byte x = 0; x < sizeof(buttonArray); x++)
  {
    byte currentButtonState = !digitalRead(buttonArray[x]);  // Read button state
    Joystick.setButton(x, currentButtonState);                // Set state in joystick
  }
 
  Joystick.sendState();              // Send the joystick data
  delay(50);                          // Wait a bit
}

So over a length of about ten to fifteen feet away from the arduino cable length, would i need to add some 1k pullup resistors as well as the internal pullups for the buttons and the encoders? Now because of you i understand the button code fully, thank you. Okay for the trackball encoders, would i be able to use the same counting technique as the normal encoder knob? I havent tried the code you posted yet as i just changed benches and some things are shuffeled around lol. I should be able to trt your code and report back to you with the results.

hydrolisk1792:
So over a length of about ten to fifteen feet away from the arduino cable length, would i need to add some 1k pullup resistors as well as the internal pullups for the buttons and the encoders?
1K seems a bit strong as a pullup but this will all depend on the type of wire and if it's screened. If your getting spurious readings the maybe start with 10K and work your way down toward 1K. Another option might be to put the Arduino near the encoders and run a longer USB lead back to the computer.

Now because of you i understand the button code fully, thank you.
The original code was just the example supplied with the joystick library but it doies not suit none contiguous pin numbers so using an array seemed the sensible thing to do.

Okay for the trackball encoders, would i be able to use the same counting technique as the normal encoder knob?
Not sure what you mean here. As the test code stands it sends the joystick data every 50 milliseconds (plus overhead) and the encoders are read in a interrupt so may/may not update more than once in that time. How fast they update also depends on there resolution and how fast you turn them and this might be okay at a lower speed.
The test code reads the encoder counts every 50ms then zeros them and prints it out so you should be able to determine how many pulses you get at different encoder speeds and this information can be used to add velocity to the encoder joystick axis.
If you want to add a third encode to the mix then either the other two encoders need connecting differently so only one interrupt is used per encoder instead of two (reducing performance) or the code will need to poll the third encoder quickly to manually count pulses.

Okay I hooked the Trackball to to the serial monitor and that is exactly what I needed the trackball to do. So I will try to somehow mix that code into the joystick library and see what happens. The Minimum number is about 0 - 1 Plus Minus. and the max number is roughly 210 - 222 Plus Minus. I also unhooked the trackball and hooked up one rotary encoder to the serial monitor and I'm thinking that my rotary encoder is damaged or something because I couldn't get it to go above Plus Minus 2 in the serial monitor... I'm going to try spraying some cleaner into it and see if that will fix it. I've seen this happen to rotary encoder knobs on the Microwaves we have at my work and I spray them with this special cleaner and they work like new, so I'll take it to work with me tonight and spray some stuff in it and see if that does the trick... All the buttons work BTW :slight_smile: Thank you for that. I'm going to experiment with the two codes you gave me and see if I can get the track ball to act the way it does in the serial monitor.

So I tried a bunch of things and just kept getting errors when I went to verify the code... I only came up with one that didn't throw an error and was actually able to upload but it doesn't work at all. All it does is fidget around the cross in the properties window in like a one pixel circle. All the buttons still work though. :confused: I'll post the code that "Kind of" works.

#include <Encoder.h>
#include <Joystick.h>
  
Encoder axisX(0, 1);
Encoder axisY(2, 3);
Encoder axisZ(4, 5);


//Number of Physical Pins that buttons are attached to. Ground out to simulate button press.
const byte buttonArray[] = {6, 7, 8, 9, 10, 14, 15, 16, 18, 19, 20, 21}; 

void setup() {  
  // Initialization of Buttons with internal pullup resistors
  for(byte x = 0; x < sizeof(buttonArray); x++)
  {
    pinMode(buttonArray[x], 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(newX != 210);           // 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(newX != -210);          // 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(newY != 210);
    axisY.write(0);
  }
  if (newY < 0)
  {
    Joystick.setYAxis(newY != -210);
    axisY.write(0);
  }
  
  Joystick.setZAxis(0);               // Center joystick Z
  int newZ = axisZ.read();
  if (newZ > 0)
  {
    Joystick.setZAxis(newZ != 63);
    delay(50);
    axisZ.write(0);
  }
  if (newZ < 0)
  {
    Joystick.setZAxis(newZ != -63);
    delay(50);
    axisZ.write(0);
  }


  // Read button pin values
  for (byte x = 0; x < sizeof(buttonArray); x++)
  {
    byte currentButtonState = !digitalRead(buttonArray[x]);     // Read button state
    Joystick.setButton(x, currentButtonState);                  // Set state in joystick
  }

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

So I did this (see code) instead and it is working a load better. However the actual rotary encoder knob I have on the Z axis is still acting up. I haven't cleaned it yet but when I do I will report back to you and let you know.

#include <Encoder.h>
#include <Joystick.h>
  
Encoder axisX(0, 1);
Encoder axisY(2, 3);
Encoder axisZ(4, 5);


//Number of Physical Pins that buttons are attached to. Ground out to simulate button press.
const byte buttonArray[] = {6, 7, 8, 9, 10, 14, 15, 16, 18, 19, 20, 21}; 

void setup() {  
  // Initialization of Buttons with internal pullup resistors
  for(byte x = 0; x < sizeof(buttonArray); x++)
  {
    pinMode(buttonArray[x], 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(axisX.read());           // 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(axisX.read());          // 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(axisY.read());
    axisY.write(0);
  }
  if (newY < 0)
  {
    Joystick.setYAxis(axisY.read());
    axisY.write(0);
  }
  
  Joystick.setZAxis(0);               // Center joystick Z
  int newZ = axisZ.read();
  if (newZ > 0)
  {
    Joystick.setZAxis(axisZ.read());
    axisZ.write(0);
  }
  if (newZ < 0)
  {
    Joystick.setZAxis(axisZ.read());
    axisZ.write(0);
  }


  // Read button pin values
  for (byte x = 0; x < sizeof(buttonArray); x++)
  {
    byte currentButtonState = !digitalRead(buttonArray[x]);     // Read button state
    Joystick.setButton(x, currentButtonState);                  // Set state in joystick
  }

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

Try the below code that maps the values (with a little overhead) you supplied from #29 to the range expected by the joystick.

When you say the Z encoder did not work well it may be because the encoder is not as higher resolution as the trackball but it might also be because of what pins you connected it to?

Deleted due to being wrong version.