Raspberry-Pi-Projekte: Temperatur- und Feuchtesensor HDC1008

Prof. Jürgen Plate

Raspberry Pi: Temperatur- und Feuchtesensor HDC1008

Allgemeines

Der HDC1008 von Texas Instruments ist ein digitaler Luftfeuchtigkeitssensor mit integriertem Temperatursensor, der eine exzellente Messgenauigkeit bei sehr geringer Leistungsaufnahme bietet (wenige Mikroampere). Die Messung der Luftfeuchtigkeit erfolgt mithilfe eines neuartigen kapazitiven Sensors. Die Luftfeuchtigkeits- und Temperatursensoren sind werkseitig kalibriert. Mit ihrem ultrakompakten Gehäuse ermöglicht die innovative WLCSP-Ausführung (Wafer-Level-CSP-Gehäuse) eine einfachere Auslegung. Das Sensorelement des HDC1008 befindet sich im unteren Teil der Komponente, wodurch der HDC1008 besser vor Schmutz, Staub und anderen Umweltschadstoffen geschützt ist. Der HDC1008 ist für Temperaturbereiche von -40 °C bis +125 °C spezifiziert. Er wird über ein I2C-Interface angebunden. Der Sensor kann an 3,3-V- oder 5-V-Systemen genutzt werden.


Aufbau des HDC1008

Bei Watterott oder Adafruit wird ein sogenanntes Breakout-Board angeboten, auf dem der Sensor aufgelötet ist und das den Anschluss über eine Stiftleiste oder dergleichen ermöglicht. Über Jumper kann die 2-Bit-Adresse des Sensors im Bereich von 0x40 bis 0x43 eingestellt werden. Ohne I2C-Multiplexer oder Abschaltung einzelner Sensoren können also bis zu vier Sensoren parallel betrieben werden (siehe Bild Jumper beim Watterott-Breakout-Board).


Die Breakout-Boards von Watterott und Adafruit

Das HDC1008-Breakout-Board hat folgende Features:

Für den Arduino (die IC-Anschlüsse befinden sich beim Arduino Uno auf den Pins A4 = SDA und A5 = SCL) bietet Adafruit eine Bibliothek an, die nur heruntergeladen und installiert werden muss. Bei Raspberry Pi muss man selbst tätig werden. Mit Python oder C kommt man recht schnell zu einem lauffähigen Ergebnis (siehe unten). Die Verdrahtung zwischen Board und RasPi ist recht einfach, es werden nur vier Leitungen benötigt:

PinSignal
13,3 V
3SDA
5SCL
6GND

Die Umrechnung der 14-Bit-Werte des Sensors in Temperatur und Feuchte erfolgt mit den folgenden Gleichungen, wobei das [15:00] nichts weiter bedeutet, als dass es sich um eine 16-Bit-Wert (Bits 15 bis 0) handelt:

Software

Wie schon gesagt, sind beide Programme zum Auslesen des Sensors recht kurz und kompakt. Das Python-Programm braucht nur Standardbibliotheken, insbesondere "io" und "fcntl". Es werden zwei Filehandles geöffnet, fr zum Lesen und fw zum Schreiben direkt auf das Device. Mittels fcntl.ioctl wird die Adresse des Sensors festgelegt. Das Breakout-Board von Watterott ist per Default auf 0x43 eingestellt. Wer etwas anderes nimmt oder die Adresse geändert hat, muss die Knstante HDC1008_ADDR anpassen oder das Programm erweitern, damit es die Adresse beispielsweise von der Kommadozeile entgegennimmt. Insbesondere sind die Wartezeiten einzuhalten, die im Datenblatt angegeben sind.

#!/usr/bin/python
import struct, array, time, io, fcntl

I2C_SLAVE=0x0703

# select address according to jumper setting
# address  (40,41,42,43) can be found with
# sudo i2cdetect -y 1
HDC1008_ADDR = 0x43

bus = 1
fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
fw = io.open("/dev/i2c-"+str(bus), "wb", buffering=0)

