atMETEO
An ATmega based weather station
dht22.h
Go to the documentation of this file.
1 /*
2  * atMETEO - An ATmega based weather station
3  * Copyright (C) 2014-2015 Christian Fetzer
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #pragma once
21 
36 #include "lib/utils.h"
37 
38 #include "pin.h"
39 
40 namespace Avr
41 {
42 
54 template <typename TPin>
55 class Dht22
56 {
57 public:
65  bool isValid() const { return m_valid; }
66 
74  float temperature() const {
75  return m_temperature;
76  }
77 
85  float humidity() const {
86  return m_humidity;
87  }
88 
95  bool read()
96  {
97  uint8_t bits[5] = {};
98  m_valid = false;
99 
100  // Request sample from sensor by setting the pin to low
101  // (T_be: min 0.8 ms, typ 1 ms, max 20 ms), then to high
102  // (T_go: min 20 us, typ 30 us, max 200 us) and wait for an
103  // acknowledgement from the sensor.
104  m_pin.setOutput();
105  m_pin.off(); // T_be
106  _delay_ms(1);
107  m_pin.on(); // T_go
108  m_pin.setInput();
109 
110  // The sensor will respond with setting the pin to low and then to
111  // high (T_rel, T_reh: min 75 us, typ 80 us, max 85 us).
112  if (!waitForFallingEdge(c_timeout * 2)) return false; // T_rel
113  if (!waitForRisingEdge()) return false; // T_reh
114 
115  // Read 40 bit of sensor data. Each bit is started with a low
116  // value (T_LOW: min 48 us, typ 50 us, max 55 us). The value of the bit
117  // is signaled by a short (T_H0: min 22 us, typ 26 us, max 30 us) or a
118  // long high (T_H1: min 68 us, typ 70 us, max 75 us) value.
119  if (!waitForFallingEdge()) return false; // T_LOW
120  for (uint8_t byteIndex = 0; byteIndex < 5; byteIndex++) {
121  uint8_t byte = 0;
122  for (uint8_t bitIndex = 0; bitIndex < 8; bitIndex++) {
123  if (!waitForRisingEdge()) return false; // T_H0/H1
124  _delay_us(30);
125  Sensors::bitWrite(byte, 7 - bitIndex, m_pin.isSet());
126  if (!waitForFallingEdge()) return false; // T_LOW
127  }
128  bits[byteIndex] = byte;
129  }
130 
131  // Reset sensor.
132  m_pin.setOutput();
133  m_pin.on();
134 
135  // Parse sensor data. The High most temperature bit indicates negative
136  // temperature.
137  m_humidity = Sensors::word(bits[0], bits[1]) / 10.0;
138  m_temperature = Sensors::word(bits[2] & 0x7F, bits[3]) / 10.0;
139  if (Sensors::bitRead(bits[2], 7)) m_temperature = -m_temperature;
140 
141  // Verify checksum.
142  m_valid = ((uint8_t)(bits[0] + bits[1] + bits[2] + bits[3]) == bits[4]);
143  return m_valid;
144  }
145 
146 private:
147  static const uint16_t c_timeout = F_CPU / 40000;
148 
149  TPin m_pin;
150  bool m_valid = false;
151  float m_temperature = 0.0F;
152  float m_humidity = 0.0F;
153 
154  bool waitForEdge(bool edge, uint16_t timeout = c_timeout) {
155  uint16_t cycle = 0;
156  while (m_pin.isSet() != edge)
157  if (++cycle >= timeout) return false;
158  return true;
159  }
160 
161  bool waitForFallingEdge(uint16_t timeout = c_timeout)
162  {
163  return waitForEdge(false, timeout);
164  }
165 
166  bool waitForRisingEdge(uint16_t timeout = c_timeout)
167  {
168  return waitForEdge(true, timeout);
169  }
170 };
171  // \addtogroup libtarget_dht22
173 
174 } // namespace Avr
void bitWrite(T &value, uint8_t bit, bool bitValue)
Writes the bit in the given value.
Definition: utils.h:106
Decodes data from DHT22 / AM2302 Temperature and humidity sensors.
Definition: dht22.h:55
Bit manipulation utilities.
Namespace containing all symbols of the AVR C++ utilities library.
Definition: adc.h:48
bool bitRead(T &value, uint8_t bit)
Returns the bit in the given value.
Definition: utils.h:92
float temperature() const
Retrieves the cached temperature value.
Definition: dht22.h:74
float humidity() const
Retrieves the cached humidity value.
Definition: dht22.h:85
bool isValid() const
Determines if the last sensor access was valid.
Definition: dht22.h:65
bool read()
Reads the temperature and humidity from the sensor and updates the cached values. ...
Definition: dht22.h:95
uint16_t word(uint8_t highByte, uint8_t lowByte)
Converts two bytes to a word.
Definition: utils.h:162
Wrapper for accessing digital I/O ports.