Zee Sim Rig

I was fooled into buying a Logitech G940. Should/could have been a must have but spoiled by cheap pots and wires too short in the throttle leavers which caused them stretch and break. After they stopped manufacturing them Logi admitted that the poor performance of the software was caused by trying to mask the noise from the pots.
 
From what research I have bothered to do the patent troll aspect is largely overblown internet drama… see Brunner’s existence as a case in point.

Ultimately however it’s meaningless. Patents are ultimately irrelevant when you are building something for personal use… Under UK patent law:

“An act which, apart from this subsection, would constitute an infringement of a patent for an invention shall not do so if
(a) it is done privately and for purposes which are not commercial;”

Section 60(5) of the manual of patent practise. https://www.gov.uk/guidance/manual-of-patent-practice-mopp/section-60-meaning-of-infringement

If I were to try and commercialise it then that would be a different story, and I would have to make sure that patents indeed weren’t being infringed. I do however have zero interest in doing so anyway.

I believe your sidewinder is, by the way, usable in MSFS with certain addons. One such example (there’s at least one more but it escapes me at the moment) https://www.fsmissioneditor.com/product/xpforce/

Thanks for that - will have a play.

I was intrigued more by how you were going to impliment feedback if it is no longer available by default in game - how do you tell the rig what to simulate? I had assumed that with the lack of basic consumer feedback hardware out there, games would not include it by default. Does this require some high technical merit coding by you to make it all work?
 
@cavemanoc understood.

The code for FFB is still there dormant in MSFS2020 apparently, a legacy from the older FS roots. Perhaps one day it will be enabled, but it's quite basic. I would most likely just use something like XP force in MSFS as it would likely provide a far better experience than the basic native support anyway. Apps like this (or indeed something you code yourself if you have the ability!) generally have access to an incredible amount of data through the telemetry streams - same data I use for driving the motion rig. Gives you all sort of parameters about the aircraft and events that occur, so extracting the data and creating some FFB effects isn't ultimately that difficult and they can get quite creative with extra effects (some more useful/realistic than others).

Some games still seem to support FFB out of the box, DCS and IL2 for example both seem to have FFB support. I first found out DCS supports force feedback because it started moving my blooming steering wheel about during flight if it wasn't turned off!

Those are my only 3 flying games currently anyway... and if anything else is needed if it has telemetry for the motion rig, it has data that can most likely be used to drive FFB.


@DD_Crash yeah the Brunners are crazy money. It can be done pretty cheaply DIY though, and seems to be becoming more common to see people making DIY FFB Yokes and joysticks... haven't seen anyone go for a FFB rudder yet which seems like it would be simple to build!

Never had hands on with a G940. Design flaws sound pretty easy to fix with replacing the pots and wiring, but if the software is naff perhaps not.
 
I fixed the throttle wiring issue and used a Bodnar board to add more buttons. Someone has reworked the software, but the attitude of the manufactures annoyed me so much that I gave up with the stick, and the rudder pedals were not up to much anyway.
 
So got an unexpected day to play from the wife, so been a productive one!

Made and mounted up the front wheel mounts, got the actuators fitted and added a piece of aluminium angle at the front to add some rigidity (since it lacks the upper cross bar that the back has).

LvFirit.jpg


Almost ready to rock - just need to swap 3 more servo side power cables over to shielded, and then finish the wiring in the control box itself.... oh and the foot pads. Few more hours work maybe.

eEI8Q2L.jpg
wow that is seriously good work......... i am rather jealous, esp like the fact it does not take up too much space and it is on wheels so presumably it is semi mobile (to move around your room not to carry to your mates house).......
 
Just a little update video… friend trying out the rig for the first time.

https://youtube.com/shorts/wPab56wFymQ?feature=share

I have a few more things to share as well which I’ll try to upload later, also for Christmas the wife got me what I need to add wind simulation to the rig so looking forward to making stuff for that and trying that out!

esp like the fact it does not take up too much space and it is on wheels so presumably it is semi mobile (to move around your room not to carry to your mates house).......

Yeah this was a key requirement as space in the man cave is limited. Compacted up its quite reasonable space wise and as you say can easily be wheeled around as needed to get out of the way of the CNC or printer etc.
 
Last edited:
I have a few more things to share as well which I’ll try to upload later, also for Christmas the wife got me what I need to add wind simulation to the rig so looking forward to making stuff for that and trying that out!
.

