ArduinoJoystickWithFFBLibrary icon indicating copy to clipboard operation
ArduinoJoystickWithFFBLibrary copied to clipboard

Gains

Open pkaser opened this issue 4 years ago • 13 comments

It appears gains should be set in setup() and not before as in your example.

pkaser avatar May 26 '20 12:05 pkaser

In fact, this is not important, as long as it is called before getForce(), because these two interfaces are used to pass the array address, otherwise it will cause a null pointer exception.

YukMingLaw avatar May 26 '20 12:05 YukMingLaw

It is important because your example wont compile and gives and error. I posted this so that you could adjust your example so other people that aren't experienced programmers will be able to get their code to compile.

X spring forces also seem to always calculate out to 0. Y seems to work fine, but I am double checking my code to verify I havent made a typo.

pkaser avatar May 26 '20 13:05 pkaser

The example code just shows the calling process, it is not compilable.

Check whether the effect params settings are correct and whether the X axis is used as the action axis in the game.

YukMingLaw avatar May 26 '20 14:05 YukMingLaw

I guess if you want to have examples that work or dont is up to you.

The effect params are set. the X and Y axis are reporting correct values. The X force is always 0. If I swap the effect params I still only get Y forces calculated. I am using ForceTest, not a game. It simulates a lot of the FFB variables.

pkaser avatar May 26 '20 16:05 pkaser

Could you send me the ForceTset please?I will check it later.

YukMingLaw avatar May 26 '20 16:05 YukMingLaw

as well as your code.

YukMingLaw avatar May 26 '20 16:05 YukMingLaw

Here is ForceTest.exe:

https://www.dirks-software.ca/downloads/ForceTest.exe

pkaser avatar May 26 '20 19:05 pkaser

Here is my current code. I havent figured out the effects yet, like damper, inertia, friction, etc setting yet so they may be all wrong the way I have them implemented. Same with almost everything in here. I'm new to Arduino. It is a joystick made from a Leonardo, a MotoShield, a 12v/2amp power supply, and an old Microsoft Sidewinder Pro Force Feedback V1 that has had all the electronics removed. I am using only the motors and the yoke and have 3D printed a temporary testing mounting bracket. 90% of it works great with XPForce with X-Plane 11.41.

I really appreciate how much you have done to make this happen, and I happily share my code for anyone else trying to do the same thing.

