Browse Source

htu21d: sensor added

Signed-off-by: William Penner <william.penner@intel.com>
Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
William Penner 10 years ago
parent
commit
b53881a8d6

BIN
docs/images/htu21d.jpeg View File


+ 3
- 0
examples/CMakeLists.txt View File

@@ -42,6 +42,7 @@ add_executable (joystick12-example joystick12-example.cxx)
42 42
 add_executable (lol-example lol-example.cxx)
43 43
 add_executable (nrf_ble_broadcast-example ble_broadcast.cxx)
44 44
 add_executable (tsl2561-example tsl2561.cxx)
45
+add_executable (htu21d-example htu21d.cxx)
45 46
 
46 47
 include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l)
47 48
 include_directories (${PROJECT_SOURCE_DIR}/src/grove)
@@ -75,6 +76,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/lsm303)
75 76
 include_directories (${PROJECT_SOURCE_DIR}/src/joystick12)
76 77
 include_directories (${PROJECT_SOURCE_DIR}/src/lol)
77 78
 include_directories (${PROJECT_SOURCE_DIR}/src/tsl2561)
79
+include_directories (${PROJECT_SOURCE_DIR}/src/htu21d)
78 80
 
79 81
 target_link_libraries (hmc5883l-example hmc5883l ${CMAKE_THREAD_LIBS_INIT})
80 82
 target_link_libraries (groveled-example grove ${CMAKE_THREAD_LIBS_INIT})
@@ -120,3 +122,4 @@ target_link_libraries (joystick12-example joystick12 ${CMAKE_THREAD_LIBS_INIT})
120 122
 target_link_libraries (lol-example lol ${CMAKE_THREAD_LIBS_INIT})
121 123
 target_link_libraries (nrf_ble_broadcast-example nrf24l01 ${CMAKE_THREAD_LIBS_INIT})
122 124
 target_link_libraries (tsl2561-example tsl2561 ${CMAKE_THREAD_LIBS_INIT})
125
+target_link_libraries (htu21d-example htu21d ${CMAKE_THREAD_LIBS_INIT})

+ 72
- 0
examples/htu21d.cxx View File

