Datenlogger mit Messverstärker

© Dejan Veljkovic, 123RF

Heißkalt serviert

Wie verwandelt sich ein Linux-System auf einem RasPi in einen Datenlogger? Indem es mit einem Bluetooth-fähigen Multimeter spricht.

Viele Microcontroller bringen von Haus aus einen Analog/Digital-Wandler mit. Der Einplatinencomputer Raspberry Pi besitzt zumindest einige digitale Ein- und Ausgänge, über die Sie externe A/D-Wandler ansteuern; bei neueren PCs suchen Sie solche Schnittstellen vergeblich.

Allerdings misst kaum jemand Spannungen lediglich im Bereich von 0 bis 5 Volt (Arduino) oder 0 bis 3,3 Volt (Raspberry Pi). Gefordert ist also ein Verstärker, der nicht nur Spannungen von 500 Volt positiv oder negativ verträgt, sondern zusätzlich Ströme, Kapazitäten, Widerstände oder Temperaturen misst.

Vielfachinstrumente gibt es für kleines Geld, seit wenigen Jahren sinken die Preise für Bluetooth-Module drastisch. Das Gerät Owon B35T der Firma Lilliput kombiniert beides (Abbildung 1). Als Software verweist der Hersteller auf seine Apps für Android und iOS, die die Messwerte des Multimeters auslesen und anzeigen. Auf die Frage, ob ein Koppeln mit einem Rechner möglich ist, gibt er sich ahnungslos.

Abbildung 1: Ein geöffnetes Owon-B35T-Multimeter mit dem aufgelöteten BLE-Modul oben links.

Das Gerät macht den Eindruck, als hätte der Hersteller das Bluetooth-Modul nachträglich zu einem bestehenden Messgerät hinzugefügt. Es überträgt ausschließlich Daten und steuert nicht das Gerät selbst.

Bluetooth mit PC

Trotz der Namensgleichheit umfasst Bluetooth zwei völlig unterschiedliche Protokolle: das normale Bluetooth und ab Version 4.0 zusätzlich Bluetooth Low Energy, kurz BLE. Nähere Informationen liefert das Programm Hciconfig – HCI steht hier für Host Controller Interface für Bluetooth (Listing 1).

Es findet zwei Controller, einen eingebauten (HCI-0) und einen Dongle (HCI-1), die sich deutlich voneinander unterscheiden (Listing 2): Das eingebaute Interface HCI-0 ist zu alt und kennt kein BLE, nur Bluetooth 3.0. Anders der aufgesteckte Dongle HCI-1, der auch Bluetooth 4.0 unterstützt.

Listing 1

 

$ hciconfig
hci1: Type: BR/EDR  Bus: USB
      BD Address: 00:2b:33:5A:62:22  ACL MTU: 310:10  SCO MTU: 64:8
      UP RUNNING
      RX bytes:688 acl:0 sco:0 events:49 errors:0
      TX bytes:3429 acl:0 sco:0 commands:49 errors:0
hci0: Type: BR/EDR  Bus: USB
      BD Address: 40:F8:1A:BC:F6:4A  ACL MTU: 1021:8  SCO MTU: 64:1
      DOWN
      RX bytes:7530 acl:100 sco:0 events:361 errors:0
      TX bytes:13138 acl:101 sco:0 commands:264 errors:0

Listing 2

 

$ hciconfig hci0 version
< HCI Command: Read Local Version Information (0x04|0x0001) plen 0
> HCI Event: Command Complete (0x0e) plen 12
      Read Local Version Information (0x04|0x0001) ncmd 1
        Status: Success (0x00)
        HCI version: Bluetooth 3.0 (0x05) - Revision 517 (0x0205)
...
$ hciconfig hci1 version
< HCI Command: Read Local Version Information (0x04|0x0001) plen 0
> HCI Event: Command Complete (0x0e) plen 12
      Read Local Version Information (0x04|0x0001) ncmd 1
        Status: Success (0x00)
        HCI version: Bluetooth 4.0 (0x06) - Revision 8891 (0x22bb)
...

Der Befehl hcitool scan listet die MAC-Adresse aller normalen Bluetooth-Geräte (Listing 3, erster Aufruf). Mit der Option lescan (low energy scan) liefert Hcitool die Geräte mit BLE-Kennung, sofern sie sich im sogenannten Advertising Mode befinden. Im Beispiel findet die Software das Handy und den RasPi nur im normalen Bluetooth-Modus, während die Geräte mit dem Verweis unknown ausschließlich im BLE-Mode funken (zweiter Aufruf).

Listing 3

 

