YukMingLaw / ArduinoJoystickWithFFBLibrary

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

BTS7960 + DC Motor for FFB Wheel #43

Open Vee-21 opened 2 years ago

Vee-21 commented 2 years ago

Hi all

First of all thanks YukMingLaw for creating this, I think this will be the final piece to finish my racing arcade cabinet project.

I've got my arcade wheel, pedals and 6 speed shifter working using the standard Joystick library and I'm now trying to get FFB working. I'm still new to Arduino and coding so my logic and explanation will be very basic.

My steering wheel uses a potentiometer and is connected to A0 on the Leonardo. As far as I know the BTS7960 motor drive has two input pins Right PWM and Left PWM which I've connected to pin 3 and 4.

My question is would this setup work with this library? I saw that the example has 3 outputs which I'm not sure how they would work with the BTS7960. I'm guessing in the example (SingleJoystickFFB.ino) Pin 6 and 7 would connect to the BTS7960 motor drive Right and Left PWM?

Any help/links would be appreciated.

Cheers

crimzzon92 commented 2 years ago

I have 775 DC motor driven by BTS7960 and it works perfectly.

Drive motors whit this code. I have the two enable pins connected to the same pin on Arduino. that's way I only cal out right or left in the code.

 // X Axis Funktion

if(forces[0] > 0){ analogWrite(ROLL_L_PWM,abs(forces[0])); analogWrite(ROLL_R_PWM, 0); digitalWrite(ROLL_L_EN,HIGH); }else{ analogWrite(ROLL_R_PWM,abs(forces[0])); analogWrite(ROLL_L_PWM, 0); digitalWrite(ROLL_R_EN,HIGH); }

Vee-21 commented 2 years ago

Thanks for the response crimzzon92. I'm still new to all this so I'm a bit confused how to wiring would look like for your example.

So in the code I would have something like:

const int bts_R_PWM = 3; const int bts_L_PWM = 4; const int bts_R_Enable = 5; //Left and right enable = the same pin? const int bts_L_Enable = 5; //Left and right enable = the same pin?

pinMode(3, OUTPUT); //Connected to BTS7960 Pin 1 - Right PWM pinMode(4, OUTPUT); //Connected to BTS7960 Pin 2 - Left PWM pinMode(5, OUTPUT); //Connected to BTS7960 Pin 3 & 4 (Right Enable / Left Enable Input) ?

if(forces[0] > 0){ analogWrite(L_PWM,abs(forces[0])); analogWrite(R_PWM, 0); digitalWrite(L_Enable,HIGH); } else{ analogWrite(R_PWM,abs(forces[0])); analogWrite(L_PWM, 0); digitalWrite(R_Enable,HIGH); }

crimzzon92 commented 2 years ago

I should work.

I have the pins signed like this

const int PITCH_R_EN = 16; const int PITCH_L_EN = 16; const int PITCH_R_PWM = 10; const int PITCH_L_PWM = 5;

Another tips are to make the PWM frequency higher on the arduino. the default is 950 Hz & 500 Hz for the PWM pins on the Arduino pro micro. I had a really bad noise coming from the dc motors. So I find an old library that allows you to change the frequency in fixed ranges. The only useable range is 4000Hz because the max is 31000 Hz but the BTS7960 only handles up to 25000Hz.

but 4000Hz makes a big difference in the sound coming from the motors.

include

