2DOF harness tensionner with Fly PTmover

Hi!

My cockpit is static, I've build a pressure gSeat with bladders and RC servo.
I wanted to increase immersion by a harness tensionner.

I'd already tested a static harness tensionner on a 2 DOF plateform, and the feeling was great.
As my rig is static, I'll have to actuate the harness but the advantage is that I can make a 2 DOF tensionner.

principle:
2 DOF harness -> the strength on the right shoulder and left shoulder will be different

both will react along Surge (longitudinal acceleration)
and Sway (lateral acceleration) will tight one shoulder or the other (depending on left turn or right turn)
(maybe later add some heave information?)

harness : 5 points
the 5th will prevent the harness to move up, this will give actual tension (vs movement)!

prefer larger harness 3" (vs only 2")

actuators:
RC servos 35kg.cm (5V to 8,3V)
PSU @7,3V

arduino:
code for 4 servos as I want to combine the harness and the gSeat pressure bladders also RC servo driven.

software:
FlyPT mover https://www.xsimulator.net/community/faq/flypt-mover.29/category

1607507030563.png


1607507067271.png


Here is a video showing step by step how I drive the 2 DOF belt with Fly PTmover:

The strength from 35kg.cm servo is enough.
Power up the servo, sit down, thight the belt as you wish, and start the sim. If you tight the belt before powering up the servos, they are loose and they could be pushed out of their range...

The only drawback, in my opinion is the noise of the servos: they are whinning...

here some infos gathered in this FAQ https://www.xsimulator.net/community/faq/harness-tensioner-simulation.361/

► shopping list
"HV high torque servo motor Robot servo 35kg RDS3235 Metal gear Coreless motor digital servo arduino servo for Robotic DIY"
17€
I chose 270° range
You'll need a dedicated power supply (5V slower to 7,4V fastest)

Speed: 0.13sec/60 degree at(5v)
0.12sec/60 degree at(6v)
0.11sec/60 degree at(7.4v)

Torque: 29kg.cm.at(5v) -1.9A
32kg.cm.at(6v) -2.1A
35kg.cm.at(7.4v) -2.3A

or stronger but unecessary in my opinion
60kgcm 24€
https://www.aliexpress.com/item/4000055027119.html

speed is voltage related
torque is current related!

1/ choose speed AKA voltage
2/ check the spec which gives you the current at chosen voltage
3/ buy your PSU ;-)

if you choose 7,4V PSU, verify it'll be able to deliver up to 2.3A in order to give full torque (add a BIG margin ;-) )
https://fr.aliexpress.com/item/32823922664.html
11€ 7V 10A


here is my ball bearing support (12€ for 2 supports)
they are made of:
P000 https://www.aliexpress.com/item/32833812473.html
Zinc Alloy Diameter Bore Ball Bearing Pillow Block Mounted Support
they allow a big static disalignment as the bearing is mounted like a joint articulation :)

and 200mm Ø10 linear shaft Cylinder Chrome Plated Liner Rods
https://www.aliexpress.com/item/4001294745058.html

roller-jpg.434449


ball-bearing-harness-2-jpg.439581


ball-bearing-harness-1-jpg.439582


► budget:
2x 17€ for 35 kg.cm servo
11€ for 7V 10A PSU
(maybe consider a 12V 10A PSU + an Adjustable Power Module Constant Current 5A)
12€ for bearing rollers
15€ any arduino with a USB port (an original to support the community or a clone)

50€ for a used 3" width 5 points harness
total = 120€ all included



arduino code (for up to 4 servos)
C++:
// Multi Direct
// -> 4 servos
// <255><LeftBelt><127><127><RightBelt>
// Rig : Bit output -> 8 bits
// avec inversion
// PT Mover envoie de 0 à 255 par axe

/*Mover = output "Binary" et "10bits"
Arduino = Byte Data[2]
Data[0] = Serial.read();
Data[1] = Serial.read();
result = (Data[0] * 256 + Data[1]);

OU

Mover = output "Binary" et "8bits"
Arduino = Byte Data
Data = Serial.read(); on obtient directement le résultat*/

#include <Servo.h>  // local library "Servo.h" vs library partagée <Servo.h>

const byte nbServos = 4;

// create servo objects to control any servo
Servo myServo[nbServos];
const byte servoPin[nbServos] = {2, 3, 4, 5};  // pins digitales (pas forcément ~pwm)
const byte inversion[nbServos] = {1, 1, 0, 0 }; // paramètre à changer si un servo part le mauvais sens
int OldSerialValue[nbServos] = {0, 0, 0, 0};
int NewSerialValue[nbServos] = {0, 0, 0, 0};

