SingleWireSensor.c 9.1 KB

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