• Welcome to PiBoSo Official Forum. Please login or sign up.
June 20, 2019, 01:08:10 pm


GP Bikes beta15b available! :)

The Lumberbar/MCCC/M300/M301

Started by Chris_Beeves, May 06, 2019, 09:07:40 pm

Previous topic - Next topic


The second prototype I made was made for DS1 mode (torque). It is all explained in my first post here I think. No ffb was planned for that one, only adjustable resistance from the GPBikes plugin depending on a number of factors.

After seeing Marcel's video (and his advice) I switched to ffb and DS2.  Now I just use the load cells for brakes.

With a better implementation of DS1 in the game I think prototype 2 would have worked fine though. :)
I had to try..


Found out that I have access to Visual Studio Enterprise, so today I started looking at writing the example .dlo for my knee rumblers.

The function I want from the .dlo is receiving the lean angle and sending it to an Arduino via serial port.
Receiving the lean angle seems simple enough (just copy the example code), but everything with the serial port handling makes it a bit complicated.
Especially since I have never seen Visual Studio until today  ;D

I have no idea what I am doing so far, but with enough trials and errors I guess I will get there in time..
This is what I have come up with so far. In my naive mind I just need to figure out the magic word that makes the .dlo spit out telemetry data through the (hopefully) opened serial port:

#include <stdio.h>

If compiled as C++, extern "C" must be added to declaration of functions to export

X+ is right, Y+ is top and Z+ is forward.

extern "C" __declspec(dllexport) char* GetModID()
return "gpbikes";

extern "C" __declspec(dllexport) int GetModDataVersion()
return 8;

extern "C" __declspec(dllexport) int GetInterfaceVersion()
return 9;

structures and functions to receive data from the simulated bike
extern "C" typedef struct
int m_iRPM; /* engine rpm */
float m_fEngineTemperature; /* degrees Celsius */
float m_fWaterTemperature; /* degrees Celsius */
int m_iGear; /* 0 = Neutral */
float m_fFuel; /* liters */
float m_fSpeedometer; /* meters/second */
float m_fPosX, m_fPosY, m_fPosZ; /* world position of a reference point attached to chassis ( not CG ) */
float m_fVelocityX, m_fVelocityY, m_fVelocityZ; /* velocity of CG in world coordinates. meters/second */
float m_fAccelerationX, m_fAccelerationY, m_fAccelerationZ; /* acceleration of CG local to chassis rotation, expressed in G ( 9.81 m/s2 ) and averaged over the latest 10ms */
float m_aafRot[3][3]; /* rotation matrix of the chassis. It incorporates lean and wheeling */
float m_fYaw, m_fPitch, m_fRoll; /* degrees, -180 to 180 */
float m_fYawVelocity, m_fPitchVelocity, m_fRollVelocity; /* degress / second */
float m_afSuspLength[2]; /* shocks length. meters. 0 = front; 1 = rear. */
float m_afSuspVelocity[2]; /* shocks velocity. meters/second. 0 = front; 1 = rear */
int m_iCrashed; /* 1 = rider is detached from bike */
float m_fSteer; /* degrees. Negative = right  */
float m_fThrottle; /* 0 to 1 */
float m_fFrontBrake; /* 0 to 1 */
float m_fRearBrake; /* 0 to 1 */
float m_fClutch; /* 0 to 1. 0 = Fully engaged */
float m_afWheelSpeed[2]; /* meters/second. 0 = front; 1 = rear */
int m_aiWheelMaterial[2]; /* material index. 0 = not in contact */
float m_fSteerTorque; /* Nm */
int m_iPitLimiter; /* 1 = pit limiter is activated */
int m_iECUMode; /* 0 = engine mapping; 1 = traction control; 2 = engine braking */
char m_szEngineMapping[3];
int m_iTractionControl;
int m_iEngineBraking;
int m_iAntiWheeling;
int m_iECUState; /* bit field. Bit 1 = TC active; bit 2 = engine braking active; bit 3 = antiwheeling active */
} SPluginsBikeData_t;

/* called when software is started */

extern "C" __declspec(dllexport) int Startup(char* _szSavePath)
return value is requested rate
0 = 100hz; 1 = 50hz; 2 = 20hz; 3 = 10hz; -1 = disable
return 3;

int main()
hComm = CreateFile("\\\\.\\COM24", //port name
0, // No Sharing                               
NULL, // No Security                             
OPEN_EXISTING, // Open existing port only                     
0, // Non Overlapped I/O                           
NULL); // Null for Comm Devices

