Simulator ENSEM1A14

Running simulator build projects.
Please use the image gallery for your pictures, a short tutorial can be found here.
The first image in the first post will be shown in the project gallery.

Simulator ENSEM1A14

Postby ENSEM1A14 » Fri 30. May 2014, 15:01

Hello, we give you our new simulator. It's a scholar engineering project. :geek:
We had to build a 2DOF race simulator.
2913

All the structure was made wooden.8-)
It is cheaper than a metallic structure, more easy to built and move and it's as light as a Aluminum one.
Last edited by ENSEM1A14 on Fri 30. May 2014, 18:38, edited 2 times in total.
ENSEM1A14
 
Posts: 7
Images: 24
Joined: Thu 2. Jan 2014, 22:21
Has thanked: 0 time
Been thanked: 0 time

Re: Simulator ENSEM1A14

Postby ENSEM1A14 » Fri 30. May 2014, 15:25

For the designing part

It was necessary to design the basis of the simulator allowing to put in movement the cockpit, which is constituted by two engines which by means of a system of connecting rods make turn according to two axes of rotation the cockpit.
To relieve the effort of engines, a system by spring was set up (at the end of every rail on the figure).

For the "special" parts, we thus realized plans by means of a software of CAD Solidworks
Inspiration:





2911

2912

2914
Last edited by ENSEM1A14 on Fri 30. May 2014, 17:26, edited 2 times in total.
ENSEM1A14
 
Posts: 7
Images: 24
Joined: Thu 2. Jan 2014, 22:21
Has thanked: 0 time
Been thanked: 0 time

Re: Simulator ENSEM1A14

Postby ENSEM1A14 » Fri 30. May 2014, 15:39

One of the major problems of the realization was to find the cardan joint which is in the center of the structure.
Finally we found a cardan joint sizes of which were compatible with the structure.
2915
ENSEM1A14
 
Posts: 7
Images: 24
Joined: Thu 2. Jan 2014, 22:21
Has thanked: 0 time
Been thanked: 0 time

Re: Simulator ENSEM1A14

Postby ENSEM1A14 » Fri 30. May 2014, 15:45

Oculus Rift

For our project, we decide to use The oculus rift instead of screens.
So it's appeared necessary to use a TRACK-IR to compense the picture deformations due to the head's movements while the cockpit is moving. We also need it to shut off the inertial centrals from the oculus rift. Then this is the TRACK-IR which provides the head's movements in the game
2910
2916
Last edited by ENSEM1A14 on Fri 30. May 2014, 17:27, edited 1 time in total.
ENSEM1A14
 
Posts: 7
Images: 24
Joined: Thu 2. Jan 2014, 22:21
Has thanked: 0 time
Been thanked: 0 time

Re: Simulator ENSEM1A14

Postby ENSEM1A14 » Fri 30. May 2014, 16:04

Mechanical part

To insure the movement of the cockpit + user of a maximal mass of 150Kg, engines have to divide up the efforts necessary for the movement. It is essential while every engine develops a minimal couple of 16 Nm. Beyond the constraints of effort, engines also have to supply speeds necessary for the simulation of the various movements of the nacelle. Engines so have to have a minimal rotation speed of 30tr / mn and it in both directions of rotations.
2917
Last edited by ENSEM1A14 on Fri 30. May 2014, 17:32, edited 1 time in total.
ENSEM1A14
 
Posts: 7
Images: 24
Joined: Thu 2. Jan 2014, 22:21
Has thanked: 0 time
Been thanked: 0 time

Re: Simulator ENSEM1A14

Postby ENSEM1A14 » Fri 30. May 2014, 17:18

A system of connecting rods is fixed to every engine to transmit the movement to the cockpit.
One of the rods is linked to the engine and the other to the platform to help engines to compensate for the weight of the cickpit during a slope of this one.(see solidworks plans)
2918

2920

2921

