PDA

View Full Version : BMW e36 dashboard with project cars data



apophis
08-09-2015, 13:00
Hey,

simplesimson (http://forum.projectcarsgame.com/member.php?109595-simplesimson) and me are currently working on getting project cars telemetry showing on a BMW e36 dashboard.
We got inspired by some people doing this around the web (www.sim-pc.de (http://www.sim-pc.de) for example) and want to show you the progress. :)

First of all a video of the current state, so you have an idea of what we are doing:
Video: dashboard with pcars speed and rpm:


https://www.youtube.com/watch?v=X107zaq17NQ


Video: rpm-LEDs and gear indicator with "simulated data" (the noise is the road beside my flat :D):


http://youtu.be/neztCBVheew


Things we use:
e36 dashboard
arduino uno
some shift registers

Things we plan:
Use as much of the things the dashboard can display :D:
-> speed, rpm, fuel, fuel consumption, temperatur
-> rpm lights and gear indicator
-> abs, traction controll, light ...
-> possible an additional display to show times, tire temperaturs and so on
-> Use the indicators to show if another car is on the right / left side
-> things i forgot to mention :D

Ideas about 'the tacho disc only shows 220km/h and 7000rpm':
-> Design a tacho disc with around 350km/h and 10k-14k rpm (or 18k for FA :D), but we need to find someone who can do such things (with good quality) and does not cost that much ;)
-> Use mph for speed and device RPM and possibly the fuel consumption by 2.

Implementation:
Read pcars shared memory and send "events" via serial port (USB) to the arduino.
The arduino will then trigger ports.
It is very early in development, so not much to show at the moment.
I will provide the code and circuit layout and everything if it has some more progress on github or something, but the arduino code is quite similar (but extended) to the code shown at http://www.sim-pc.de/tachosketch/

My plan is to implement it flexible, so other games could also be added easily.
At the moment the part on the PC is only a loop reading pcars shared memory and send them via USB ;)


If you like it, I will update this first post with some more progress :)
Feel free to discuss or give some ideas.

apophis
08-09-2015, 13:03
reserved

apophis
08-09-2015, 13:03
...

FRosad
24-09-2015, 04:15
Hi apophis,

can you share your arduino code please? I need a really simple things comparing with what you are doing. I'm doing a thesis project in a OBD applications and I need to get data from some car simulator to test it.
I'm using arduino due so basically I need an arduino code which prints on the serial in loop all the data like: speed, rpm,oil temperature, oil pressure, water temperature, water pressure, fuel pressure, fuel level, fuel capacity, throttle, clutch, steering, brake, gear, Odometer, air ambient temperature,...

thank you in advance :D

apophis
25-09-2015, 10:15
Hi apophis,

can you share your arduino code please? I need a really simple things comparing with what you are doing. I'm doing a thesis project in a OBD applications and I need to get data from some car simulator to test it.
I'm using arduino due so basically I need an arduino code which prints on the serial in loop all the data like: speed, rpm,oil temperature, oil pressure, water temperature, water pressure, fuel pressure, fuel level, fuel capacity, throttle, clutch, steering, brake, gear, Odometer, air ambient temperature,...

thank you in advance :D

hey,

I'm not at home till sunday and I didn't do much on the project the last 2 weeks (holiday and work).
But I can provide you some work in progress code when I'm back at home.

FRosad
29-09-2015, 14:03
hey,

I'm not at home till sunday and I didn't do much on the project the last 2 weeks (holiday and work).
But I can provide you some work in progress code when I'm back at home.

Ok, thank you. As soon as you can your code would be helpfull :D

apophis
30-09-2015, 18:45
I took the most interesting things of the code....
I have very much WIP code in it, which would make it more complex to read ;)
All in all it is not the cleanest and best code and will crash if wrong data is sent :D