Brussels sprouts are darn useful. :)

I'm envious as anything of the skills on display here. As everyone else has said, just amazing work.
 
A little update then.

Biggest change recently to the cave was the addition of a new printer - the RatRig Vcore3 400mm... This has been absorbing a lot of my time of late as I design mods for it, but in between I actually occasionally use it for making proper stuff too lol. Absolutely amazing machine, huge build area and I can easily go 4-5x faster with better quality than on my old one.

Some in progress prints:

faOuZ2d.jpg

A47kD9X.jpg

and a cool little timelapse:



So a recent addition that I've just finally finished is a quick release centre mount for a joystick... I realised that 99% of the time I am flying either a warbird or a fast jet and having the stick on the side just isn't cricket... not only that but moving it to the middle frees up the side mounts for other stuff like the H-pattern gearbox I intend to build shortly.

I cheekily upgraded to a VKB MCG ultimate which is just stunning... so much functionality in their software and after adding a little nyogel damping grease to the dry clutches the feel is absolutely brilliant.

I printed an adaptor which would allow me to use the same sort of quick connect I use for my steering wheel:


For convenience I also want the connection to work through the quick disconnect itself so I don't need to plug/unplug anything. Initially my plan was just to move the controller's stock connector to the bottom to facilitate this, but it became clear that the have built one of the hall effect sensors for the gimbal into the same board the connector is on so it needs to stay where it is. I ended up just soldering my own connector onto the board with an extension to allow me to route the cable down to the bottom:

355QLJ5.jpg

I used magnetic couplings, and 3d printed some adaptors for the quick connect. one side has the ability to float back and forth by a couple of mm so it doesn't get damage while the pins align, and then snaps into place with the magnetic force. This seems to be working very well and now means I don't need to bother plugging/unplugging the controller - simply snap the whole thing on or off as needed!

sxdacS9.jpg

c71n3V9.jpg

fZ71PiJ.jpg


I've also added a 34" ultrawide for non-VR gaming. This is especially useful for kids that want to use the rig as it's much easier than over-sized VR headsets and you can coach them much more easily... it's also quite nice to sometimes have the option to use the rig outside of VR.

shp1Gkj.jpg

2KP8obn.jpg

To help with the non-VR gaming I also added a Vocore secondary display for gear/rpm/car info etc which you can see through the steering wheel here:

kAELVbu.jpg


I'm also in the process of finalising the addition of wind. I've got that mostly up and running although I'm struggling to get the arduino working with FlyPT which is what I use for flying games... it is working flawlessly for driving using the simhub sketch so clearly just me needing to learn more about Arduino coding to figure out why I can't get it to work with FlyPT... hopefully we'll get there. I'm looking forward to being able to open the canopy of the spitfire and get an immersion explosion from the air rushing past!
 
Thanks guys!

Anyone here good with arduino?

I've got a sketch that my ignorant self (finally) managed to adapt to my needs for driving the fans with FlyPT but I'm stuck on one last bit... Basically the code is looking for the fan speed value eg S000 where S = both fans and 000 = fan speed 0-255. Everything works in the sense that if I send commands via the serial monitor to the arduino all behaves and fans respond as they should.

The remaining problem is the FlyPT software sends the bit output as a total value so a bit value of 0 is sent as just 0 (48) rather than 000 (48 48 48). The code is looking for all 3 digit values so only kicks the fan into life at S100 and above where it all populates as "083 049 48 48"

My issue is I'm too stupid to figure out how to adjust the code so that it will read the bit value in that way without breaking it. If anyone is good with this stuff please feel free to chime in!

Sketch is below:

