YukMingLaw / ArduinoJoystickWithFFBLibrary

An Arduino Joystick Library With Force Feedback Feature
GNU Lesser General Public License v3.0
208 stars 55 forks source link

Gains and Effects? #10

Closed gagagu closed 3 years ago

gagagu commented 3 years ago

Hi, i've used the based joystick library to repair my broken Saitek Yoke and it's working perfect. Now, i want to extend it to a FFB Yoke. My plan is to use a strong RC Servo (35Kg) to create the force. The Serve should rotate in the same angle as the yoke plus or minus the measured force. I've made some tests with X-Plane and the XPForce Plugin but i have some problems to understand the Gains and Effects Parameters. Basely i do understand for what they are but i don't have enough experience to select the correct gains and parameters settings. Is it possible for you to help me out to find the correct configuration?

Thx forward for your work!

YukMingLaw commented 3 years ago

Hi, The gains are the magnitude of each force,range0-100. The effects parameters are the dynamic parameters,they should bind with the current state of the action-axis.Like axis's position(degree),axis's speed(delta degree),and axis's accelation(delta speed). Hopes it can help you.

waggy685 commented 3 years ago

Hi, i've used the based joystick library to repair my broken Saitek Yoke and it's working perfect. Now, i want to extend it to a FFB Yoke. My plan is to use a strong RC Servo (35Kg) to create the force. The Serve should rotate in the same angle as the yoke plus or minus the measured force. I've made some tests with X-Plane and the XPForce Plugin but i have some problems to understand the Gains and Effects Parameters. Basely i do understand for what they are but i don't have enough experience to select the correct gains and parameters settings. Is it possible for you to help me out to find the correct configuration?

Thx forward for your work!

Hi GAGAGU !

Would you share your *.ino file ? Because a got stuck... I have the same Joystick. Thanks !

Best regards

gagagu commented 3 years ago

@YukMingLaw: I't helps me a little bit, even if i don't know which Gains i should use.

@waggy685: Yes, of course. If you wonder what i've done: 1: i didn't know the map command when programming this. 2: I've made a small Filter routine to flatten the reaction curve

If you have some problems with my german langage, contact me for help.

include "Joystick.h"

define JOYSTICK_THROTTLE_ID 0x03

Joystick_ Joystick(JOYSTICK_THROTTLE_ID, JOYSTICK_TYPE_JOYSTICK, 14, 1, true, true, false, false, false, false, false, false, false, false, false);

// Number of Readings for Smoothing const int numReadings = 20; int readIndexDigitalPins = 0; // the index of the current reading

// Constant that maps the phyical pin to the joystick button. int inputPinQuerruder = A0; int inputPinHoehenruder = A1;

// Last state of the button int lastButtonState[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int val0 = 0; int val1 = 0;

int alteWerte[3] = {0, 0}; float diff = 0.0; float teiler = 0.0; float valFloat = 0.0;

// Höhenruder int hoeheUnderBorder = 315; int hoeheUpperBorder = 900;

int readingsHoehenruder[numReadings]; // the readings from the analog input int readIndexHoehenruder = 0; // the index of the current reading int totalHoehenruder = 0; // the running total int averageHoehenruder = 0; // the average

// Querruder int querUnderBorder = 330; int querUpperBorder = 920;

int readingsQuerruder[numReadings]; // the readings from the analog input int readIndexQuerruder = 0; // the index of the current reading int totalQuerruder = 0; // the running total int averageQuerruder = 0; // the average