To avoid to damage rods coonected to engines by the movement of lace of the cockpit, we made two cages which block the rotation with regard to the vertical line of the cockpit. Those cages can also be used like a support to put a drink or a cell phone on it ;)
2923
2922
2924


Electronic part
We use cards arduino and to motomonster which delivers the necessary power for the functioning of engines. We also use potentiometers in order to te acheive the subjection of engines. Concerning the potentiometers, we got problems about its integration into the engines. So we built a wooden plate which transmits the rotation of the driving shaft to the potentiometer.

2929

2931


Arduino card

2919

Motomonster card
2925

We designed a box which contains the two cards. In the box, there is a ventilator which will allow to cool cards during the using.
2928
2930

For the electric supply of the electric part, we use a power supply of 12.6V and 47A

2909

Concerning the steering wheel and the crankset, we bought the logitech G27. And the seat was found on internet at 75 euros

Here is our arduino code. It is a modified code from THIS forum. The code is not complete yet. There are some others modifictaions to do.

Code: Select all
/*
Arduino code for dynamic playseat 2DOF - www.X-sim.de
Created 24 May 2011 by Jim Lindblom SparkFun Electronics https://www.sparkfun.Created 24 Apr 2012 by Jean David SEDRUE Version betatest26 - 2
Updated 20 May 2013 by RacingMat in english http://www.x-sim.de/forum/viewtopic.Updated 10 January 2014 by Guillaume Rosa and Guillaume MAS
*/
#define BRAKEVCC 0
#define RV 2 //beware it's depending on your hardware wiring
#define FW 1 //beware it's depending on your hardware wiring
#define STOP 0
#define BRAKEGND 3
////////////////////////////////////////////////////////////////////////////////
#define pwmMax 255 // or less, if you want to lower the maximum
// defining the range of potentiometer's rotation
const int potMini=208;
const int potMaxi=815;
////////////////////////////////////////////////////////////////////////////////
#define motLeft 0
#define motRight 1
#define potL A5
#define potR A4
////////////////////////////////////////////////////////////////////////////////
// DECLARATIONS
////////////////////////////////////////////////////////////////////////////////
/* VNH2SP30 pin definitions*/
int inApin[2] = {
7, 4}; / / INA: Clockwise input
int inBpin[2] = {
8, 9}; // INB: Counter-clockwise input
int pwmpin[2] = {
5, 6}; // PWM input
int cspin[2] = {
2, 3}; // CS: Current sense ANALOG input
int enpin[2] = {
0, 1}; // EN: Status of switches output (Analog pin)
int statpin = 13; / /not explained by Sparkfun
/* init position value*/
int DataValueL=512; //middle position 0-1024
int DataValueR=512; //middle position 0-1024
////////////////////////////////////////////////////////////////////////////////
// INITIALIZATION
////////////////////////////////////////////////////////////////////////////////
void setup()
{
// serial initialization
Serial.begin(115200);
// initialization of Arduino's pins
pinMode(statpin, OUTPUT); //not explained by Sparkfun ( creator
digitalWrite(statpin, LOW);
for (int i=0; i<2; i++)
{
pinMode(inApin[i], OUTPUT); // initialization of pins for mot
pinMode(inBpin[i], OUTPUT);
pinMode(pwmpin[i], OUTPUT);
}
// Initialize braked for motor
for (int i=0; i<2; i++)
{
digitalWrite(inApin[i], LOW);
digitalWrite(inBpin[i], LOW);
}
}
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// Main Loop ////////////////////
////////////////////////////////////////////////////////////////////////////////
void loop()
{
int sensorL,sensorR;
readSerialData(); / / DataValueR & L contain the last order re
// the previous order will still be used by the PID regulation
sensorR = analogRead(potR); // range 0-1024
sensorL = analogRead(potL); // range 0-1024
motorMotion(motRight,sensorR,DataValueR);
motorMotion(motLeft,sensorL,DataValueL);
}
////////////////////////////////////////////////////////////////////////////////
// Procedure: wait for complete trame
////////////////////////////////////////////////////////////////////////////////
void readSerialData()
{
byte Data[3]={
'0','0','0' };
// keep this function short, because the loop has to be short
if (Serial.available()>2){
//parse the buffer : test if the byte is the first of the or
Data[0]=Serial.read();
if (Data[0]=='R'){
Data[1]=Serial.read();
Data[2]=Serial.read();
// call the function that converts the hexa in decimal an
DataValueR=NormalizeData(Data);
}
if (Data[0]=='L'){
Data[1]=Serial.read();
Data[2]=Serial.read();
// call the function that converts the hexa in decimal an
DataValueL=NormalizeData(Data);
}
}
if (Serial.available()>16) Serial.flush();
}
////////////////////////////////////////////////////////
void motorMotion(int numMot,int actualPos,int targetPos)
////////////////////////////////////////////////////////
{
int Tol=20; // no order to move will be sent to the motor if th
// this prevents short jittering moves
//could be a parameter read from a pot on an analogic pin
// the highest value, the calmest the simulator would be (less
int gap;
int pwm;
int brakingDistance=30;
// security concern : targetPos has to be within the mechanica
targetPos=constrain(targetPos,potMini+brakingDistance,potMaxi-brakingDistance);
gap=abs(targetPos-actualPos);
if (gap<= Tol) {
motorOff(numMot); //too near to move
}
else {
// PID : calculates speed according to distance
pwm=195;
if (gap>50) pwm=215;
if (gap>75) pwm=235;
if (gap>100) pwm=255;
pwm=map(pwm, 0, 255, 0, pwmMax); / /adjust the value accordin
// if motor is outside from the range, send motor back to th
// go forward (up)
if ((actualPos<potMini) || (actualPos<targetPos)) motorGo(nu
// go reverse (down)
if ((actualPos>potMaxi) || (actualPos>targetPos)) motorGo(nu
}
}
////////////////////////////////////////////////////////////////////////////////
void motorOff(int motor){ //Brake Ground : free wheel actually
////////////////////////////////////////////////////////////////////////////////
digitalWrite(inApin[motor], LOW);
digitalWrite(inBpin[motor], LOW);
analogWrite(pwmpin[motor], 0);
}
////////////////////////////////////////////////////////////////////////////////
void motorOffBraked(int motor){ // "brake VCC" : short-circuit in
////////////////////////////////////////////////////////////////////////////////
digitalWrite(inApin[motor], HIGH);
digitalWrite(inBpin[motor], HIGH);
analogWrite(pwmpin[motor], 0);
}
////////////////////////////////////////////////////////////////////////////////
void motorGo(uint8_t motor, uint8_t direct, uint8_t pwm)
////////////////////////////////////////////////////////////////////////////////
{
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], pwm);
}
}
}
////////////////////////////////////////////////////////////////////////////////
void motorDrive(uint8_t motor, uint8_t direct, uint8_t pwm)
////////////////////////////////////////////////////////////////////////////////
{
// more readable function than Jim's (for educational purpose)
// but 50 octets heavier -> unused
if (motor <= 1 && direct <=4)
{
switch (direct) {
case 0: //electromagnetic brake : brake VCC
digitalWrite(inApin[motor], HIGH);
digitalWrite(inBpin[motor], HIGH);
break;
case 3: //Brake Ground (free wheel)
digitalWrite(inApin[motor], LOW);
digitalWrite(inBpin[motor], LOW);
break;
case 1: // forward : beware it's depending on your hardware
digitalWrite(inApin[motor], HIGH);
digitalWrite(inBpin[motor], LOW);
break;
case 2: // Reverse : beware it's depending on your hardware
digitalWrite(inApin[motor], LOW);
digitalWrite(inBpin[motor], HIGH);
break;
}
analogWrite(pwmpin[motor], pwm);
}
}
////////////////////////////////////////////////////////////////////////////////
// testPot
////////////////////////////////////////////////////////////////////////////////
void testPot(){
Serial.print(analogRead(A4));
Serial.print(";");
Serial.println(analogRead(A5));
delay(250);
}
////////////////////////////////////////////////////////////////////////////////
void testpulse(){
int pw=120;
while (true){
motorGo(motLeft, FW, pw);
delay(250);
motorOff(motLeft);
delay(250);
motorGo(motLeft, RV, pw);
delay(250);
motorOff(motLeft);
delay(500);
motorGo(motRight, FW, pw);
delay(250);
motorOff(motRight);
delay(250);
motorGo(motRight, RV, pw);
delay(250);
motorOff(motRight);
Serial.println("testpulse pwm:80");
delay(500);
}
}
////////////////////////////////////////////////////////////////////////////////
// Function: convert Hex to Dec // this part was difficult to
//this conversion is using the ASCII code to convert data from He
////////////////////////////////////////////////////////////////////////////////
int NormalizeData(byte x[3])
////////////////////////////////////////////////////////////////////////////////
{
int result;
if (x[2]==13) / / only a LSB and Carrier Return
{
x[2]=x[1]; / /move MSB to LSB
x[1]='0'; //clear MSB
}
for (int i=1; i<3; i++)
{
if (x[i]>47 && x[i]<58 ){//for xA to xF
x[i]=x[i]-48;
}
if ( x[i]>64 && x[i]<71 ){//for x0 to x9
x[i]=x[i]-55;
}
}
// map the range from Xsim (0 <-> 255) to the mechanically auth
result=map((x[1]*16+x[2]),0,255,potMini,potMaxi);
return result;
}
ENSEM1A14
 
