Blame view

RIOT/drivers/hih6130/hih6130.c 3.58 KB
a752c7ab   elopes   add first test an...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  /*
   * Copyright (C) 2015 Eistec AB
   *
   * This file is subject to the terms and conditions of the GNU Lesser
   * General Public License v2.1. See the file LICENSE in the top level
   * directory for more details.
   */
  
  /**
   * @ingroup     drivers_hih6130
   * @{
   *
   * @file
   * @brief       Device driver implementation for Honeywell HumidIcon Digital
   *              Humidity/Temperature Sensors: HIH-6130/6131 Series
   *
   * @author      Joakim Nohlgård <joakim.nohlgard@eistec.se>
   *
   * @}
   */
  
  #include <stddef.h>
  #include <stdint.h>
  
  #include "hih6130.h"
  #include "periph/i2c.h"
  #include "xtimer.h"
  
  #define ENABLE_DEBUG    (0)
  #include "debug.h"
  
  /* Humidity is stored in the first 2 bytes of data */
  #define HIH6130_HUMIDITY_DATA_LENGTH (2)
  /* Humidity + temperature data is 4 bytes long */
  #define HIH6130_FULL_DATA_LENGTH (4)
  /* Bit mask for the status bits in the first byte transferred */
  #define HIH6130_STATUS_MASK      (0xc0)
  /* Bit mask for the humidity data */
  #define HIH6130_HUMIDITY_MASK    (0x3fff)
  /* Temperature data is left adjusted within the word */
  #define HIH6130_TEMPERATURE_SHIFT (2)
  
  enum {
      HIH6130_STATUS_OK           = 0x00,
      /**
       * stale data: data that has already been fetched since the last measurement
       * cycle, or data fetched before the first measurement has been completed.
       */
      HIH6130_STATUS_STALE_DATA   = 0x40,
      HIH6130_STATUS_COMMAND_MODE = 0x80,
      HIH6130_STATUS_DIAGNOSTIC   = 0xc0,
  };
  
  /** @brief Delay between requesting a measurement and data becoming ready */
  #define MEASUREMENT_DELAY   (50LU * US_PER_MS)
  
  /** @brief Trigger a new measurement on the sensor */
  static inline int hih6130_measurement_request(const hih6130_t *dev)
  {
      i2c_acquire(dev->i2c);
  
      /* An empty write request triggers a new measurement */
      if (i2c_write_bytes(dev->i2c, dev->addr, NULL, 0) < 0) {
          i2c_release(dev->i2c);
          return -1;
      }
  
      i2c_release(dev->i2c);
  
      return 0;
  }
  
  void hih6130_init(hih6130_t *dev, i2c_t i2c, uint8_t address)
  {
      /* write device descriptor */
      dev->i2c = i2c;
      dev->addr = address;
  }
  
  static inline int hih6130_get_humidity_temperature_raw(const hih6130_t *dev, uint16_t *humidity_raw, uint16_t *temperature_raw)
  {
      int status;
      uint8_t buf[HIH6130_FULL_DATA_LENGTH];
  
      i2c_acquire(dev->i2c);
  
      if (i2c_read_bytes(dev->i2c, dev->addr, &buf[0], sizeof(buf)) != sizeof(buf)) {
          i2c_release(dev->i2c);
          return -1;
      }
  
      i2c_release(dev->i2c);
  
      /* data is in big-endian format, with status bits in the first byte. */
      switch (buf[0] & HIH6130_STATUS_MASK) {
          case HIH6130_STATUS_OK:
              status = 0;
              break;
          case HIH6130_STATUS_STALE_DATA:
              status = 1;
              break;
          default:
              return -2;
      }
  
      *humidity_raw    = ((buf[0] << 8) | buf[1]) & HIH6130_HUMIDITY_MASK;
      *temperature_raw = (((buf[2] << 8) | buf[3]) >> HIH6130_TEMPERATURE_SHIFT);
  
      return status;
  }
  
  int hih6130_get_humidity_temperature_float(const hih6130_t *dev,
      float *relative_humidity_percent, float *temperature_celsius)
  {
      uint16_t hum_raw, temp_raw;
      int status;
  
      if (hih6130_measurement_request(dev) != 0) {
          return -1;
      }
  
      xtimer_usleep(MEASUREMENT_DELAY);
  
      status = hih6130_get_humidity_temperature_raw(dev, &hum_raw, &temp_raw);
  
      if (status < 0) {
          return -1;
      }
  
      if (relative_humidity_percent != NULL) {
          *relative_humidity_percent = hum_raw * (100.f / 16383.f);
      }
      if (temperature_celsius != NULL) {
          *temperature_celsius = temp_raw * (165.f / 16383.f) - 40.f;
      }
  
      return status;
  }