I used a window motor from an Audi A4 (cheapest on eBay) connected to where the GS's shift lever used to fit. The PRNDL switch on the side of the gearbox provides feedback telling the motor when to stop turning.
The Audi A4 unit has two relays built in, one for up and one for down, cross wired to provide the two directions. There was also a PCB with various IC's on there, it's likely CAN driven. I ripped out the PCB and drive the relays diretly from digital outputs via a MOSFET and some protection.
If you use a dumb motor then you'd need a H bridge, relays, etc to handle control. Maybe a stepper motor would be a good solution. The window motor was good for me as it comes with a gearbox already and is quite compact. And cheap.
Code is from a larger function but here's what I used. Sorry.
Code: Select all
//Parking Lock
#define LOCK_PARK 0
#define LOCK_NEUTRAL 1
#define LOCK_NEITHER 2
#define LOCK_ERROR 3
#define VEH_SPEED_SHIFT_THRESHOLD_LOW 1 //speed below which gear shift / park lock will happen
#define VEH_SPEED_SHIFT_THRESHOLD_HIGH 10 //speed above which prnd input is ignored
byte parking_lock = 2;
bool shifting = 0;
//read park lock state
if (!digitalRead(pin_trans_neutral) && digitalRead(pin_trans_park))parking_lock = LOCK_NEUTRAL;
else if (digitalRead(pin_trans_neutral) && !digitalRead(pin_trans_park))parking_lock = LOCK_PARK;
else if (digitalRead(pin_trans_neutral) && digitalRead(pin_trans_park))parking_lock = LOCK_NEITHER;
else if (!digitalRead(pin_trans_neutral) && !digitalRead(pin_trans_park))parking_lock = LOCK_NEITHER;
if (current_gear == GEAR_PARK || shifting) //currently in park, request to come out of park
{
shifting = 1;
if (veh_speed_kph < VEH_SPEED_SHIFT_THRESHOLD_LOW && veh_speed_kph > -VEH_SPEED_SHIFT_THRESHOLD_LOW)
{
Serial.print("\tParking Lock: ");
switch (parking_lock)
{
case LOCK_PARK: Serial.print("Engaged (Park)"); break;
case LOCK_NEUTRAL: Serial.print("Disengaged (Neutral)"); break;
case LOCK_NEITHER: Serial.print("Neither"); break;
case LOCK_ERROR: default: Serial.print("Error"); break;
}
Serial.print("\treleasing parking pawl\n");
if (parking_lock == LOCK_PARK || parking_lock == LOCK_NEITHER)
{
digitalWrite(pin_trans_motor_neutral, 1);
digitalWrite(pin_trans_motor_park, 0);
}
if (parking_lock == LOCK_NEUTRAL)
{
digitalWrite(pin_trans_motor_neutral, 0);
current_gear = prnd_gear; //after parking lock has finished, update the current gear
shifting = 0;
}
Serial.println(digitalRead(pin_trans_motor_park));
Serial.println(digitalRead(pin_trans_motor_neutral));
}
return;
}
if (prnd_gear == GEAR_PARK || shifting) //currently not in park, request to go into park
{
shifting = 1;
current_gear = GEAR_NEUTRAL;
if (veh_speed_kph < VEH_SPEED_SHIFT_THRESHOLD_LOW && veh_speed_kph > -VEH_SPEED_SHIFT_THRESHOLD_LOW)
{
Serial.print("\tParking Lock: ");
switch (parking_lock)
{
case LOCK_PARK: Serial.print("Engaged (Park)"); break;
case LOCK_NEUTRAL: Serial.print("Disengaged (Neutral)"); break;
case LOCK_NEITHER: Serial.print("Neither"); break;
case LOCK_ERROR: default: Serial.print("Error"); break;
}
Serial.print("\tlocking parking pawl\n");
if (parking_lock == LOCK_NEUTRAL || parking_lock == LOCK_NEITHER)
{
digitalWrite(pin_trans_motor_neutral, 0);
digitalWrite(pin_trans_motor_park, 1);
}
if (parking_lock == LOCK_PARK)
{
digitalWrite(pin_trans_motor_park, 0);
current_gear = prnd_gear;
shifting = 0;
}
Serial.println(digitalRead(pin_trans_motor_park));
Serial.println(digitalRead(pin_trans_motor_neutral));
}
return;
}
Note that I never used the VCU or the ZombieVerter, those were both forked from my early code (just after I got the inverter working), so I doubt anything I post here would be compatible.