SingleWireSensor.c 9.4 KB

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