Teil 9: Analog-Digital-Wandler PCF8591

© Marc Torrell Faro, 123RF

Durchgestuft

Mit dem PCF8591 schlagen Sie eine Brücke zur analogen Welt. Allerdings will der Einsatz gut bedacht sein.

Bisher ging es in unserer Reihe zum I2C-Bus nur um rein digitale Halbleiterbausteine. Mit dem PCF8591 kommt nun zum ersten Mal ein A/D-D/A-Wandler ins Spiel. Dabei handelt es sich um einen relativ einfachen Wandler mit 8 Bit Auflösung, was für viele Anwendungen völlig genügt.

Der PCF8591 verfügt über vier analoge Eingänge sowie einen analogen Ausgang und kommt in einem bastlerfreundlichen DIL-16-Gehäuse daher (Abbildung 1). Der Chip verfügt über drei Adressleitungen, sodass Sie theoretisch an einem I2C-Bus acht dieser Bausteine betreiben können, die dann die Adressen 0x48 bis 0x4F belegen.

Abbildung 1: Das Pinout des PCF8591.

Der PCF8591 arbeitet in Bezug auf die Spannung in einem Bereich von 2,6 bis 6 Volt. Der Messbereich reicht von 0 Volt bis zur eigenen Betriebsspannung. Sie steuern alle Funktionen über ein Kontrollregister; die Tabelle "PCF8591: Steuerregister" zeigt die Bedeutung der einzelnen Bits.

PCF8591: Steuerregister

Bit

Funktion

0, 1

Auswahl des A/D-Kanals. 00: Kanal 0, 01: Kanal 1, 10: Kanal 2, 11: Kanal 3

2

Auto-Inkrement-Funktion (high = aktiv)

3

immer 0

4, 5

Programmieren der Analogkanäle (Details siehe Datenblatt)

6

Analog-Output aktivieren (high = aktiv)

7

immer 0

Die analogen Eingänge weisen einen maximalen Leckstrom von 100 Nanoampere auf – so wenig, dass es Messungen nur minimal verfälscht. Sie benötigen also keine zusätzlichen Operationsverstärker zur Impedanzwandlung der Analogeingänge. Für weitergehende Informationen empfiehlt sich ein Blick ins Datenblatt des Wandlers, der im Test in einem einfachen Versuch zum Einsatz kam.

Im Einsatz

Der Aufbau eines Schaltkreises mit dem Wandler erfordert nur wenige Komponenten. Die vier analogen Eingänge wurden für das Beispiel, wie im Schaltplan zu sehen, mit Potentiometern beschaltet. Mithilfe der Potis erzeugen Sie Analogwerte zwischen 0 Volt und der Betriebsspannung. Achten Sie bei der Auswahl der Potentiometer darauf, dass sie eine lineare Charakteristik aufweisen, keine logarithmische.

Potis mit linearer Charakteristik stellen deshalb eine bessere Wahl dar, weil bei ihnen eine bestimmte Winkeldifferenz immer einer festen Differenz der Spannung entspricht. Sie eignen sich also als Positionsgeber, weil sie in der Mittelstellung die Spannung genau halbieren. Potis mit logarithmischer Charakteristik dagegen kommen beispielsweise in Verstärkerstufen zum Einstellen der Lautstärke zum Einsatz, weil das menschliche Gehör eine logarithmische Charakteristik aufweist.

An den analogen Ausgang schließen Sie ein handelsübliches Multimeter an. Sie finden den kompletten Schaltplan (Abbildung 2) auch als gEDA- und EPS-Datei auf der Heft-DVD. Abbildung 3 zeigt den kompletten Versuchsaufbau. Um dessen Funktion zu testen, verwenden Sie das Tool I2cdetect (Listing 1).

Abbildung 2: Der Schaltplan unseres Versuchsaufbaus.
Abbildung 3: Der Testaufbau auf einem Prototyping Board.

Listing 1

 

