Adapter für Lenkrad-Fernbedienung

Möchte man ein Autoradio, welches nicht vom Autohersteller kommt, an die Lenkradfernbedienung anschließen, kostet ein entsprechender Adapter oft an die 100 EUR. Hier stelle ich das Prinzip meines selbstgebauten Adapters vor. Es ist keine komplette Bauanleitung, ich denke aber, dass mit etwas Erfahrung der Nachbau kein Problem sein dürfte.

Mit einem Multimeter nachgemessen, habe ich festgestellt, dass die Lenkrad-Fernbedienung bei meinem Opel Astra G einfach verschiedene Widerstände (bzgl. Masse) bei den Tastendrücken erzeugt. Der Pin der Lenkradfernbedienung ist (bei Opel) Pin 2 der ISO Strombuchse.

Taste links oben ca. 470 Ohm
Taste links mitte ca. 800 Ohm
Taste links unten ca 1470 Ohm
Taste rechts oben ca. 170 Ohm
Taste rechts mitte ca. 85 Ohm
Taste rechts unten ca. 290 Ohm

Man erhält die gedrückte Taste also, wenn man mit dem Spannungsteiler-Prinzip diesen Widerstand mißt. Dieses habe ich mit einem Mikrocontroller realisiert, der die Information als 3-Bit-Wert an die parallele Schnittstelle des PC liefert. Gleichzeitig erkennt er noch, ob mein Jukebox-Programm über die parallele Schnittstelle das Display einschalten möchte und schaltet dann (entprellt und den Einschaltimpuls beim Einschalten des PCs ignorierend) ein Relais.

Der ADC_VCC Pin wird als Referenzspannung genommen. Er ist mit dem VCC (Versorgungsspannung 5V) zu verbinden. An Pin PC2 kann eine LED mit einem 330 Ohm Vorwiderstand angeschlossen werden.

Das Prinzip, dass Tastendrücke einer Lenkradfernbedienung durch Widerstandswerte repräsentiert werden, scheint auch bei anderen Automarken verbreitet zu sein. Daher ist die Schaltung dann auch dort einsetzbar und nicht auf Opel-Lenkradfernbedienungen beschränkt.


LFBKalibrierung

An Pin PC2 ist ein Piezo-Summer anschließbar. Beim ersten Anschalten oder auf Wunsch auch nach Betätigung einer Taste länger als 60 Sekunden kommt man in den Konfigurationsmodus. Durch akustische Signale wird dieser vom Ablauf her verdeutlicht. Man drückt alle 6 Tasten in beliebiger Reihenfolge nacheinander für ein paar Sekunden, bis jeweils ein Dauerton hörbar ist. Wenn alle Tasten (die resultierenden Widerstände) gemessen wurden, werden diese automatisch sortiert, die benötigten Mittelwerte gebildet und im EEPROM abgelegt. Ab dem Zeitpunkt werden immer diese Werte benutzt, bis eine erneute Kalibrierung durchgeführt wird.


Folgendes C-Programm für den eingesetzten ATMega8 (mit eingebautem A/D-Wandler) löst mein Problem (kompletter Quelltext zum Download):

int main(void)
{
	unsigned int b1, b2, b3;
	unsigned int d1, d2, d3;
	unsigned int sameValueCount;
	unsigned int oldValue;
	unsigned int sameButtonCount;
	unsigned int oldButton;
	
	io_init();
	adc_init();
	sei();

	// read thresholds from eeprom
	eeprom_read_block(&thresholds, &eeprom_adr, 6 * sizeof(int));

	// enter config if EEPROM empty
	if (0xFFFF == thresholds[0])
	{
		config();
	}

	// Remove comment to measure voltages and write to eeprom
	//test();
	
	while(1)
	{
		// Tastendruck von Opel Lenkradfernbedienung erkennen
		// Entprellen = Taste muss über 30ms Konstant sein
		sleep(10);
		b1 = voltage2button(read_adc(0));
		d1 = bit_is_set(PIND, 3) && (!bit_is_set(PIND, 4));
		sleep(10);
		b2 = voltage2button(read_adc(0));
		d2 = bit_is_set(PIND, 3) && (!bit_is_set(PIND, 4));
		sleep(10);
		b3 = voltage2button(read_adc(0));
		d3 = bit_is_set(PIND, 3) && (!bit_is_set(PIND, 4));
		if ((b1 == b2) && (b2 == b3))
		{
			if (b1 & 1) sbi(PORTD, 0); else cbi(PORTD, 0);
			if (b1 & 2) sbi(PORTD, 1); else cbi(PORTD, 1);
			if (b1 & 4) sbi(PORTD, 2); else cbi(PORTD, 2);
			// Taste über 100 ms senden
			// damit > Pollzyklus von Delphi Programm (50ms)
			if (b1 > 0) { sleep(120); }

			if ((oldButton == b1) && (b1 > 0))
	    	{
	    		if (sameButtonCount < TIMEOUT_ENTER_CONFIG_MODE_SEC * 10)
	    			sameButtonCount++;
    		} else {
	    		sameButtonCount = 0;
    		}
    		oldButton = b1;
			
			if (TIMEOUT_ENTER_CONFIG_MODE_SEC * 10 == sameButtonCount)
			{
				config();
			}
		}
		
		// erkennen, ob PC über Parallelport (PinD3, PinD4)
		// Display einschalten will
		// muss 1 Sek. konstant sein
		if ((d1 == d2) && (d2 == d3))
		{
	    	if (oldValue == d1)
	    	{
	    		if (sameValueCount < 300)
	    			sameValueCount++;
    		} else {
	    		sameValueCount = 0;
    		}
    		oldValue = d1;
    		
    		if ((sameValueCount == 150) && d1) // Display Einschalten mit 5 Sek Verzögerung
    		{
   				sbi(PORTD, 5);
   			}
   			else
    		if ((sameValueCount == 300) && !d1) // Display Ausschalten mit 10 Sek Verzögerung
   			{
   				cbi(PORTD, 5);
   			}
    	}
	}
}

Das Programm hat auch eine Testroutine, mit der die vom Mikrocontroller erkannten Spannungswerte im EEPROM abgelegt werden. Ein Auskommentieren der "test" Methode führt dazu, dass diese ausgeführt wird.


Lesen und Schreiben der parallelen Schnittstelle in Delphi

Ich habe die io.dll von Geek Hideout zur Ansteuerung der parallelen Schnittstelle verwendet. Folgendermaßen kann man damit einen Tastendruck einlesen (die Werte sind natürlich abhängig davon, an welche Statuspins des Parallelports man den Mikrocontroller anschließt):

// io.dll
function PortIn(Port : Word) : Byte; stdcall; external 'io.dll';

...

// empfangenen Wert von Microcontroller in Tastenwert umrechnen
function parPortKey() : byte;
var b : byte;
    res : byte;
begin
  b := PortIn(889);
  case b of
    200 : res := 0;
    216 : res := 3;
    232 : res := 2;
    248 : res := 1;
    72  : res := 6;
    88  : res := 4;
    104 : res := 5;
  else
    res := 0;
  end;
  parPortKey := res;
end;