// servo span:
int servoHomeDegres[nbServos] = { 0, 0, 0, 0}; //sera mis à jour avec la mesure de pression initiale
int servoMaxDegres[nbServos] = { 90, 90, 90, 90}; // cuisseG, cuisseD, côtéG, côtéD
int servoPositionTarget[nbServos] = {0, 0, 0, 0};

const byte deadZone = 0;

// =======================================
// Variables for info received from serial
// =======================================
int bufferPrevious = 0;      // To hold previous read fom serial command
int bufferCurrent = 0;       // To hold current read fom serial command
int bufferCount = 0;         // To hold current position in bufferCommand array
// byte bufferCommand[2*nbServos] = {0};  // (*2 if 10 bits) To hold received info from serial
int bufferCommand[4] = {0};  // To hold received info from serial

void setup()
{
  Serial.begin(115200); // opens serial port at specified baud rate

  // attach the Servos to the pins
  for (byte i = 0; i < nbServos; i++) {
    // pinMode(servoPin[i], OUTPUT); // done within the library
    myServo[i].attach(servoPin[i]);  // attaches the servo on servoPin pin
    }
  // move the servos to signal startup
  MoveAllServos255toDegres(125); // mi-course
  delay(1000);
  // send all servos to home
  MoveAllServos255toDegres(0);
}

void loop()
{
  // SerialValues contain the last order received (if there is no newer received, the last is kept)

  if (Serial.available())
  {
    bufferPrevious = bufferCurrent; // Store previous byte
    bufferCurrent = Serial.read(); // Get the new byte
    bufferCommand[bufferCount] = bufferCurrent; // Put the new byte in the array
    bufferCount++; // Change to next position in the array
    if (bufferCurrent == 255) bufferCount = 0; // one 255 is the start of the position info
    if (bufferCount == nbServos) //si 8 bits, nbServos // si 10 bits nbServos*2
      //Having reach buffer count, means we have the new positions and that we can update the aimed position
    {
      for (byte i = 0; i < nbServos; i++) {
        NewSerialValue[i] = bufferCommand[i];
        //NewSerialValue[i]= (bufferCommand[i*2] * 256) + bufferCommand[i*2+1]; // si 10 bits
      }
      bufferCount = 0;
    }
  }
  // Update orders sent to motor driver
  for (byte i = 0; i < nbServos; i++) {
    if (abs(OldSerialValue[i] - NewSerialValue[i]) > deadZone) {
      if (inversion[i] == 1)
      {
        envoiServoConsigne255toDegres(i, (255 - NewSerialValue[i]));
      }
      else
      {
        envoiServoConsigne255toDegres(i, NewSerialValue[i]);
      }
      OldSerialValue[i] = NewSerialValue[i];
    }
  }
}

void envoiServoConsigne255toDegres(byte servoID, int val )
{
  byte targetDegres;
  val = constrain(val, 0, 255); // constrain coupe au dessus et en dessous : écrêtage et pas mise à l'échelle (comme map)
  // sécurité pour éviter les cas où Simtools enverrait du négatif ou au-delà de 255
  targetDegres = map(val, 0, 255, servoHomeDegres[servoID], servoMaxDegres[servoID]);
  //  map(value, fromLow, fromHigh, toLow, toHigh)
  myServo[servoID].write(targetDegres);              // tell servo to go to position in variable : in steps of 1 degree
  // servo.write(angle)  -> angle: the value to write to the servo, from 0 to 180
}

void MoveAllServos255toDegres( int target)
{
  // send all servos to home
  for (byte i = 0; i < nbServos; i++) {
    envoiServoConsigne255toDegres(i, target);
  }
}

here is the setup:
setup 2DOF harness.png


and the file itself: replace .txt extension by .Mover extension
 

Attachments

  • 4Dof_Belt_255_multiDirect_v6bALPHA.txt
    94.9 KB · Views: 454
