REFERENCE: https://github.com/Cryocrat/LeonardoJoystick
What do we need?
1. Check version of Arduino IDE installed ... specifically 1.6.6 does not work with the updated files at the above link - to avoid compile errors we had to uninstall IDE and install 1.6.3.
2. Move files aside ...
C: cd "C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" move HID.cpp HID.old.cpp move USBAPI.h USBAPI.old.h
3. Copy in replacement versions of HID.cpp and USBAPI.h from the above link or from HERE.
How do we confirm that this works?
1. Copy leojoy.ino from the above link to ...
C:\Users\Ian\Documents\Arduino\hid_joystick\hid_joystick.ino
2. Upload program via IDE (CTRL+U)
3. Confirm operation of the code by browsing to: http://html5gamepad.com/
4. This should show the axes 0-7 and axis 9 being set to random numbers and buttons 0-32 being set then reset
How do we connect a push button to the arduino to simulate a joystick button?
1. Connect a momentary push button switch between pin 2 and GND on the arduino.
2. Connect a 10K ohm resistor between pin 2 and 5V on the arduino.
3. replace the hid_joystick.ino code with the following in the arduino IDE:
/* Arduino Leonardo Joystick! */ // "axes" are allocated as follows ... // // axis 0 = xAxis // axis 1 = yAxis // axis 2 = zAxis // axis 3 = xRotAxis // axis 4 = yRotAxis // axis 5 = zRotAxis // axis 6 = rudder // axis 7 = throtle // axis 8 = (not used?) // axis 9 = hatSw1 and hatSw2 (4 bits each)(hatSw2 does not seem to impact axis 9 on http://html5gamepad.com/) JoyState_t joySt; const int buttonPin = 2; int buttonState = 0; void setup() { pinMode(buttonPin, INPUT); joySt.xAxis = 0; joySt.yAxis = 0; joySt.zAxis = 0; joySt.xRotAxis = 0; joySt.yRotAxis = 0; joySt.zRotAxis = 0; joySt.throttle = 0; joySt.rudder = 0; joySt.hatSw1 = 0; joySt.hatSw2 = 0; joySt.buttons = 0; } void loop() { joySt.xAxis = random(255); joySt.yAxis = random(255); joySt.zAxis = random(255); joySt.xRotAxis = random(255); joySt.yRotAxis = random(255); joySt.zRotAxis = random(255); joySt.rudder = random(255); joySt.throttle++; buttonState = digitalRead(buttonPin); // check if the pushbutton is pressed. // if it is, the buttonState is HIGH: // then lets set the next joystick // button by shifting the button // register ... if (buttonState == HIGH) joySt.buttons <<= 1; if (joySt.buttons == 0) joySt.buttons = 1; joySt.hatSw1++; joySt.hatSw2--; if (joySt.hatSw1 > 8) joySt.hatSw1 = 0; if (joySt.hatSw2 > 8) joySt.hatSw2 = 8; delay(1000); // Call Joystick.move Joystick.setState(&joySt); }
4. Save and upload to the arduino with CTRL+S and CTRL+U
5. Check the operation of the joystick by browsing to http://html5gamepad.com/
6. Operation will be similar to the initial program but this time you should only see the active button advance when you press the push button. If this does not occur then double check that your have good connections on the arduino and/or breadboard if you used one in steps 1 and 2 above
7. The above code is actually far more complex than we really need. If we simply want to have the push button switch control a single joystick button then we can replace joystick_hid.ino with:
/* Arduino Leonardo Joystick! */ // TO DO: the values below don't quite zero out JoyState_t joySt; const int buttonPin = 2; int buttonState = 0; void setup() { pinMode(buttonPin, INPUT); joySt.xAxis = 0; joySt.yAxis = 0; joySt.zAxis = 0; joySt.xRotAxis = 0; joySt.yRotAxis = 0; joySt.zRotAxis = 0; joySt.throttle = 0; joySt.rudder = 0; joySt.hatSw1 = 0; joySt.hatSw2 = 0; joySt.buttons = 0; } void loop() { joySt.xAxis = 128; joySt.yAxis = 128; joySt.zAxis = 128; joySt.xRotAxis = 128; joySt.yRotAxis = 128; joySt.zRotAxis = 128; joySt.throttle = 128; joySt.rudder = 128; joySt.hatSw1 = 0; joySt.hatSw2 = 0; buttonState = digitalRead(buttonPin); // check if the pushbutton is pressed. // if it is, the buttonState is HIGH: // lets pass this on by turning on a // single joystick button (all others // are off) ... if (buttonState == HIGH) { joySt.buttons = 1; } else { joySt.buttons = 0; } delay(100); // Call Joystick.move Joystick.setState(&joySt); }
8. With this version of the code you should just see button 1 activated at http://html5gamepad.com/ when you press the push button.
9. If you want to play with multiple buttons then you need to extend the code as shown below. Note that you could implement this in a far better way using a shift register and arrays.
/* Arduino Leonardo Joystick! */ // TO DO: the values below don't quite zero out JoyState_t joySt; const int button00Pin = 2; const int button01Pin = 3; const int button02Pin = 4; const int button03Pin = 5; const int button04Pin = 6; const int button05Pin = 7; const int button06Pin = 8; const int button07Pin = 9; const int button08Pin = 10; const int button09Pin = 11; const int button10Pin = 12; const int button11Pin = 13; int button00State = 0; int button01State = 0; int button02State = 0; int button03State = 0; int button04State = 0; int button05State = 0; int button06State = 0; int button07State = 0; int button08State = 0; int button09State = 0; int button10State = 0; int button11State = 0; void setup() { pinMode(button00Pin, INPUT); pinMode(button01Pin, INPUT); pinMode(button02Pin, INPUT); pinMode(button03Pin, INPUT); pinMode(button04Pin, INPUT); pinMode(button05Pin, INPUT); pinMode(button06Pin, INPUT); pinMode(button07Pin, INPUT); pinMode(button08Pin, INPUT); pinMode(button09Pin, INPUT); pinMode(button10Pin, INPUT); pinMode(button11Pin, INPUT); joySt.xAxis = 0; joySt.yAxis = 0; joySt.zAxis = 0; joySt.xRotAxis = 0; joySt.yRotAxis = 0; joySt.zRotAxis = 0; joySt.throttle = 0; joySt.rudder = 0; joySt.hatSw1 = 0; joySt.hatSw2 = 0; joySt.buttons = 0; } void loop() { joySt.xAxis = 128; joySt.yAxis = 128; joySt.zAxis = 128; joySt.xRotAxis = 128; joySt.yRotAxis = 128; joySt.zRotAxis = 128; joySt.throttle = 128; joySt.rudder = 128; joySt.hatSw1 = 0; joySt.hatSw2 = 0; button00State = digitalRead(button00Pin); button01State = digitalRead(button01Pin); button02State = digitalRead(button02Pin); button03State = digitalRead(button03Pin); button04State = digitalRead(button04Pin); button05State = digitalRead(button05Pin); button06State = digitalRead(button06Pin); button07State = digitalRead(button07Pin); button08State = digitalRead(button08Pin); button09State = digitalRead(button09Pin); button10State = digitalRead(button10Pin); button11State = digitalRead(button11Pin); // check if the pushbutton is pressed. // if it is, the buttonState is HIGH: // lets pass this on by turning on a // single joystick button (all others // are off) ... joySt.buttons = 0; if (button00State == HIGH) { joySt.buttons += 1; } if (button01State == HIGH) { joySt.buttons += 2; } if (button02State == HIGH) { joySt.buttons += 4; } if (button03State == HIGH) { joySt.buttons += 8; } if (button04State == HIGH) { joySt.buttons += 16; } if (button05State == HIGH) { joySt.buttons += 32; } if (button06State == HIGH) { joySt.buttons += 64; } if (button07State == HIGH) { joySt.buttons += 128; } if (button08State == HIGH) { joySt.buttons += 256; } if (button09State == HIGH) { joySt.buttons += 512; } if (button10State == HIGH) { joySt.buttons += 1024; } if (button11State == HIGH) { joySt.buttons += 2048; } delay(100); // Call Joystick.move Joystick.setState(&joySt); }
How do we confirm that this will work with the FRC Driver Station?
NOTE: the arduino may not work with all USB ports on your PC. In our case it did not work reliably with any of the DELL D620 USB ports but the classmate seemed to work fine.
WARNING: DO NOT ENABLE THE ROBOT UNLESS YOU HAVE IT SAFELY UP ON CHOCKS - THERE IS A HIGH CHANCE THAT YOU WILL HAVE THE JOYSTICK ZERO VALUES INCORRECTLY SET AND THE ROBOT WILL PIN YOU TO THE WALL AS SOON AS YOU ENABLE IT - - - YOU HAVE BEEN WARNED :)
1. Using a USB cable, connect the arduino into a PC that has the FRC Driver Station software installed.
2. Start the Driver Station software.
3. Select the "USB Devices" tab on the driver station. You should see "Arduino Leonardo" listed, select that device and you will see the current joystick positions and button values displayed graphically to the right.
4. If the arduino is not listed then try an alternative USB port. If the PC USB ports can't provide adequate power then you may also need to provide a power supply to the arduino.
5. RE-READ THE WARNING ABOVE. NOW, IF THE JOYSTICK AXES VALUES ARE ALL AT THE MID-POINT THEN YOU CAN TRY ENABLING THE ROBOT. Nothing should happen.
6. Now take a look at the FRC Driver Station Dashboard - in the "Variables" tab look for "Joystick 0" > "Buttons". This should show the button values as 32 element boolean array (e.g. TFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF). If all is well you should be able to see the first element flip between "T" and "F" when you press the push button that is connected to the arduino.