`#include "Joystick.h" #include "Encoder.h"

int32_t forces[2] = { 0 };

long posX; long posY;

int centerX; int centerY;

int lastX = 0; int lastY = 0;

// Motor int dirX = 12; int dirY = 13;

int brakeX = 9; // NIU int brakeY = 8; // NIU

int motorX = 3; // int motorY = 11; //

//current draw on motors int loadX = A0; int loadY = A1;

// joystick encoders int encoderX1 = 0; int encoderX2 = 1; int encoderY1 = 2; int encoderY2 = 4;

int xDirection = LOW; int yDirection = LOW; int centerFound = LOW;

int dur = 2; int strength = 100;

long oldX = -999; long oldY = -999;

const int loopDelay = 20;

int minX = 0; int maxX = 0; int minY = 0; int maxY = 0;

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_JOYSTICK, 0, 0, // Button Count, Hat Switch Count true, true, false, // X and Y, but no Z Axis false, false, false, // No Rx, Ry, or Rz false, false, // No rudder or throttle false, false, false); // No accelerator, brake, or steering

Gains gain[2]; EffectParams effects[2];

//

Encoder encoderX(encoderX1, encoderX2); Encoder encoderY(encoderY1, encoderY2);

void setup() { Serial.begin(9600); delay(2000); //Give the serial port time to catch up so we can debug Serial.println("Setting up..."); pinMode(dirX, OUTPUT); //Initiates Motor Channel X pin pinMode(dirY, OUTPUT); //Initiates Motor Channel Y pin

Joystick.begin(true); doSetGains(); }

void loop(){ if (centerFound == 0){ Serial.println("--Centering"); doFindCenter(); } doJoystickStuff(); doFFBStuff(); delay(loopDelay); }

void doFindCenter(){ int cDur = 80; int cStrength = 255; int tXDir; int tYDir; int tPosX; int tPosY;

doMoveX(cStrength,cDur,HIGH); maxX = stopXMove(); doMoveX(cStrength,cDur,LOW);
minX = stopXMove(); int centerX = (minX + maxX)/2; doMoveY(cStrength,cDur,HIGH); maxY = stopYMove(); doMoveY(cStrength,cDur,LOW);
minY = stopYMove(); int centerY = (minY + maxY)/2;

centerX = ((minX + maxX)/2)-2; centerY = ((minY + maxY)/2)-2;

Joystick.setXAxisRange(minX,maxX); Joystick.setYAxisRange(minY,maxY); tPosX = encoderX.read(); tPosY = encoderY.read(); do { //center X
if (centerX > tPosX){tXDir = HIGH;} else {tXDir = LOW;} doMoveX(255,2,tXDir); tPosX = stopXMove();

} 
while (tPosX != centerX);

do { //center Y
if (centerY > tPosY){tYDir = HIGH;} else {tYDir = LOW;} doMoveY(255,2,tYDir); tPosY = stopYMove();

} 
while (tPosY != centerY);
stopXMove();
stopYMove();
centerFound = 1;

}

int stopXMove(){ return doMoveX(0, 10, HIGH); }

int stopYMove(){ return doMoveY(0, 10, HIGH); }

int doMoveX(int tStrength, int tDuration, int tDirection){ digitalWrite(dirX, tDirection); //High=Forward / Low=Reverse analogWrite(motorX, tStrength); //Spins the motor on Channel A at full speed delay(tDuration); // analogWrite(motorX, 0); //Stops motor delay(2); return encoderX.read(); }

int doMoveY(int tStrength, int tDuration, int tDirection){ digitalWrite(dirY, tDirection); //High=Forward / Low=Reverse analogWrite(motorY, tStrength); //Spins the motor on Channel A at full speed delay(tDuration); // analogWrite(motorY, 0); //Stops motor delay(2); return encoderY.read(); }

void doFFBStuff(){ //}

}

void doJoystickStuff(){

posX = encoderX.read(); posY = encoderY.read();

Joystick.setXAxis(posX); Joystick.setYAxis(posY);

effects[0].springMaxPosition = maxX/2; effects[1].springMaxPosition = maxY/2; effects[0].frictionMaxPositionChange = lastX - posX; effects[1].frictionMaxPositionChange = maxY; effects[0].inertiaMaxAcceleration = maxX; effects[1].inertiaMaxAcceleration = 100; effects[0].damperMaxVelocity = 10; effects[1].damperMaxVelocity = 100;

effects[0].springPosition = posX; effects[1].springPosition = posY; effects[0].frictionPositionChange = lastX - posX; effects[1].frictionPositionChange = lastY - posY; effects[0].inertiaAcceleration = 100; effects[1].inertiaAcceleration = 100; effects[0].damperVelocity=100; effects[1].damperVelocity=100;

Joystick.setEffectParams(effects); Joystick.getForce(forces);

int xMoveDir = 0; int yMoveDir = 0; //Get Force [-255,255] you can set PWM with this value Serial.println(""); Serial.print(" - XF: "); Serial.print(forces[0]); Serial.print(" YF: "); Serial.print(forces[1]); //if (forces[0] != 0 || forces[1] != 0 ){ if (forces[0]<0){ xMoveDir = LOW; } else if (forces[0]>0){ xMoveDir = HIGH; } if (forces[1]<0){ yMoveDir = LOW; } else if (forces[1]>0){ yMoveDir = HIGH; } if (forces[0]!=0){ doMoveX(abs(forces[0]),dur,xMoveDir); } else { doMoveX(0,2,xMoveDir); }; if (forces[1]!=0) { doMoveY(abs(forces[1]),dur,yMoveDir); } else { doMoveY(0,2,yMoveDir); };

lastX = posX; lastY = posY;

}

void doSetGains(){ //set x axis gains gain[0].totalGain = 100; gain[0].constantGain = 100; gain[0].rampGain = 100; gain[0].squareGain = 100; gain[0].sineGain = 100; gain[0].triangleGain = 100; gain[0].sawtoothdownGain = 100; gain[0].sawtoothupGain = 100; gain[0].springGain = 100; gain[0].damperGain = 100; gain[0].inertiaGain = 100; gain[0].frictionGain = 100;

//set y axis gains gain[1].totalGain = 100; gain[1].constantGain = 100; gain[1].rampGain = 100; gain[1].squareGain = 100; gain[1].sineGain = 100; gain[1].triangleGain = 100; gain[1].sawtoothdownGain = 100; gain[1].sawtoothupGain = 100; gain[1].springGain = 100; gain[1].damperGain = 100; gain[1].inertiaGain = 100; gain[1].frictionGain = 100;

Joystick.setGains(gain);

} `