# set device address
fcntl.ioctl(fr, I2C_SLAVE, HDC1008_ADDR)
fcntl.ioctl(fw, I2C_SLAVE, HDC1008_ADDR)
time.sleep(0.015) # 15ms startup time

# set config register
s = [0x02,0x02,0x00]
s2 = bytearray(s)
fw.write(s2) #sending config register bytes
time.sleep(0.015) # From the data sheet

# read temperature
s = [0x00]
s2 = bytearray(s)
fw.write(s2)
time.sleep(0.0625) # From the data sheet
data = fr.read(2)  # read 2 byte temperature data
buf = array.array('B', data)
temp = ((((buf[0]<<8) + (buf[1]))/65536.0)*165.0) - 40.0
print ("Temperatur:  %7.2f" % temp)
time.sleep(0.015)  # From the data sheet

# read humidity
s = [0x01]
s2 = bytearray(s)
fw.write(s2)
time.sleep(0.0625) # From the data sheet
data = fr.read(2)  # read 2 byte temperature data
buf = array.array('B', data)
humid = ((((buf[0]<<8) + (buf[1]))/65536.0)*100.0)
print ("Luftfeuchte: %7.2f%%" % humid)

Auch das C-Programm ist nicht viel länger, wobei hier mehr Konstante definiert werden müssen. Es verfolgt auch einen etwas anderen Ansatz: es wird die wiringPi-Bilbliothek verwendet, um eine gewisse Hardware-Abstraktion erhalten. Gelesen und geschrieben wird jedoch mit den Standard-Low-Level-Routinen red()write(). In der Initialisierungs-Funktion werden zuerst die tt>wirigPi-Bibliothek und dann der Sensor initialisiert. Auch bei dem C-Beispiel ist die Sensoradresse durch eine Konstante festgelegt, die ggf. geändert werden muss (oder Angabe über die Kommandozeile ist zu programmieren). Den Kern bildet die Funktion i2c_read16(), die ein Kommandobyte (reg) sendet und dann einen 16-Bit-Wert in der richtigen Byte-Reihenfolge zurückgibt (ntohs aus arpa/inet.h). In HDC1000_readTemperature() bzw. HDC1000_readHumidity() wird der Rückgabewert jeweils in einer Double-Variablen gespeichert und dann nach den obigen Formeln umgerechnet.

#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>

/* change address to 40, 41, 42, 43
   accordig to jumper setting on breakout board
*/
#define HDC1000_I2CADDR      0x43

/* Definitions for HDC1008 chip */
#define HDC1000_TEMP         0x00
#define HDC1000_HUMID        0x01
#define HDC1000_CONFIG       0x02
#define HDC1000_GFG_MODE     0x1000
#define HDC1000_GFG_RST      0x8000
#define HDC1000_GFG_TRES_14  0
#define HDC1000_GFG_HRES_14  0
#define HDC1000_MANUFID      0xFE
#define HDC1000_DEVICEID     0xFF
#define HDC1000_MANUF_RET    0x5449
#define HDC1000_DEVICE_RET   0x1000

uint16_t i2c_read16(int fd, uint8_t reg)
  /* read 16 bit value from selected register */
  {
  uint16_t retval;
  write(fd, ®, 1);
  delay(50);
  read(fd, &retval, 2);
  return ntohs(retval);
  }

int HDC1000_Init(uint8_t addr)
  {
  /* init wiringPi I2C and HDC1008 chip */
  uint32_t x;
  int fd = wiringPiI2CSetup(addr);
  if (fd == -1)
    {
    printf("wiringPiI2CSetup for HDC1008 failed\n");
    return -1;
    }

  /* reset, and select 14 bit temp & humidity */
  uint16_t config =  HDC1000_GFG_RST | HDC1000_GFG_MODE | HDC1000_GFG_TRES_14 | HDC1000_GFG_HRES_14;
  write(fd, &config, HDC1000_CONFIG);
  delay(50);

  /* read manufacture id and devce id, check for HDC1008 */
  x = i2c_read16(fd,HDC1000_MANUFID);
  if (x != HDC1000_MANUF_RET)
    {
    printf("Manufacture Id returned %4X\n",x);
    return -1;
    }
  x = i2c_read16(fd,HDC1000_DEVICEID);
  if (x != HDC1000_DEVICE_RET)
    {
    printf("Device Id returned %4X\n",x);
    return -1;
    }
  return fd;
  }

