theperson Posted December 11, 2021 Posted December 11, 2021 3 hours ago, slimheli said: Wow. This looks amazing! What material and thickness did you specify for the metal bits? I followed propeler's design specs so I wouldn't have to recalculate bend radii. Cheap and cheerful A36 mild steel @ 3mm. With the slots there's some wiggle room, but my holes are lined up basically in the middle of the slots. Eventually I may need to add some sort of rust preventative though. The thickness is needed for the tapped holes mounting the main gimbal frame bearings. As designed there's no space for hex nuts there. If you lengthened the shoulder on the arm frames and spaced out the sheet metal plates and mounting holes accordingly you could get away with using thinner steel that you could bend in your garage. Arduino -> oDrive serial connection keeps dropping due to noise, and Amazon has lost two separate ferrite ring orders. Why did I have to forget those on my digikey order? I've been mourning the loss of Radioshack and Fry's recently.
robjos1 Posted December 11, 2021 Posted December 11, 2021 @theperson which encoders did you end up using? The as5048a? I have previously used the odrive board with the AMT102 and would like to keep using these if possible, would they work? When you finish the wiring for your setup would you mind posting the final arduino code you use and a quick schematic for which pins on the odrive and arduino you are using for the connection. Keep up the great work
theperson Posted December 11, 2021 Posted December 11, 2021 (edited) 30 minutes ago, robjos1 said: @theperson which encoders did you end up using? The as5048a? I have previously used the odrive board with the AMT102 and would like to keep using these if possible, would they work? When you finish the wiring for your setup would you mind posting the final arduino code you use and a quick schematic for which pins on the odrive and arduino you are using for the connection. Keep up the great work Correct, I'm using the as5048a's. While using incremental encoders is probably do-able, its a lot simpler to have the odrive already know where it is at startup without needing to do an index search. Remember that the joystick has limited travel and the motors can't make a full rotation. With the designed gear ratio the motors have a lock-to-lock range of ~half a rotation total (+/- 0.25 rotations each side). With a stick extension I'm only going to be using about half of that available travel on the roll axis, so the 2048ppr resolution of the amt102's might start becoming noticeable. Edited December 11, 2021 by theperson
TomVR Posted December 12, 2021 Posted December 12, 2021 7 hours ago, slimheli said: Hey @TomVR, did you see my question regarding the f3d file you posted? It doesn't seem to want to open in Fusion. Any idea what was causing that? I'd like to try printing your case, and maybe adapt it for the ODrive motors I have. are you cloning the entire repo? If you right click and save as on github it just downloads an html which contains a bunch of useless binary text. You have to either use a git client or download the entire repo
TomVR Posted December 13, 2021 Posted December 13, 2021 (edited) In the gimbal design, has anyone had a problem with a clunk on the pitch axis? Feels like the "GIMBAL_CORE_JOINT.STL" part is shifting back and forth while crossing the center on the pitch, making a popping noise and a felt clunk. Only happens when there is an external load on the axis from the gear teeth (or my cam springs) recorded a video of it happening. https://imgur.com/a/QQP1L1s Edited December 13, 2021 by TomVR
robjos1 Posted December 13, 2021 Posted December 13, 2021 @theperson Out of interest which magnets did you fix to the end of the motor to control the AS5048A?
theperson Posted December 14, 2021 Posted December 14, 2021 9 hours ago, robjos1 said: @theperson Out of interest which magnets did you fix to the end of the motor to control the AS5048A? I'm using the development boards, which each came with a small round magnet (AS5000-MD6H-2 diametric magnet). I printed the encoder mounts such that the surface of the chip would be 1.5mm away from the magnet, since the datasheet recommends a 0.5-2.5mm range. No luck with shielding and ferrite rings fixing my odrive->arduino communication problem. Posting about it here in the odrive forums. @propeler let me know if you need any testers for the odrive firmware
theperson Posted December 15, 2021 Posted December 15, 2021 Downgrading the odrive firmware to 0.5.1 fixed all my serial dropout problems. I kludged together some code using this library on an arduino pro micro protip: spring effects in that library expect you to set your joystick range as (-min,max), not (0,max) like it shows in the example [at least to make effects in DCS work] I've spent about 30 minutes just making sure it works right and getting gains in the right neighborhood to where they won't break the gimbal. I'll get my setup mounted properly and clean up the code in the next couple days and post some more. 2
robjos1 Posted December 15, 2021 Posted December 15, 2021 Brilliant news, well done there! If you could post up your code and pertinent odrive settings with a quick list of which pins you used to hook it all up that would be amazing! Thanks again for all your efforts 1
0xDEADBEEF Posted December 16, 2021 Posted December 16, 2021 On 12/15/2021 at 9:58 AM, theperson said: I kludged together some code using this library on an arduino pro micro Would you mind sharing your code? I just finished my mechanics and am about to tackle exactly this. I was actually looking at fino, but it seems it does not really matter which library to use I'm going direct drive with hoverboard motors by the way, landed a nice deal on a used hoverboard without charger for 30€. I was lucky the seller did not check used prices on those boards, a charger would have only been 15€ on amazon ...
theperson Posted December 16, 2021 Posted December 16, 2021 (edited) On 12/16/2021 at 8:41 AM, 0xDEADBEEF said: Would you mind sharing your code? I just finished my mechanics and am about to tackle exactly this. I was actually looking at fino, but it seems it does not really matter which library to use I'm going direct drive with hoverboard motors by the way, landed a nice deal on a used hoverboard without charger for 30€. I was lucky the seller did not check used prices on those boards, a charger would have only been 15€ on amazon ... Be warned, it's still very much in the kludged-together state. I'm thinking of trying out the Fino library instead, since he's got nice rate control and the friction position change/velocity calculations set up already. It's a bit jittery in DCS, and I'm not sure quite sure how much of that is forcefeedback vibration or jittery encoder vibration. My problems with the Odrive UART not responding to the GetPosition() calls were solved by flashing the older 0.5.1 firmware. I also downgraded the odrivetool command line to keep things compatible. BAD CODE USED TO BE HERE, REMOVED TO SAVE THE WORLD FROM MY INEPTITUDE LOOK AT A LATER POST BELOW FOR BETTER CODE I included the Ewma library for input filtering, which is available to install through the arduino library manager window. For the ArduinoJoystickWithFFBLibrary and the OdriveArduino library you'll have to download them separately and move them into your ~/Documents/Arduino/libraries folder. And these are the commands for setting up the odrive parameters with the as5048a encoders: //Initial Setup odrv0.axis0.motor.config.resistance_calib_max_voltage = 4 odrv0.axis0.encoder.config.abs_spi_cs_gpio_pin = 6 odrv0.axis0.encoder.config.mode = ENCODER_MODE_SPI_ABS_AMS odrv0.axis0.encoder.config.cpr = 2**14 odrv0.axis1.motor.config.resistance_calib_max_voltage = 4 odrv0.axis1.encoder.config.abs_spi_cs_gpio_pin = 7 odrv0.axis1.encoder.config.mode = ENCODER_MODE_SPI_ABS_AMS odrv0.axis1.encoder.config.cpr = 2**14 odrv0.config.uart_baudrate = 500000 ...with the 0.5.1 firmware the brake resistor is just assumed to be connected ...for the newer firmwares you'll need to configure it odrv0.config.enable_brake_resistor = True ...I set the current limits to 6, I dont really need more with my motors odrv0.axis0.motor.config.current_lim = 6 odrv0.axis1.motor.config.current_lim = 6 ...raise the velocity limits to 6rev/s, you can pretty easily hit the 2rev/s default odrv0.axis0.controller.config.vel_limit = 6 odrv0.axis1.controller.config.vel_limit = 6 odrv0.save_configuration() odrv0.reboot() //Motor and Encoder Calibration //do these with the motors free to spin, not hooked up to the gimbal odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE odrv0.axis0.motor.config.pre_calibrated = True odrv0.axis0.encoder.config.pre_calibrated = True odrv0.axis1.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE odrv0.axis1.motor.config.pre_calibrated = True odrv0.axis1.encoder.config.pre_calibrated = True odrv0.save_configuration() odrv0.reboot() odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL odrv0.axis1.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL ...this should turn on the motors and have them hold position where they are ...try turning the motors by hand and see if they push back ...if motors aren't on check for errors by running: dump_errors(odrv0) ...you can follow the Tuning section to tune the gains: https://docs.odriverobotics.com/control.html ...but it might be better to do that with the belts connected //Anticogging Calibration //do these with the motors free to spin, not hooked up to the gimbal odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL odrv0.axis0.controller.start_anticogging_calibration() odrv0.axis1.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL odrv0.axis1.controller.start_anticogging_calibration() ...wait for anticogging to finish, it can take a while like 10 minutes ...you can increase pos_gain and vel_integrator_gain by a factor of 10 to speed it up, but remember to set them back ...you can check if anticogging calibration is finished by running: odrv0.axis0.controller.config.anticogging.calib_anticogging ...and if it returns True, calibration is still running, it will return False when its complete odrv0.axis0.controller.config.anticogging.anticogging_enabled = True odrv0.axis1.controller.config.anticogging.anticogging_enabled = True odrv0.save_configuration() odrv0.reboot() Edited January 25, 2022 by theperson 3 1
0xDEADBEEF Posted December 16, 2021 Posted December 16, 2021 Very nice, thank you! I had no clue there was an odrive library for arduino This alone will save me hours! I had the original MS FFB Pro in the 90s, I think it's still in my basement. Can't wait to finally fly with force feedback again with a proper grip and more torque thank you guys! What a fun project!!
robjos1 Posted December 16, 2021 Posted December 16, 2021 Thanks so much for all the details, can't wait to get this up and running on my diy ffb yoke
SquidgyB Posted December 17, 2021 Posted December 17, 2021 @theperson Nice work! You said that downgrading the firmware helped with SPI issues? These have plagued my setup throughout, to the point that I've ordered two separate single-axis ODrive clones to get around the issue - Axis1 seemed to have SPI_COM_FAIL errors on calibration every time while Axis0 stayed ok. I tried with tri-state buffers but these didn't seem to help with the dropouts, though they seemed to work as the data was still being passed on when checking SHADOW_COUNT. At the moment I've got some jitter on both encoders, where it wasn't present when I was building a few months ago - I suspect I might have some alignment issues on the magnet/motor, so I'll have a bit of a re-think of the encoder enclosures as they were a bit... hastily built, shall we say. Right now I have it all set up as a simple "return to center" stick, pedals and throttle all ready, so I just need to add the Arduino Due (which has enough com lines to speak to two ODrives simultaneously) and bodge together some FINO/ODrive Arduino example code - all the code you've posted is going to come in *VERY* handy for that, and I thank you greatly for providing it. I've also given up on the 4-motor configuration I was hoping for - two hoverboard motors is absolutely enough. I'm not sure what the strength of the motors is currently running at, but I've dialled it down a lot, and the grip mount (VKB Gunfighter MKIII) and stick seem a little bit flexy when pushed to the far diagonals - not really enough to worry about, but enought to make me think I'd really like a solid metal grip...
theperson Posted December 17, 2021 Posted December 17, 2021 (edited) 3 hours ago, SquidgyB said: @theperson Nice work! You said that downgrading the firmware helped with SPI issues? These have plagued my setup throughout, to the point that I've ordered two separate single-axis ODrive clones to get around the issue - Axis1 seemed to have SPI_COM_FAIL errors on calibration every time while Axis0 stayed ok. I tried with tri-state buffers but these didn't seem to help with the dropouts, though they seemed to work as the data was still being passed on when checking SHADOW_COUNT. Sorry, but the comms issues I was having was just with the serial output to the arduino. My SPI comms seem to be solid. With the motors turned on the odrive would just stop responding to GetPosition() calls after a couple seconds. It would take longer at slower baudrates but it would eventually happen. The strange thing was the SetPosition() commands going the other way would get through just fine, even when the odrive stopped responding to position requests. Do you have ferrite toroids on the motor leads, shielding wrap on your motor wires and encoder wires, grounding said shielding wrap to the V- input pad? Also just routing the encoder cables away from the motors and motor leads. A word of warning on the Due - the ArduinoJoystickWithFFBLibrary and Fino are built around the usb comms of an ATmega32u4 chip. I spent a little while trying to see if I could run it on a SAMD51 chip, and couldn't figure it out. I've determined that the jitter is the encoder data, definitely not a commanded vibration input. With friction turned on it gets pretty horrible with how it's trying to apply friction forces to the constantly changing position. I'm going to take a look at redoing my encoder/magnet mounts to see if I can reduce some jitter that way. With how much I've turned down my motors I could probably eliminate the belts and just direct-drive the gimbal, so I'll figure out how best to mount everything for that. I figure the loss of encoder resolution will be worth it. Edited December 17, 2021 by theperson 1
SquidgyB Posted December 17, 2021 Posted December 17, 2021 3 hours ago, theperson said: Sorry, but the comms issues I was having was just with the serial output to the arduino. My SPI comms seem to be solid. With the motors turned on the odrive would just stop responding to GetPosition() calls after a couple seconds. It would take longer at slower baudrates but it would eventually happen. The strange thing was the SetPosition() commands going the other way would get through just fine, even when the odrive stopped responding to position requests. Do you have ferrite toroids on the motor leads, shielding wrap on your motor wires and encoder wires, grounding said shielding wrap to the V- input pad? Also just routing the encoder cables away from the motors and motor leads. A word of warning on the Due - the ArduinoJoystickWithFFBLibrary and Fino are built around the usb comms of an ATmega32u4 chip. I spent a little while trying to see if I could run it on a SAMD51 chip, and couldn't figure it out. I've determined that the jitter is the encoder data, definitely not a commanded vibration input. With friction turned on it gets pretty horrible with how it's trying to apply friction forces to the constantly changing position. I'm going to take a look at redoing my encoder/magnet mounts to see if I can reduce some jitter that way. With how much I've turned down my motors I could probably eliminate the belts and just direct-drive the gimbal, so I'll figure out how best to mount everything for that. I figure the loss of encoder resolution will be worth it. Ah, I see. Yep, I've worked through a lot of variations to get where it is now and never quite figured out what was wrong, the only way to work around it I've found that consistently works is just to not use the second axis! I've got RJ45 breakouts with each signal wire paired with a ground wire, shielded enclosures, toroids on the motor cables routing cables as best I can away from each other... As for the Due, FINO does have an "experimental" branch for the Due, I haven't fully tested it but it can be flashed and shows up in Windows as a joystick - but I have a plethora of Arduino, RPi and teensy controllers, so one way or another I'll make it work hehe! 1
theperson Posted December 18, 2021 Posted December 18, 2021 (edited) My previous arduino code is garbage and I am deleting it out of shame. Here is the much much better Fino implementation. Download the Fino library, put it in your ~/Documents/Arduino/libraries folder and replace the Fino.ino and joystick.ino files with the code below. I'm also filtering the input encoder position with a simple MovingAverage library - available through the library manager as MovingAverager by Ian Carey I have my DCS controls FF_Tune menu set as follows: Trimmer Force = 75 Shake Force = 5 Swap Axis = unchecked Invert X = unchecked Invert Y = unchecked Fino.ino #define DEBUGNO // the digits mean Mmmmrrr (M=Major,m=minor,r=revision) #define SKETCH_VERSION 3000001 #include "src/Joystick.h" #include "config.h" #include "order.h" #include <ODriveArduino.h> #include <ODriveEnums.h> #include <HardwareSerial.h> #include <MovingAverage.h> // Printing with stream operator helper functions template<class T> inline Print& operator <<(Print &obj, T arg) { obj.print(arg); return obj; } template<> inline Print& operator <<(Print &obj, float arg) { obj.print(arg, 4); return obj; } // ------------------------- // Various global variables // ------------------------- unsigned long lastEffectsUpdate; unsigned long nextJoystickMillis; unsigned long nextEffectsMillis; // -------------------------- // Joystick related variables // -------------------------- #define minX -10000 #define maxX 10000 #define minY -10000 #define maxY 10000 //forces[] has a range of +/-10000, so this sets a safe motor amperage float motorAmps = 1; float forceToAmps; //sets the values of all the periodic function gains float periodicGain = 0.05; bool is_connected = false; bool forces_requested = false; bool pos_updated = false; int16_t pos[2] = {0, 0}; int lastX; int lastY; int lastVelX; int lastVelY; int lastAccelX; int lastAccelY; float scaleFactorX; float scaleFactorY; //Input filters - the number is the # of readings its averageing, higher number more stable but slower, lower number less filtered but faster response int readX; MovingAverage filterX(4); int readY; MovingAverage filterY(4); //because odrive reports in motor rotations we have to do some converting //these are the limits and center for my joystick in odrive-reported-rotations //maxX is joystick to the right, maxY is joystick pushed away from you float maxXRot = 0.13; float minXRot = -0.11; float maxYRot = -0.23; float minYRot = 0.17; float centerXRot = 0.02; float centerYRot = -0.03; //Hardware serial port HardwareSerial& odrive_serial = Serial1; // ODrive object ODriveArduino odrive(odrive_serial); EffectParams effects[2]; int32_t forces[2] = {0, 0}; Joystick_ Joystick( JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_JOYSTICK, 0, 0, // Button Count, Hat Switch Count true, true, false, // X, Y, Z false, false, false, // Rx, Ry, Rz false, false); // rudder, throttle void setup() { //Makes uploading the new sketch easier, because serial can get flooded //if you have trouble hit the reset pin as it finishes compiling delay(2000); setupJoystick(); // setup communication Serial.begin(SERIAL_BAUD); // setup timing and run them as soon as possible lastEffectsUpdate = 0; nextJoystickMillis = 0; nextEffectsMillis = 0; } void loop(){ //get_messages_from_serial(); //i setup my odrive as motor 1 is x, 0 is y :bigbrain: readX = (int)((odrive.GetPosition(1)-centerXRot)*scaleFactorX); readY = (int)((odrive.GetPosition(0)-centerYRot)*scaleFactorY); //I'm sure this wont cause any issues in the future pos_updated = true; pos[0] = filterX.addSample(readX); pos[1] = filterY.addSample(readY); //Serial << "x" << pos[0] << ", y" << pos[1] << "\n"; unsigned long currentMillis; currentMillis = millis(); // do not run more frequently than these many milliseconds if (currentMillis >= nextJoystickMillis) { updateJoystickPos(); nextJoystickMillis = currentMillis + 2; // we calculate condition forces every 100ms or more frequently if we get position updates if (currentMillis >= nextEffectsMillis || pos_updated) { updateEffects(true); nextEffectsMillis = currentMillis + 100; pos_updated = false; } else { // calculate forces without recalculating condition forces // this helps having smoother spring/damper/friction // if our update rate matches our input device updateEffects(false); } //Again, i have mine set up as X axis is motor 1, Y axis is motor 0 odrive.SetCurrent(1,(float)forces[0]*forceToAmps); odrive.SetCurrent(0,(float)-forces[1]*forceToAmps); //Serial << "fx" << (forces[0]*forceToAmps) << ", fy" << (forces[1]*forceToAmps) << "\n"; } } joystick.ino void setupJoystick() { forceToAmps = motorAmps/10000; scaleFactorX = (2*maxX) / (maxXRot - minXRot); scaleFactorY = (2*maxY) / (maxYRot - minYRot); Joystick.setXAxisRange(minX, maxX); Joystick.setYAxisRange(minY, maxY); Joystick.begin(); Gains gains[FFB_AXIS_COUNT]; gains[0].springGain = 0.7; gains[1].springGain = 0.7; gains[0].frictionGain = 0.25; gains[1].frictionGain = 0.25; gains[0].squareGain = periodicGain; gains[1].squareGain = periodicGain; gains[0].sineGain = periodicGain; gains[1].sineGain = periodicGain; gains[0].triangleGain = periodicGain; gains[1].triangleGain = periodicGain; gains[0].sawtoothupGain = periodicGain; gains[1].sawtoothupGain = periodicGain; gains[0].sawtoothdownGain = periodicGain; gains[1].sawtoothdownGain = periodicGain; Joystick.setGains(gains); odrive_serial.begin(500000); //Serial.println("requesting torque control"); //sometimes it fails to turn on axis 0, so i dunno, try it twice? odrive.run_state(0, AXIS_STATE_CLOSED_LOOP_CONTROL, false); delay(100); odrive.run_state(1, AXIS_STATE_CLOSED_LOOP_CONTROL, false); delay(50); odrive.run_state(0, AXIS_STATE_CLOSED_LOOP_CONTROL, false); } void updateJoystickPos() { Joystick.setXAxis(pos[0]); Joystick.setYAxis(pos[1]); } void updateEffects(bool recalculate){ for (int i =0; i < 2; i++) { effects[i].frictionMaxPositionChange = 25; // TODO: find proper values for these automatically effects[i].inertiaMaxAcceleration = 10; effects[i].damperMaxVelocity = 40; } effects[0].springMaxPosition = maxX; effects[1].springMaxPosition = maxY; effects[0].springPosition = pos[0]; effects[1].springPosition = pos[1]; unsigned long currentMillis; currentMillis = millis(); int16_t diffTime = currentMillis - lastEffectsUpdate; if (diffTime > 0 && recalculate) { lastEffectsUpdate = currentMillis; int16_t positionChangeX = pos[0] - lastX; int16_t positionChangeY = pos[1] - lastY; int16_t velX = positionChangeX / diffTime; int16_t velY = positionChangeY / diffTime; int16_t accelX = ((velX - lastVelX) * 10) / diffTime; int16_t accelY = ((velY - lastVelY) * 10) / diffTime; effects[0].frictionPositionChange = velX; effects[1].frictionPositionChange = velY; effects[0].inertiaAcceleration = accelX; effects[1].inertiaAcceleration = accelY; effects[0].damperVelocity = velX; effects[1].damperVelocity = velY; #ifdef DEBUG write_order(LOG); Serial.print(currentMillis); Serial.print("X"); Serial.print(pos[0]); Serial.print("Y"); Serial.print(pos[1]); Serial.print("C"); Serial.print(positionChangeX); Serial.print(","); Serial.print(positionChangeY); Serial.print("V"); Serial.print(velX); Serial.print(","); Serial.print(velY); Serial.print("A"); Serial.print(accelX); Serial.print(","); Serial.print(accelY); #endif lastX = pos[0]; lastY = pos[1]; lastVelX = velX; lastVelY = velY; lastAccelX = accelX; lastAccelY = accelY; } else { effects[0].frictionPositionChange = lastVelX; effects[1].frictionPositionChange = lastVelY; effects[0].inertiaAcceleration = lastAccelX; effects[1].inertiaAcceleration = lastAccelY; effects[0].damperVelocity = lastVelX; effects[1].damperVelocity = lastVelY; } Joystick.setEffectParams(effects); Joystick.getForce(forces); #ifdef DEBUG if (diffTime > 0 && recalculate) { Serial.print("F"); Serial.print(forces[0]); Serial.print(","); Serial.println(forces[1]); } #endif } If I turn the gains up too high it'll start oscillating something fierce, but these seem alright for my setup. Maybe direct-driving the gimbals would take out that small springiness of the belt and allow for higher gains? Edited December 30, 2021 by theperson 1
propeler Posted December 21, 2021 Author Posted December 21, 2021 Will hope that Maxim translate it to einglish as well)) 3 1
Bard_the_Bowman Posted December 21, 2021 Posted December 21, 2021 (edited) On 12/9/2021 at 10:38 AM, TomVR said: So i've had to put my plans for the project on hold for awhile as the costs of motors + odrive I keep putting into regular life/house stuff instead of this hobby, but just had a really dumb idea of remixing the object-77b cams and cheap skateboard bearings. https://imgur.com/a/DeUFvlK The roller at the bottom and the piece that holds it flexes too much so I'm either going to have to make that part from metal or cantilever it with a strap going over the top of the cams to pull it back straight. Using the miss's hairbands as temp springs. I actually wonder if having a cam spring, even with the motors engaged could be balanced to "neutralize" the weight of the grip over the long extension. On Cinema camera heads we use a similar system of counterbalance springs to make a 60lb+ camera be able to tilt up and down without being difficult to operate. My thought is having a light cam centering system tuned to keep the grip balanced might help a lot with the motors having to work much less to keep the stick centered. For now I'm just gonna use it so I get get a working stick and get around to adding the motors much later. edit: also in reality it would just be way way easier to take the entire object-77b gimbal and scale it up but damn it I'm too far along now! My concern with using centering springs to “help” the motors would be trimming. Depending how your aircraft is trimmed the motors may end up fighting the springs. Also, it would make the stick not work very well for helicopters at all for much the same reason. On 12/2/2021 at 9:45 PM, Thadiun Okona said: I love all the creative ideas but still can't fathom why not just let the roll motor/pulley for for a ride as you move the stick in pitch. It's easy to counterbalance the mass and you never saw on the stick in pitch in any form of flying though you might vigorously slam the ailerons from stop to stop. Even aerobatics pitch inputs are relatively tame but most types of flying you hold steady pitch for long periods and do minute adjustments. I mean, I understand why it was done on the MSFF II, it makes a smaller/more marketable base that follow domestic joystick expectations but anyone making one of these at this caliber here are not constrained by that yet the trend seems to be towards increasingly large and complex workarounds. Keeping both motors stationary on the base seems like a solution looking for a problem. I agree with all this. Having a very large metal gimbal that the roll axis rides on is the way to go imo. If I ever replace my propeler-gimbal ffb2 frankenstick, I’m probably going to use this method, possibly direct drive. Edited December 21, 2021 by Bard_the_Bowman
Bard_the_Bowman Posted December 21, 2021 Posted December 21, 2021 On 12/12/2021 at 5:07 PM, TomVR said: In the gimbal design, has anyone had a problem with a clunk on the pitch axis? Feels like the "GIMBAL_CORE_JOINT.STL" part is shifting back and forth while crossing the center on the pitch, making a popping noise and a felt clunk. Only happens when there is an external load on the axis from the gear teeth (or my cam springs) recorded a video of it happening. https://imgur.com/a/QQP1L1s It may be an alignment issue. the two gimbal arms have to be aligned almost perfectly to get smooth operation. and even so I will get very minor "clunks" from time to time.
TomVR Posted December 22, 2021 Posted December 22, 2021 (edited) 22 hours ago, Bard_the_Bowman said: It may be an alignment issue. the two gimbal arms have to be aligned almost perfectly to get smooth operation. and even so I will get very minor "clunks" from time to time. ended up reprinting the core joint and rotating the arm pillow blocks and that removed the clunk. 23 hours ago, Bard_the_Bowman said: My concern with using centering springs to “help” the motors would be trimming. Depending how your aircraft is trimmed the motors may end up fighting the springs. Also, it would make the stick not work very well for helicopters at all for much the same reason. Yeah my unique case is I'm trying to mount a GR tornado grip to the top of the gimbal which comes it at a staggering 1.7kilos for just the grip, so my hope was to tune the cams to try and keep the weight of the grip itself balanced. What I've ended up finding though is the linkages from the gimbal are too complex and there are too many cantilevered parts in the design so it just flexes and breaks with strong enough springs. Such heavy cams need to be as close to the original "axis" of rotation as possible. I might instead try just having a single spring that comes right out of the bottom of the core joint that goes to the bottom of the box as just a very basic "centering" force to see if that elevates the weight. Edited December 22, 2021 by TomVR
theperson Posted December 22, 2021 Posted December 22, 2021 (edited) On 12/12/2021 at 5:07 PM, TomVR said: In the gimbal design, has anyone had a problem with a clunk on the pitch axis? Feels like the "GIMBAL_CORE_JOINT.STL" part is shifting back and forth while crossing the center on the pitch, making a popping noise and a felt clunk. Only happens when there is an external load on the axis from the gear teeth (or my cam springs) recorded a video of it happening. https://imgur.com/a/QQP1L1s I had a similar "clunk" when going from one direction of force to the other. Noticed the frames were flexing and allowing the bearings to slide in and out on the joints. Fixed by tapping the holes on the joints and securing the bearings that way. Clunk-1.webm Edited December 23, 2021 by theperson 1
TomVR Posted December 23, 2021 Posted December 23, 2021 yeah I ended up shimming the inside of the joint by expanding the width axis by 0.5% in my slicer settings, but that might be a good idea if things wear down overtime.
Chuls Posted December 27, 2021 Posted December 27, 2021 On 12/18/2021 at 6:23 AM, theperson said: My previous arduino code is garbage and I am deleting it out of shame. Here is the much much better Fino implementation. Download the Fino library, put it in your ~/Documents/Arduino/libraries folder and replace the Fino.ino and joystick.ino files with the code below. I'm also filtering the input encoder position with a simple MovingAverage library - available through the library manager as MovingAverager by Ian Carey I have my DCS controls FF_Tune menu set as follows: Trimmer Force = 75 Shake Force = 5 Swap Axis = unchecked Invert X = unchecked Invert Y = unchecked ... If I turn the gains up too high it'll start oscillating something fierce, but these seem alright for my setup. Maybe direct-driving the gimbals would take out that small springiness of the belt and allow for higher gains? Great job @theperson! When I created that Fino library I thought the most useful part would be the library but reusing the sketch that way is a great idea. I'll change it a bit so that it's easier to reuse but what you did is great. Just one comment about when you wonder about the "pos_updated" variable. I just had to do that because the Brunner joystick refreshes the X and Y axes at different intervals and made recalculating inertia and friction really tricky, so I just calculate those at a lower frequency. Using the filter as you are doing is a very similar idea. I'll make some changes so it's easier to debug these. Also, someone was kind enough to send me a Due which uses a SAM3X8E and everything but the USB communication is working. There's some issue there that I'm trying to find but it's quite tricky. I have read many messages online that the Arduino USB libraries are full of bugs but I don't know if that's still the case or I just have a lot to learn about all this. I hope to get this working during January 3
theperson Posted December 27, 2021 Posted December 27, 2021 10 hours ago, Chuls said: Great job @theperson! When I created that Fino library I thought the most useful part would be the library but reusing the sketch that way is a great idea. I'll change it a bit so that it's easier to reuse but what you did is great. Just one comment about when you wonder about the "pos_updated" variable. I just had to do that because the Brunner joystick refreshes the X and Y axes at different intervals and made recalculating inertia and friction really tricky, so I just calculate those at a lower frequency. Using the filter as you are doing is a very similar idea. I'll make some changes so it's easier to debug these. Also, someone was kind enough to send me a Due which uses a SAM3X8E and everything but the USB communication is working. There's some issue there that I'm trying to find but it's quite tricky. I have read many messages online that the Arduino USB libraries are full of bugs but I don't know if that's still the case or I just have a lot to learn about all this. I hope to get this working during January Thank you for making it available. You absolutely saved me a lot of headache getting it figured out. I took a look at trying to run it on an SAME51 chip (basically an SAMD51 chip with a CAN bus - supposedly more reliable than the odrive serial uart) but the USB library stuff goes way over my head. I think my next step is adding some switches to the arduino to turn on/off motors as well as adding some damping that isnt dependent on it being enabled in-game. I also replaced the m5 bolt that runs up through the GIMBAL_CORE_JOINT with a proper 5mm shaft, since the bolt threads were slightly undersized for the bearing ID and caused a barely perceptible amount of slop.
Recommended Posts