$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Alternativ fragen Sie die einzelnen analogen Eingänge mithilfe des Werkzeugs I2cget ab (Listing 2). Der entsprechende Befehl wirkt auf den ersten Blick etwas komplex. Das liegt jedoch schlicht daran, dass Sie alle vier Kanäle hintereinander abfragen und der erste Messwert pro Kanal immer den Wert der vorherigen Messung liefert. Wie das zustande kommt, ist einfach zu erklären: Mit dem ersten Zugriff weisen Sie den Baustein an, einen neuen Wert zu messen. Der steht dann beim nächsten Zugriff im entsprechenden Register.

Listing 2

 

$ watch -n 0.5 '\
i2cget -y 1 0x48 0x40 > /dev/null; i2cget -y 1 0x48 0x40; \
i2cget -y 1 0x48 0x41 > /dev/null; i2cget -y 1 0x48 0x41; \
i2cget -y 1 0x48 0x42 > /dev/null; i2cget -y 1 0x48 0x42; \
i2cget -y 1 0x48 0x43 > /dev/null; i2cget -y 1 0x48 0x43'

Beim Ausprobieren sehen Sie hier schon, dass es zwischen den einzelnen Kanälen ein Übersprechen gibt. Bei einem Stückpreis von unter 3 Euro für den PCF8591 lassen sich solche Effekte aber kaum vermeiden – für hochwertigere Wandler müssen Sie wesentlich tiefer in die Tasche greifen.

Um einen Analogwert am Ausgang des PCF8591 zu erzeugen, verwenden Sie die Kommandos aus Listing 3.

Listing 3

 

$ i2cset -y 1 0x48 0x40 0x00
$ i2cset -y 1 0x48 0x40 0xff

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);
    }
  }
}

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 5 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Raspberry Pi Geek kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

Aktuelle Ausgabe

12/2019
RasPi-Alternativen

Diese Ausgabe als PDF kaufen

Preis € 9,99
(inkl. 19% MwSt.)

Stellenmarkt

Neuigkeiten

  • Grußbotschaften

    Mit Sonic Pi zaubern Sie komplexe Sounds, die Sie bei Bedarf sogar noch während des Abspielens modifizieren.

  • Das Runde und das Eckige

    Mit dem MCP4725 ergänzen Sie einen RasPi um einem D/A-Wandler, der bei Bedarf noch weitere Funktionen erfüllt.

  • Alles unter Kontrolle

    Schon ein einfaches Mikrocontrollerboard wie das CY8CKIT-049-42xx bietet erstaunlich viele Möglichkeiten beim Ansteuern von Hardware.

  • Viele Kerne

    Das Spresense Development Board von Sony lässt sich mit der Arduino IDE programmieren und bringt auch ein eigenes Entwickler-SDK mit.

  • Exotische Früchte

    Der aus China stammende Orange Pi positioniert sich mit einem guten Preis und interessanten Features gegen die RasPi-Truppe. Kann er sich auch behaupten?

  • Flexibler Surfer

    Mit dem neuen RasPi 4 setzen Sie einen öffentlichen Webkiosk schnell und kostengünstig auf.

  • Auskunftsfreudig

    Viele Devices, so auch der E.ON-Aura-Controller, verwenden eine Schnittstelle namens REST, um Zustandsdaten zu übermitteln. Mit ein wenig Bastelei lesen Sie diese auch über Ihr Smartphone aus.

  • Doppelt gemessen

    Mit wenig Aufwand und einem Pi Zero realisieren Sie einen mobilen Zweikanal-Spannungsprüfer.

  • Elegant zusammengeführt

    Tizonia streamt Musik von Online-Quellen und lokalen Sammlungen. Die schlanke Architektur macht den Player zur guten Wahl für den Einsatz auf dem RasPi.

  • Kommunikativ

    Nicht jeder traut sich zu, sein eigenes Smartphone zu bauen. Allerdings kann jeder Linux-Nutzer den Raspberry Pi im Handumdrehen zu einem VoIP-Telefon aufrüsten.