I've spent two days now trying out different firmware and rewriting my code trying to get this to work.
BACKSTORY: After surgery my dad and I wen't to goodwill I was still on drugs from the operation so he had to drive me around, I found an old joystick made In 1983 and decided to get it as a funny project to see if I could get it to work. My original Idea was to use a serial to USB converter but that caused problems so I decided it would be easier to hook it up to a ArduinoUNO and try making an Arduino HID.
PROBLEM: I've tried using the UnoJoy firmware and example code. This seemed to work just fine at first but I noticed that the output I was getting from the analog reading was non-liner. This is a problem since it makes fine controls impossible. I determined that the cause of this non-liner data as I moved the joystick at a liner speed was due to the fact that instead of potentiometers, the joystick uses variable resistors or rheostats.(yey 1980s tech) Simple enough of a fix, just needed to write some code to take the voltage input(non-liner) and determine the resistance(liner) using a voltage divider. Then I mapped the outputs I was getting to go from 0-255 since UnoJoy requires an 8 bit value for its joystick axis. But now when I upload this sketch to the Arduino and load the firmware, the Arduino not only gives me random analog axis values but also randomly "presses" buttons. This is frustrating especially since the serial output shows it functioning normally.
MODIFIED EXAMPLE SKETCH I'M USING :
#include "UnoJoy.h"
int X;
int Y;
int rectX;
int rectY;
void setup(){
setupPins();
setupUnoJoy();
Serial.begin(9600);
pinMode(13, OUTPUT);
}
void loop(){
// Always be getting fresh data
dataForController_t controllerData = getControllerData();
setControllerData(controllerData);
}
void setupPins(void){
// Set all the digital pins as inputs
// with the pull-up enabled, except for the
// two serial line pins
for (int i = 2; i <= 12; i++){
pinMode(i, INPUT);
digitalWrite(i, HIGH);
}
pinMode(A4, INPUT);
digitalWrite(A4, HIGH);
pinMode(A5, INPUT);
digitalWrite(A5, HIGH);
}
dataForController_t getControllerData(void){
// Set up a place for our controller data
// Use the getBlankDataForController() function, since
// just declaring a fresh dataForController_t tends
// to get you one filled with junk from other, random
// values that were in those memory locations before
dataForController_t controllerData = getBlankDataForController();
// Since our buttons are all held high and
// pulled low when pressed, we use the "!"
// operator to invert the readings from the pins
controllerData.triangleOn = !digitalRead(2);
controllerData.circleOn = !digitalRead(3);
controllerData.squareOn = !digitalRead(4);
controllerData.crossOn = !digitalRead(5);
controllerData.dpadUpOn = !digitalRead(6);
controllerData.dpadDownOn = !digitalRead(7);
controllerData.dpadLeftOn = !digitalRead(8);
controllerData.dpadRightOn = !digitalRead(9);
controllerData.l1On = !digitalRead(10);
controllerData.r1On = !digitalRead(11);
controllerData.selectOn = !digitalRead(12);
controllerData.startOn = !digitalRead(A4);
controllerData.homeOn = !digitalRead(A5);
//Get raw and rectify data
X = analogRead(A0);
Y = analogRead(A1);
rectify();
// Set the analog sticks
// Since analogRead(pin) returns a 10 bit value,
// we need to perform a bit shift operation to
// lose the 2 least significant bits and get an
// 8 bit number that we can use
controllerData.leftStickX = rectX;
Serial.print("X: ");
Serial.print(rectX);
controllerData.leftStickY = rectY;
Serial.print(" Y: ");
Serial.println(rectY);
controllerData.rightStickX = analogRead(A2) >> 2;
controllerData.rightStickY = analogRead(A3) >> 2;
//DEBUG light
if(rectX == 127 && rectY == 127){
digitalWrite(13, HIGH);
}else{
digitalWrite(13, LOW);
}
// And return the data!
return controllerData;
}
void rectify() //kinda useless I know but this function will do more in the future
{
rectifyX();
rectifyY();
}
void rectifyX()
{
int raw = 0; // variable to store the raw input value
int Vin = 5; // variable to store the input voltage
float Vout = 0; // variable to store the output voltage
float R1 = 10; // variable to store the R1 value
float R2 = 0; // variable to store the R2 value
float buffer = 0; // buffer variable for calculation
//Takes raw value and calculates resistance in kOhms
raw = X;
Vout = (5.0 / 1023.0) * raw;
buffer = (Vin / Vout) -1;
R2 = R1 / buffer;
//maps asymmetrical output to symmetrical 8 bit number
rectX = map(R2, 0, 183, 0, 255);
rectX = constrain(rectX, 0, 255);
if(rectX >= 117 && rectX <= 137){ //deadzone
rectX = 127;
}
}
void rectifyY()
{
int raw = 0; // variable to store the raw input value
int Vin = 5; // variable to store the input voltage
float Vout = 0; // variable to store the output voltage
float R1 = 10; // variable to store the R1 value
float R2 = 0; // variable to store the R2 value
float buffer = 0; // buffer variable for calculation
//Takes raw value and calculates resistance in kOhms
raw = Y;
Vout = (5.0 / 1023.0) * raw;
buffer = (Vin / Vout) -1;
R2 = R1 / buffer;
//maps asymmetrical output to symmetrical 8 bit number
rectY = map(R2, 0, 207, 0, 255);
rectY = constrain(rectY, 0, 255);
if(rectY >= 117 && rectY <= 137){ //deadzone
rectY = 127;
}
}
As far as I know nothing in that code would change the value of the buttons so that it thought they were being pressed. The rectX and rectY values are both 8 bit numbers like UnoJoy requires and the serial output works perfectly. I need help here.
OTHER:
I'm using TocaEdit to show the raw values coming from the UnoJoy controller : http://www.x360ce.com/
Here's a link to UnoJoy Google Code Archive - Long-term storage for Google Code Project Hosting. I am using the latest windows version.