Blame view

RIOT/drivers/dht/dht.c 3.97 KB
fb11e647   vrobic   reseau statique a...
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  /*
   * Copyright 2015 Ludwig Knüpfer
   *           2015 Christian Mehlis
   *           2016 Freie Universität Berlin
   *
   * 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_dht
   * @{
   *
   * @file
   * @brief       Device driver implementation for the DHT 11 and 22
   *              temperature and humidity sensor
   *
   * @author      Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
   * @author      Christian Mehlis <mehlis@inf.fu-berlin.de>
   * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
   *
   * @}
   */
  
  #include <stdint.h>
  #include <string.h>
  
  #include "log.h"
  #include "xtimer.h"
  #include "timex.h"
  #include "periph/gpio.h"
  
  #include "dht.h"
  #include "dht_params.h"
  
  #define ENABLE_DEBUG    (0)
  #include "debug.h"
  
  #define PULSE_WIDTH_THRESHOLD       (40U)
  
  /**
   * @brief   Allocation of memory for device descriptors
   */
  dht_t dht_devs[DHT_NUMOF];
  
  static uint16_t read(gpio_t pin, int bits)
  {
      uint16_t res = 0;
  
      for (int i = 0; i < bits; i++) {
          uint32_t start, end;
          res <<= 1;
          /* measure the length between the next rising and falling flanks (the
           * time the pin is high - smoke up :-) */
          while (!gpio_read(pin));
          start = xtimer_now_usec();
          while (gpio_read(pin));
          end = xtimer_now_usec();
          /* if the high phase was more than 40us, we got a 1 */
          if ((end - start) > PULSE_WIDTH_THRESHOLD) {
              res |= 0x0001;
          }
      }
      return res;
  }
  
  void dht_auto_init(void)
  {
      for (unsigned i = 0; i < DHT_NUMOF; i++) {
          if (dht_init(&dht_devs[i], &dht_params[i]) < 0) {
              LOG_ERROR("Unable to initialize DHT sensor #%i\n", i);
          }
  #ifdef MODULE_SAUL_REG
          for (int j = 0; j < 2; j++) {
              dht_saul_reg[i][j].dev = &dht_devs[i];
              saul_reg_add(&dht_saul_reg[i][j]);
          }
  #endif
      }
  }
  
  int dht_init(dht_t *dev, const dht_params_t *params)
  {
      DEBUG("dht_init\n");
  
      memcpy(dev, params, sizeof(dht_t));
  
      if (gpio_init(dev->pin, GPIO_OUT) == -1) {
          return -1;
      }
      gpio_set(dev->pin);
  
      xtimer_usleep(2000 * MS_IN_USEC);
  
      DEBUG("dht_init: success\n");
      return 0;
  }
  
  int dht_read(dht_t *dev, int16_t *temp, int16_t *hum)
  {
      uint8_t csum, sum;
      uint16_t raw_hum, raw_temp;
  
      /* send init signal to device */
      gpio_clear(dev->pin);
      xtimer_usleep(20 * MS_IN_USEC);
      gpio_set(dev->pin);
      xtimer_usleep(40);
  
      /* sync on device */
      gpio_init(dev->pin, dev->in_mode);
      while (!gpio_read(dev->pin)) ;
      while (gpio_read(dev->pin)) ;
  
      /*
       * data is read in sequentially, highest bit first:
       *  40 .. 24  23   ..   8  7  ..  0
       * [humidity][temperature][checksum]
       */
  
      /* read the humidity, temperature, and checksum bits */
      raw_hum = read(dev->pin, 16);
      raw_temp = read(dev->pin, 16);
      csum = (uint8_t)read(dev->pin, 8);
  
      /* set pin high again - so we can trigger the next reading by pulling it low
       * again */
      gpio_init(dev->pin, GPIO_OUT);
      gpio_set(dev->pin);
  
      /* validate the checksum */
      sum = (raw_temp >> 8) + (raw_temp & 0xff) + (raw_hum >> 8) + (raw_hum & 0xff);
      if ((sum != csum) || (csum == 0)) {
          DEBUG("error: checksum invalid\n");
          return -1;
      }
  
      /* parse the RAW values */
      DEBUG("RAW values: temp: %7i hum: %7i\n", (int)raw_temp, (int)raw_hum);
      switch (dev->type) {
          case DHT11:
              *temp = (int16_t)((raw_temp >> 8) * 10);
              *hum = (int16_t)((raw_hum >> 8) * 10);
              break;
          case DHT22:
              *hum = (int16_t)raw_hum;
              /* if the high-bit is set, the value is negative */
              if (raw_temp & 0x8000) {
                  *temp = (int16_t)((raw_temp & ~0x8000) * -1);
              }
              else {
                  *temp = (int16_t)raw_temp;
              }
              break;
          default:
              return -2;
      }
  
      return 0;
  }