PC code (reading and sending the data):
I took this serial class (http://playground.arduino.cc/Interfacing/CPPWindows) and the pcars shared memory header and following code (based on shared memory example):

// Used for memory-mapped functionality
#include <windows.h>
#include "sharedmemory.h"
#include <string>

// Used for this example
#include <stdio.h>
#include <conio.h>
#include "serial.h"

#include <sys/time.h>
#include <math.h>
#define _USE_MATH_DEFINES

// Name of the pCars memory mapped file
#define MAP_OBJECT_NAME "$pcars$"

using namespace std;

void sendData(Serial* SP, char* key, int iValue) {
char value[16];
sprintf(value, "%d", iValue);
char msg[32] = "^";

strcat(msg,key);
strcat(msg,",");
strcat(msg,value);
strcat(msg,"\n\0");

SP->WriteData(msg, sizeof(msg));
}

int main()
{
// Open the memory-mapped file
HANDLE fileHandle = OpenFileMapping( PAGE_READONLY, FALSE, MAP_OBJECT_NAME );
if (fileHandle == NULL) {
printf( "Could not open file mapping object (%d).\n", GetLastError() );
return 1;
}

// Get the data structure
const SharedMemory* sharedData = (SharedMemory*)MapViewOfFile( fileHandle, PAGE_READONLY, 0, 0, sizeof(SharedMemory) );
if (sharedData == NULL) {
printf( "Could not map view of file (%d).\n", GetLastError() );
CloseHandle( fileHandle );
return 1;
}

// Ensure we're sync'd to the correct data version
if ( sharedData->mVersion != SHARED_MEMORY_VERSION ) {
printf( "Data version mismatch\n");
return 1;
}

Serial* SP = new Serial("\\\\.\\COM3"); // adjust as needed

if (SP->IsConnected())
printf("We're connected");

Sleep(500);
int SLEEP_LOOP_MS = 10;
printf( "ESC TO EXIT\n\n");

while (true) {
int maxRpm = floor(sharedData->mMaxRPM+0.5);
sendData(SP, "maxrpm", maxRpm);
float speedMS = sharedData->mSpeed;
int speed = floor(speedMS*3.6 + 0.5);
sendData(SP, "tempo", speed);
int rpm = floor(sharedData->mRpm+0.5);
sendData(SP, "rpm", rpm);
int gear = sharedData->mGear;
sendData(SP, "gear", gear);
int fuel = floor(sharedData->mFuelCapacity*sharedData->mFuelLevel + 0.5);
sendData(SP, "fuelleft", fuel);

if ( _kbhit() && _getch() == 27 ) // check for escape {
break;
}
Sleep(SLEEP_LOOP_MS);
}

// Cleanup
UnmapViewOfFile( sharedData );
CloseHandle( fileHandle );

return 0;
}


Arduino code (receiving messages):
There I call functions like 'setGear' and 'setRpm', but I did not include them atm, because they are not finished or not working at all and not in your interest ;))



//timeout for serial read
int timeout = 10;

//maximum char[] lengh
int STRING_MAX = 255;

int mTempCrit = 0;
int mMaxRpm = 0;

// the setup routine runs once when you press reset:
void setup() {
Serial.begin(115200);
}

bool readSerialMessage(char* key, char *value) {
int count = 0;
int state = 0;
int keyCount = 0;
int valueCount = 0;

unsigned long previousMillis = millis();
while ((millis() - previousMillis) < timeout && count < STRING_MAX-1) {

if (Serial.available() > 0 ) {

bool keyOrValue = false;
char c = Serial.read();

switch (c) {
case '^':
if (state == 0)
state = 1;
break;
case ',':
if (state == 1)
state = 2;
break;
case '\n':
if (state == 2)
state = 3;
count = STRING_MAX;
break;
default:
keyOrValue = true;
break;
}

if (keyOrValue) {
switch (state) {
case 1:
key[keyCount] = c;
keyCount++;
break;
case 2:
value[valueCount] = c;
valueCount++;
break;
}
}
count++;
} else {
delay(1);
}
}
value[valueCount] = '\0';
key[keyCount] = '\0';

if (state == 3) {
return true;
}
else {
return false;
}
}

// the loop routine runs over and over again forever:
void loop() {

char key[STRING_MAX]; char value[STRING_MAX];
bool ret = readSerialMessage(key, value);
if (ret) {
if (strcmp(key, "gear") == 0) {
setGear(value[0]);
} else if (strcmp (key, "rpm") == 0) {
setRpm(atoi(value));
} else if (strcmp (key, "maxrpm") == 0) {
mMaxRpm = atoi(value);
} else if (strcmp (key, "tempo") == 0) {
setTempo(atoi(value));
} else if (strcmp (key, "fuelleft") == 0) {
setFuelLeft(atoi(value));
} else if (strcmp (key, "fuelcur") == 0) {
setFuelCur(atoi(value));
} else if (strcmp (key, "temp") == 0) {
setTemp(atoi(value));
} else if (strcmp (key, "tempcrit") == 0) {
mTempCrit = atoi(value);
} else if (strcmp (key, "abs") == 0) {
setAbs(value[0]);
} else if (strcmp (key, "trac") == 0) {
setTraction(value[0]);
} else if (strcmp (key, "inlight") == 0) {
setIngameLight(value[0]);
}
}

delay(1);
}