SingleWireSensor.c 9.2 KB

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