$ sudo hcitool scan
Scanning ...
        24:51:7A:B3:AC:21       Samsung Galaxy S7
        40:F8:1A:BC:F6:4A       PC
        28:A7:E3:E2:2A:87       raspberrypi
$ sudo hcitool lescan
LE Scan ...
    76:72:AD:1B:A0:31 (unknown)
    7D:3B:9B:8A:A4:B3 (unknown)
    EA:E6:C2:A5:17:35 (unknown)
    EA:E6:C2:A5:17:35 OWON B35T

Die Python-Bibliothek Bluepy unterstützt die Kommunikation zwischen der Skriptsprache und entsprechenden Geräten [2]. Sie bringt das Programm blescan mit, mit dem Sie die Stärke des Signals messen (Listing 3). Der Parameter -i=1 ist nur dann erforderlich, wenn Sie nicht den Adapter hci0 ansprechen.

Sofern nicht anders angegeben, genügen die Versionen der Programme, wie sie im jeweiligen Repository vorliegen. Python-Skripte in diesem Beitrag basieren ausschließlich auf Python 3. Zur Erinnerung: Python 2.x erhält nur noch bis zum Jahr 2020 Support [3]. Sofern beide Versionen auf dem Rechner laufen, sollten Sie gegebenenfalls die erforderlichen Bibliotheken nicht über Pip, sondern Pip3 nachinstallieren.

Listing 4

 

$ sudo blescan -i=1
Scanning for devices...
  Device (new): e0:e5:cf:25:c8:66 (public), -51 dBm
    Flags: <06>
    0x12: <08000800>
    Tx Power: <00>
    Complete Local Name: 'OWON B35T'

Hier und im Folgenden benötigen Sie die Python-Bibliothek nicht unbedingt, siehe Listing 5, Zeilen 1 und 6. Die Stärke ist mit -54 dBm (RSSI, Received Signal Strength Indication) recht hoch. In zehn Metern Abstand sinkt sie auf -80 dBm. Bei ungefähr -85 dBm reißt die Verbindung ab, abhängig von der Empfindlichkeit des Empfängers.

Listing 5

 

$ sudo btmon &
[2] 6159
Bluetooth monitor ver 5.37
= New Index: 00:2b:33:5A:62:22 (BR/EDR,USB,hci1)                [hci1] 0.064000
[...]
$ sudo hcitool lescan
< HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7      [hci1] 9.817539
[...]
EA:E6:C2:A5:17:35 (unknown)
> HCI Event: LE Meta Event (0x3e) plen 15                       [hci1] 9.906668
    LE Advertising Report (0x02)
      Num reports: 1
        Event type: Connectable undirected - ADV_IND (0x00)
        Address type: Public (0x00)
        Address: EA:E6:C2:A5:17:35 (Texas Instruments)
        Data length: 3
        Flags: 0x06
          LE General Discoverable Mode
          BR/EDR Not Supported
        RSSI: -54 dBm (0xca)
EA:E6:C2:A5:17:35 (unknown)

Bluetooth ersetzt Kabel durch eine Funkverbindung. Daten fließen zwischen genau zwei Geräten erst dann, wenn Sie diese miteinander verbinden. Das Programm Gatttool steuern Sie über eine Python-Bibliothek, was Bluepy entbehrlich macht. GATT steht für Generic Attribute Profile, über die Software beeinflussen Sie die BLE-Parameter. Dank des einfachen Aufbaus des Protokolls beim Multimeter Owon B35T genügen wenige Grundbegriffe, um an die Messdaten zu gelangen.

Der Aufruf aus der ersten Zeile von Listing 6 startet das Programm, als Parameter übergeben Sie die MAC-Adresse des Multimeters (aus Listing 3). In Zeile 3 wartet gatttool auf Anweisungen. Der Befehl connect stellt eine Punkt-zu-Punkt-Verbindung zum Messgerät her. Manchmal dauert es mehrere Sekunden, bis das Tool den Erfolg mit Connection successful quittiert.

Listing 6

 

$ sudo gatttool -b EA:E6:C2:A5:17:35 -I
[EA:E6:C2:A5:17:35][LE]> connect
Attempting to connect to EA:E6:C2:A5:17:35
Connection successful
[EA:E6:C2:A5:17:35][LE]> char-read-uuid 00002a00-0000-1000-8000-00805
handle: 0x0003   value: 4c 49 4c 4c 49 50 55 54
[EA:E6:C2:A5:17:35][LE]> char-read-uuid 0x2a00
handle: 0x0003   value: 4c 49 4c 4c 49 50 55 54
[EA:E6:C2:A5:17:35][LE]> char-read-hnd 0x0003
Characteristic value/descriptor: 4c 49 4c 4c 49 50 55 54
Notification handle = 0x002e value: 2b 30 30 32 34 20 30 00 00 00 02 00 0d 0a
Notification handle = 0x002e value: 2b 30 30 32 33 20 30 00 00 00 02 00 0d 0a

