Stammt ursprünglich aus dem pCARS Thread, aber hier ist eindeutig der bessere Ort also hier nochmal:
Da jemand per PM angefragt, ob ich eine Anleitung zu meinem Schalthebel schreiben könnte, habe ich mal eine kleine Erklärung zusammen gehackt. Habe das Ganze nicht besonders aufbereitet, sondern einfach so runtergeschrieben. Bei Fragen einfach eine PM schreiben.
Die Idee stammt nicht von mir, sondern aus dem virtualracing Forum (
DIY Shifter - Thread). Habe den Thread nur teilweise überflogen, aber ich bin mir sicher, dass es dort viele Zusatzinformationen gibt.
Worum geht es:
Einen BMW E39 Steptronic Schalthebel so umzubauen, dass er als USB Gerät erkannt wird. Man erhält einen sequentiellen Schalthebel hervorragender mechanischer Qualität und etwas mehr „Knöpfen“ als ein normaler sequentieller Schalthebel. Das Ganze gibt es für knapp 30 €.
Der Schalthebel hat ursprünglich folgende Stellungen/Funktionen:
Im Automatikmodus (Hebel in der Mitte) wird über einen Schiebeschalter die Position ausgelesen. Es gibt meine ich R, P, N, D, also vier Stellungen, die man auslesen kann. Im Steptronic Modus (Schalter in der D Position nach links kippen) kann sequentiell ein Gang hoch oder runter geschaltet werden. Hier sind drei Mikroschalter verbaut (einer um zu ermitteln ob der Hebel nach links gekippt ist und jeweils einer für Gang hoch bzw. runter).
Was braucht man:
- E39 Steptronic Schaltkulisste (meine hat die Teilenummer 1 422 834). Die Dinger gehen bei Ebay für 10 – 30 € weg. Ich habe direkt eine mit Knauf gekauft, da ich keinen Bock hatte mich später darum zu kümmern und so auch der Sperrmechanismus des Rückwärtsgangs erhalten blieb.
- Arduino mit USB Host Funktionalität (am besten irgendein Arduino Leonardo – 9 – 10 € bei Ebay). Es gibt Alternativen, aber die üblichen Verdächtigen sind teurer (Leo Bodnar, Teensy) und wer selber nen Mikrochip programmieren will, braucht bestimmt kein Tutorial. Ich verwende aktuell einen Arduino UNO, den ich per HoodLoader2 und vier zusätzlich angelöteten Sockeln USB fähig gemacht habe. Die Tutorials dazu sind ganz gut, daher schreibe ich mal nix dazu. Bei Fragen einfach eine PM schreiben.
- Ein paar Kabel
Schalthebel „strippen“:
Der E39 Schalthebel muss etwas zerfleddert werden. Es gibt einen Haken, der den Hebel festhält und einen Mechanismus, der per Elektromagnet eine Sperre ausfährt, sofern er unter Strom steht. Beides muss weg. Die schwarze „Führung“ mit dem Flachbandkabel muss bleiben. So sieht der Hebel bei mir aus:
Schaltstellungen auslesen + Schaltlogik:
- Die drei Mikroschalter sind am gelben Stecker auslesbar:
Gang hoch (schwarz), Gang runter (grün) und Steptronic aktiv bzw. Hebel nach links gekippt (grau) werden jeweils mit der Masse (blau) verbunden, wenn der entsprechende Taster aktiv ist.
- Der Schiebeschalter ist über das graue Flachbandkabel auslesbar:
Je nach Position ist die Masse (schwarz markiert, Pin 1) mit dem entsprechenden Pin verbunden. Pin 2 -> Rückwärtsgang, Pin 3 -> sinnlose Zwischenstellung, Pin 4 -> nutzbare Mittelstellung, wenn man die Sperre für den Rückwärtsgang erhalten hat (also mit original Knauf gekauft hat), Pin 5 -> Fahrposition (hier kann der Hebel nach links gekippt werden).
Auch wenn der Schalthebel nach links gekippt ist, liefert der Schiebeschalter natürlich Signale. Wer also selber einen Sketch schreiben will, muss jeweils die Position des „grauen“ Mikroschalters berücksichtigen.
- Mein Sketch sendet jeweils einen Gamepad Tastendruck, wenn die entsprechende Stellung des Schiebeschalters erreicht wird. Wenn also der Rückwärtsgang eingelegt wurde, wird einmal Taste 6 gesendet. Ist kein Problem es so zu ändern, dass ein Dauersignal kommt, mit war das beschriebene Verhalten lieber.
Gang hoch -> Taste 1
Gang runter -> Taste 2
Hebel in die Mitte kippen -> Taste 3
D Position -> Taste 4
N Position -> Taste 6
R Position -> Taste 5
Verkabelung:
Masse (gelber Stecker blau, grauer Stecker schwarz) jeweils an die Masse des Arduino anschließen. Die anderen Pins an irgendwelche Inputs des Arduino (in meinem Sketch ist das per Kommentar erklärt).
Je nach verwendetem Arduino müssen im Sketch die Pins geändert werden (steht auch dort in den Kommentaren) und nach dem Hochladen kann es direkt losgehen.
Der Sketch stammt von mir. Den könnt ihr kopieren wie ihr wollt und meinetwegen auch auf Klopapier drucken. Anregungen sind gerne gesehen. Nach dem Motto "Nichts hält länger als ein Provisorium" habe ich allerdings nur begrenzt Hirnschmalz investiert. Der Sketch ist wenig elegant.
Code:
// Die eingetragenen Pins sind für einen Arduino UNO mit HoodLoader2 und zusätzlich aufgelöteten Sockeln.
//
// Falls ein Arduino Leonardo verwendet wird, empfiehlt es sich zumindest Pin 1 durch einen anderen zu ersetzen,
// da dieser für die serielle Kommunikation benötigt wird. Einfach das Kabel woanders einstecken und den GearUp Pin
// durch den verwendeten ersetzen.
const int GearUp = 1; // schwarzes Kabel vor dem gelben Stecker
const int GearDown = 2; // grünes Kabel vor dem gelben Stecker
const int StepTronic = 3; // graues Kabel vor dem gelben Stecker
const int Leerlauf = 4; // Pin 4 Flachbandstecker
const int Rueck = 5; // Pin 2 Flachbandstecker
const int Zwischen = 6; // Pin 4 Flachbandstecker
const int DelayTime = 50; // Ohne Delay wurden bei mir die Tastendrücke nicht vernünftig registriert.
// Habe mich nicht besonders damit auseinandergesetzt. Die Zeit sollte kurz genug sein,
// damit sie nicht stört.
boolean GearUpState = HIGH;
boolean GearDownState = HIGH;
boolean StepTronicState = LOW;
boolean LeerState = HIGH;
boolean RueckState = HIGH;
boolean ZwischenState = HIGH;
boolean GearUpLast = HIGH;
boolean GearDownLast = HIGH;
boolean StepTronicLast = LOW;
boolean LeerLast = HIGH;
boolean RueckLast = HIGH;
boolean ZwischenLast = HIGH;
void setup() {
Gamepad.begin();
pinMode(GearUp, INPUT_PULLUP);
pinMode(GearDown, INPUT_PULLUP);
pinMode(StepTronic, INPUT_PULLUP);
pinMode(Leerlauf, INPUT_PULLUP);
pinMode(Rueck, INPUT_PULLUP);
pinMode(Zwischen, INPUT_PULLUP);
}
void loop() {
if (digitalRead(GearUp) == LOW) {
Gamepad.press(1);
}
else
Gamepad.release(1);
if (digitalRead(GearDown) == LOW) {
Gamepad.press(2);
}
else
Gamepad.release(2);
Gamepad.write();
StepTronicState = digitalRead(StepTronic);
if (StepTronicState != StepTronicLast && StepTronicState == HIGH) {
Gamepad.press(3);
Gamepad.write();
delay(DelayTime);
}
if (StepTronicState == StepTronicLast || StepTronicState == LOW) {
Gamepad.release(3);
Gamepad.write();
}
StepTronicLast = StepTronicState;
LeerState = digitalRead(Leerlauf);
if (LeerState != LeerLast && LeerState == LOW) {
Gamepad.press(4);
Gamepad.write();
delay(DelayTime);
}
if (LeerState == LeerLast || LeerLast == HIGH) {
Gamepad.release(4);
Gamepad.write();
delay(DelayTime);
}
LeerLast = LeerState;
ZwischenState = digitalRead(Zwischen);
if (ZwischenState!= ZwischenLast && ZwischenState == LOW) {
Gamepad.press(5);
Gamepad.write();
delay(DelayTime);
}
if (ZwischenState == ZwischenLast || ZwischenState == HIGH) {
Gamepad.release(5);
Gamepad.write();
}
ZwischenLast = ZwischenState;
RueckState = digitalRead(Rueck);
if (RueckState!= RueckLast && RueckState == LOW) {
Gamepad.press(6);
Gamepad.write();
delay(DelayTime);
}
if (RueckState == RueckLast || RueckState == HIGH) {
Gamepad.release(6);
Gamepad.write();
}
RueckLast = RueckState;
}