Grove DHT22 high-accuracy temperature and humidity sensor

From Teknologisk videncenter
Jump to: navigation, search
Grove - DHT22 Temperature & Humidity Sensor Pro - Seeed Studio.png

DHT22 is also named as AM2302.

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 }