Posts: 7
Images: 24
Joined: Thu 2. Jan 2014, 22:21
Has thanked: 0 time
Been thanked: 0 time

Re: Simulator ENSEM1A14

Postby RacingMat » Sat 31. May 2014, 11:14

Hello Ensem1a14!

Good project! And nice thread with pictures :-)

Could you explain what improvment did you implement in the code?

Beware that I corrected a bug (low hex values conversion): the code is updated in my tutorial.

Yours
Mat
2 DOF playseat : arduino, motomonster, 12V truck wiper motors
http://www.x-sim.de/forum/viewtopic.php?f=37&t=943
User avatar
RacingMat
X-Sim Stage 2 edition
 
Posts: 456
Images: 147
Joined: Wed 20. Feb 2013, 21:30
Location: Marseille - FRANCE
Has thanked: 4 times
Been thanked: 130 times

Re: Simulator ENSEM1A14

Postby ENSEM1A14 » Sun 1. Jun 2014, 16:52

Hey racingmat,

thank you.

In fact this code is yours if i remember we took it from your post.

And on our post it s exactly the same of you because we havent finished yet our improvments and we had to post somethong on x sim in order to have our key activation to use the software offline because in our school the port 80 was disabled....

In fact, the modification are essentially due to the position of our potentiometer from the dc motors. More over we installed an emergency stop button which put the simulator horyzontaly and stop motors.

We ll update the code soon and we ll show you soon a demo : )
ENSEM1A14
 
Posts: 7
Images: 24
Joined: Thu 2. Jan 2014, 22:21
Has thanked: 0 time
Been thanked: 0 time

Re: Simulator ENSEM1A14

Postby RacingMat » Mon 2. Jun 2014, 07:36

Eager to see that! :-)

Please don't spread identical versions of code but rather add a link to the tutorial ;-)
It's easier for bug tracking and correcting!

Yours
Mat
2 DOF playseat : arduino, motomonster, 12V truck wiper motors
http://www.x-sim.de/forum/viewtopic.php?f=37&t=943
User avatar
RacingMat
X-Sim Stage 2 edition
 
Posts: 456
Images: 147
Joined: Wed 20. Feb 2013, 21:30
Location: Marseille - FRANCE
Has thanked: 4 times
Been thanked: 130 times


Return to Motion simulator Projects in progress

Who is online

Users browsing this forum: No registered users and 4 guests

cron