void setup(){ // Set the PWM to 4000 Hz frequency setPWMPrescaler(5, 8); setPWMPrescaler(6, 8); setPWMPrescaler(9, 8); setPWMPrescaler(10, 8); }

Link to Library: https://github.com/TheDIYGuy999/PWMFrequency

Vee-21 commented 2 years ago

Thanks for the help crimzzon92!

My last question how did you setup your Joystick? For my current setup which doesn't use FFB I use:

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_MULTI_AXIS, 8, 0, // Button Count, Hat Switch Count false, false, false, // X, Y, Z Axis false, false, false, //Rx, Ry, Rz false, false, //rudder, throttle true, true, true); //accelerator, brake, steering

From what I understand I need to enable X Y Axis for the FFB to work so would I just simply use:

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_MULTI_AXIS, 8, 0, // Button Count, Hat Switch Count true, true, false, // X, Y, Z Axis false, false, false, //Rx, Ry, Rz false, false, //rudder, throttle true, true, true); //accelerator, brake, steering

My complete code is below:

`

include

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_MULTI_AXIS, 8, 0, // Button Count, Hat Switch Count true, true, false, // X, Y, Z Axis - X & Y enabled for FFB false, false, false, //Rx, Ry, Rz false, false, //rudder, throttle true, true, true); //accelerator, brake, steering

//Setup steering, brake and accel pins const int steerPin = A0; const int brakePin = A2; const int accelPin = A1;

//BTS7960 Pins (RPWM / LPWM) (Right / Left Pulse Width Modulation) const int bts_R_PWM = 3; //Yellow const int bts_L_PWM = 4; //Purple const int bts_R_Enable = 5; //Left and right enable = Pin 5 (Orange) const int bts_L_Enable = 5; //Left and right enable = Pin 5 (Orange)

//Setup Values int steerValue; int brakeValue; int accelValue;

//Setup FFB Gains Gains mygains[2]; EffectParams myeffectparams[2]; int32_t forces[2] = {0};

void setup() {

//Initialise button pins pinMode(7, INPUT_PULLUP); //Mode pinMode(8, INPUT_PULLUP); //View pinMode(3, OUTPUT); //Connected to BTS7960 Pin 1 - Right PWM pinMode(4, OUTPUT); //Connected to BTS7960 Pin 2 - Left PWM pinMode(5, OUTPUT); //Connected to BTS7960 Pin 3 & 4 (Right Enable / Left Enable Input)

//set X Axis gains mygains[0].totalGain = 50; mygains[0].springGain = 80;

//set Y Axis gains mygains[1].totalGain = 50; mygains[1].springGain = 70;

//Steering Options - X Axis or Steering //Joystick.setXAxisRange(0, 1023); //Steering Wheel - Joystick.setXAxisRange(min, max); Joystick.setSteeringRange(0, 960);

//Brake Options - Y Axis or Brake //Joystick.setYAxisRange(0, 1023); //Brake Pedal - Joystick.setYAxisRange(min, max); Joystick.setBrakeRange(400, 767);

//Accelerator Options - Z Axis or Acceleratro //Joystick.setZAxisRange(0, 1023); //Accel Pedal - Joystick.setZAxisRange(min, max); Joystick.setAcceleratorRange(490, 915);

//Enable FFB gains Joystick.setGains(mygains);

//Start Joystick Joystick.begin(); }

//Start loop void loop() { BrakePedal(); SteerWheel(); AccelPedal(); FFB(); }

void SteerWheel(){ steerValue = analogRead(steerPin); //Joystick.setXAxis(steerValue); Joystick.setSteering(steerValue); }

void BrakePedal(){ brakeValue = analogRead(brakePin); Joystick.setBrake(brakeValue); Serial.println(brakeValue); // Testing analog input }

void AccelPedal(){ accelValue = analogRead(accelPin); Joystick.setAccelerator(accelValue); }

void FFB(){ //FFB - Set X Axis Spring Effect Param myeffectparams[0].springMaxPosition = 960; myeffectparams[0].springPosition = steerValue;

//FFB - Send HID data to PC Joystick.setXAxis(steerValue);

//FFB - Receive HID-PID data from PC and calculate forces Joystick.setEffectParams(myeffectparams); Joystick.getForce(forces); if(forces[0] > 0){ analogWrite(bts_L_PWM,abs(forces[0])); analogWrite(bts_R_PWM, 0); digitalWrite(bts_L_Enable,HIGH); } else{ analogWrite(bts_R_PWM,abs(forces[0])); analogWrite(bts_L_PWM, 0); digitalWrite(bts_R_Enable,HIGH); } }`

crimzzon92 commented 2 years ago

Yes, you need X & Y to be true for FFB to work. Then change JOYSTICK_TYPE_MULTI_AXIS to JOYSTICK_TYPE_JOYSTICK. fore some reason. when using Multi_Axis windows won't see your device. then put in all the forces gain into the code. If I did not, the forces acted weird on me. you can just set the ones you don't want to 0. Remember to set the gain value low when testing whit motor. if your motor is powerful you can get hurt. a 775 dc motor on 100% is strong. I have everything set to around 20-30%. but that value depends on gearing a so one.

mygains[0].rampGain = 100;//0-100 mygains[0].squareGain = 100;//0-100 mygains[0].sineGain = 100;//0-100 mygains[0].triangleGain = 100;//0-100 mygains[0].sawtoothdownGain = 100;//0-100 mygains[0].sawtoothupGain = 100;//0-100 mygains[0].constantGain = 100;//0-100 mygains[0].springGain = 100;//0-100 mygains[0].damperGain = 100;//0-100 mygains[0].inertiaGain = 100;//0-100 mygains[0].frictionGain = 100;//0-100 mygains[0].customGain = 100;//0-100

Hope its helps!

1781741527 commented 1 year ago

Hello, I would like to ask, have you ever encountered a situation where the force feedback done by this library causes the game to drop frames in the game? I'm also having a similar issue, I seem to have fixed the issue with force feedback acquisition, but it's causing my game to drop frames very badly! I feel like the device is constantly fetching game data from the game, causing the game to drop frames, but I don't know how to fix it yet, so I'm wondering if your project is complete? Can you give me some help?