SingleWireSensor.c 9.2 KB

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