SingleWireSensor.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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 (single wire)",
  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 (single wire)",
  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. //Низкий уровень по умолчанию
  91. furi_hal_gpio_write(instance->gpio->pin, false);
  92. //Режим работы - аналог, подтяжка выключена
  93. furi_hal_gpio_init(
  94. instance->gpio->pin, //Порт FZ
  95. GpioModeAnalog, //Режим работы - аналог
  96. GpioPullNo, //Подтяжка выключена
  97. GpioSpeedLow); //Скорость работы - минимальная
  98. return true;
  99. }
  100. bool unitemp_singleWire_sensorSetGPIO(Sensor* sensor, const GPIO* gpio) {
  101. if(sensor == NULL || gpio == NULL) return false;
  102. SingleWireSensor* instance = sensor->instance;
  103. instance->gpio = gpio;
  104. return true;
  105. }
  106. const GPIO* unitemp_singleWire_sensorGetGPIO(Sensor* sensor) {
  107. if(sensor == NULL) return NULL;
  108. SingleWireSensor* instance = sensor->instance;
  109. return instance->gpio;
  110. }
  111. UnitempStatus unitemp_singleWire_update(Sensor* sensor) {
  112. SingleWireSensor* instance = sensor->instance;
  113. //Массив для приёма данных
  114. uint8_t data[5] = {0};
  115. /* Запрос */
  116. //Опускание линии
  117. furi_hal_gpio_write(instance->gpio->pin, false);
  118. //Ожидание более 18 мс
  119. furi_delay_ms(19);
  120. //Выключение прерываний, чтобы ничто не мешало обработке данных
  121. __disable_irq();
  122. //Подъём линии
  123. furi_hal_gpio_write(instance->gpio->pin, true);
  124. /* Ответ датчика */
  125. //Переменная-счётчик
  126. uint16_t timeout = 0;
  127. //Ожидание подъёма линии
  128. while(!furi_hal_gpio_read(instance->gpio->pin)) {
  129. timeout++;
  130. if(timeout > POLLING_TIMEOUT_TICKS) {
  131. //Включение прерываний
  132. __enable_irq();
  133. //Возврат признака отсутствующего датчика
  134. return UT_TIMEOUT;
  135. }
  136. }
  137. timeout = 0;
  138. //Ожидание спада линии
  139. while(furi_hal_gpio_read(instance->gpio->pin)) {
  140. timeout++;
  141. if(timeout > POLLING_TIMEOUT_TICKS) {
  142. //Включение прерываний
  143. __enable_irq();
  144. //Возврат признака отсутствующего датчика
  145. return UT_TIMEOUT;
  146. }
  147. }
  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. timeout = 0;
  159. //Ожидание спада линии
  160. while(furi_hal_gpio_read(instance->gpio->pin)) {
  161. timeout++;
  162. if(timeout > POLLING_TIMEOUT_TICKS) {
  163. //Включение прерываний
  164. __enable_irq();
  165. //Возврат признака отсутствующего датчика
  166. return UT_TIMEOUT;
  167. }
  168. }
  169. /* Чтение данных с датчика*/
  170. //Приём 5 байт
  171. for(uint8_t a = 0; a < 5; a++) {
  172. for(uint8_t b = 7; b != 255; b--) {
  173. uint16_t hT = 0, lT = 0;
  174. //Пока линия в низком уровне, инкремент переменной lT
  175. while(!furi_hal_gpio_read(instance->gpio->pin) && lT != 65535) lT++;
  176. //Пока линия в высоком уровне, инкремент переменной hT
  177. while(furi_hal_gpio_read(instance->gpio->pin) && hT != 65535) hT++;
  178. //Если hT больше lT, то пришла единица
  179. if(hT > lT) data[a] |= (1 << b);
  180. }
  181. }
  182. //Включение прерываний
  183. __enable_irq();
  184. //Проверка контрольной суммы
  185. if((uint8_t)(data[0] + data[1] + data[2] + data[3]) != data[4]) {
  186. //Если контрольная сумма не совпала, возврат ошибки
  187. return UT_BADCRC;
  188. }
  189. /* Преобразование данных в явный вид */
  190. //DHT11 и DHT12
  191. if(sensor->type == &DHT11 || sensor->type == &DHT12_SW) {
  192. sensor->hum = (float)data[0];
  193. sensor->temp = (float)data[2];
  194. //Проверка на отрицательность температуры
  195. if(data[3] != 0) {
  196. //Проверка знака
  197. if(!(data[3] & (1 << 7))) {
  198. //Добавление положительной дробной части
  199. sensor->temp += data[3] * 0.1f;
  200. } else {
  201. //А тут делаем отрицательное значение
  202. data[3] &= ~(1 << 7);
  203. sensor->temp += data[3] * 0.1f;
  204. sensor->temp *= -1;
  205. }
  206. }
  207. }
  208. //DHT21, DHT22, AM2320
  209. if(sensor->type == &DHT21 || sensor->type == &DHT22 || sensor->type == &AM2320_SW) {
  210. sensor->hum = (float)(((uint16_t)data[0] << 8) | data[1]) / 10;
  211. //Проверка на отрицательность температуры
  212. if(!(data[2] & (1 << 7))) {
  213. sensor->temp = (float)(((uint16_t)data[2] << 8) | data[3]) / 10;
  214. } else {
  215. data[2] &= ~(1 << 7);
  216. sensor->temp = (float)(((uint16_t)data[2] << 8) | data[3]) / 10 * -1;
  217. }
  218. }
  219. //Возврат признака успешного опроса
  220. return UT_OK;
  221. }