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:
Replacement RDS3235 draws only about 0.01A no load,
compared with over 0.2A by its predecessor before failure
It is somehow too easy to damage an RDS3235
so that it draws 0.2A with no load, which I have done again.
That is enough to provoke eventual death by overheating.

One original and another replacement together draw only 0.02A no load.

Meanwhile, STM32 Blue Pill sim wind experiments begin:
STM32fanPWM.jpg

FWIW, 4-wire fans run full speed with no connection to PWM pins,
and 100cfm PC fans become both loud and self-propelled;
inlet grilles are wanted.
 
Last edited:
Upvote 0
it draws 0.2A with no load
One aggravating factor is stiction in RDS3235 servo bracket plastic bushing,
despite having been greased, effectively imposing loads
which resist servos fully homing to commanded angles.
Having worn its bushing and reduced stiction, the older RDS3235 runs cooler.

Perhaps RDS5160 servos are a better option,
having bearings instead of bushings for non-driven bracket legs.
RDS5160 bracket legs could be re-drilled and cut 10mm shorter
to match RDS3235 maximum strap excursions
while working at a smaller fraction of RDS5160 rating.

Otherwise, RDS3235 servos should probably be "broken in" by
  • initial sessions of 1 minute or so,
  • then power removed for 5 minutes or so
    • for heat to dissipate.
 
Upvote 0
This is my solution, square aluminum profile and aluminum tube, drilled a hole for the tube and secured it with a bolt. Profile is monted to the seat with the top bolt and strong double sided tape. Simple and it works just fine.

Edit: noticed i uploaded the wrong picture, shoult be correct now.
 

Attachments

  • IMG_20210723_131125.jpg
    IMG_20210723_131125.jpg
    215.3 KB · Views: 161
Last edited:
Upvote 0
@Henrikk thanks for posting a picture of your build! It's nice and neat
could you share with us what motor and controller you bought?
it looks like you 3Dprinted arms :)

maybe you would like to reduce friction between harness and seat with a roller?
 
Upvote 0
@Henrikk thanks for posting a picture of your build! It's nice and neat
could you share with us what motor and controller you bought?
it looks like you 3Dprinted arms :)

maybe you would like to reduce friction between harness and seat with a roller?
First i did buy a couple of 35kg servos but then i saw @Wotevers solution so i went that route.

There really are no friction to talk about so i don't think i need rollers, the motors are plenty strong to squeeze the air out of me :D

After a bit of tweaking and getting used to it's a really cool addition to the rig, already feels strange when it's not turned on, a big thank you guys for the inspiration.
 
Upvote 0
I like small compact design. Maybe using those small motors https://fr.aliexpress.com/item/32881467792.html with pwm and pot would do the trick. Those motors are strong and also can be fused.
Maybe also Monster Motor driver would do the trick.
We have used the same motors in this project https://github.com/aenniw/ARDUINO/tree/master/skarsta
 
Upvote 0
I like small compact design. Maybe using those small motors https://fr.aliexpress.com/item/32881467792.html with pwm
Given that we are really only interested in tension,
then position feedback may be unnecessary;
PWM will control motor torque, which directly relates to tension.
120rpm means 1/240 second thru 180 degrees.
27.0Kg.cm yields 3cm travel in 180 degrees with 1cm radius pulley for 27 kgf.
0.5cm pulley radius yields 54 kgf, which seems plenty, but 3cm travel is low,
with 1/120 second for 360 degrees, which is faster than most game telemetry updates.

One trick may be sorting residual tension when pulse width = 0;
some reverse PWM may be wanted to quickly release tensions,
which may vary over time as gears wear or grease heats, becoming less viscous.
 
Upvote 0
When i was testing those motors I have also look inside them and they are all metal made. Grease can be applied easily and lithium one can be good till 125C. The motors are strong and I was testing it with 4A fuse and 12v and this is a safe for motors not to burn them in any way. This was the schematics we have used for table. https://github.com/aenniw/ARDUINO/blob/master/skarsta/docs/case_bridge-v2.md
Here are also some 3d printable models that can be used for motors. https://github.com/aenniw/ARDUINO/tree/master/skarsta/models
Also maybe rod with coupler could be used and some kind of mount for belts.
 
Last edited:
Upvote 0
This could do it or. something 3d printed would also be possible similar to the simhub belt tensioner.
Do you think that your sketch for arduino would work with this option or. which sketch should be usefull?
 
Upvote 0
Hi,

@blekenbleu Could you confirm the wiring from my schematics please ?
If it's ok, feel free to use it on your github.io page ;-)

wirring.png



You say
super capacitors effectively short-circuit supplies at power on, requiring current limiting.
Using an automotive headlamp bulb as a "dummy load",

How to wire the headlamp bulb ? On the "+" and "-" of supercapacitor ?
Have you any advice about the lamp to use please ? Or maybe something else than headlamp.

Thank you
 
Upvote 0
How to wire the headlamp bulb ? On the "+" and "-" of supercapacitor ?
Apologies for being unclear;
the headlamp bulb is for current limit adjustment
BEFORE connecting supercaps.
Otherwise, there is some risk of cooking the buck regulator.

That is a nice diagram; one of many skills that I lack...
Thanks!
 
Upvote 0
Looking to some schematics that were used for 2dof motion.
I have not used real Arduinos, so guess that connections from it
to motor control boards are for steps and direction?
If left image motors are open loop (only 2 wires shown),
I don't know how positions are determined.
Do you think this wiring would work without pots?
Potentiometers can be typically be replaced by digital signals based on e.g. software sliders,
unless they are mechanically linked to motors for position feedback, as in @RacingMat's diagram.
Do your sketch uses only Bluepill?
It is known to also work with Black Pill.
I have not researched compatibility with other boards supported by Arduino environment,
but aside from available pins and library support, processing power may be another limitation.
Maybe this design would work with original SimHub belt tensioner plugin?
I hacked a version of my sketch to work with @Wotever's plugin,
(which I would not describe as original, since ours was implemented earlier).
His plugin has sliders to control stepper rates, which are inapplicable to servos,
and has controls only for max positions, not min and neutral.
It is also too specialized; we want one plugin, sketch and module
to be able to control e.g. harness, speed fans and G seat.
 
Upvote 0
Apologies for being unclear;
the headlamp bulb is for current limit adjustment
BEFORE connecting supercaps.
Otherwise, there is some risk of cooking the buck regulator.

That is a nice diagram; one of many skills that I lack...
Thanks!
Thank's, I understand well.
I've not a pot to limit the intensity :-/ I'm using this model
However I think there is a protection (according to the description)

My diagram was build with this free tool. I'm using invisible square in certain places to have "connector" for the line ;-)
it's much less complicated than what you did arround simhub ;-)
 
Upvote 0
Back
Top