Samstag, 14. September 2013

Raspberry Pi - Mach mir das Autoradio! (Teil 1)

1. Übersicht  


Autoradio?! Warum will man sich selber ein Autoradio bauen, wenn man diese doch in allen Auführungen kaufen kann?

Die Idee ist eine modulare Plattform zu haben, welche nach und nach beliebig erweitert werden kann. Die Basis bilden der Raspberry Pi und der von diesem gesteuerte FM-Tuner Si4703. Normalerweise hat ein Autoradio z.B. an der Front ein Display eingelassen. Dieses Konzept erlaubt mir aber auch ein Smartphone oder Tablet als Display zu nutzen. Unterstützung für GPS, Bluetooth, WiFi, etc. lassen sich vergleichsweise einfach nachrüsten. Der RPi kann auch auf beliebige Arten online gehen, womit sich dann unter anderem Verkehrs- und Wetterdaten abrufen lassen. Interessant ist auch die Anbindung des Fahrzeugdiagnosesystems (OBD). Desweiteren ist auch eine Musiksammlung, gespeichert auf einem internen Massenspeicher, fest eingeplant. Diese soll sich mit einem passenden Endgerät (Smartphone, Laptop, etc.) synchronisieren lassen.

Raspberry Pi Rev.2 (www.raspberrypi.org)
Okay, Autoradio schön und gut, jedoch wie darf man sich den Aufbau vorstellen?

Zunächst einmal braucht man ein Gehäuse, in diesem Fall ein leeres ISO 7736 Gehäuse ohne Frontabdeckung, jedoch mit rückseitiger Anschlussleiste. Das Herzstück ist ein Raspberry Pi (Modell B, 512 MB) mit Raspbian "Wheezy" an dem das FM-Tuner Board Si4703 von SparkFun (Silicon Labs) angeschlossen ist.

FM-Tuner Board Si4703 (www.sparkfun.com)

Einen DC/DC-Wandler um aus der 12V Boardspannung 3.3V und 5V für Tuner und RPi zu erzeugen. Weiters wird auch ein Leistungsverstärker für das Audiosignal vom Tuner zu den Lautsprechern benötigt. Die Frontabdeckung wird wohl eine besondere Herausforderung werden, da ich diese mittels 3D-Druck erstellen möchte.

Der erste Schwerpunkt wird die Ansteuerung des FM-Tuners sein.

2. Ansteuerung des FM-Tuners



Laut Datenblatt kann man mit dem Chip via 2-Wire und 3-Wire kommunizieren. Wir verwenden 2-Wire, was im Prinzip I²C ist.

Unter Raspbian muss man zunächst das I²C-Subsystem zum laufen bringen. Dafür wird zunächst folgender Befehl ausgeführt:
sudo nano /etc/modules
Anschließend fügt man folgende zwei Zeilen hinzu:
i2c-bcm2708
i2c-dev
Damit werden beide Module beim Booten automatisch geladen.
sudo modprobe i2c-bcm2708
sudo modprobe i2c-dev
sudo apt-get install i2c-tools
Nun werden die Module sofort geladen und der wichtige Befehl i2cdetect installiert.

Wenn man sich ein wenig mit I²C beschäftigt fliegen einem ein paar weitere Begriffe wie 2-Wire/TWI und SMBus um die Ohren. I²C, TWI (Two Wire Interface) und SMBus (Service Message Bus) sind 2-Draht-Protokolle, welche untereinander weitgehend, für Taktfrequenzen bis 100 kHz, kompatibel sind.

Der FM-Tuner muss zuerst auf 2-Wire initialisiert werden, damit wir mit ihm sprechen können. Dies lässt sich einfach via GPIO bit-banging realisieren, und müssen dabei auch nicht schnell sein. Die Installation von wiringPi wird hier beschrieben.
/* i2c-init.c */
#include <wiringPi.h>

int main() {
    int resetPin = 23; // GPIO23
    int sdaPin = 0; // GPIO0

    /* Setup GPIO access in BCM mode */
    wiringPiSetupGpio();

    /* Set pins as output */
    pinMode(resetPin, OUTPUT);
    pinMode(sdaPin, OUTPUT);

    /* A low SDA indicates a 2-wire interface */
    digitalWrite(sdaPin, LOW);
    /* Put chip into reset */
    digitalWrite(resetPin, LOW); 
    /* 1ms delay to allow pins to settle */ 
    delay(1);
    /* Bring chip out of reset with SDIO set low
    and SEN pulled high (with pull-up resistor) */
    digitalWrite(resetPin, HIGH); 

    return 0;
}
Die Datei i2c-init.c wird nun kompiliert und ausgeführt:
gcc -o i2c-init i2c-init.c -lwiringPi
sudo ./i2c-init
Die Ausgabe von i2cdetect muss nun wie folgt aussehen:
$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: 10 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --  
Der Wert 0x10 stellt die Adresse des FM-Tuners dar und kann nicht geändert werden. Wir können ab jetzt auf die Register zugreifen, also den Chip steuern.

Ich habe dafür die Arduino Bibliothek von SparkFun für den RPi portiert, siehe hier.
Lässt man das Testprogramm "Radio" laufen, so sollte man in ausgezeichneter Qualität den Radiosender FM4 (104,0 Mhz) empfangen können =)

Welche 2-Wire-Funktionen der Chip wirklich unterstützt verrät uns folgender Befehl:
$ i2cdetect -F -y 1
Functionalities implemented by /dev/i2c-1:
I2C                              yes
SMBus Quick Command              yes
SMBus Send Byte                  yes
SMBus Receive Byte               yes
SMBus Write Byte                 yes
SMBus Read Byte                  yes
SMBus Write Word                 yes
SMBus Read Word                  yes
SMBus Process Call               yes
SMBus Block Write                yes
SMBus Block Read                 no
SMBus Block Process Call         no
SMBus PEC                        yes
I2C Block Write                  yes
I2C Block Read                   yes
Dies ist nur interessant, falls man selber Funktionen zum Zugriff auf die Register schreiben möchte.

to be continued ...