SingleWireSensor.c 9.2 KB

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