Da ich unglaublich viele Anfragen aus dem Aus-Inland bekommen habe ob ich nicht mal ein kleines Tutorial für ein Golftacho machen kann, will ich das hier mal umsetzten.
Aber erstmal ein großes Danke an Daniel, welcher in Österreich wohnt und mir eine großzügige Spende sowie auch 2 x Golf 3 Tachos kostenlos zur verfügung gestellt hat.
Prinzipiell ist der Aufbau ähnlich wie schon bei dem BMW e36 Tacho. Die Kmh/h-Anzeige wird mit auch mit 5v angesteuert.
Das besondere beim VW-Tacho ist eben das das Rpm-Signal mit 12v angesteuert wird. Fuel und Temp, genau wie bei BMW über Widerstandsveränderungen.
Hier möchte ich anmerken, dass VW bei dem Golf 3 gleich 6 verschiedene Tachos verbaut hat. Ich habe hier ein VDO und ein TRW die Beide bei 0 Kmh anfangen. Wer mag, kann hier ein wenig nachlesen: Tachoumbau.com
Leider musste ich für eine saubere Tachojustierung das Tacho öffnen. Der Grund dafür ist das ich mit der Feinjustierung vom RPM nicht unter 1.000 gekommen bin. Ein ähnliches Problem gibt es auch beim e36 Tacho. Dort gehts nicht unter 750rpm. In Rennspiele vielleicht nicht das Problem aber einige (viele) bauen einen LKW-Simulatur. Da sollte dann auch die Anzeige unter 1000 funktionieren. Dazu aber später mehr.
Als erstes also das Tacho öffnen, so dass wir an die Nadeln drann kommen.
Jetzt gehts an die Verkabelung. (Das flashen des Arduinos sollte schon fertig sein)
Wenn alles richtig verkabelt ist machen wir eine Vorabkonfigurierung im „rcc“ für das Tacho.
(im Tab „Hardware“). Das Tacho noch NICHT mit Strom versorgen.
An diesem Punkt sollte das Rpm etwa 1000 auf dem Tacho anzeigen. Ihr könnt jetzt noch versuchen weiter den kleinsten möglichen Wert zu ermitteln in dem ihr wieder zurück auf „adj“ klickt und mit dem Schieberegler versucht die Nadel soweit wie möglich richtung 0 zu bringen.
Bei mir war „min=31“ der beste Wert. Alles darunter fing die Nadel an zu zappeln.
Nun steht die Nadel bei 1000 und nicht da wo sie hin soll.
Ich denke das der Arduino nicht mit der Hz-Zahl klar kommt was das Tacho will. Also hab ich ein wenig getrickst.
Sollte jemand eine bessere Lösung haben, kann er sie gerne unten in die Kommentare schreiben.
Zu diesem Zeitpunkt trennt ihr jetzt das Tacho vom Strom. (Die Nadel bleibt bei ca. 1000 stehen)
Hebelt die Nadel vorsichtig ab und bringt sie wieder in der Nullposition an.
Der Ardunino schafft zwar nicht unter dem dem Wert aber sehr wohl über den Wert. Heisst, er schafft die Nadel auch weit über die Anzeige raus. Und genau das machen wir uns zu nutze.
Jetzt noch nach oben beschriebene Anleitung den oberen rpm-Wert mit „max“ einjustieren
Bei „speed“ ebenso verfahren. Niedrigsten und höchsten Wert mittels Schieberegler einstellen.
Es ist KEINE Nadeländerung nötig.
Bei allen Speichervorgängen im rcc muss der „Testmodus“ aktiviert sein, sonst funktioniert es nicht.
Viel Spaß beim nachbauen.
Um noch mehr „feeling“ in den Simulator zu bringen habe ich mich entschlossen eine Unterstützung für Bodyshaker einzubauen.
Die ersten Tests mit Assetto Corsa sind gut gelaufen.
Im rcc werden NICHT die Sounds aus dem Game sondern die physikalichen Daten des Fahrzeuges zur Erzeugung der Vibrationen genutzt.
Zum testen hab ich eine externe USB-Soundkarte, einen Mini-Verstärker und ein paar Bodyshaker genommen.
Hier mal ein erster Test einer 6DOF Stewart Plattform auf Servo und arduino-basis in Verbindung mit SIMTOOLS.
/*
//********************************************************************************************
// RC Model Servo
// Original code By EAOROBBIE (Robert Lindsay)
// Completely mangled by aarondc
// For free use for Sim Tool Motion Software
// Changed by SIM-PC.de for 6DOF
//********************************************************************************************
#include
//#define DEBUG 1 // comment out this line to remove debuggin Serial.print lines
const int kActuatorCount = 6; // how many Actuators we are handling
// the letters ("names") sent from Sim Tools to identify each actuator
// NB: the order of the letters here determines the order of the remaining constants kPins and kActuatorScale
const char kActuatorName[kActuatorCount] = { 'A', 'B', 'C', 'D', 'E', 'F' };
const int kPins[kActuatorCount] = {2, 3, 4, 5, 6, 7};
const int kActuatorScale[kActuatorCount][6] = { { 0, 179 } , // 1 Actuator scaling
{ 0, 179 } , // 2 Actuator scaling
{ 0, 179 } , // 3 Actuator scaling
{ 0, 179 } , // 4 Actuator scaling
{ 0, 179 } , // 5 Actuator scaling
{ 0, 179 } // 6 Actuator scaling
};
const char kEOL = '~'; // End of Line - the delimiter for our acutator values
const int kMaxCharCount = 3; // some insurance...
Servo actuatorSet[kActuatorCount]; // our array of Actuators
int actuatorPosition[kActuatorCount] = {90,90,90,98,90,90}; // current Actuator positions, initialised to 90
int currentActuator; // keep track of the current Actuator being read in from serial port
int valueCharCount = 0; // how many value characters have we read (must be less than kMaxCharCount!!
// set up some states for our state machine
// psReadActuator = next character from serial port tells us the Actuator
// psReadValue = next 3 characters from serial port tells us the value
enum TPortState { psReadActuator, psReadValue };
TPortState currentState = psReadActuator;
void setup()
{
// attach the Actuators to the pins
for (int i = 0; i < kActuatorCount; i++)
actuatorSet[i].attach(kPins[i]);
// initialise actuator position
for (int i = 0; i < kActuatorCount; i++) updateActuator(i); Serial.begin(38400); // opens serial port at a baud rate of 9600 } void loop() { } // this code only runs when we have serial data available. ie (Serial.available() > 0).
void serialEvent() {
char tmpChar;
int tmpValue;
while (Serial.available()) {
// if we're waiting for a Actuator name, grab it here
if (currentState == psReadActuator) {
tmpChar = Serial.read();
// look for our actuator in the array of actuator names we set up
#ifdef DEBUG
Serial.print("read in ");
Serial.println(tmpChar);
#endif
for (int i = 0; i < kActuatorCount; i++) {
if (tmpChar == kActuatorName[i]) {
#ifdef DEBUG
Serial.print("which is actuator ");
Serial.println(i);
#endif
currentActuator = i; // remember which actuator we found
currentState = psReadValue; // start looking for the Actuator position
actuatorPosition[currentActuator] = 0; // initialise the new position
valueCharCount = 0; // initialise number of value chars read in
break;
}
}
}
// if we're ready to read in the current Actuator's position data
if (currentState == psReadValue) {
while ((valueCharCount < kMaxCharCount) && Serial.available()) {
tmpValue = Serial.read();
if (tmpValue != kEOL) {
tmpValue = tmpValue - 48;
if ((tmpValue < 0) || (tmpValue > 9)) tmpValue = 0;
actuatorPosition[currentActuator] = actuatorPosition[currentActuator] * 10 + tmpValue;
valueCharCount++;
}
else break;
}
// if we've read the value delimiter, update the Actuator and start looking for the next Actuator name
if (tmpValue == kEOL || valueCharCount == kMaxCharCount) {
#ifdef DEBUG
Serial.print("read in ");
Serial.println(actuatorPosition[currentActuator]);
#endif
// scale the new position so the value is between 0 and 179
actuatorPosition[currentActuator] = map(actuatorPosition[currentActuator], 0, 255, kActuatorScale[currentActuator][0], kActuatorScale[currentActuator][1]);
#ifdef DEBUG
Serial.print("scaled to ");
Serial.println(actuatorPosition[currentActuator]);
#endif
updateActuator(currentActuator);
currentState = psReadActuator;
}
}
}
}
// write the current Actuator position to the passed in Actuator
void updateActuator(int thisActuator) {
actuatorSet[thisActuator].write(actuatorPosition[thisActuator]);
}
Da doch einige Anfragen zur Ansteuerung eines TM1638 mit dem rcc gekommen sind, habe ich hier mal ein einfaches Beispiel für eine Drehzahlanzeige gemacht.
//https://github.com/rjbatista/tm1638-library
#include
// define a module on data (DIO) pin 8, clock (CLK) pin 9
// and strobe (STB0)pin 10
TM1638 module(8, 9, 10);
String ver = "2.0.0.0";
const int nChar = 30; // size of char
String inString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
int vRpm;
void setup()
{
Serial.begin(38400);
}
void readdata() {
if (stringComplete) {
if (inString.substring(0, 2) == "RR") {
vRpm = inString.substring(2, 6).toInt();
module.setDisplayToDecNumber(vRpm * 10,0,false);
}
inString = "";
stringComplete = false;
}
}
void serialReadEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inString += inChar;
if (inChar == ';') {
stringComplete = true;
}
}
}
void loop() {
serialReadEvent();
readdata();
}
Im moment arbeite ich an eine stark erweiterte Version vom
rcc (real cockpit connector) als kompletter Gamedash zur Ansteuerung von unterschiedlichster Hardware.
Ein einfaches Möglichkeit um z.b. eine Drehzahlanzeige in einem Cockpit zu steuern wäre die Kontrolle mit einem Servo.
/*
This is a servo sample for rcc with rpm
http://www.arduino.cc/en/Tutorial/Sweep
*/
#include Servo myservo; // create servo object to control a servo,
//twelve servo objects can be created on most boards
String ver = "2.0.0.3";
const int servPin = 9; // Servo Pin
const int nChar = 30; // size of char
String inString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
void setup() {
myservo.attach(servPin); // attaches the servo to the servo object
inString.reserve(nChar);
Serial.begin(38400);
}
void readdata() {
if (stringComplete) {
if (inString.substring(0, 2) == "RR") {
int vRpm = inString.substring(2, 6).toInt();
int pos = map(vRpm, 0, 800, 255, 0);
myservo.write(pos);
}
inString = "";
stringComplete = false;
}
}
void serialReadEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inString += inChar;
if (inChar == ';') {
stringComplete = true;
}
}
}
void loop() {
serialReadEvent();
readdata();
}
Gestern sind aus „good old China“ meine Breakoutboards für den Arduino Nano und den Mega gekommen.
(Für den Uno lohnt sich das für mich nicht da der Nano die geichen Funktionen hat und wesentlich kleiner ist)
Warum Breakoutboard ?
Ganz einfach. Die Arduinos sind super um kleine Schaltungen mit Steckverbindungen zu testen. Für eine dauerhafte Lösung muss dann aber gelötet oder geklebt werden.
Da ich meine Arduinos aber stellenweise für die unterschiedlichsten Projekte verwende musste eine andere Lösung her.
Bei beiden Shields lassen sich die Kabel normal anschrauben.
Beim MegaShield besteht zusätzlich noch die möglichkeit den Arduino weiter für Steckverbindungen und/oder Lötverbindungen zu nutzen.
Rundum durchdacht.
Das Mega Shield gibt es hier: zur Bucht