1. /* 2. * DHT.h 4. * 10/28/17 6. * Library providing functions to read the DHT 22 temperature/ 8. * library into C (MIT License), with other input from the DHT 22 10. */ 12. #include 14. #define DHT_PORT PORTD 16. #define DHT_DDR DDRD 18. #define LOW 0 20. 22. uint8_t data[6]; 24. /* 25. * Call at the beginning of any program that uses the DHT sensor 26. * @param pin – indicates the pin in PORTD to be used 27. * to communicate with the DHT sensor 28. */ 29. void dht_init(uint8_t pin); 30. 31. /* 32. * returns the temperature read by the sensor 33. * @param rdFar – set to 1 to return temp in Farenheit, 0 for celcius 34. */ 35. float readTemp(uint8_t rdFar); 36. 37. /* 38. * Used by read temp to convert output to the correct units 39. */ 40. float convCtoF(float c); 41. float convFtoC(float f); 42. 43. /* 44. * reads the humidity read by the sensor 45. */ 46. float readHumidity(void); 47. 48. /* 49. * executes the read operation 50. * used by readHumidity and readTemperature 51. */ 52. uint8_t read(void); 53. 54. /* 55. * Used in determining the length of each puls 56. */ 57. uint32_t expectPulse(uint8_t lvl); 23. } 24. 25. float readTemp(uint8_t rdFar) { 26. 27. float f = 0; // could be NAN 28. 29. if (read()) { 30. f = data[2] & 0x7F; // high bit 31. f *= 256; 32. f += data[3]; // decimal portion 33. f *= 0.1; // comes out of sensor 10x actual value 34. if (data[2] & 0x80) 35. f *= -1; // check sign bit 36. if (rdFar) 37. f = convCtoF(f); 38. } 39. return f; 40. } 41. 42. float convCtoF(float c) { 43. return (c * (9.0/5.0)) + 32; 44. } 45. 46. float convFtoC(float f) { 47. return (f - 32) * (5.0/9.0); 48. } 49. 50. float readHumidity(void) { 51. 52. float f = 0; 53. if (read()) { // doesnt have the force term (note to self) 54. f = data[0]; // high bit 55. f *= 256; 56. f += data[1]; // decimal portion 57. f *= 0.1; // comes out of sensor 10x actual value 58. } 59. return f; 60. } 61. 62. uint8_t read(void) { 63. 64. int i; 65. uint32_t cycles[80]; 66. uint32_t lowCycles; 67. uint32_t highCycles; 68. 69. // clear out data from last read 70. data[0] = data[1] = data[2] = data[3] = data[4] = 0; 71. 72. // START SIGNAL 73. // see DHT22 datasheet for signal diagram 74. 75. DHT_PORT |= (1 << _pin); // go into high impedance state ?(conflicts with data she et) 76. _delay_ms(250); // PUD in MCUCR? 77. 78. // pull data line low for 20 ms 79. DHT_DDR |= (1 << _pin); 80. DHT_PORT &= ~(1 << _pin); 81. _delay_ms(20); 82. 83. cli(); // timing is critical, can't be interrupted 84. DHT_PORT |= (1 << _pin); 85. _delay_us(40); // per datasheet 86. 87. // READ RESPONSE 88. // convert pin to input with pull up enabled 89. DHT_DDR &= ~(1 << _pin); 90. DHT_PORT |= (1 << _pin); 91. _delay_us(10); 92. 93. // Expect a low signal for ~80us followed by a high signal 94. // for ~80us again 95. if (expectPulse(LOW) == 0) 96. return 0; 97. 98. if (expectPulse(HIGH) == 0) 99. return 0; 100. 101. for (i = 0; i < 80; i+=2) { 102. cycles[i] = expectPulse(LOW); 103. cycles[i+1] = expectPulse(HIGH); 104. } 105. 106. sei(); // timing no longer critical 107. 108. for (i = 0; i < 40; ++i) { 109. lowCycles = cycles[2*i]; 110. highCycles = cycles[2*i+1]; 111. if (lowCycles == 0 || highCycles == 0) // error handling 112. return 0; 113. data[i/8] <<= 1; 114. 115. // check cycle time to determine if the bit is a 1 or a zero 116. if (highCycles > lowCycles) 117. data[i/8] |= 1; 118. // otherwise the bit is a 0 119. } 120. 121. if (data[4] == ((data[3] + data[2] + data[1] + data[0]) & 0xFF)) 122. return 1; 123. else 124. return 0; 125. } 126. 127. uint32_t expectPulse(uint8_t lvl) { 128. 129. uint32_t count = 0; 130. uint8_t portState; 131. while (((DHT_PIN & (1<<_pin)) >> _pin) == lvl) { // while still expec ted state 132. if (count++ >= _maxCycles) { // exit if it goes too long 133. return 0; // Exceeded timeout, fail. 134. } 135. } 136. return count; 137. 138. } 139.