void setup() { Joystick.setXAxisRange(querUnderBorder, querUpperBorder); Joystick.setYAxisRange(hoeheUnderBorder, hoeheUpperBorder);

pinMode(A0, INPUT_PULLUP); pinMode(A1, INPUT_PULLUP); pinMode(A2, INPUT_PULLUP); pinMode(A3, INPUT_PULLUP); pinMode(A4, INPUT_PULLUP); pinMode(A5, INPUT_PULLUP);

pinMode(0, INPUT_PULLUP); pinMode(1, INPUT_PULLUP); 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(11, INPUT_PULLUP); pinMode(12, INPUT_PULLUP); pinMode(13, INPUT_PULLUP);

Joystick.begin();

//Serial.begin(9600); }

void SetHatSwitch() { //Serial.print("set head"); if ((lastButtonState[7] == 0) && (lastButtonState[8] == 0) && (lastButtonState[9] == 0) && (lastButtonState[10] == 0)) { Joystick.setHatSwitch(0, -1); } if ((lastButtonState[7] == 1) && (lastButtonState[8] == 0) && (lastButtonState[9] == 0) && (lastButtonState[10] == 0)) { Joystick.setHatSwitch(0, 270); } if ((lastButtonState[7] == 1) && (lastButtonState[8] == 1) && (lastButtonState[9] == 0) && (lastButtonState[10] == 0)) { Joystick.setHatSwitch(0, 225); } if ((lastButtonState[7] == 0) && (lastButtonState[8] == 1) && (lastButtonState[9] == 0) && (lastButtonState[10] == 0)) { Joystick.setHatSwitch(0, 180); } if ((lastButtonState[7] == 0) && (lastButtonState[8] == 1) && (lastButtonState[9] == 1) && (lastButtonState[10] == 0)) { Joystick.setHatSwitch(0, 135); } if ((lastButtonState[7] == 0) && (lastButtonState[8] == 0) && (lastButtonState[9] == 1) && (lastButtonState[10] == 0)) { Joystick.setHatSwitch(0, 90); } if ((lastButtonState[7] == 0) && (lastButtonState[8] == 0) && (lastButtonState[9] == 1) && (lastButtonState[10] == 1)) { Joystick.setHatSwitch(0, 45); } if ((lastButtonState[7] == 0) && (lastButtonState[8] == 0) && (lastButtonState[9] == 0) && (lastButtonState[10] == 1)) { Joystick.setHatSwitch(0, 0); } if ((lastButtonState[7] == 1) && (lastButtonState[8] == 0) && (lastButtonState[9] == 0) && (lastButtonState[10] == 1)) { Joystick.setHatSwitch(0, 315); }

} //SetHatSwitch

void SetDigitalPins(){ // Nur alle X Durchläufe lesen if(readIndexDigitalPins>=numReadings){ readIndexDigitalPins=0; // Read pin values for (int index = 0; index < 14; index++) { int currentButtonState = !digitalRead(index ); delay(1); if (currentButtonState != lastButtonState[index]) { lastButtonState[index] = currentButtonState; if ((index >= 7) && (index <= 10)) { SetHatSwitch(); } else { Joystick.setButton(index, currentButtonState); }

  }
}

}else{ readIndexDigitalPins++; } } // SetDigitalPins

void loop() { // **** // digitale Pins // **** SetDigitalPins();

// **** // Querruder // ****

totalQuerruder = totalQuerruder - readingsQuerruder[readIndexQuerruder]; readingsQuerruder[readIndexQuerruder] = analogRead(inputPinQuerruder); delay(1); totalQuerruder = totalQuerruder + readingsQuerruder[readIndexQuerruder]; readIndexQuerruder = readIndexQuerruder + 1; averageQuerruder = totalQuerruder / numReadings;

if (readIndexQuerruder >= numReadings) { readIndexQuerruder = 0; Joystick.setXAxis(averageQuerruder); }

// **** // Hoehenruder // ****

totalHoehenruder = totalHoehenruder - readingsHoehenruder[readIndexHoehenruder]; readingsHoehenruder[readIndexHoehenruder] = analogRead(inputPinHoehenruder); delay(1); totalHoehenruder = totalHoehenruder + readingsHoehenruder[readIndexHoehenruder]; readIndexHoehenruder= readIndexHoehenruder + 1; averageHoehenruder = totalHoehenruder / numReadings;

if (readIndexHoehenruder >= numReadings) { readIndexHoehenruder = 0; Joystick.setYAxis(averageHoehenruder); }

//delay(5); }

You have to change the (for Arduino Leonaro, change other place for other Arduino type) C:\Program Files (x86)\Arduino\hardware\arduino\avr\boards.txt from

leonardo.build.vid=0x2341 leonardo.build.pid=0x8036 leonardo.build.usb_product="Arduino Leonardo"

to

leonardo.build.vid=0x9998 leonardo.build.pid=0x9998 leonardo.build.usb_product="Arduino Yoke"

You have to restart you PC after change. This will rename the usb name of the Yoke.

YukMingLaw commented 3 years ago

Hi,

struct Gains{
        uint8_t totalGain         = FORCE_FEEDBACK_MAXGAIN;
    uint8_t constantGain      = FORCE_FEEDBACK_MAXGAIN;
    uint8_t rampGain          = FORCE_FEEDBACK_MAXGAIN;
    uint8_t squareGain        = FORCE_FEEDBACK_MAXGAIN;
    uint8_t sineGain          = FORCE_FEEDBACK_MAXGAIN;
    uint8_t triangleGain      = FORCE_FEEDBACK_MAXGAIN;
    uint8_t sawtoothdownGain  = FORCE_FEEDBACK_MAXGAIN;
    uint8_t sawtoothupGain    = FORCE_FEEDBACK_MAXGAIN;
    uint8_t springGain        = FORCE_FEEDBACK_MAXGAIN;
    uint8_t damperGain        = FORCE_FEEDBACK_MAXGAIN;
    uint8_t inertiaGain       = FORCE_FEEDBACK_MAXGAIN;
    uint8_t frictionGain      = FORCE_FEEDBACK_MAXGAIN;
    uint8_t customGain        = FORCE_FEEDBACK_MAXGAIN;
};

The struct initialized with max gain,so if you dont know how to set this param.just creat a gain var Gains mygains[2]; and invoke setGains(mygains) in setup().