printf("Error in opening Serial port");
printf("\nopening serial port successful\n");

DCB dcbSerialParams = { 0 }; // Initializing DCB structure
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

Status = GetCommState(hComm, &dcbSerialParams);

dcbSerialParams.BaudRate = CBR_9600; // Setting BaudRate = 9600
dcbSerialParams.ByteSize = 8; // Setting ByteSize = 8
dcbSerialParams.StopBits = ONESTOPBIT; // Setting StopBits = 1
dcbSerialParams.Parity = NOPARITY; // Setting Parity = None

SetCommState(hComm, &dcbSerialParams);

COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 50; // in milliseconds
timeouts.ReadTotalTimeoutConstant = 50; // in milliseconds
timeouts.ReadTotalTimeoutMultiplier = 10; // in milliseconds
timeouts.WriteTotalTimeoutConstant = 50; // in milliseconds
timeouts.WriteTotalTimeoutMultiplier = 10; // in milliseconds

/* called when software is closed */
extern "C" __declspec(dllexport) void Shutdown()
int main()

CloseHandle(hComm); //Closing the Serial Port
return 0;

Any input on this would be very much appreciated!

Until next time..  :o
I had to try..


Try to look at existing libraries for low-level stuff like handling of serial ports, it's always easier.
For a past project, I used this: https://www.teuniz.net/RS-232/


Great tip! Thanks!

Looks a fair bit simpler than the standard windows stuff.
I had to try..


Still waiting for the motor driver board to make the first prototype.. Somebody is probably swimming the package over to Sweden from the UK.
I have a holiday coming up in two weeks so hopefully I'll get some time to get it running.
Can't wait to have a working rig so I can play again soon!
I had to try..


Well, some good news is that I got my motor drivers! :D
Bad news, they were damaged..
Good news, I fixed them!

Bad news, I can't seem to get the encoder working on the Arduino Leonardo.. On the Uno it works perfect, but the Leo, no..
So I'm kind of stuck trying to find out what the problem might be..
The different FFB programs I have tried for the Arduino Leonardo won't recognize it either.

Probably a good thing since I need to be focusing on my studies at the moment! Hard though, when this is so much more interesting..
I had to try..



Ran the encoder through my new 5€ Arduino oscilloscope and saw that the signals made much more sense when running the board on 3,3V instead of 5V.

So now it seems like I have almost all the components I need in order to build a working prototype! :D
All I need now is some connection from the motor to the steering axle.
I'm thinking belt drive, but with the ratio I want (something like 1:15) it would require quite a large pulley on the steering axle..
I had to try..


very nice. can't wait to see it in action.

maybe you could use a few pulleys to step up the ratio instead of one large pulley. something like this maybe....



Quote from: TimboC137 on May 31, 2019, 06:18:12 pmvery nice. can't wait to see it in action.

maybe you could use a few pulleys to step up the ratio instead of one large pulley. something like this maybe....

I know! Me neither!! ;D
(Damn you, lack of time)

I thought about that too, and probably it is the only choice I have.
I wanted to avoid it, since it doesn't only add cost but also takes space and makes the FFB less "direct"..

Since using a BLDC or stepper motor (super expensive drivers) is out of the question, I'm going to have to use a high gear
ratio to get high torque. Even a large 350W e-bike motor is 3000rpm, and since I will only be using 50 degrees of movement, I won't have the need for that kind of speed. A 1:30 ratio on that kind of a motor would probably be fast enough and that would give me about 30Nm of stall torque :O
If I don't gear it I think I'm just going to burn motors.
I had to try..


I have been experimenting a bit with The Arduinos and decided to rip out the internals of the Logitech wheel and try to replace them.

Bought an Arduino Pro Micro, which is pretty much a tiny Leonardo, off eBay and I already had motor driver boards.
The wheel has an optical encoder, similar to the one I already tested, so I wanted to see if I could get it working with the Arduino.
It worked like a charm, so I decided to try switching out the "motherboard".

I wanted to see how the resolution and force feedback feeling would be. It was a huge step up! Feels like the original hard/software is on power save mode, not doing much work unless it really has to. The new brain has much less of a weak center, and reacts much quicker! Plus, I can tweak the ffb effects a bit.
All this I managed to do without cutting a single wire, so it is fully restorable.

After using the Pro Micro,  replacing the little breadboard with a smaller soldered version and resoldering the capacitor and all connectors of the motor driver to the bottom of the PCB, I could even get the cover on! This is so much fun..

Now I have to reassemble the handlebar controls again, I want to try this with GPB!
I had to try..