Looking for advice for motion control project

I have a usb game pad that I've managed to get into and I've found a way to apply voltage to the joystick potentiometer in a way that tricks Windows into thinking the joystick is being moved. I've also managed to rig this up to an arduino which I have put inside the controller along with a single axis gyro sensor.

The aim of this was to create a motion controller such that the gamepad could be held up and steered left or right like a steering wheel for driving video games. I had this working great , the only problem was the large drift I would get over a short amount of time. I assumed that if I used a 3-axis accelerometer in conjunction with the single axis gyro, I would get a better result.

However, I have tried this and am struggling to find a way in which I can use the accelerometer for the desired function. I am able to get the roll and pitch angle of the accelerometer, but I am unsure how to apply these to my end result. I have the gyro set up in the plane of the controller, so that rolling the controller to the left produces a negative angle (until -90 degrees), and rolling right produces positive angle (until +90 degrees). This works no matter which way up the controller is, so long as I zero the angle initially while holding the controller level.

I can use the accelerometer roll angle, but it only remains usable when the controller is held vertically with no pitch. If the controller is leaned away or towards me, the accelerometer roll angle reading changes largely and becomes unusable.

Does anyone know the maths I need to apply to the accelerometer angles to make them behave in the same way as the gyro sensor?

Sorry for the long text, and thanks for reading. :slight_smile:

It may help if you tell us what hardware you're using (provide links to it, or better to the datasheet of it).

Also post the sketch you're testing with and the output you get for the various holding positions. If possible, also provide the schematics of the circuit you're using for that.

Edit: I have fixed the problem! See bottom of post.

The arduino board, accelerometer, and gyro are the following:
http://aud.dx.com/product/diy-atmega328p-16mhz-electric-block-module-blue-961172858
http://aud.dx.com/product/adxl345-digital-3-axis-gravity-acceleration-sensor-module-blue-961149476

I am using a modification of this basic code for the accelerometer:
https://www.sparkfun.com/tutorials/240

The code simply retrieves the x,y,z values from the accelerometer. I've managed to determine that the maximum values I can get in any direction (by shaking the accelerometer vigorously) are -512 to 512, which puzzles me slightly as the datasheet for the accelerometer says that the max and min values for +-4g mode (the one that is selected in the setup method of that tutorial) are things like 25 to 270 for x axis (https://www.sparkfun.com/datasheets/Sensors/Accelerometer/ADXL345.pdf, page 13 bottom right).

If I lay the acc. flat (components facing up), I get values approximately (0, 0, -50).
If i stand it up so that positive y-axis faces down, I get approximately (0, 64, 0).
Not sure why the magnitude of the gravity-direction is slightly different either.

I've been using the following code to determine roll and pitch angle (placed directly below the code that retrieves x,y,z):

accPitch = (int)((atan2(y, z) + PI) * (57296 / 1000)); 
accRoll =  (int)((atan2(x, z) + PI) * (57296 / 1000));

I found this code at another tutorial (Guide to gyro and accelerometer with Arduino including Kalman filtering - Sensors - Arduino Forum)


Edit: In trying to explain what I have been doing, I have solved the problem. My calculations for accRoll is different for my project compared with the tutorial code I used because my neutral down axis is actually positive-y (meaning that I have my acc. mounted in my game pad at a different angle to what is used in that tutorial), instead of positive-z. This means that I had to change accRoll :

//Old code
accRoll =  (int)((atan2(x, z) + PI) * (57296 / 1000));

//New code
accRoll =  (int)((atan2(x, y) + PI) * (57296 / 1000));

Changing this makes my roll angle reliable with little variation when I change the pitch of the accelerometer. A similar problem is probably present in the code for accPitch, but as my project does not require pitch, I don't need to work it out.
Thanks for reading, sorry for wasting forum space. Hopefully this can save someone the hours I spent trying to find the problem.