Last edited:
Any idea of the right strength of the springs?
About 20kg (measured) peak strap tensions feel adequate.
With a seat mover capable of supporting an additional 40kg of load
(having read that Next Level Racing's Motion Platform V3 is marginal),
then one unknown (to me) is effective belt movement.
For example, if maximum travel is 50mm,
then a spring rate of around 0.4kg/mm is wanted.
A little less or more, depending on initial tension and peak strength personal preferences.
Sadly U.S. traditional metrics involve e.g rods, yards, fortnights, etc,
with 1 kg/mm spring rate working out to about 56 lb/in.

While chasing down code to drive a Fanatec Maclaren V2 rim from USB via STM32,
this image popped up:

IMG_1246.jpg

.. which suggests using weaker springs, then adding to suit.
 
Last edited:
Upvote 0
Updated (more) code
As previously threatened, Noticeable.shsds now supports a new Arduino sketch: BlueLUT_Servo. SimHub Custom serial profile changes include
  1. Modifying the first Update message to download LUTs updated based on Setting panel tension changes.
  2. disabling Update messages 2-4, which are intended for the original Blue_ASCII_Servo sketch.
  3. Adding Update message 4, which directs the new sketch to return ASCII feedback.
  4. Adding Update message 5, which sends 4-bit LUT indices instead of actual servo values. These are currently constrained to support only 2 servo channels, but the sketch already contains code to support up to 7 hobby servo channels. Additional code will be required for PC fan PWM support. That support cannot be borrowed from the SimHub PWM fan library, which supports Arduino rather than STM32 modules.
  5. Setting panel adds a "special" slider for selecting the amount of ASCII feedback
    1. 0 = none
    2. 1 = return 'F', corresponding to maximum tension, to provide some notion of possible clipping.
    3. 2 = return hex values for all tension changes, which will be left, right pairs
    4. 3 = echo hex for all received traffic.
Setting.png

Servos are not expected to arrive for at least another week;
code has been verified only to work as intended, not to yield satisfying results...
 
Last edited:
Upvote 0
SimHub "Controllers input" plugin exposes button box and joystick controls as properties.
Harness tensioner Javascript can be hacked to enable
e.g. changing tensioner gains by otherwise unused wheel controls.
To identify naming conventions for available HID devices,
  • restart SimHub after enabling "Controllers input",
  • open "Controls and events"
  • click [New mapping]
  • press available HID device buttons:
picker.gif
 
Last edited:
Upvote 0
Would you install the seatbelts crossed on the back of the seat (for a seat mover)? I mean that way when the seat moves left you would feel some tension on the right belt? Or isn't it worth?
no need to physically cross your belts (it would induce some friction between them), you can swapp the effect (right from left and left from right) by the settings (in FlyPTmover ou Simhub, ...) ;)
SimHub "Controllers input" plugin exposes button box and joystick controls as properties.
Harness tensioner Javascript can be hacked to enable
e.g. changing tensioner gains by otherwise unused wheel controls.
that's cool! :cool:
 
Last edited:
Upvote 0
As previously threatened, Noticeable.shsds now supports a new Arduino sketch: BlueLUT_Servo
60Kg and replacement 35Kg servos arrived;
this enabled debugging this SimHub custom serial device
and matching Arduino driver using recorded session telemetry.

Replacement RDS3235 draws only about 0.01A no load,
compared with over 0.2A by its predecessor before failure,
encouraging expectation of longer service life,
particularly with power dropped to 7.4V.
With wheel stand currently undergoing rework,
evaluation of quantization artifacts from 16 entry tension LUT is yet to do.

While geometry suggest that RDS5160 servo brackets limit max strap tensions to 35Kg servo levels,
more massive (207 vs 76g) servo cases should better resist overheating.
 
Last edited:
Upvote 0
Fool me twice
Overheating causes hobby servos failures,
and stalling is a major cause of overheating.
Driving servos against hard limits will stall and overheat them.
Built-in stops provoke overheating if sending pulse widths wider or narrower
than those which drive servos to those built-in limits.
For the STM32 Arduino servo library,
that upper limit value is around 180 for (270
degree) RDS3235 servos.
It makes sense (to me) that drive splines should be engaged so that
brackets' arc limits for maximum strap tension match servo internal limit,
allowing a gap for strap thickness:
limit.jpg

Geometry dictates that minimizing servo torque required for maximum tension
wants straps sections aligned with the direction of strap tension.

If/when new servo body bracket strap clamps are fabricated,
clamps will be offset towards rotating bracket. Meanwhile,
reducing rotating bracket width also reduces strap offset at max tension:
StrapOffset.jpg

These RDS3235 servos do not "growl" while stalled enough to overheat;
monitoring current draw is the easy way to detect it..
 
Last edited:
Upvote 0
Not sure if this is helpful or noise, but I tried this bungee arrangement after hearing the high praise of doing this on Boosted Media. They are only loose because the belts are not secured. I felt like they did next to nothing for me so I removed them.

BungeeTake2_6253.jpg
 
Upvote 0
they did next to nothing for me
I am mostly surprised that so many represent passive tensioning as praiseworthy
and suppose that our hobby servo tensioners are less popular
because few can imagine how effective they are.
Direct drive belt tensioners should be more responsive, if not usefully quieter,
but for less than 20% the cost and effort, this RDS3235 solution
delivers worthwhile, if not 80% of maximum potential, effect.
 
Upvote 0
I am mostly surprised that so many represent passive tensioning as praiseworthy
and suppose that our hobby servo tensioners are less popular
because few can imagine how effective they are.
Direct drive belt tensioners should be more responsive, if not usefully quieter,
but for less than 20% the cost and effort, this RDS3235 solution
delivers worthwhile, if not 80% of maximum potential, effect.
I have a number of very high torque servos for my RC helicopters and I never once thought about them working for this application. The idea is interesting.

