OneWireSensor.c 9.2 KB

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