BLE-Geräte stellen sogenannte Services bereit und identifizieren diese über 128 Bit (32 Byte) lange eindeutige Ziffernfolgen (UUID, Universally Unique Identifier). Auch Variablen, die sogenannten Characteristics, sprechen Sie über solche UUIDs an. Sie lesen sie auf diese Weise aus oder setzen die Werte; unser Beispiel beschränkt sich auf das Auslesen.

Der Befehl char-read-uuid in Zeile 7, gefolgt von der UUID, liefert zwei Werte zurück: ein Handle, etwa zu vergleichen mit einem symbolischen Namen, und eine Zeichenkette. Die Ziffernfolge 0x2a00 genügt bereits als Eingabe, da diese Characteristic standardisiert ist: Sie benennt den Hersteller. Mit dem symbolischen Handle 0x0003 gelingt die Abfrage ebenfalls. Interpretiert man die Ziffern als hexadezimale ASCII-Zeichen, lautet der Text "LILLIPUT" – der Name der Inhaberin der Marke Owon.

Ohne weiteres Zutun registriert Gatttool fortlaufend sogenannte Notifications. Bei diesen Zeichenketten handelt es sich um die gesuchten Werte des Messgeräts. Die Ziffern der Anzeige (mit Vorzeichen) stehen am Anfang der 14 Bytes. Etwas mehr Mühe macht das Zuordnen der restlichen Bits.

Datenerfassung mit Python

Das Programm empfängt zwei- bis dreimal pro Sekunde 14 Bytes für den Messwert und die Einstellungen des Geräts. Listing 6 zeigt am Schluss exemplarisch die Zeichenfolge 2b 30 30 32 33 20 30 00 00 00 02 00 0d 0a.

Legen Sie nun den ASCII-Zeichensatz zugrunde, lautet die Ziffernfolge der Bytes von 0 bis 4 "+ 0 0 2 3". Byte 10 kodiert die Einheit, hier die Ziffer 0x02 für Grad Celsius. Demnach misst das Multimeter gerade eine Temperatur von 23 Grad Celsius.

Byte 6 kodiert die Kommastelle der Anzeige, Byte 9 das Präfix der Einheit, die Bytes 7 und 8 den Rest – etwa Gleich- oder Wechselspannung, Minimum/Maximum oder einen niedrigen Ladestand der internen Batterie des Geräts.

Die Bibliothek Pexpect weist Python an, Eingaben in der Konsole zu simulieren. Mit ihr beauftragen Sie die Skriptsprache, Gatttool aufzurufen und die zurückgelieferten Daten zu lesen und auszuwerten. Sie installieren das Programm mit dem Aufruf sudo pip3 install pexpect.

In der fünften Zeile von Listing 7 übermittelt Python den Befehl gatttool -b EA:E6:C2:A5:17:35 -I so, als käme er direkt aus einem Terminal. Meldet sich Gatttool zurück, sendet Python den Befehl, sich mit dem Gerät zu verbinden (Zeile 6). In der Schleife wartet das Programm auf Ausgaben, die neben den Messwerten die Zeichenkette Notification handle enthalten (Listing 6), um sie anschließend auszugeben (Listing 8).

Listing 7

 

import pexpect
device_owon= 'EA:E6:C2:A5:17:35'
gattinst = pexpect.spawn("gatttool -b {} -I".format(device_owon))
gattinst.sendline("connect")
while True:
    gattinst.expect("Notification handle", timeout=2)
    print(gattinst.before)

Listing 8

 

b' = 0x002e value: 2b 30 30 32 32 20 30 00 00 00 02 00 0d 0a \r\n\x1b[0;94m[EA:E6:C2:A5:17:35]\x1b[0m[LE]> \r\x1b[K'

Die Fleißarbeit besteht darin, die Informationen zu extrahieren und aufzubereiten. Listing 9 zeigt ein einfaches Skript in Python, das diese Aufgabe übernimmt. Der Einfachheit halber verzichtet es auf das Dekodieren der Bytes 7 und 8.

Listing 9

 