@@ -0,0 +1,72 @@
1
+/*
2
+ * Author: William Penner <william.penner@intel.com>
3
+ * Copyright (c) 2014 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+#include <unistd.h>
26
+#include <iostream>
27
+#include "htu21d.h"
28
+#include <signal.h>
29
+
30
+int doWork = 0;
31
+upm::HTU21D *sensor = NULL;
32
+
33
+void
34
+sig_handler(int signo)
35
+{
36
+    printf("got signal\n");
37
+    if (signo == SIGINT) {
38
+        printf("exiting application\n");
39
+        doWork = 1;
40
+    }
41
+}
42
+
43
+int
44
+main(int argc, char **argv)
45
+{
46
+    //! [Interesting]
47
+    int32_t humidity = 0;
48
+    int32_t temperature = 0;
49
+    int32_t compRH = 0;
50
+
51
+    sensor = new upm::HTU21D(0, HTU21D_I2C_ADDRESS);
52
+
53
+    while (!doWork) {
54
+        humidity = sensor->getRHumidity(&temperature);
55
+        compRH = sensor->getCompRH();
56
+
57
+        std::cout << "humidity value = " <<
58
+                    (float)humidity / 1000.0 <<
59
+                    ", temperature value = " <<
60
+                    (float)temperature / 1000.0 <<
61
+                    ", compensated RH value = " <<
62
+                    (float)compRH / 1000.0 << std::endl;
63
+        usleep (100000);
64
+    }
65
+    //! [Interesting]
66
+
67
+    std::cout << "exiting application" << std::endl;
68
+
69
+    delete sensor;
70
+
71
+    return 0;
72
+}

+ 5
- 0
src/htu21d/CMakeLists.txt View File

@@ -0,0 +1,5 @@
1
+set (libname "htu21d")
2
+set (libdescription "libupm Humidity Sensor")
3
+set (module_src ${libname}.cpp)
4
+set (module_h ${libname}.h)
5
+upm_module_init()

+ 243
- 0
src/htu21d/htu21d.cpp View File

@@ -0,0 +1,243 @@
1
+/*
2
+ * Author: William Penner <william.penner@intel.com>
3
+ * Copyright (c) 2014 Intel Corporation.
4
+ *
5
+ * This driver supports the HTU21D digital humidity and temperature
6
+ * sensor. The datasheet is available from:
7
+ * http://www.meas-spec.com/downloads/HTU21D.pdf
8
+ *
9
+ * This program is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program; if not, write to the Free Software
21
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
+ */
23
+
24
+#include <iostream>
25
+#include <unistd.h>
26
+#include <stdlib.h>
27
+
28
+#include "htu21d.h"
29
+
30
+using namespace upm;
31
+
32
+HTU21D::HTU21D(int bus, int devAddr) {
33
+    m_temperature = 0;
34
+    m_humidity    = 0;
35
+
36
+    m_name = HTU21D_NAME;
37
+
38
+    m_controlAddr = devAddr;
39
+    m_bus = bus;
40
+
41
+    m_i2ControlCtx = mraa_i2c_init(m_bus);
42
+
43
+    mraa_result_t ret = mraa_i2c_address(m_i2ControlCtx, m_controlAddr);
44
+    if (ret != MRAA_SUCCESS) {
45
+        fprintf(stderr, "Error accessing i2c bus\n");
46
+    }
47
+}
48
+
49
+HTU21D::~HTU21D() {
50
+    mraa_i2c_stop(m_i2ControlCtx);
51
+}
52
+
53
+int32_t
54
+HTU21D::htu21_temp_ticks_to_millicelsius(int ticks)
55
+{
56
+    ticks &= ~0x0003; /* clear status bits */
57
+    /*
58
+     * Formula T = -46.85 + 175.72 * ST / 2^16 from datasheet p14,
59
+     * optimized for integer fixed point (3 digits) arithmetic
60
+     */
61
+    return ((21965 * (int32_t)ticks) >> 13) - 46850;
62
+}
63
+
64
+int32_t
65
+HTU21D::htu21_rh_ticks_to_per_cent_mille(int ticks)
66
+{
67
+    ticks &= ~0x0003; /* clear status bits */
68
+    /*
69
+     * Formula RH = -6 + 125 * SRH / 2^16 from datasheet p14,
70
+     * optimized for integer fixed point (3 digits) arithmetic
71
+     */
72
+    return ((15625 * (int32_t)ticks) >> 13) - 6000;
73
+}
74
+
75
+int
76
+HTU21D::sampleData(void)
77
+{
78
+    uint32_t itemp;
79
+
80
+    itemp = i2cReadReg_16(HTU21D_T_MEASUREMENT_HM);
81
+    m_temperature = htu21_temp_ticks_to_millicelsius(itemp);
82
+
83
+    itemp = i2cReadReg_16(HTU21D_RH_MEASUREMENT_HM);
84
+    m_humidity = htu21_rh_ticks_to_per_cent_mille(itemp);
85
+
86
+    return 0;
87
+}
88
+
89
+int32_t
90
+HTU21D::getTemperature(void)
91
+{
92
+    return m_temperature;
93
+}
94
+
95
+int32_t
96
+HTU21D::getHumidity(void)
97
+{
98
+    return m_humidity;
99
+}
100
+
101
+/*
102
+ * This is the primary function to read the data.  It will initiate
103
+ * a measurement cycle and will then return both the humidity and
104
+ * temperature values.  piTemperature can be NULL.
105
+ */
106
+
107
+int32_t
108
+HTU21D::getRHumidity(int32_t* piTemperature)
109
+{
110
+    sampleData();
111
+    if (NULL != piTemperature)
112
+        *piTemperature = m_temperature;
113
+    return m_humidity;
114
+}
115
+
116
+/*
117
+ * Use the compensation equation from the datasheet to correct the
118
+ * current reading
119
+ * RHcomp = RHactualT + (25 - Tactual) * CoeffTemp
120
+ * RHcomp is in units of %RH * 1000
121
+ */
122
+int32_t
123
+HTU21D::getCompRH(void)
124
+{
125
+    return m_humidity + (25000 - m_temperature) * 3 / 20;
126
+}
127
+
128
+
129
+/*
130
+ * Test function: when reading the HTU21D many times rapidly should
131
+ * result in a temperature increase.  This test will verify that the
132
+ * value is changing from read to read
133
+ */
134
+
135
+int
136
+HTU21D::testSensor(void)
137
+{
138
+    int iError = 0;
139
+    int i, j;
140
+    int32_t iTemp, iHum;
141
+    int32_t iTempMax, iTempMin;
142
+    int32_t iHumMax, iHumMin;
143
+    int32_t iHumFirst, iTempFirst;
144
+
145
+    fprintf(stdout, "Executing Sensor Test.\n  Reading registers 100 times to look for operation\n" );
146
+
147
+    iHum = getRHumidity(&iTemp);
148
+    iTempFirst = iTempMax = iTempMin = iTemp;
149
+    iHumFirst  = iHumMax  = iHumMin  = iHum;
150
+
151
+    for (i=0; i < 100; i++) {
152
+        iHum = getRHumidity(&iTemp);
153
+        if (iHum  < iHumMin)  iHumMin  = iHum;
154
+        if (iHum  > iHumMax)  iHumMax  = iHum;
155
+        if (iTemp < iTempMin) iTempMin = iTemp;
156
+        if (iTemp > iTempMax) iTempMax = iTemp;
157
+//        fprintf(stdout, "Temp: %d  Humidity: %d\n", iTemp, iHum);
158
+    }
159
+
160
+    if ((iTemp - iTempFirst) <= 0) {
161
+        fprintf(stdout, "! Temperature should have increased, but didn't\n" );
162
+        iError++;
163
+    }
164
+
165
+    if (iHumMin == iHumMax) {
166
+        fprintf(stdout, "! Humidity was unchanged - not working?\n" );
167
+        iError++;
168
+    }
169
+
170
+    if (iTempMin == iTempMax) {
171
+        fprintf(stdout, "! Temperature was unchanged - not working?\n" );
172
+        iError++;
173
+    }
174
+
175
+    if (iError == 0) {
176
+        fprintf(stdout, "  Device appears functional\n" );
177
+    }
178
+
179
+    fprintf(stdout, "  Test complete\n" );
180
+
181
+    return iError;
182
+}
183
+
184
+/*
185
+ * Functions to read and write data to the i2c device
186
+ */
187
+
188
+mraa_result_t
189
+HTU21D::i2cReadRegValue(int reg, uint32_t* puint32, int ibytes) {
190
+    uint32_t data = 0;
191
+
192
+    if (ibytes > 4)
193
+        ibytes = 4;
194
+
195
+    mraa_i2c_address(m_i2ControlCtx, m_controlAddr);
196
+    mraa_i2c_write_byte(m_i2ControlCtx, reg);
197
+
198
+    mraa_i2c_address(m_i2ControlCtx, m_controlAddr);
199
+    mraa_i2c_read(m_i2ControlCtx, (uint8_t *)&data, ibytes);
200
+
201
+    fprintf(stdout, "reg data = %08x\n", data);
202
+    *puint32 = be32toh(data) >> ((4-ibytes) * 8);
203
+    fprintf(stdout, "reg return = %08x\n", *puint32);
204
+
205
+    return MRAA_SUCCESS;
206
+}
207
+
208
+mraa_result_t
209
+HTU21D::i2cWriteReg (uint8_t reg, uint8_t value) {
210
+    mraa_result_t error = MRAA_SUCCESS;
211
+
212
+    uint8_t data[2] = { reg, value };
213
+    error = mraa_i2c_address (m_i2ControlCtx, m_controlAddr);
214
+    error = mraa_i2c_write (m_i2ControlCtx, data, 2);
215
+
216
+    return error;
217
+}
218
+
219
+/*
220
+ * Function to read 16 bits starting at reg.  This function
221
+ * was replaced due to functionality of using read() to
222
+ * access i2c data.
223
+ */
224
+uint16_t
225
+HTU21D::i2cReadReg_16 (int reg) {
226
+    uint16_t data;
227
+    mraa_i2c_address(m_i2ControlCtx, m_controlAddr);
228
+    data  = (uint16_t)mraa_i2c_read_byte_data(m_i2ControlCtx, reg) << 8;
229
+    data |= (uint16_t)mraa_i2c_read_byte_data(m_i2ControlCtx, reg+1);
230
+    return data;
231
+}
232
+
233
+/*
234
+ * Function to read 8 bits starting at reg.  This function
235
+ * was replaced due to functionality of using read() to
236
+ * access i2c data.
237
+ */
238
+uint8_t
239
+HTU21D::i2cReadReg_8 (int reg) {
240
+    mraa_i2c_address(m_i2ControlCtx, m_controlAddr);
241
+    return mraa_i2c_read_byte_data(m_i2ControlCtx, reg);
242
+}
243
+