pkaser avatar May 26 '20 21:05 pkaser

Hi,there is no wrong in your code. I Traced the USB report output which from ForceTest.It set the multi-axis ffb paramers in a different way,it may take me a few more days to figure this out.

YukMingLaw avatar May 27 '20 17:05 YukMingLaw

Hello, fist thank you very much for your work. I try to build an Yoke with your library and i have following components in use: Arduino Leonardo and two BTS7960B H-Bridges. I used the Code from "pkaser" and have now the Problem, that the Y axis work great with all Effects in XPForce, but the X axis wont work in XPForce. In the TestForce tool, the X axis generate Force but no Effects. Has anybody an Idea, what the Problem is?

"#include "Joystick.h" #include "Encoder.h"

int32_t forces[2] = {0};

long posX; long posY;

int centerX; int centerY;

int lastX = 0; int lastY = 0;

// MotorX int motorXR = 5; // int motorXL = 6; //

// MotorY int motorYR = 10; // int motorYL = 11; //

// joystick encoders int encoderX1 = 0; int encoderX2 = 1; int encoderY1 = 2; int encoderY2 = 3;

int xDirection = LOW; int yDirection = LOW; int centerFound = LOW;

int dur = 2; int strength = 100;

long oldX = -999; long oldY = -999;

const int loopDelay = 5;

int minX = 0; int maxX = 0; int minY = 0; int maxY = 0;

//X-axis & Y-axis REQUIRED Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_JOYSTICK, 0, 0, // Button Count, Hat Switch Count true, true, false, // X and Y, but no Z Axis false, false, false, // No Rx, Ry, or Rz false, false, // No rudder or throttle false, false, false); // No accelerator, brake, or steering

Gains gain[2]; EffectParams effects[2];

//

Encoder encoderX(encoderX1, encoderX2); Encoder encoderY(encoderY1, encoderY2);

void setup() { Serial.begin(9600); delay(2000); //Give the serial port time to catch up so we can debug Serial.println("Setting up...");

Joystick.begin(true); doSetGains(); }

void loop() { if (centerFound == 0) { Serial.println("--Centering"); doFindCenter(); } doJoystickStuff(); doFFBStuff(); delay(loopDelay); }

void doFindCenter() { int cDur = 1000; int cStrength = 50; int tXDir; int tYDir; int tPosX; int tPosY;

doMoveX(cStrength, cDur, HIGH); maxX = stopXMove(); Serial.println(maxX); doMoveX(cStrength, cDur, LOW); minX = stopXMove(); int centerX = (minX + maxX) / 2; doMoveY(cStrength, cDur, HIGH); maxY = stopYMove(); Serial.println(maxY); doMoveY(cStrength, cDur, LOW); minY = stopYMove(); int centerY = (minY + maxY) / 2;

centerX = ((minX + maxX) / 2) - 2; centerY = ((minY + maxY) / 2) - 2;

Joystick.setXAxisRange(minX, maxX); Joystick.setYAxisRange(minY, maxY); tPosX = encoderX.read(); tPosY = encoderY.read(); do { //center X if (centerX < tPosX) { tXDir = HIGH; } else { tXDir = LOW; } doMoveX(155, 2, tXDir); tPosX = stopXMove();

} while (tPosX != centerX);

do { //center Y if (centerY < tPosY) { tYDir = HIGH; } else { tYDir = LOW; } doMoveY(155, 2, tYDir); tPosY = stopYMove();

} while (tPosY != centerY); // stopXMove(); //stopYMove(); centerFound = 1;

}