# -*- coding: utf-8 -*-
'''
Daten von Owon B35T Multimeter über Bluetooth BLE einlesen.
Ausgabe:
  outstr: Textstring einschließlich Einheit
  datax: Zeitpunkt der Messung in Sekunden seit Start des Programms
  datay: Messwert als Zahl
'''
import pexpect
import time
device_owon= 'EA:E6:C2:A5:17:35'
logdata = 'datalog.txt'
def formatinput(a, test=False):
  prefixlist = {0: '' , 4: "ov", 8: "Diode", 16: 'M',  32: 'k', 64: 'm', 128: 'u', 2: 'n'}
  unitlist = {1: 'F', 2: '°C',  4: 'F', 8: 'Hz', 16: 'hFE', 32: 'Ohm', 64: 'A', 128: 'V'}
  expolist = {0: 1., 1: 1000., 2: 100., 4: 10.}  # 30, 31, 32, 34-> 0000, 0.000, 00.00, 000.0
  modelist = {48: "DC auto", 40: "AC auto", 16: "DC man", 8: "AC man", 32: "", 0: ""}
  multlist  = {0: 1, 4: 1, 16: 1e6, 32: 1e3, 64: 1e-3, 128: 1e-6, 2: 1e-9}
  data=a.split(b'\r')[0].split(b'value: ')[1][:-1].split(b' ')
  c=[chr(int('0x'+str(x.decode('ascii')),16)) for x in data]
  if len(c) != 14:
    return["Wait for data", 0, 0]
  values=c[0:5]
  expo=int(c[6])
  mode=ord(c[7])
  prefix=ord(c[9])
  unit= ord(c[10])
  val=''.join(values)
  try:
    val1=int(val)
    val1 /=expolist.get(expo,1)
    datay = val1 * multlist.get(prefix, 1)
  except:
    # probably overflow
    val1=9999
    datay= 9999
  # Ohne folgende Korrektur würde "F! statt "nF" als Einheit ausgegeben
  if (unit == 4) and (prefix == 0):
    prefix= 2
  prefixo=prefixlist.get(prefix)
  unito=unitlist.get(unit)
  modesel= modelist.get(mode&56, '')
  datax= round(time.time()-now, 1)
  outstr='{:7.3f}  {:1}{:3}  {:5s}'. format(val1, prefixo, unito, modesel)
  return[outstr, datax, datay]
def init():
  global gattinst, now
  now = time.time()
  print('Initialization')
  gattinst = pexpect.spawn("gatttool -b {} -I".format(device_owon))
  gattinst.sendline("connect")
  # drop first 14 input lines
  for i in range(4):
    gattinst.expect("handle", timeout=3)
    #print("1. ", gattinst.before)
def mloop():
  print('Time in seconds after start, reading and unit')
  print('Write time and reading to file', logdata)
  with open(logdata,'w',encoding='utf8') as f:
    # nur Daten, die sich um mehr als deltay unterscheiden
    # werden gespeichert.
    deltay=0    # Wenn 0, werden alle Daten gespeichert
    oldval=0
    while True:
      try:
        gattinst.expect("handle", timeout=2)
        outp= (formatinput(gattinst.before))
        if outp[1] != 0:
          if abs(outp[2]-oldval) >= deltay:
            print("* {}, {}".format(outp[1], outp[2]))
            f.write("{}, {} <br>\n".format(outp[1], outp[2]))
            f.flush()
            oldval=outp[2]
          else:
            print("  {} {}". format(outp[1], outp[0]))
      except pexpect.exceptions.TIMEOUT:
        pass
        print('timeout')
        break
      except KeyboardInterrupt:
        print("interrupt")
        break
    print('Terminated')
init()
mloop()

Wie schon in Listing 7 initialisiert auch das Python-Skript in Listing 9 das Loggen mit einer kleinen Schleife, um die Synchronisation der Daten zu gewährleisten. Die Schleife mloop() schreibt kontinuierlich in die Datei logdata. Um bei einem Abbruch durch einen Timeout (keine Daten vom Messgerät) oder über [Strg]+[C] keine Werte zu verlieren, fängt die Software solche Ereignisse ab und schließt die Datei ordnungsgemäß. Den Flush-Befehl benötigen Sie nur, wenn Sie Daten während des Messens aus der Datei lesen möchten.

Das Unterprogramm formatinput() definiert zunächst mehrere Dictionaries zum Übersetzen der Werte – teils, um die Anzeige zu dekodieren, teils, um die Werte in eine Zahl mit der richtigen Dimension umzurechnen. Es formatiert den Eingabestring und gibt drei Werte zurück: eine Zeichenkette mit Messwert und Einheiten, den Zeitpunkt der Messung in Sekunden und den Messwert als Zahl (Abbildung 2).

Abbildung 2: Drahtlos überträgt das Multimeter seine Daten entweder über einen modernen Bluetooth-Dongle direkt zum PC oder zunächst an einen Raspberry Pi.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 9 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.