float HDC1000_readTemperature(int fd)
  {
  /* read temperature out of register 00
     refer to data sheet
  */
  double temp = 1.0*i2c_read16(fd, HDC1000_TEMP);
  temp /= 65536.0;
  temp *= 165.0;
  temp -= 40;
  delay(625);
  return temp;
  }

float HDC1000_readHumidity(int fd)
  {
  /* read humidity out of register 01
     refer to data sheet
  */
  double hum = 1.0*i2c_read16(fd, HDC1000_HUMID);
  hum /= 65536;
  hum *= 100;
  delay(625);
  return hum;
  }

int main()
  {
  int fd;
  double xc, xh;

  fd = HDC1000_Init(HDC1000_I2CADDR);
  if (fd == -1)
    {
    printf("HDC1000_Init failed\n");
    return 0;
    }

  xc = HDC1000_readTemperature(fd);
  printf("Temperatur:  %7.2f\n", xc);
  xh = HDC1000_readHumidity(fd);
  printf("Luftfeuchte: %7.2f%%\n", xh);

  return 0;
  }

Die gefühlte Temperatur

Jeder hat schon in einem Wetterbericht den Begriff "Windchill" oder "gefühlte Temperatur" gehört. Damit soll berücksichtigt werden, dass bei starkem Wind die von einem Menschen gefühlte Temperatur niedriger sein kann als die tatsächliche Temperatur.

Die Lufttemperatur, die wir empfinden, wird als "gefühlte Temperatur" bezeichnet. Diese gefühlte Lufttemperatur ist von vielen Faktoren abhängig, beispielsweise

Die "gefühlte Temperatur" ist damit von Mensch zu Mensch sehr unterschiedlich. Es gibt, neben den oben genannten, weitere Parameter, die hier eine Rolle spielen. Sogar eine Hautcreme kann das Temperaturempfinden verändern. Dann gibt es eine genetisch verankerte Widerstandsfähigkeit gegenüber tiefen Temperaturen, und auch der geschlechtsspezifische Unterschied ist unübersehbar. Frauen frieren meist schneller als Männer. So gibt es nicht nur eine Definitionen für die "gefühlte Temperatur".

Die Angabe der "gefühlten Temperatur" im Wetterbericht bezieht sich auf einen Modell-Menschen. Der Deutsche Wetterdienst verwendet dazu das Klima-Michel-Modell. Dies ist ein computersimulierter Durchschnittsmensch mit folgenden Eigenschaften: Es ist ein 35 Jahre alter und 1,75 Meter großer Mann mit einem Körpergewicht von 75 Kilogramm, der sich mit ca. 5 km/h im Freien fortbewegt und der Witterung entsprechend gekleidet ist.

Man kann die gefühlte Temperatur nach der folgenden, relativ einfachen Formel ausrechnen, in die nur die tatsächliche Temperatur (t) in Grad Celsius und die Windgeschwindigkeit (v) in km/h eingehen. Der Windchill (W) in Grad Celsius ergibt sich aus:

W = 13,12 + 0,6215 * t – 11,37 * v0,16 + 0,3965 * t * v0,16
Ein Beispiel dazu: Bei einer Temperatur von –5 Grad Celsius und einer Windgeschwindigkeit von 15 Kilometer pro Stunde beträgt die gefühlte Temperatur rund –11 Grad Celsius.

Links


Copyright © Hochschule München, FK 04, Prof. Jürgen Plate und die Autoren
Letzte Aktualisierung: