Testprogramm
Damit beim Ausprobieren keine Langeweile aufkommt, greifen Sie im nächsten Beispiel zu einem in Java geschriebenen Testprogramm mit grafischer Oberfläche (Abbildung 4). Allerdings hat Oracle im JDK für die ARM-Architektur die JavaFX-Komponenten entfernt, sodass Sie auf das gute alte AWT zurückgreifen müssen. Wie schon im letzten Teil unserer I2C-Serie setzen wir wieder auf der Java-Umgebung aus Teil 6 der Reihe auf.

Abbildung 4: Das Frontend des kleinen Testprogramms macht auf den ersten Blick nicht viel her. Es genügt aber, um die Abläufe in der Hardware anzuzeigen.
Es gibt nun mehrere Möglichkeiten, ein Programm mit grafischer Oberfläche auf dem RasPi auszuführen. Die simpelste, aber am wenigsten effiziente besteht darin, direkt auf dem Mini-PC einen X-Server zu betreiben. Besser ist es, Sie leiten das Display des Raspberry Pi auf einen Desktop-PC um. Das erfordert nur wenige Schritte: Zunächst verbinden Sie sich vom Desktop-Rechner aus via SSH mit dem RasPi, um dort zu experimentieren. Nutzen Sie dabei die Option -X, leitet SSH die Ausgabe vom RasPi automatisch zum lokalen Rechner weiter.
Das klappt aber nur im Kontext desjenigen Nutzers, über dessen Account Sie die Verbindung aufgebaut haben. Das Werkzeug Pi4j verwendet beim Ausführen von Programmen die Rechte des Benutzers root. Der hat aber nicht die Berechtigung, das Display des Desktop-PCs zu verwenden. Deshalb greifen Sie zu einem Workaround: Sie nehmen die Pi4j-Bibliotheken in den Klassenpfad auf und starten das Programm direkt mit Java (Listing 4).
Listing 4
$ export CLASSPATH=$CLASSPATH:.:/opt/pi4j/lib/* $ javac pcf8591/Pcf8591.java $ java pcf8591/Pcf8591
Das Display auf einen Desktop-PC umzuleiten setzt voraus, dass darauf ein X-Server läuft. Linux und Mac OS X haben diesen in aller Regel schon betriebsbereit an Bord. Unter Windows weichen Sie auf einen freien X-Server wie Xming aus, den Sie dazu aus dem Netz herunterladen [2].
Das Testprogramm selbst (Listing 5) ist schnell erklärt: Mit dem Konstruktor bauen Sie ein Frontend mit AWT-Komponenten auf. An die zwei Schaltflächen hängen Sie einfache Event-Listener an, die das Programm aufruft, sobald Sie die Schaltflächen drücken. Der mit Exit beschriftete Button beendet das Programm. Drücken Sie I2C, dann kommunizieren Sie mit dem PCF8591 und sehen die Werte.
Die Klasse pcfListener dient lediglich dazu, auf das Event zum Schließen des Fensters zu reagieren. Das Eingabefeld für den Analogausgang nimmt einen Wert für den D/A-Wandler entgegen, ohne ihn zu prüfen.
Aktuell liest das Programm die Werte aus den Wandlerregistern aus. Das sagt jedoch noch nichts über die Spannungen aus. Möchten Sie wissen, welcher Spannung der Wert in den Registern entspricht, multiplizieren Sie ihn mit der Referenzspannung (3,3 Volt) und teilen ihn danach durch die Anzahl der Wandlerstufen (256 bei 8 Bit Auflösung). Ändern Sie die Referenzspannung, so beeinflusst das den Messbereich und damit die Genauigkeit.
Listing 5
package pcf8591;
import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CDevice;
import com.pi4j.io.i2c.I2CFactory;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Pcf8591 extends Frame {
Button exit = new Button("Exit");
Button i2c = new Button("I2C");
static TextField ain0= new TextField();
static TextField ain1= new TextField();
static TextField ain2= new TextField();
static TextField ain3= new TextField();
static TextField aout= new TextField("0");
int address=0x48;
public Pcf8591 () {
setTitle("PCF8591 AD DA Wandler");
setSize(300, 200);
addWindowListener(new pcfListener());
setLayout(new GridLayout(6, 2));
setVisible(true);
add(new Label("AIN0"));
add(ain0);
add(new Label("AIN1"));
add(ain1);
add(new Label("AIN2"));
add(ain2);
add(new Label("AIN3"));
add(ain3);
add(new Label("AOUT"));
add(aout);
exit.addActionListener(new ExitActionListener());
i2c.addActionListener(new I2cActionListener());
add(exit);
add(i2c);
pack();
}
public static void main(String[] args) {
new Pcf8591 ();
}
private class pcfListener extends WindowAdapter {
public void windowClosing(WindowEvent e) {
e.getWindow().dispose();
System.exit(0);
}
}
private class I2cActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int inValues[] = new int[4];
int outValue=0;
try {
I2CBus bus = I2CFactory.getInstance(I2CBus.BUS_1);
I2CDevice dev = bus.getDevice(address);
for (int i = 0; i <= 3; i++) {
dev.read((byte) (0x40 | (i & 3)));
inValues[i]=dev.read((byte) (0x40|(i&3)));
inValues[i]=dev.read();
System.out.println(inValues[i]);
}
Pcf8591.ain0.setText(String.valueOf(inValues[0]));
Pcf8591.ain1.setText(String.valueOf(inValues[1]));
Pcf8591.ain2.setText(String.valueOf(inValues[2]));
Pcf8591.ain3.setText(String.valueOf(inValues[3]));
outValue = Integer.parseInt("0"+aout.getText());
dev.write((byte) 0x40, (byte) outValue);
}
catch(Exception ex) {
System.out.println(ex.toString());
}
}
}
private class ExitActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
}
Fazit
Für den Einstieg in die analoge Welt eignet sich der PCF8591 bestens. Sie erhalten den Baustein günstig bei allen einschlägigen Elektronikhändlern. Durch die Kombination von vier analogen Eingängen (oder zwei im Differenzbetrieb) und einem analogen Ausgang lässt er sich in vielen Projekten einsetzen. Allerdings erscheint die 8-Bit-Auflösung des Wandlers nicht mehr ganz zeitgemäß, für den Einsatz in der Messtechnik arbeitet er etwas zu ungenau. Für Projekte, in denen Sie Analogwerte mit nicht ganz so hoher Genauigkeit erfassen wollen, stellt er aber eine passende Wahl dar.
Infos
- Datenblatt PCF8591: http://www.nxp.com/documents/data_sheet/PCF8591.pdf
- Xming (X-Server für Windows): http://sourceforge.net/projects/xming/