#include <DualVNH5019MotorShield.h>
// Arduino Uno code based hugely on the work of SilentChill, Avenga76, and a number of others.
// Forked off to support right and left speed commands (R000 and L000, etc) as well as traditional S000 format.
// Version - 02_23_2021
#define FALSE 0
#define TRUE 1
#define BRAKEVCC 0
#define CW 1
#define CCW 2
#define BRAKEGND 3
#define CS_THRESHOLD 100
// If left and right fan control is swapped, just swap the values defined here for LEFT and RIGHT.
#define BOTH 0
#define LEFT 1
#define RIGHT 2
// Idle speed setting if you want the Arduino to reset or cold start with some air flow. Useful for
// providing a light wind for VR comfort. Range is 0 to 255. I use 20 with TerraBloom fans. Default
// value is 0 to not surprise anyone but change as you wish. There are no checks on this so you can
// break the code if you use values less than 0 or more than 255.
#define IDLESPEED 0
int inApin[2] = {2, 7}; // INA: Clockwise output
int inBpin[2] = {4, 8}; // INB: Counter-clockwise output
int pwmpin[2] = {9, 10}; // PWM output
int cspin[2] = {0, 1}; // CS: Current sense ANALOG input
int enpin[2] = {0, 1}; // EN: Status of switches output (Analog pin)
int statpin = 13;
// pwmMode - sets the PWM frequency, valid options as follows:
// pwmMode = 0 will use 980Hz PWM, default mode which will work with all fan types, will cause coil whine if using a MM.
// pwmMode = 1 will use 4kHz PWM, might reduce coil whine for blowers, use heatsinks on the MM - check MM temp at a low fan speed.
// pwmMode = 2 will use 8kHz PWM, might be OK for blowers with active cooling on the MM - check MM temp at a low fan speed.
// pwmMode = 3 will use 31kHz PWM, use with caution - not for blowers with MM as it will cause very high temps. Check MM temp at a low fan speed.
// server fans - should be able to use pwmMode = 2 or 3. If you are using the PWM control on the server fan, leave this at default 0.
// if you have blowers with a monster moto, try pwmMode = 1 or 2 and check whether your monster moto temp at low speeds.
int pwmMode = 1; // value of 0, 1, 2 or 3 - modes 2 and 3 will overheat a Monster Moto if used with blowers

int Speed = 40;
int bufferArray[4];
int whichFan = BOTH;
void setup()
{
Serial.begin(115200, SERIAL_8N1);
// initialize digital pins as outputs
for (int i=0; i<2; i++)
{
pinMode(inApin, OUTPUT);
pinMode(inBpin, OUTPUT);
pinMode(pwmpin, OUTPUT);
digitalWrite(inApin, LOW);
digitalWrite(inBpin, LOW);
}
// disable timer0's interrupt handler - this will disable Arduino's time keeping functions such as delay()
TIMSK0 &= B11111110;
if (pwmMode == 1)
{
// Set pins 5 & 6 to Phase-correct PWM of 3.9 kHz (prescale factor of 8)
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00); // phase-correct PWM
TCCR0B = _BV(CS01); // prescaler of 8, gives frequency 61kHz/8/2 = 3.9kHz
}
else if (pwmMode == 2)
{
// Set pins 5 & 6 to Fast PWM of 7.8 kHz (prescale factor of 8)
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00); // fast PWM
TCCR0B = _BV(CS01); // prescaler of 8, gives frequency 61kHz/8 = 7.8kHz
}
else if (pwmMode == 3)
{
// Set pins 5 & 6 to Phase-correct PWM of 31.25 kHz (prescale factor of 1)
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00); // phase-correct PWM
TCCR0B = _BV(CS00); // prescaler of 1, gives frequency 61kHz/1/2 = 31.25kHz
}
else
{
// Set pins 5 & 6 to Fast PWM of 980Hz (prescale factor of 64)
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00); // fast PWM
TCCR0B = _BV(CS01) | _BV(CS00); // prescaler of 64, gives frequency 61kHz/64 = 980Hz
}
// Just throw on a low speed in case no wind support in application...
motorGo(0, CW, IDLESPEED); //Motor1
motorGo(1, CW, IDLESPEED); //Motor2
}

void loop()
{
ReadData();
if (whichFan == BOTH)
{
motorGo(0, CW, Speed); //Motor1
motorGo(1, CW, Speed); //Motor2
if (Speed == 0) motorOff(0);
if (Speed == 0) motorOff(1);
}
if (whichFan == LEFT)
{
motorGo(0, CW, Speed); //Motor1
if (Speed == 0) motorOff(0);
}
if (whichFan == RIGHT)
{
motorGo(1, CW, Speed); //Motor2
if (Speed == 0) motorOff(1);
}
}
void motorOff(int motor)
{
// Initialize braked
for (int i=0; i<2; i++)
{
digitalWrite(inApin, LOW);
digitalWrite(inBpin, LOW);
}
}
void motorGo(uint8_t motor, uint8_t direct, uint8_t Speed)
{
if (motor <= 1)
{
if (direct <=4)
{
// Set inA[motor]
if (direct <=1)
digitalWrite(inApin[motor], HIGH);
else
digitalWrite(inApin[motor], LOW);
// Set inB[motor]
if ((direct==0)||(direct==2))
digitalWrite(inBpin[motor], HIGH);
else
{
digitalWrite(inBpin[motor], LOW);
analogWrite(pwmpin[motor], Speed);
}
}
}
}