int stopXMove() { return doMoveX(0, 10, HIGH); }

int stopYMove() { return doMoveY(0, 10, HIGH); }

int doMoveX(int tStrength, int tDuration, int tDirection) { if (tDirection == HIGH) { analogWrite(motorXL, tStrength); //Spins the motor on Channel A at full speed } else { analogWrite(motorXR, tStrength); //Spins the motor on Channel A at full speed } delay(tDuration); analogWrite(motorXR, 0); //Stops motor analogWrite(motorXL, 0); //Stops motor delay(2); return encoderX.read(); }

int doMoveY(int tStrength, int tDuration, int tDirection) { if (tDirection == HIGH) { // Serial.print("High"); analogWrite(motorYR, tStrength); //Spins the motor on Channel A at full speed } else { analogWrite(motorYL, tStrength); //Spins the motor on Channel A at full speed } delay(tDuration); analogWrite(motorYR, 0); //Stops motor analogWrite(motorYL, 0); //Stops motor delay(2); return encoderY.read(); }

void doFFBStuff() { //}

}

void doJoystickStuff() {

posX = encoderX.read(); posY = encoderY.read();

Joystick.setXAxis(posX); Joystick.setYAxis(posY);

effects[0].springMaxPosition = maxX / 2; effects[1].springMaxPosition = maxY / 2; effects[0].frictionMaxPositionChange = maxX; effects[1].frictionMaxPositionChange = maxY; effects[0].inertiaMaxAcceleration = 100; effects[1].inertiaMaxAcceleration = 100; effects[0].damperMaxVelocity = 100; effects[1].damperMaxVelocity = 100;

effects[0].springPosition = posX; effects[1].springPosition = posY; effects[0].frictionPositionChange = lastX - posX; effects[1].frictionPositionChange = lastY - posY; effects[0].inertiaAcceleration = 100; effects[1].inertiaAcceleration = 100; effects[0].damperVelocity = 100; effects[1].damperVelocity = 100;

Joystick.setEffectParams(effects); Joystick.getForce(forces);

int xMoveDir = 0; int yMoveDir = 0; //Get Force [-255,255] you can set PWM with this value //Serial.println(""); //Serial.print(" - XF: "); //Serial.print(forces[0]); //Serial.print(" YF: "); //Serial.print(forces[1]); if (forces[0] > 0) { xMoveDir = LOW; } else if (forces[0] < 0) { xMoveDir = HIGH; } if (forces[1] < 0) { yMoveDir = LOW; } else if (forces[1] > 0) { yMoveDir = HIGH; } if (forces[0] != 0) { doMoveX(abs(forces[0]), dur, xMoveDir); } else { doMoveX(0, 2, xMoveDir); }; if (forces[1] != 0) { doMoveY(abs(forces[1]), dur, yMoveDir); } else { doMoveY(0, 2, yMoveDir); };

lastX = posX; lastY = posY;

}

void doSetGains() { //set x axis gains gain[0].totalGain = 100; gain[0].constantGain = 100; gain[0].rampGain = 100; gain[0].squareGain = 100; gain[0].sineGain = 100; gain[0].triangleGain = 100; gain[0].sawtoothdownGain = 100; gain[0].sawtoothupGain = 100; gain[0].springGain = 100; gain[0].damperGain = 100; gain[0].inertiaGain = 100; gain[0].frictionGain = 100;

//set y axis gains gain[1].totalGain = 100; gain[1].constantGain = 100; gain[1].rampGain = 100; gain[1].squareGain = 100; gain[1].sineGain = 100; gain[1].triangleGain = 100; gain[1].sawtoothdownGain = 100; gain[1].sawtoothupGain = 100; gain[1].springGain = 100; gain[1].damperGain = 100; gain[1].inertiaGain = 100; gain[1].frictionGain = 100;

Joystick.setGains(gain);

}"

ZockZock avatar Sep 29 '20 13:09 ZockZock

can you guy post encoder files for test. I can't found compatible library for this. Thank you

billydragon avatar Nov 08 '20 14:11 billydragon

Can you post your doFFBStuff() function ?

Thank you

fcppenta avatar Mar 09 '21 20:03 fcppenta

Here is my current code. I havent figured out the effects yet, like damper, inertia, friction, etc setting yet so they may be all wrong the way I have them implemented. Same with almost everything in here. I'm new to Arduino. It is a joystick made from a Leonardo, a MotoShield, a 12v/2amp power supply, and an old Microsoft Sidewinder Pro Force Feedback V1 that has had all the electronics removed. I am using only the motors and the yoke and have 3D printed a temporary testing mounting bracket. 90% of it works great with XPForce with X-Plane 11.41.

I really appreciate how much you have done to make this happen, and I happily share my code for anyone else trying to do the same thing.

`#include "Joystick.h" #include "Encoder.h"

int32_t forces[2] = { 0 };

long posX; long posY;

int centerX; int centerY;

int lastX = 0; int lastY = 0;

// Motor int dirX = 12; int dirY = 13;

int brakeX = 9; // NIU int brakeY = 8; // NIU

int motorX = 3; // int motorY = 11; //

//current draw on motors int loadX = A0; int loadY = A1;

// joystick encoders int encoderX1 = 0; int encoderX2 = 1; int encoderY1 = 2; int encoderY2 = 4;

int xDirection = LOW; int yDirection = LOW; int centerFound = LOW;

int dur = 2; int strength = 100;

long oldX = -999; long oldY = -999;

const int loopDelay = 20;

int minX = 0; int maxX = 0; int minY = 0; int maxY = 0;

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_JOYSTICK, 0, 0, // Button Count, Hat Switch Count true, true, false, // X and Y, but no Z Axis false, false, false, // No Rx, Ry, or Rz false, false, // No rudder or throttle false, false, false); // No accelerator, brake, or steering

Gains gain[2]; EffectParams effects[2];

//

Encoder encoderX(encoderX1, encoderX2); Encoder encoderY(encoderY1, encoderY2);

void setup() { Serial.begin(9600); delay(2000); //Give the serial port time to catch up so we can debug Serial.println("Setting up..."); pinMode(dirX, OUTPUT); //Initiates Motor Channel X pin pinMode(dirY, OUTPUT); //Initiates Motor Channel Y pin

Joystick.begin(true); doSetGains(); }

void loop(){ if (centerFound == 0){ Serial.println("--Centering"); doFindCenter(); } doJoystickStuff(); doFFBStuff(); delay(loopDelay); }

void doFindCenter(){ int cDur = 80; int cStrength = 255; int tXDir; int tYDir; int tPosX; int tPosY;

doMoveX(cStrength,cDur,HIGH); maxX = stopXMove(); doMoveX(cStrength,cDur,LOW); minX = stopXMove(); int centerX = (minX + maxX)/2; doMoveY(cStrength,cDur,HIGH); maxY = stopYMove(); doMoveY(cStrength,cDur,LOW); minY = stopYMove(); int centerY = (minY + maxY)/2;

centerX = ((minX + maxX)/2)-2; centerY = ((minY + maxY)/2)-2;

Joystick.setXAxisRange(minX,maxX); Joystick.setYAxisRange(minY,maxY); tPosX = encoderX.read(); tPosY = encoderY.read(); do { //center X if (centerX > tPosX){tXDir = HIGH;} else {tXDir = LOW;} doMoveX(255,2,tXDir); tPosX = stopXMove();

} 
while (tPosX != centerX);

do { //center Y if (centerY > tPosY){tYDir = HIGH;} else {tYDir = LOW;} doMoveY(255,2,tYDir); tPosY = stopYMove();

} 
while (tPosY != centerY);
stopXMove();
stopYMove();
centerFound = 1;

}

int stopXMove(){ return doMoveX(0, 10, HIGH); }

int stopYMove(){ return doMoveY(0, 10, HIGH); }

int doMoveX(int tStrength, int tDuration, int tDirection){ digitalWrite(dirX, tDirection); //High=Forward / Low=Reverse analogWrite(motorX, tStrength); //Spins the motor on Channel A at full speed delay(tDuration); // analogWrite(motorX, 0); //Stops motor delay(2); return encoderX.read(); }

int doMoveY(int tStrength, int tDuration, int tDirection){ digitalWrite(dirY, tDirection); //High=Forward / Low=Reverse analogWrite(motorY, tStrength); //Spins the motor on Channel A at full speed delay(tDuration); // analogWrite(motorY, 0); //Stops motor delay(2); return encoderY.read(); }

void doFFBStuff(){ //}

}

void doJoystickStuff(){

posX = encoderX.read(); posY = encoderY.read();

Joystick.setXAxis(posX); Joystick.setYAxis(posY);

effects[0].springMaxPosition = maxX/2; effects[1].springMaxPosition = maxY/2; effects[0].frictionMaxPositionChange = lastX - posX; effects[1].frictionMaxPositionChange = maxY; effects[0].inertiaMaxAcceleration = maxX; effects[1].inertiaMaxAcceleration = 100; effects[0].damperMaxVelocity = 10; effects[1].damperMaxVelocity = 100;

effects[0].springPosition = posX; effects[1].springPosition = posY; effects[0].frictionPositionChange = lastX - posX; effects[1].frictionPositionChange = lastY - posY; effects[0].inertiaAcceleration = 100; effects[1].inertiaAcceleration = 100; effects[0].damperVelocity=100; effects[1].damperVelocity=100;

Joystick.setEffectParams(effects); Joystick.getForce(forces);

int xMoveDir = 0; int yMoveDir = 0; //Get Force [-255,255] you can set PWM with this value Serial.println(""); Serial.print(" - XF: "); Serial.print(forces[0]); Serial.print(" YF: "); Serial.print(forces[1]); //if (forces[0] != 0 || forces[1] != 0 ){ if (forces[0]<0){ xMoveDir = LOW; } else if (forces[0]>0){ xMoveDir = HIGH; } if (forces[1]<0){ yMoveDir = LOW; } else if (forces[1]>0){ yMoveDir = HIGH; } if (forces[0]!=0){ doMoveX(abs(forces[0]),dur,xMoveDir); } else { doMoveX(0,2,xMoveDir); }; if (forces[1]!=0) { doMoveY(abs(forces[1]),dur,yMoveDir); } else { doMoveY(0,2,yMoveDir); };

lastX = posX; lastY = posY;

}

void doSetGains(){ //set x axis gains gain[0].totalGain = 100; gain[0].constantGain = 100; gain[0].rampGain = 100; gain[0].squareGain = 100; gain[0].sineGain = 100; gain[0].triangleGain = 100; gain[0].sawtoothdownGain = 100; gain[0].sawtoothupGain = 100; gain[0].springGain = 100; gain[0].damperGain = 100; gain[0].inertiaGain = 100; gain[0].frictionGain = 100;

//set y axis gains gain[1].totalGain = 100; gain[1].constantGain = 100; gain[1].rampGain = 100; gain[1].squareGain = 100; gain[1].sineGain = 100; gain[1].triangleGain = 100; gain[1].sawtoothdownGain = 100; gain[1].sawtoothupGain = 100; gain[1].springGain = 100; gain[1].damperGain = 100; gain[1].inertiaGain = 100; gain[1].frictionGain = 100;

Joystick.setGains(gain);

} `

Hello Pkaser did you find a solution and got it to work perfectly?

Cardoba avatar Jul 29 '22 22:07 Cardoba