SingleWireSensor.c 9.3 KB

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