void ReadData()
{
// We need 4 characters - the command followed by three digits
bool haveCommand = FALSE;
bool haveStart = FALSE;
while (haveCommand == FALSE) // can't exit until have a full valid cddd command
{
// where c is a valid char and ddd is a valid 3
// character representation of three digits
// Valid command always starts with an S (legacy for both fans), L (left fan), or R (right fan)
while (haveStart == FALSE)
{
while (Serial.available() == 0); // spin and wait for data
bufferArray[0] = Serial.read(); // have data, read it
if (bufferArray[0] == 'S') //S
{
whichFan = BOTH;
haveStart = TRUE;
}
else if (bufferArray[0] == 'L') //L
{
whichFan = LEFT;
haveStart = TRUE;
}
else if (bufferArray[0] == 'R') //R
{
whichFan = RIGHT;
haveStart = TRUE;
}
}

// Now need the numbers - will just read three and throw them away if any don't qualify
// if we unsynchronize, it will fail valid digits and go back to waiting for command char
for (int i = 1; i < 4; i++) // read and label each byte.
{
while (Serial.available() == 0); // spin and wait for each character to arrive
bufferArray = Serial.read(); // store as they come in
}
// Check the numbers for validity
if (isDigit(bufferArray[1]) && isDigit(bufferArray[2]) && isDigit(bufferArray[3]))
// all are numbers - have a full cddd command
haveCommand = TRUE; // otherwise start over looking for a new and valid command
}
// Now turn that into a number and clip to 255 - rely on Game Dash for proper scaling
Speed = ((bufferArray[1]-48)*100) + ((bufferArray[2]-48)*10) + ((bufferArray[3]-48)*1);
//Serial.println(SpeedGameDash);
if (Speed > 255)
Speed = 255;
 
Last edited:
Good news is that with the help of Gwiz on xsim nudging in the right direction I've arrived remapping FlyPT's output to 100-255, and then changing the sketch to if (speed == 100) motorOff(0) (and the same for motor 2 of course).

That is perhaps a little cludgy and loses some resolution but importantly it works, and the resolution drop from 255 to 155 is unlikely to be significant for driving fans. I can now successfully link the fans to windspeed which is affected by canopy position, so close the canopy and zero wind, open it and you get the fans spinning up relative to the windspeed the aircraft is experiencing with full blast happening around 80-90kts. The only thing I'm missing is the ability to also modify rpm by canopy position to be able to fine tune prop wash separate from windspeed but I think that'll come in FlyPT 4.0 at some point which I believe will have more advanced options like being able to modify variable X by variable Y.

Wind system here: 3d printed shrouds and mounts on Bgear fans (printed parts still WIP, so needs some finishing), powered by an arduino UNO and VNH5019.

3ULZg1F.jpg

w2lAHDz.jpg


Unfortunately I can't go and enjoy it because I'm in the middle of a tear down to replace my pedal platform actuator system which finally broke free from the excessive brake pedal force, with the weak point being the single central actuator rod slipping from the sled that was holding it in place.

Rather than fix the existing actuator I've decided to go with a new design that will use two separate leadscrews either side, combined with thrust bearings and beefier blocks which should result in a much stronger holding force and prevent it from ever breaking again, while also removing the small amount of flex I was getting from that central mounting point.

Current actuator in the middle, and the new side mounted units in progress here (excuse the mess!))

8YjoSME.jpg


Also in other news - that nice 34" ultrawide is now dead... I smashed it by dropping a fan which then swung down on the cable it was still connected by and smashed point first into the screen. FML.

Can’t really justify the cost of replacing it at the moment so will have to wait till I have some cash burning a hole in my pocket. Back to only VR it is!

cyct22F.jpg
 
Last edited:
Back
Top Bottom