+ 169
- 0
src/htu21d/htu21d.h View File

@@ -0,0 +1,169 @@
1
+/*
2
+ * Author: William Penner <william.penner@intel.com>
3
+ * Copyright (c) 2014 Intel Corporation.
4
+ *
5
+ * Based on code adapted from the kernel HTU21 driver and
6
+ * code by: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
7
+ * Copyright (c) 2014 Intel Corporation.
8
+ *
9
+ * This program is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program; if not, write to the Free Software
21
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
+ */
23
+
24
+#pragma once
25
+
26
+#include <string>
27
+#include <mraa/i2c.h>
28
+#include <math.h>
29
+
30
+#define HTU21D_NAME     "htu21d"
31
+#define HTU21D_I2C_ADDRESS  0x40
32
+
33
+/* HTU21 Commands */
34
+#define HTU21D_T_MEASUREMENT_HM   0xE3
35
+#define HTU21D_RH_MEASUREMENT_HM  0xE5
36
+
37
+namespace upm {
38
+
39
+/**
40
+ * @brief HTU21D humidity sensor library
41
+ * @defgroup htu21d libupm-htu21
42
+ */
43
+
44
+/**
45
+ * @brief C++ API for HTU21D chip (Atmospheric Pressure Sensor)
46
+ *
47
+ * Measurement Specialties [HTU21D]
48
+ * (http://www.meas-spec.com/downloads/HTU21D.pdf)
49
+ * is a digital humidity sensor with temperature output.
50
+ * RH will report between 0 and 100% and temperature range is
51
+ * -40 to +125 degC
52
+ *
53
+ * @ingroup htu21d i2c
54
+ * @snippet htu21d.cxx Interesting
55
+ * @image html htu21d.jpeg
56
+ */
57
+class HTU21D {
58
+    public:
59
+        /**
60
+         * Instanciates a HTU21D object
61
+         *
62
+         * @param bus number of used bus
63
+         * @param devAddr address of used i2c device
64
+         * @param mode HTU21D oversampling
65
+         */
66
+        HTU21D (int bus=0, int devAddr=HTU21D_I2C_ADDRESS);
67
+
68
+        /**
69
+         * HTU21D object destructor, basicaly it close i2c connection.
70
+         */
71
+        ~HTU21D ();
72
+
73
+        /**
74
+         * Initiate a temp/pressure mesasurement and wait for function
75
+         * to complete.  The humidity and temp registers can be read
76
+         * after this call.
77
+         */
78
+        int sampleData(void);
79
+        
80
+        /**
81
+         * Get the current measured humidity [RH * 1000]
82
+         * To convert to Relative Humidity, divide by 1000
83
+         *
84
+         */
85
+        int32_t getHumidity(void);
86
+
87
+        /**
88
+         * Get the humidity cell temperature [degC * 1000]
89
+         * To convert to Temperature, divide by 1000
90
+         */
91
+        int32_t getTemperature(void);
92
+        
93
+        /**
94
+         * Reads both temperature and humidity together
95
+         * To convert to Relative Humidity, divide by 1000
96
+         * To convert to Temperature, divide by 1000
97
+         *
98
+         * @param pointer to int32_t buffer for temp
99
+         */
100
+        int32_t getRHumidity(int32_t* iTemperature);
101
+        
102
+        /**
103
+         * Using the current humidity and temperature the function
104
+         * will calculate the compensated RH using the equation from
105
+         * the datasheet.
106
+         */
107
+        int32_t getCompRH(void);
108
+        
109
+        /**
110
+         * Function intended to test the device and verify it
111
+         * is correctly operating.
112
+         *
113
+         */
114
+        int testSensor(void);
115
+        
116
+        /**
117
+         * Read 1 to 4 bytes from i2c registers
118
+         *
119
+         * @param reg address of a register
120
+         * @param puint32 pointer to buffer for register data
121
+         * @param ibytes number of bytes to be returned
122
+         */
123
+        mraa_result_t i2cReadRegValue (int reg, uint32_t* puint32, int ibytes);
124
+
125
+        /**
126
+         * Read two bytes register
127
+         *
128
+         * @param reg address of a register
129
+         */
130
+        uint16_t i2cReadReg_16 (int reg);
131
+
132
+        /**
133
+         * Write to one byte register
134
+         *
135
+         * @param reg address of a register
136
+         * @param value byte to be written
137
+         */
138
+        mraa_result_t i2cWriteReg (uint8_t reg, uint8_t value);
139
+
140
+        /**
141
+         * Read one byte register
142
+         *
143
+         * @param reg address of a register
144
+         */
145
+        uint8_t i2cReadReg_8 (int reg);
146
+
147
+    private:
148
+
149
+        /**
150
+         * Convert temp register to value * 1000
151
+         */
152
+        int32_t htu21_temp_ticks_to_millicelsius(int ticks);
153
+
154
+        /**
155
+         * Convert temp register to value * 1000
156
+         */
157
+        int32_t htu21_rh_ticks_to_per_cent_mille(int ticks);
158
+
159
+        std::string m_name;
160
+
161
+        int m_controlAddr;
162
+        int m_bus;
163
+        mraa_i2c_context m_i2ControlCtx;
164
+        
165
+        int32_t m_temperature;
166
+        int32_t m_humidity;
167
+};
168
+
169
+}

+ 8
- 0
src/htu21d/jsupm_htu21d.i View File

@@ -0,0 +1,8 @@
1
+%module jsupm_htu21d
2
+%include "../upm.i"
3
+
4
+%{
5
+    #include "htu21d.h"
6
+%}
7
+
8
+%include "htu21d.h"

+ 13
- 0
src/htu21d/pyupm_htu21d.i View File

@@ -0,0 +1,13 @@
1
+%module pyupm_htu21d
2
+%include "../upm.i"
3
+
4
+%feature("autodoc", "3");
5
+
6
+#ifdef DOXYGEN
7
+%include "htu21d_doc.i"
8
+#endif
9
+
10
+%include "htu21d.h"
11
+%{
12
+    #include "htu21d.h"
13
+%}