DHT22 library, based on Simon Cooksey's. Improved with some error checking and more rigid timing (interrupts off).
Fork of lib_dht22 by
dht22.cpp@2:02cbaab7c6cd, 2016-11-02 (annotated)
- Committer:
- co657_jnp8
- Date:
- Wed Nov 02 16:29:53 2016 +0000
- Revision:
- 2:02cbaab7c6cd
- Parent:
- 0:257ba13e416e
- Child:
- 3:40df3c72813f
Initial commit;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
co657_sjc80 | 0:257ba13e416e | 1 | /* |
co657_sjc80 | 0:257ba13e416e | 2 | * (C) The University of Kent and Simon Cooksey 2015. |
co657_sjc80 | 0:257ba13e416e | 3 | */ |
co657_sjc80 | 0:257ba13e416e | 4 | |
co657_sjc80 | 0:257ba13e416e | 5 | #include "mbed.h" |
co657_sjc80 | 0:257ba13e416e | 6 | #include <inttypes.h> |
co657_sjc80 | 0:257ba13e416e | 7 | |
co657_sjc80 | 0:257ba13e416e | 8 | #include "dht22.h" |
co657_sjc80 | 0:257ba13e416e | 9 | |
co657_sjc80 | 0:257ba13e416e | 10 | /* |
co657_sjc80 | 0:257ba13e416e | 11 | * The DHT22 uses a 1 wire interface, sending 1's and 0s by varying the length |
co657_sjc80 | 0:257ba13e416e | 12 | * of the HIGH time on the signal pin. |
co657_sjc80 | 0:257ba13e416e | 13 | */ |
co657_sjc80 | 0:257ba13e416e | 14 | |
co657_sjc80 | 0:257ba13e416e | 15 | /* |
co657_sjc80 | 0:257ba13e416e | 16 | * Wait for a rising or falling edge on the sense pin. |
co657_sjc80 | 0:257ba13e416e | 17 | * |
co657_sjc80 | 0:257ba13e416e | 18 | * Returns: the number of uS elapsed before the transition |
co657_sjc80 | 0:257ba13e416e | 19 | */ |
co657_sjc80 | 0:257ba13e416e | 20 | int DHT22::wait_for_edge(edge_type_t type) |
co657_sjc80 | 0:257ba13e416e | 21 | { |
co657_jnp8 | 2:02cbaab7c6cd | 22 | //__disable_irq (); |
co657_sjc80 | 0:257ba13e416e | 23 | dht22_s.input(); |
co657_sjc80 | 0:257ba13e416e | 24 | |
co657_sjc80 | 0:257ba13e416e | 25 | // Timing is done by increasing this number, as the Timer class appears to |
co657_sjc80 | 0:257ba13e416e | 26 | // be super slow. |
co657_sjc80 | 0:257ba13e416e | 27 | int time = 0; |
co657_sjc80 | 0:257ba13e416e | 28 | do { |
co657_sjc80 | 0:257ba13e416e | 29 | wait_us(2); |
co657_sjc80 | 0:257ba13e416e | 30 | time+=2; |
co657_sjc80 | 0:257ba13e416e | 31 | } while(dht22_s != (int)type); |
co657_sjc80 | 0:257ba13e416e | 32 | |
co657_sjc80 | 0:257ba13e416e | 33 | // wait for the edge to transition properly |
co657_sjc80 | 0:257ba13e416e | 34 | wait_us(2); |
co657_jnp8 | 2:02cbaab7c6cd | 35 | //__enable_irq (); |
co657_sjc80 | 0:257ba13e416e | 36 | return time; |
co657_sjc80 | 0:257ba13e416e | 37 | } |
co657_sjc80 | 0:257ba13e416e | 38 | |
co657_sjc80 | 0:257ba13e416e | 39 | /* |
co657_sjc80 | 0:257ba13e416e | 40 | * Send a start bit to the DHT22 |
co657_sjc80 | 0:257ba13e416e | 41 | */ |
co657_sjc80 | 0:257ba13e416e | 42 | void DHT22::send_start() |
co657_sjc80 | 0:257ba13e416e | 43 | { |
co657_jnp8 | 2:02cbaab7c6cd | 44 | //__disable_irq (); |
co657_sjc80 | 0:257ba13e416e | 45 | dht22_s.output(); |
co657_sjc80 | 0:257ba13e416e | 46 | dht22_s = 0; |
co657_sjc80 | 0:257ba13e416e | 47 | wait_us(DHT22_START_BIT_TIME); |
co657_sjc80 | 0:257ba13e416e | 48 | dht22_s = 1; |
co657_sjc80 | 0:257ba13e416e | 49 | dht22_s.input(); |
co657_jnp8 | 2:02cbaab7c6cd | 50 | //__enable_irq (); |
co657_sjc80 | 0:257ba13e416e | 51 | } |
co657_sjc80 | 0:257ba13e416e | 52 | |
co657_sjc80 | 0:257ba13e416e | 53 | /* |
co657_sjc80 | 0:257ba13e416e | 54 | * Wait for the DHT22 to send the start bit ACK, after this we can read data. |
co657_sjc80 | 0:257ba13e416e | 55 | */ |
co657_sjc80 | 0:257ba13e416e | 56 | void DHT22::await_start_response() |
co657_sjc80 | 0:257ba13e416e | 57 | { |
co657_sjc80 | 0:257ba13e416e | 58 | dht22_s.input(); |
co657_sjc80 | 0:257ba13e416e | 59 | wait_for_edge(EDGE_TYPE_FALLING); // 20-40 uS |
co657_sjc80 | 0:257ba13e416e | 60 | wait_for_edge(EDGE_TYPE_RISING); // 80 uS |
co657_sjc80 | 0:257ba13e416e | 61 | wait_for_edge(EDGE_TYPE_FALLING); // 80 uS |
co657_sjc80 | 0:257ba13e416e | 62 | } |
co657_sjc80 | 0:257ba13e416e | 63 | |
co657_sjc80 | 0:257ba13e416e | 64 | /* |
co657_sjc80 | 0:257ba13e416e | 65 | * Reads 16 bits of data from the DHT22 |
co657_sjc80 | 0:257ba13e416e | 66 | * |
co657_sjc80 | 0:257ba13e416e | 67 | * Returns: the signed value read. dht22_t. |
co657_sjc80 | 0:257ba13e416e | 68 | * NB. the DHT22 uses a sign bit to do -ve and positive, but this is |
co657_sjc80 | 0:257ba13e416e | 69 | * incompatible with signed numbers in C, so the conversion is done here. |
co657_sjc80 | 0:257ba13e416e | 70 | */ |
co657_sjc80 | 0:257ba13e416e | 71 | int16_t DHT22::read_word() |
co657_sjc80 | 0:257ba13e416e | 72 | { |
co657_sjc80 | 0:257ba13e416e | 73 | dht22_s.input(); |
co657_sjc80 | 0:257ba13e416e | 74 | int32_t duration; |
co657_sjc80 | 0:257ba13e416e | 75 | int16_t word = 0x00; |
co657_sjc80 | 0:257ba13e416e | 76 | for(char bit = 0; bit < 16; bit++) |
co657_sjc80 | 0:257ba13e416e | 77 | { |
co657_sjc80 | 0:257ba13e416e | 78 | /* /-----------\ |
co657_sjc80 | 0:257ba13e416e | 79 | * / duration \ 50us |
co657_sjc80 | 0:257ba13e416e | 80 | * ----/ \------- |
co657_sjc80 | 0:257ba13e416e | 81 | */ |
co657_sjc80 | 0:257ba13e416e | 82 | wait_for_edge(EDGE_TYPE_RISING); |
co657_sjc80 | 0:257ba13e416e | 83 | duration = wait_for_edge(EDGE_TYPE_FALLING); |
co657_sjc80 | 0:257ba13e416e | 84 | |
co657_sjc80 | 0:257ba13e416e | 85 | if(duration > DHT22_SIGNAL_HIGH_LOW_BOUNDARY) |
co657_sjc80 | 0:257ba13e416e | 86 | { |
co657_sjc80 | 0:257ba13e416e | 87 | word |= (1 << 15-bit); |
co657_sjc80 | 0:257ba13e416e | 88 | } |
co657_sjc80 | 0:257ba13e416e | 89 | else |
co657_sjc80 | 0:257ba13e416e | 90 | { |
co657_sjc80 | 0:257ba13e416e | 91 | word |= (0 << 15-bit); |
co657_sjc80 | 0:257ba13e416e | 92 | } |
co657_sjc80 | 0:257ba13e416e | 93 | } |
co657_sjc80 | 0:257ba13e416e | 94 | if(word & 0x8000) |
co657_sjc80 | 0:257ba13e416e | 95 | return 1 - (word ^ 0x8000); |
co657_sjc80 | 0:257ba13e416e | 96 | return word; |
co657_sjc80 | 0:257ba13e416e | 97 | } |
co657_sjc80 | 0:257ba13e416e | 98 | |
co657_sjc80 | 0:257ba13e416e | 99 | /* |
co657_sjc80 | 0:257ba13e416e | 100 | * Reads 8 bits of data from the DHT22 |
co657_sjc80 | 0:257ba13e416e | 101 | * |
co657_sjc80 | 0:257ba13e416e | 102 | * Returns: the unsigned checksum value read. dht22_t. |
co657_sjc80 | 0:257ba13e416e | 103 | */ |
co657_sjc80 | 0:257ba13e416e | 104 | uint8_t DHT22::read_checksum() |
co657_sjc80 | 0:257ba13e416e | 105 | { |
co657_sjc80 | 0:257ba13e416e | 106 | dht22_s.input(); |
co657_sjc80 | 0:257ba13e416e | 107 | uint32_t duration; |
co657_sjc80 | 0:257ba13e416e | 108 | uint8_t word; |
co657_sjc80 | 0:257ba13e416e | 109 | for(char bit = 0; bit < sizeof(uint8_t)*8; bit++) |
co657_sjc80 | 0:257ba13e416e | 110 | { |
co657_sjc80 | 0:257ba13e416e | 111 | /* /-----------\ |
co657_sjc80 | 0:257ba13e416e | 112 | * / duration \ 50us |
co657_sjc80 | 0:257ba13e416e | 113 | * ----/ \------- |
co657_sjc80 | 0:257ba13e416e | 114 | */ |
co657_sjc80 | 0:257ba13e416e | 115 | wait_for_edge(EDGE_TYPE_RISING); |
co657_sjc80 | 0:257ba13e416e | 116 | duration = wait_for_edge(EDGE_TYPE_FALLING); |
co657_sjc80 | 0:257ba13e416e | 117 | |
co657_sjc80 | 0:257ba13e416e | 118 | if(duration > DHT22_SIGNAL_HIGH_LOW_BOUNDARY) |
co657_sjc80 | 0:257ba13e416e | 119 | { |
co657_sjc80 | 0:257ba13e416e | 120 | word |= (1 << 7-bit); |
co657_sjc80 | 0:257ba13e416e | 121 | } |
co657_sjc80 | 0:257ba13e416e | 122 | else |
co657_sjc80 | 0:257ba13e416e | 123 | { |
co657_sjc80 | 0:257ba13e416e | 124 | word |= (0 << 7-bit); |
co657_sjc80 | 0:257ba13e416e | 125 | } |
co657_sjc80 | 0:257ba13e416e | 126 | } |
co657_sjc80 | 0:257ba13e416e | 127 | return word; |
co657_sjc80 | 0:257ba13e416e | 128 | } |
co657_sjc80 | 0:257ba13e416e | 129 | |
co657_sjc80 | 0:257ba13e416e | 130 | /* |
co657_sjc80 | 0:257ba13e416e | 131 | * Reads a packet of DHT22 data. |
co657_sjc80 | 0:257ba13e416e | 132 | * |
co657_sjc80 | 0:257ba13e416e | 133 | * Param data: the packet to fill. |
co657_sjc80 | 0:257ba13e416e | 134 | */ |
co657_sjc80 | 0:257ba13e416e | 135 | void DHT22::read(DHT22_data_t * data) |
co657_sjc80 | 0:257ba13e416e | 136 | { |
co657_sjc80 | 0:257ba13e416e | 137 | // Send start bits |
co657_sjc80 | 0:257ba13e416e | 138 | send_start(); |
co657_sjc80 | 0:257ba13e416e | 139 | |
co657_sjc80 | 0:257ba13e416e | 140 | // Wait for device to respond |
co657_sjc80 | 0:257ba13e416e | 141 | await_start_response(); |
co657_sjc80 | 0:257ba13e416e | 142 | |
co657_sjc80 | 0:257ba13e416e | 143 | // Read data bits (16+16) |
co657_sjc80 | 0:257ba13e416e | 144 | int16_t humidity = read_word(); |
co657_sjc80 | 0:257ba13e416e | 145 | int16_t temp = read_word(); |
co657_sjc80 | 0:257ba13e416e | 146 | |
co657_sjc80 | 0:257ba13e416e | 147 | // Read checksum (8) |
co657_sjc80 | 0:257ba13e416e | 148 | uint8_t checksum = read_checksum(); |
co657_sjc80 | 0:257ba13e416e | 149 | |
co657_sjc80 | 0:257ba13e416e | 150 | data->humidity = (humidity); |
co657_sjc80 | 0:257ba13e416e | 151 | data->temp = (temp); |
co657_sjc80 | 0:257ba13e416e | 152 | data->checksum = checksum; |
co657_sjc80 | 0:257ba13e416e | 153 | } |