SingleWireSensor.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include "SingleWireSensor.h"
  2. //Максимальное количество попугаев ожидания датчика
  3. #define POLLING_TIMEOUT_TICKS 500
  4. /* Типы датчиков и их параметры */
  5. const SensorType DHT11 = {
  6. .typename = "DHT11",
  7. .interface = &SINGLE_WIRE,
  8. .datatype = UT_DATA_TYPE_TEMP_HUM,
  9. .pollingInterval = 2000,
  10. .allocator = unitemp_singlewire_alloc,
  11. .mem_releaser = unitemp_singlewire_free,
  12. .initializer = unitemp_singlewire_init,
  13. .deinitializer = unitemp_singlewire_deinit,
  14. .updater = unitemp_singlewire_update};
  15. const SensorType DHT12_SW = {
  16. .typename = "DHT12",
  17. .interface = &SINGLE_WIRE,
  18. .datatype = UT_DATA_TYPE_TEMP_HUM,
  19. .pollingInterval = 2000,
  20. .allocator = unitemp_singlewire_alloc,
  21. .mem_releaser = unitemp_singlewire_free,
  22. .initializer = unitemp_singlewire_init,
  23. .deinitializer = unitemp_singlewire_deinit,
  24. .updater = unitemp_singlewire_update};
  25. const SensorType DHT21 = {
  26. .typename = "DHT21",
  27. .altname = "DHT21 (AM2301)",
  28. .interface = &SINGLE_WIRE,
  29. .datatype = UT_DATA_TYPE_TEMP_HUM,
  30. .pollingInterval = 1000,
  31. .allocator = unitemp_singlewire_alloc,
  32. .mem_releaser = unitemp_singlewire_free,
  33. .initializer = unitemp_singlewire_init,
  34. .deinitializer = unitemp_singlewire_deinit,
  35. .updater = unitemp_singlewire_update};
  36. const SensorType DHT22 = {
  37. .typename = "DHT22",
  38. .altname = "DHT22 (AM2302)",
  39. .interface = &SINGLE_WIRE,
  40. .datatype = UT_DATA_TYPE_TEMP_HUM,
  41. .pollingInterval = 2000,
  42. .allocator = unitemp_singlewire_alloc,
  43. .mem_releaser = unitemp_singlewire_free,
  44. .initializer = unitemp_singlewire_init,
  45. .deinitializer = unitemp_singlewire_deinit,
  46. .updater = unitemp_singlewire_update};
  47. const SensorType AM2320_SW = {
  48. .typename = "AM2320",
  49. .altname = "AM2320 (single wire)",
  50. .interface = &SINGLE_WIRE,
  51. .datatype = UT_DATA_TYPE_TEMP_HUM,
  52. .pollingInterval = 2000,
  53. .allocator = unitemp_singlewire_alloc,
  54. .mem_releaser = unitemp_singlewire_free,
  55. .initializer = unitemp_singlewire_init,
  56. .deinitializer = unitemp_singlewire_deinit,
  57. .updater = unitemp_singlewire_update};
  58. bool unitemp_singlewire_alloc(Sensor* sensor, char* args) {
  59. if(args == NULL) return false;
  60. SingleWireSensor* instance = malloc(sizeof(SingleWireSensor));
  61. if(instance == NULL) {
  62. FURI_LOG_E(APP_NAME, "Sensor %s instance allocation error", sensor->name);
  63. return false;
  64. }
  65. sensor->instance = instance;
  66. int gpio;
  67. sscanf(args, "%d", &gpio);
  68. if(unitemp_singlewire_sensorSetGPIO(sensor, unitemp_gpio_getFromInt(gpio))) {
  69. return true;
  70. }
  71. FURI_LOG_E(APP_NAME, "Sensor %s GPIO setting error", sensor->name);
  72. free(instance);
  73. return false;
  74. }
  75. bool unitemp_singlewire_free(Sensor* sensor) {
  76. free(sensor->instance);
  77. return true;
  78. }
  79. bool unitemp_singlewire_init(Sensor* sensor) {
  80. SingleWireSensor* instance = ((Sensor*)sensor)->instance;
  81. if(instance == NULL || instance->gpio == NULL) {
  82. FURI_LOG_E(APP_NAME, "Sensor pointer is null!");
  83. return false;
  84. }
  85. unitemp_gpio_lock(instance->gpio, &SINGLE_WIRE);
  86. //Высокий уровень по умолчанию
  87. furi_hal_gpio_write(instance->gpio->pin, true);
  88. //Режим работы - OpenDrain, подтяжка включается на всякий случай
  89. furi_hal_gpio_init(
  90. instance->gpio->pin, //Порт FZ
  91. GpioModeOutputOpenDrain, //Режим работы - открытый сток
  92. GpioPullUp, //Принудительная подтяжка линии данных к питанию
  93. GpioSpeedVeryHigh); //Скорость работы - максимальная
  94. return true;
  95. }
  96. bool unitemp_singlewire_deinit(Sensor* sensor) {
  97. SingleWireSensor* instance = ((Sensor*)sensor)->instance;
  98. if(instance == NULL || instance->gpio == NULL) return false;
  99. unitemp_gpio_unlock(instance->gpio);
  100. //Низкий уровень по умолчанию
  101. furi_hal_gpio_write(instance->gpio->pin, false);
  102. //Режим работы - аналог, подтяжка выключена
  103. furi_hal_gpio_init(
  104. instance->gpio->pin, //Порт FZ
  105. GpioModeAnalog, //Режим работы - аналог
  106. GpioPullNo, //Подтяжка выключена
  107. GpioSpeedLow); //Скорость работы - минимальная
  108. return true;
  109. }
  110. bool unitemp_singlewire_sensorSetGPIO(Sensor* sensor, const GPIO* gpio) {
  111. if(sensor == NULL || gpio == NULL) return false;
  112. SingleWireSensor* instance = sensor->instance;
  113. instance->gpio = gpio;
  114. return true;
  115. }
  116. const GPIO* unitemp_singlewire_sensorGetGPIO(Sensor* sensor) {
  117. if(sensor == NULL) return NULL;
  118. SingleWireSensor* instance = sensor->instance;
  119. return instance->gpio;
  120. }
  121. UnitempStatus unitemp_singlewire_update(Sensor* sensor) {
  122. SingleWireSensor* instance = sensor->instance;
  123. //Массив для приёма данных
  124. uint8_t data[5] = {0};
  125. /* Запрос */
  126. //Опускание линии
  127. furi_hal_gpio_write(instance->gpio->pin, false);
  128. //Ожидание более 18 мс
  129. furi_delay_ms(19);
  130. //Выключение прерываний, чтобы ничто не мешало обработке данных
  131. __disable_irq();
  132. //Подъём линии
  133. furi_hal_gpio_write(instance->gpio->pin, true);
  134. /* Ответ датчика */
  135. //Переменная-счётчик
  136. uint16_t timeout = 0;
  137. //Ожидание подъёма линии
  138. while(!furi_hal_gpio_read(instance->gpio->pin)) {
  139. timeout++;
  140. if(timeout > POLLING_TIMEOUT_TICKS) {
  141. //Включение прерываний
  142. __enable_irq();
  143. //Возврат признака отсутствующего датчика
  144. return UT_TIMEOUT;
  145. }
  146. }
  147. timeout = 0;
  148. //Ожидание спада линии
  149. while(furi_hal_gpio_read(instance->gpio->pin)) {
  150. timeout++;
  151. if(timeout > POLLING_TIMEOUT_TICKS) {
  152. //Включение прерываний
  153. __enable_irq();
  154. //Возврат признака отсутствующего датчика
  155. return UT_TIMEOUT;
  156. }
  157. }
  158. //Ожидание подъёма линии
  159. while(!furi_hal_gpio_read(instance->gpio->pin)) {
  160. timeout++;
  161. if(timeout > POLLING_TIMEOUT_TICKS) {
  162. //Включение прерываний
  163. __enable_irq();
  164. //Возврат признака отсутствующего датчика
  165. return UT_TIMEOUT;
  166. }
  167. }
  168. timeout = 0;
  169. //Ожидание спада линии
  170. while(furi_hal_gpio_read(instance->gpio->pin)) {
  171. timeout++;
  172. if(timeout > POLLING_TIMEOUT_TICKS) {
  173. //Включение прерываний
  174. __enable_irq();
  175. //Возврат признака отсутствующего датчика
  176. return UT_TIMEOUT;
  177. }
  178. }
  179. /* Чтение данных с датчика*/
  180. //Приём 5 байт
  181. for(uint8_t a = 0; a < 5; a++) {
  182. for(uint8_t b = 7; b != 255; b--) {
  183. uint16_t hT = 0, lT = 0;
  184. //Пока линия в низком уровне, инкремент переменной lT
  185. while(!furi_hal_gpio_read(instance->gpio->pin) && lT != 65535) lT++;
  186. //Пока линия в высоком уровне, инкремент переменной hT
  187. while(furi_hal_gpio_read(instance->gpio->pin) && hT != 65535) hT++;
  188. //Если hT больше lT, то пришла единица
  189. if(hT > lT) data[a] |= (1 << b);
  190. }
  191. }
  192. //Включение прерываний
  193. __enable_irq();
  194. //Проверка контрольной суммы
  195. if((uint8_t)(data[0] + data[1] + data[2] + data[3]) != data[4]) {
  196. //Если контрольная сумма не совпала, возврат ошибки
  197. return UT_BADCRC;
  198. }
  199. /* Преобразование данных в явный вид */
  200. //DHT11 и DHT12
  201. if(sensor->type == &DHT11 || sensor->type == &DHT12_SW) {
  202. sensor->hum = (float)data[0];
  203. sensor->temp = (float)data[2];
  204. //Проверка на отрицательность температуры
  205. if(data[3] != 0) {
  206. //Проверка знака
  207. if(!(data[3] & (1 << 7))) {
  208. //Добавление положительной дробной части
  209. sensor->temp += data[3] * 0.1f;
  210. } else {
  211. //А тут делаем отрицательное значение
  212. data[3] &= ~(1 << 7);
  213. sensor->temp += data[3] * 0.1f;
  214. sensor->temp *= -1;
  215. }
  216. }
  217. }
  218. //DHT21, DHT22, AM2320
  219. if(sensor->type == &DHT21 || sensor->type == &DHT22 || sensor->type == &AM2320_SW) {
  220. sensor->hum = (float)(((uint16_t)data[0] << 8) | data[1]) / 10;
  221. //Проверка на отрицательность температуры
  222. if(!(data[2] & (1 << 7))) {
  223. sensor->temp = (float)(((uint16_t)data[2] << 8) | data[3]) / 10;
  224. } else {
  225. data[2] &= ~(1 << 7);
  226. sensor->temp = (float)(((uint16_t)data[2] << 8) | data[3]) / 10 * -1;
  227. }
  228. }
  229. //Возврат признака успешного опроса
  230. return UT_OK;
  231. }