I've got some servos with torque in about the 3 lb/ft range. Coreless servos seem to be noisy. The brushless FUTABA's are the quietest. I have many brushless futaba servers. Some of them cause me nearly $200 each.

The cyclic servos on my larger helicopters take a fairly large amount of stress.

My TDR-2 is designed to run at speeds over 170 mph and the stresses on the servos are large enough that they went to a large servo gear with a support bearing to metal slider with teeth.

Some gear reduction for this application could multiply that torque. I'm guessing you don't really need more than 1-2" of belt travel total.

TDR2build26.jpg


TDR2complete.jpg


In case you are curious what that sounds like. I didn't install my retractable landing gear after seeing a number of retract failures.

The second pass is when he starts to speed things up. Speed flying is very scary white knuckle flying. The heli becomes a tiny spec in the sky very quickly and keeping your orientation is very challenging.

 
Last edited:
Upvote 0
I'm guessing you don't really need more than 1-2" of belt travel total.
I'm guessing that your reflexes are better than mine.

For this application, relatively heavy, inefficient and cheaper servos suffice...
RDS3235 servo brackets provide up to 2" of travel
and provide useful feedback, provided that harness straps are initially tight.
There is less harness tension than from intense "real" driving maneuvers,
where one may be also bracing oneself against a dead pedal,
but tension feels credible in proportion to other sensory inputs.
Another inch of travel is wanted if/when used in conjunction
with a G-seat which pushes the torso out of the seat,
for coordinated strap relaxation during acceleration and surges.

So-called robotic digital servo brackets trivialize in-line strap shortening.
3lb-ft (42 kg-cm) conventional servos could be used with 1 inch arms,
but bolting servo bodies to a seat frame increases gear noise.

RDS5160 servo brackets offer 3 inches of travel e.g. for use with G-seat bladders,
but effectively non-linear spring rate of human torso compression
would likely make 3 inches of tensioning uncomfortable, unless straps were initially loose,
and (52 lb-in) servos would stall at about 35 pound tension with provided 1.5x longer brackets.

If already using SimHub, then adding a Custom Serial device can be relatively unstressful.
STM32 "Blue Pill" boards now cost around US$7 (compared to about $1.5 two years ago).
Consider also getting a so-called ST-Link
to simplify initializing that "Blue Pill" with the Arduino HID bootloader,
as described here and elsewhere.
 
Upvote 0
I was thinking about how you might do this without drilling your seat and without it being at all invasive.

This just a quick sketch. But the idea is that each of these would clip over a seatbelt opening, sliding under the seatbelt that is still in place and have a suction cup at the bottom for stability and to keep the seat unscarred. The roller 2nd from the top would need to be bolted in place with the seatbelt under it.

The servo would be at full extension at 90 degrees rotation and just push the seatbelt away from the seat creating positive pressure on the suction cup which would help hold this in place.


seatbelttensionerTake2.jpg
 
Last edited:
Upvote 0
clip over a seatbelt opening
For a seat with shoulder belt openings, I would want something hooked over openings like that,
but with single rollers of larger diameter, located at hook corners
servo would be at full extension at 90 degrees rotation
That is not ideal for mechanical advantage.
Servos must apply maximum torque when arms are at right angles to tension,
requiring maximum current and quickly overheating.
Better to have arms at right angles for slack, then 180 degrees for max tension.
Heat is NOT your friend.

the entire servo body could be used to add more belt travel
Servo torques are not that great, and servos will stall before delivering wanted belt tension.
Finned heat sinks added to servo bodies may be wanted regardless.
The last known reported use of servo bodies as moving arms soon resulted in burned-out servos:
@RacingMat any suggestions why the lateral G only works going around left hand corners (right belt tightens, left loosens)? Aside from that my setup is all complete!
View attachment 470774

I'm using the stronger motors and they feel pretty good
View attachment 470775

I would actually prefer the strength maybe 10% more but I can't complain, I found it worth the upgrade over 35kg force motors and the included brackets allowed for hard mounting which I preferred over the suspended orientation as it dissipates the heat better through the structure.

Also if anyone has a more elegant suggestion to replace the cable tie I would be interested to hear your suggestions, I was thinking perhaps some sort of carbine clip but I am not so sure...
 
Upvote 0
So the servo idea is officially dead?
Absolutely not; I am satisfied with mine, but one must accommodate their limitations.

What about small and quiet NEMA motors ?
I have no experience with implementing them, but small ones want gearboxes,
and any will require either dedicated controllers
or more complex DIY firmware and electronics to implement servo functionality.
@Wotever's prototype implementation is introduced in his SimHub discord.

25 Sep update: Simple motors could work quite well,
since one could control motor torque by PWM,
not caring how much rotation is involved,
since the actual wanted stimulus is harness tension == motor torque.
 
Last edited:
Upvote 0
Back
Top