trigen Posted July 10, 2021 Posted July 10, 2021 (edited) Hi there Got some questions about a conversion as my FFSB r3 decided to just die for practically no reason (second hand, out of warranty) and i do not wish to pay 415+ eur when i can fix it for 30-40 using some strain gauge amps and ardunio. While ill loose the software there's not really many axis features in the FSSB software that i cant program in ardunio in a few days. Just the angle shift really. While im fairly sure i need 4 amps is it possible to get away with 2 amps with 2 gauges connected? What ive noticed on the ones ive tested (and now lost track of so im unable to test ) is that there's a fair amount of noise even with 10x filter in MMjoy2 using these https://www.ebay.com/itm/183934688576 Would a capacitor in between the gauge and the board be fine? If so, what would be sufficient? Or any suggestions for amps are welcome. As you can see its easy to just tap into here and just use the FSSB hardware. Edited July 27, 2021 by trigen 1080 ti, i7700k 5ghz, 16gb 3600 cl14 ddr4 oc
trigen Posted July 25, 2021 Author Posted July 25, 2021 (edited) Using ardunio micro Smoothed library: Dl trough Ard software. Joystick library https://github.com/MHeironimus/ArduinoJoystickLibrary https://www.ebay.com/itm/174794426405 Ive had to make some compromises and use 4 ebay amps then combine those into 2 axes with one on each side. I invert one of the amps to get + - It works very well and cost me about 35 euro instead of 400++ due to the WH r3 being out of production. Plus their support professionalism = no comment... You should probably connect each axis strain + 1 pot and resistor for a wheatstone bridge but i had this stuff. I will program all the axis features the FSSB has and add a physical switch to change things around. Maybe later i will add a software solution. The easiest way would be to just solder on wires to the top circuit board but i needed the space so i took it out. Apart from the connection rod to the stick which needs to be strong im quite sure you could easily 3d print something similar and have no cross talk in the axes. Then you could have your own force sensing stick that does move a bit but with less force than steel which is of course best. Ignore the melted wires on the connection. I did a last ditch attempt to save it and baked it in the oven to reflow (which ive rescued other boards with) thinking the wires would not melt. I added new shielding. Please note Force and offsets and not currently working. Just added varables //#include <AnalogSmooth.h> #include <Joystick.h> #include <Smoothed.h> /* For the true false flags, use this list. Its all in Joystick.h bool includeXAxis = true, bool includeYAxis = true, bool includeZAxis = true, bool includeRxAxis = true, bool includeRyAxis = true, bool includeRzAxis = true, bool includeRudder = true, bool includeThrottle = true, bool includeAccelerator = true, bool includeBrake = true, bool includeSteering = true); */ Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_MULTI_AXIS, 32, 0, true, true, false, false, false, false, true, true, false, false, false); // Variable #define YfAxisPin A0 #define YbAxisPin A1 #define XlAxisPin A2 #define XrAxisPin A3 // Add pins for the different ranges. Just using a variable for now. // Max force from trigger height. // Max force for y is about 8kg // Max force for X left is about 8kg X right is about 6kg // Max force in % int YMaxforce = 100; int XMaxforce = 100; // add offset to X Y WIP need to figure out how to angle int Offset = 0; // Add smoothing for all axis Smoothed <int> YfAxis; Smoothed <int> YbAxis; Smoothed <int> XlAxis; Smoothed <int> XrAxis; int SmoothValue = 30; // init joystick libary void setup() { Joystick.begin(); Serial.begin(38400); // Ranges are 1023 by default Joystick.setYAxisRange(0, 2048); Joystick.setXAxisRange(0, 2048); // Begin smoothing. YfAxis.begin(SMOOTHED_AVERAGE, SmoothValue); YbAxis.begin(SMOOTHED_AVERAGE, SmoothValue); XlAxis.begin(SMOOTHED_AVERAGE, SmoothValue); XrAxis.begin(SMOOTHED_AVERAGE, SmoothValue); } void loop() { // Read the value from the sensor int YfAxisValue = analogRead(YfAxisPin); int YbAxisValue = analogRead(YbAxisPin); int XlAxisValue = analogRead(XlAxisPin); int XrAxisValue = analogRead(XrAxisPin); // Add the new value to both sensor value stores YfAxis.add(YfAxisValue); YbAxis.add(YbAxisValue); XlAxis.add(XlAxisValue); XrAxis.add(XrAxisValue); // ******** Y Axis *************** int YfAxisCValue = YfAxis.get(); int YbAxisCValue = YbAxis.get(); // remap Yaxisback YbAxisCValue = map(YbAxisCValue, 1023, 0, 0, 1023); int YcombinedValue = YfAxisCValue + YbAxisCValue; // Set joystick Axis Joystick.setYAxis(YcombinedValue + Offset); // debug prints for serial monitor // Serial.println (String("Yf:") + YfAxisCValue); // Serial.println (String("Bf:") + YbAxisCValue); // Serial.println (String("Y combined:") + YcombinedValue); // ********* X axis ************** int XlAxisCValue = XlAxis.get(); int XrAxisCValue = XrAxis.get(); XrAxisCValue = map(XrAxisCValue, 1023, 0, 0, 1023); int XcombinedValue = XlAxisCValue + XrAxisCValue; // Set joystick Axis Joystick.setXAxis(XcombinedValue + Offset); // debug prints // Serial.println (String("Xl:") + XlAxisCValue); // Serial.println (String("Xr:") + XrAxisCValue); // Serial.println (String("X combined:") + XcombinedValue); } Edited July 26, 2021 by trigen 1 1080 ti, i7700k 5ghz, 16gb 3600 cl14 ddr4 oc
trigen Posted July 25, 2021 Author Posted July 25, 2021 if you want to know how this all actually works you can follow this post. There's more in depth how ive set things up with the pots and why im using 2 inputs for each axis. but mainly im researching how to do the angle adjust. https://forum.arduino.cc/t/joystick-how-to-add-xx-offset-angle-to-x-y-for-12-degree-offset/888828/7 1080 ti, i7700k 5ghz, 16gb 3600 cl14 ddr4 oc
Boltz Posted July 25, 2021 Posted July 25, 2021 (edited) Hi trigen. Nice work with the strain gauges, they are always an interesting topic. For the rotation you will need to use "Rotation of Axes" theory. You should be able to find the equations pretty easily but they are: x' = x*cos(a) + y*sin(a) y' = -x*sin(a) + y*cos(a) Where: x and y are your raw sensor readings, a is the angle of rotation (12 deg), x' and y' are the rotated results This will bring up the problem that microcontrollers don't like trig functions so you may need to create a lookup table for it. There is likely a library for Arduino built specifically for this. At a glance the Geometry library looks like it can handle the transformations. Coding this efficiently is way out of my abilities but hope it helps get you on the right path at least. Looking forward to seeing more updates Cheers Boltz Edited July 25, 2021 by Boltz 1 A-10C Cockpit Build Thread My YouTube Channel
trigen Posted July 27, 2021 Author Posted July 27, 2021 (edited) Thank you very much for the tip Boltz! Turns out it was that easy but i would never have figured it out myself as im a math muppet so i enlisted the help of some very clever guys on the ardunio forums! /* please put some text you'll search for one day here */ const float sintheta = sin(-12 * PI / 180); const float costheta = cos(-12 * PI / 180); float x, y; float newX, newY; void setup() { Serial.begin(115200); Serial.println(sintheta); Serial.println(costheta); // set some x y vales here, whatevs x = 13.2; y = 14.6; // do the maths newX = x * costheta - y * sintheta; newY = x * sintheta + y * costheta; // and print the results here to see if Serial.println(newX); Serial.println(newY); } void loop() { } At the moment i need to add and subtract a certain number to get the center point to be correct and that isnt 1:1 and it changes depending on bitrate so with the help of the same guys i hope to find a better way to calculate that on the fly. It does however appear to work correctly. Still working out the kinks. void loop() { // Serial.println(String("Sintheta:")+ sintheta); // Serial.println(String("Sintheta:")+ costheta); // Read the value from the sensor int YfAxisValue = analogRead(YfAxisPin); int YbAxisValue = analogRead(YbAxisPin); int XlAxisValue = analogRead(XlAxisPin) + Offset; int XrAxisValue = analogRead(XrAxisPin) + Offset; // Add the new value to both sensor value stores YfAxis.add(YfAxisValue); YbAxis.add(YbAxisValue); XlAxis.add(XlAxisValue); XrAxis.add(XrAxisValue); // Get axis from smoothed // Y int YfAxisCValue = YfAxis.get(); int YbAxisCValue = YbAxis.get(); // X int XlAxisCValue = XlAxis.get(); int XrAxisCValue = XrAxis.get(); // ******** Y Axis *************** // Since we use 4 amsp 2 front 2 back that are set to 0v to get the full range one way we we need to remap one for each to reverse the numbers YbAxisCValue = map(YbAxisCValue, 1023, 0, 0, 1023); XrAxisCValue = map(XrAxisCValue, 1023, 0, 0, 1023); // combine axises and then adjust to 12 degree rotational offset float YcombinedValue = YfAxisCValue + YbAxisCValue ; float XcombinedValue = XlAxisCValue + XrAxisCValue ; newX = XcombinedValue * costheta - YcombinedValue * sintheta - 199 ; newY = XcombinedValue * sintheta + YcombinedValue * costheta + 248; // added + 248 here to conpensate for center. I can also add these at Joystick.setYAxis(newY + 248) // Set joystick Axis Joystick.setYAxis(newY); Joystick.setXAxis(newX); Edited July 27, 2021 by trigen 1080 ti, i7700k 5ghz, 16gb 3600 cl14 ddr4 oc
trigen Posted July 27, 2021 Author Posted July 27, 2021 (edited) FSSB with angle adjust v 0.9 4 amp version to combine strain gauges into one and get double resolution and gain range. You need to set all amps to 0 so you get the full range. Then in the code it will reverse one as one will compress and the other expand so they cancel each other out in this configuration. If you place one on top and one on the bottom you dont need to reverese. After its combined into one axis. Basic. 2 amp/pot version. Should be working properly but report any bugs. It will rotate both axes to emulate the HW setup in the f16 stick. Todo. Add different force levels and tie into HW switches. Huge thank you to alto777 on the Ardunio forums for helping me out. No chance i could have done it without him. And a nudge to gcjr as well. Cheers! //https://github.com/MHeironimus/ArduinoJoystickLibrary // Amps ive used https://www.ebay.com/itm/174794426405 // DL smoothed library from the ardunio IDE #include <Joystick.h> #include <Smoothed.h> #include <Adafruit_ADS1X15.h> #include<Wire.h> Adafruit_ADS1115 ads; /* Angle adjust math you set the angle on the first line with -12 (minus is clockwise) or XX value. Enable with true or false */ int SensorRotationEmu = false; int angle = -12; // Add pins for the different ranges. Just using a variable for now. Not currently implementd // Max force from trigger height. // Max force for y is about 8kg // Max force for X left is about 8kg X right is about 6kg // Max force in kg int YMaxforce = 8; int XMaxforce = 8; // set amount of smoothing for the axis int SmoothValue = 5; // Set the joystick range. Only set the positive number. Center point will be this number divided by two int joyLowRange = -32767; int joyHighRange = 32767; // 65534 /* Set flags for Joystick axes. For some reason it refuse to work with only X Y so ive added rudder and throttle For the true false flags, use this list. Its all in Joystick.h bool includeXAxis = true, bool includeYAxis = true, bool includeZAxis = true, bool includeRxAxis = true, bool includeRyAxis = true, bool includeRzAxis = true, bool includeRudder = true, bool includeThrottle = true, bool includeAccelerator = true, bool includeBrake = true, bool includeSteering = true); */ Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_MULTI_AXIS, 32, 0, true, true, false, false, false, false, true, true, false, false, false); // Add smoothing for all axis Smoothed <int> YfAxis; Smoothed <int> YbAxis; Smoothed <int> XlAxis; Smoothed <int> XrAxis; // init joystick libary void setup() { Joystick.begin(); Serial.begin(38400); Wire.begin(); ads.begin(); // ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (default) // ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV // ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV // ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV // ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV // ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV ads.setGain(GAIN_ONE); // +/- 0.256V 1 bit = 0.0078125mV // Sets joystick ranges Joystick.setYAxisRange(joyLowRange, joyHighRange); Joystick.setXAxisRange(joyLowRange, joyHighRange); // Begin smoothing. YfAxis.begin(SMOOTHED_AVERAGE, SmoothValue); YbAxis.begin(SMOOTHED_AVERAGE, SmoothValue); XlAxis.begin(SMOOTHED_AVERAGE, SmoothValue); XrAxis.begin(SMOOTHED_AVERAGE, SmoothValue); } void loop() { // Serial.println(String("Sintheta:")+ sintheta); // Serial.println(String("Sintheta:")+ costheta); // Read the value from the sensor using 4x so they will be combined later. int YfAxisValue = ads.readADC_SingleEnded(0); // Front strain gauge int YbAxisValue = ads.readADC_SingleEnded(1); // Back strain gauge int XlAxisValue = ads.readADC_SingleEnded(2);// left strain gauge int XrAxisValue = ads.readADC_SingleEnded(3); // right strain gauge // Add the new value to both sensor value stores YfAxis.add(YfAxisValue); YbAxis.add(YbAxisValue); XlAxis.add(XlAxisValue); XrAxis.add(XrAxisValue); // Get axis from smoothed // Y int YfAxisSmoothValue = YfAxis.get(); int YbAxisSmoothValue = YbAxis.get() + 16383; // X int XlAxisSmoothValue = XlAxis.get(); int XrAxisSmoothValue = XrAxis.get() + 16383; // Since we use 4 amsp 2 front 2 back that are set to 0v to get the full range one way we we need to remap one for each to reverse the numbers /* YbAxisCValue = map(YbAxisCValue, 1023, 0, 0, 1023); XrAxisCValue = map(XrAxisCValue, 1023, 0, 0, 1023); */ YbAxisSmoothValue = map(YbAxisSmoothValue, joyHighRange / 2, 0, 0, joyHighRange / 2); XrAxisSmoothValue = map(XrAxisSmoothValue, joyHighRange / 2, 0, 0, joyHighRange / 2); // combine axises and then adjust to 12 degree rotational offset float XcombinedValue = (XlAxisSmoothValue + XrAxisSmoothValue); float YcombinedValue = (YfAxisSmoothValue + YbAxisSmoothValue); if (SensorRotationEmu == true) { const float sintheta = sin(angle * PI / 180); const float costheta = cos(angle * PI / 180); //float x, y; //float newX, newY; // move the origin to 0 so the angle rotation is correct YcombinedValue -= joyHighRange / 2; // now joyX is -1023 to 1023 XcombinedValue -= joyHighRange / 2; // same //Serial.println (String("Y translation:") + YcombinedValue); float newX = XcombinedValue * costheta - YcombinedValue * sintheta; float newY = XcombinedValue * sintheta + YcombinedValue * costheta; // Send the values to the joystick library and move origin back so the center point is 1023 Joystick.setYAxis(newY + joyHighRange / 2 ); Joystick.setXAxis(newX + joyHighRange / 2 ); } else { float Xc = (XlAxisSmoothValue + XrAxisSmoothValue); // Send the values to the joystick library Joystick.setYAxis(YcombinedValue); Joystick.setXAxis(XcombinedValue); //Serial.println(XcombinedValue); char buffer[96]; for (int kk = 0; kk < 4; kk++) { sprintf(buffer, "Y f: %d Y b: %d X L: %d X R %d Y comb: %d X comb: %d \n", YbAxisSmoothValue, YfAxisSmoothValue, XrAxisSmoothValue, XlAxisSmoothValue, XcombinedValue, YcombinedValue ); Serial.println(buffer); } } } FSSB_r3.ino FSSB_r3_2_pots.ino Edited October 7, 2021 by trigen 1080 ti, i7700k 5ghz, 16gb 3600 cl14 ddr4 oc
trigen Posted August 3, 2021 Author Posted August 3, 2021 (edited) These are the brand used in the FSSB. They also sell adehsive https://www.hbm.com/en/9803/strain-gauges-for-experimental-stress-analysis/ Edited August 3, 2021 by trigen 1080 ti, i7700k 5ghz, 16gb 3600 cl14 ddr4 oc
Recommended Posts