Grove DHT22 high-accuracy temperature and humidity sensor
From Teknologisk videncenter
DHT22 is also named as AM2302.
- Seeed Studio homepage for DHT22]
- AM2302 Product manual
- DHT22 data sheet
- Seeed Studio DHT22 Grove board schematics
Basic driver example
Using Grove Starter Kit for LaunchPad connected to J13. Pin 40 is connected to P2.5 on MSP430F5529 which can be used as TA2.2 input as trigger for CCR2 on TA2.
ta2-dht22.h
1 #ifndef TA2DHT22
2 #define TA2DHT22
3
4 typedef struct {
5 unsigned int humidity;
6 signed int temperature;
7 } dht22_t;
8
9 extern void dht22_read(unsigned int *dht22_data, char *event);
10 extern signed int dht22_convert(unsigned int *dht22arr, dht22_t *dht22);
11
12 #endif
ta2-dht22.c
Missing in this file is the function dht22_convert() that needs to be developed
1 /*
2 - Purpose: Measure temperature and humidity with DHT22/AM302 sensor
3 - Board: MSP430F5529 LaunchPad
4 - Peripheral: Seeed Studio: Grove - Temperature & Humidity Sensor Pro (DHT22/AM2302) - v1.3
5 - DHT22/AM2302 signal on pin P2.5 configured to TA2.2 - CCI2A (Grove board pin 40)
6 - SMCLK: 1 MHz
7 - Author: Henrik Thomsen <heth@mercantec.dk>
8 - date: 08. dec 2022
9 - Modificatiopn log:
10 */
11 /* NOTES on DHT22:
12 - Need a minimum of 2 seconds startup time
13 - 5K Resitor pullup. (On seeed grove DHT22 board)
14 - Minmum 1 mS start signal from host (Pull down)
15 - Release start signal for 50 uS (High - pulled up)
16 - Change pin for input (start capture mode falling edge)
17 - Expect sensor response signal is 2 x 80 uS = 160 uS ( < 170 uS and > 150 uS )
18 - Read 40 databits on falling edge on Capture TA2.2
19 - 0 = 76 uS ( < 85 uS and > 70uS )
20 - 1 = 120 uS ( < 130 uS and > 116 uS )
21 - Sensor release time max 55 uS
22 - MAX read time:
23 RESPONSE_TIME_MAX + 40 * DATABITS_MAX = 170 uS + 40 * 130 uS = 5370 uS
24
25 Datasheet: https://github.com/SeeedDocument/Grove-Temperature_and_Humidity_Sensor_Pro/raw/master/res/AM2302-EN.pdf
26
27 Method:
28 CCR1: Compare mode: Time start signal - then used as Timeout error
29 CCR2: Capture mode: Falling edge time 0 or 1 from device
30
31 Interrupt driven time measurement of the response signal + 40 databits.
32 TA2R set to 0 and start counter when host release start signal
33 CCR2 trigger interrupt on falling edge storing and stores TA2R in
34 42 unsigned word array for later processing.
35
36 All values in array are readings from TA2 SAR counter in 1 uS count
37 if any errors occur the corresponding array member is et to 0xFFFF to
38 indicate the error and where it happened in the sequence
39
40 - array[0] = Start signal time
41 - array[1] = Bus master release time
42 - array[2] = Response signal time
43 - array[3-42] are data bits
44 - Zeros are between 70 and 85 uS (From datasheet)
45 - Ones are between 116 and 130 uS (From datasheet)
46 Experimentaly 0 and 1 timing is not all within time limits - based on one device!!!
47 - Need more data/evidence before used in a production!!!!!!!
48 - Zeros up 94 uS - smallest 78 uS
49 - Ones up to 142 uS - smallest 124 uS
50 */
51 #include <io430.h>
52 #include "ta2-dht22.h"
53
54 //DHT22ARRAYSIZE explained above in comment
55 #define ARRAYSIZE 43
56 #define ARRAYFIRSTBIT 3
57 #define STARTSIGNAL 1000 // Startsignal duration = 1000 uS
58 #define ZERO_MIN 70 // 70 uS from datasheet
59 #define ZERO_MAX 100 // Experimentaly found and rounded up a litte
60 #define ONE_MIN 116 // 116 uS from datasheet
61 #define ONE_MAX 160 // Experimentaly found and rounded up a litte
62
63
64 //############# Module static
65 struct module_static {
66 char *event;
67 unsigned int *dht22_array;
68 char sequence;
69 };
70
71 static struct module_static ms;
72 //#############
73
74 /*
75 Function: dht22_read
76 Abstract: Initiate retrival of data from DHT22 temperature and humidity module
77 When data ready in dht22_timing array, event is incremented by 1
78 REQUIRED: SMCLK = 1 MHz
79
80 Implementation:
81 DHT22 module is hardwired to P2.5 which alternate function is TA2 CCI2A
82
83 1: Set TA2 to SMCLK in stopmode
84 2: Set TA2 CCR1 to compare mode, TA2CCR1 = 1000 ( 1 mS)
85 3: Set TA2 CCR2 to capture mode with CCI2A on fallling edge
86 4: Check P2.5 level is 1 - 5K pullup from DHT22 (100 uS use timer?????)
87 5: Set P2.5 as low output (never high!!)- startsignal beginning
88 P2.5 has no open-drain possebility - never set output high!!!
89 6: 6: Start timer = Continuous mode and enable interrupt on TA2CCR1
90 7: Done here - ISR TA2 takes over
91 */
92 void dht22_read(unsigned int *dht22_array, char *event) {
93 ms.event = event;
94 ms.dht22_array = dht22_array;
95 for (int i=0; i < ARRAYSIZE; i++, dht22_array[i] = 0);
96 ms.sequence = 0; // Incremented on each interrupt and used as pointer to ms.dht22_timing array
97 // 1: Set TA2 to SMCLK in stopmode
98 TA2CTL = TACLR; // Clear timer and TA2CTL settings
99 TA2CTL = TASSEL1; //Continuous up count to 0xFFFF in stopmode
100 TA2EX0 = 0; // TAIDEX divide by 1
101 // 2: Set TA2 CCR1 to compare mode, TA2CCR1 = 1000 ( 1 mS)
102 TA2CCTL1 = 0; // Default setting
103 TA2CCR1 = STARTSIGNAL;
104 // 3: Set TA2 CCR2 to capture mode with CCI2A on fallling edge
105 TA2CCTL2 = 0; // Default setting
106 TA2CCTL2 = CAP | SCS | CM1;
107 // 4: Check P2.5 level is 1 - 5K pullup from DHT22 (100 uS use timer?????)
108 P2REN &= ~(BIT5); // P2.5 = Resistor disable
109 P2DIR &= ~(BIT5); // P2.5 = input
110 if ( !(P2IN & BIT5)) { // P2.5 must be high to indicate DHT22 might be ready!
111 dht22_array[0] = 0xffff; // Indicate error
112 *event++; // Set event
113 return;
114 }
115 // 5: Set P2.5 as low output (never high!!)- startsignal beginning
116 P2OUT &= ~BIT5; // Must be set to 0 before direction out
117 P2DIR |= BIT5;
118 // 6: Start timer = Continuous mode and enable interrupt on TA2CCR1
119 TA2CCTL1 |= CCIE;
120 TA2CTL |= MC1; // Start timer in continuous up count to 0xFFFF
121 // 7: Done here - ISR TA2 takes over
122
123 }
124
125 //Converts dht22_array with timer values to temperature and humidity
126 // Return 0 on succes
127 // Return -1 to indicate invalid timer value or other error from ISR
128 // return -2 to indicate parity error
129 signed int dht22_convert(unsigned int *dht22arr, dht22_t *dht22) {
130 // DEVELOP THIS FUNCTION
131 }
132
133
134
135 #pragma vector=TIMER2_A1_VECTOR
136 __interrupt void timer2_a1_isr(void) {
137 if (ms.sequence >= ARRAYSIZE) { // Array overflow if here!
138 ms.sequence--;
139 goto error_exit;
140 }
141 switch (TA2IV) { //Interrupt vector from TA2
142 case 0x02: // TA2CCR1 generated Interrupt
143 if (TA2CCR1 == STARTSIGNAL) { //Start signal elapsed
144 ms.dht22_array[ms.sequence++] = TA2R; // Record timer count - just fort fun
145 TA2CCR1 = 0xffff; // Now use for timeout
146 // Prepare P2.5 as input for TA2 CCIA2A
147 P2DIR &= ~BIT5;
148 P2SEL |= BIT5;
149 // Start TA2CCR2 as capture on falling edge and enable interrupt
150 TA2CCTL2 = CAP | SCS | CM1 | CCIE;
151 return;
152 }
153 goto error_exit;
154 break;
155 case 0x04: // TACCR2 generated Interrupt
156 ms.dht22_array[ms.sequence++] = TA2CCR2;
157 if ((TA2CCTL2 |= COV) == COV) // Capture overflow error
158 goto error_exit;
159 if (ms.sequence == ARRAYSIZE) // Done?
160 goto ok_exit;
161 return;
162 break;
163 case 0x0e: // Timer overflow
164 goto error_exit;
165 break;
166 default: // Ignore ??
167 goto error_exit;
168 break;
169 }
170 error_exit:
171 ms.dht22_array[ms.sequence] = 0xffff; // Set error in sequence
172
173 ok_exit:
174 TA2CTL &= ~(TACLR | TAIE | TAIFG); // Stop TA2 and disable and clear Interrupts
175 TA2CCTL1 &= ~CCIE;
176 TA2CCTL2 &= ~CCIE;
177
178 (*ms.event)++; // Set event to indicate finish
179 return;
180 }