
We had to build a 2DOF race simulator.
All the structure was made wooden.

It is cheaper than a metallic structure, more easy to built and move and it's as light as a Aluminum one.
/*
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;
}
Return to Motion simulator Projects in progress
Users browsing this forum: No registered users and 4 guests