OneWireSensor.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include "OneWireSensor.h"
  2. #include <furi.h>
  3. #include <furi_hal.h>
  4. #include <one_wire/one_wire_host.h>
  5. const SensorType DS18x2x = {
  6. .typename = "DS18x2x",
  7. .interface = &ONE_WIRE,
  8. .pollingInterval = 250,
  9. .allocator = unitemp_OneWire_alloc,
  10. .mem_releaser = unitemp_OneWire_free,
  11. .initializer = unitemp_OneWire_init,
  12. .deinitializer = unitemp_OneWire_deinit,
  13. .updater = unitemp_OneWire_update};
  14. /**
  15. * @brief Запуск общения с датчиком
  16. *
  17. * @param sensor Указатель на датчик
  18. * @return Истина если датчик отозвался
  19. */
  20. static bool oneWire_start(OneWireSensor* instance) {
  21. furi_hal_gpio_write(instance->gpio->pin, false);
  22. furi_delay_us(500);
  23. furi_hal_gpio_write(instance->gpio->pin, true);
  24. //Ожидание подъёма шины
  25. uint32_t t = furi_get_tick();
  26. while(!furi_hal_gpio_read(instance->gpio->pin)) {
  27. //Выход если шина не поднялась
  28. if(furi_get_tick() - t > 100) return false;
  29. }
  30. furi_delay_us(100);
  31. bool status = !furi_hal_gpio_read(instance->gpio->pin);
  32. furi_delay_us(400);
  33. return status;
  34. }
  35. /**
  36. * @brief Запись байта на шину One Wire
  37. *
  38. * @param instance Указатель на инстанс датчика
  39. * @param data Записываемый байт
  40. */
  41. static void oneWire_write(OneWireSensor* instance, uint8_t data) {
  42. for(int i = 0; i < 8; i++) {
  43. if((data & (1 << i)) != 0) {
  44. // write 1
  45. furi_hal_gpio_write(instance->gpio->pin, false);
  46. furi_delay_us(1);
  47. furi_hal_gpio_write(instance->gpio->pin, true);
  48. furi_delay_us(90);
  49. } else {
  50. furi_hal_gpio_write(instance->gpio->pin, false);
  51. furi_delay_us(90);
  52. furi_hal_gpio_write(instance->gpio->pin, true);
  53. //Ожидание подъёма шины
  54. uint32_t t = furi_get_tick();
  55. while(!furi_hal_gpio_read(instance->gpio->pin)) {
  56. //Выход если шина не поднялась
  57. if(furi_get_tick() - t > 100) return;
  58. }
  59. }
  60. }
  61. }
  62. /**
  63. * @brief Чтение бита на шине One Wire
  64. *
  65. * @param instance Указатель на инстанс датчика
  66. * @return Логический уровень бита
  67. */
  68. static bool oneWire_read_bit(OneWireSensor* instance) {
  69. furi_hal_gpio_write(instance->gpio->pin, false);
  70. furi_delay_us(2); // Длительность низкого уровня, минимум 1 мкс
  71. furi_hal_gpio_write(instance->gpio->pin, true);
  72. furi_delay_us(8); // Пауза до момента сэмплирования, всего не более 15 мкс
  73. bool r = furi_hal_gpio_read(instance->gpio->pin);
  74. furi_delay_us(80); // Ожидание до следующего тайм-слота, минимум 60 мкс с начала низкого уровня
  75. return r;
  76. }
  77. /**
  78. * @brief Чтение байта с шины One Wire
  79. *
  80. * @param instance Указатель на инстанс датчика
  81. * @return Байт информации
  82. */
  83. static uint8_t oneWire_read(OneWireSensor* instance) {
  84. uint8_t r = 0;
  85. for(uint8_t p = 8; p; p--) {
  86. r >>= 1;
  87. if(oneWire_read_bit(instance)) r |= 0x80;
  88. }
  89. return r;
  90. }
  91. /**
  92. * @brief Чтение массива байт с шины One Wire
  93. *
  94. * @param instance Указатель на инстанс датчика
  95. * @param data Указатель на массив, куда будут записаны данные
  96. * @param len Количество байт
  97. */
  98. static void oneWire_readBytes(OneWireSensor* instance, uint8_t* data, size_t len) {
  99. for(size_t i = 0; i < len; i++) {
  100. data[i] = oneWire_read(instance);
  101. }
  102. }
  103. /**
  104. * @brief Запись массива байт на шину One Wire
  105. *
  106. * @param instance Указатель на инстанс датчика
  107. * @param data Указатель на массив, откуда будут записаны данные
  108. * @param len Количество байт
  109. */
  110. static void oneWire_writeBytes(OneWireSensor* instance, uint8_t* data, size_t len) {
  111. for(size_t i = 0; i < len; i++) {
  112. oneWire_write(instance, data[i]);
  113. }
  114. }
  115. bool unitemp_OneWire_alloc(void* s, uint16_t* anotherValues) {
  116. Sensor* sensor = (Sensor*)s;
  117. OneWireSensor* instance = malloc(sizeof(OneWireSensor));
  118. if(instance == NULL) {
  119. FURI_LOG_E(APP_NAME, "Sensor %s instance allocation error", sensor->name);
  120. return false;
  121. }
  122. sensor->instance = instance;
  123. instance->gpio = unitemp_GPIO_getFromInt(anotherValues[0]);
  124. if(instance->gpio != NULL) {
  125. return true;
  126. }
  127. FURI_LOG_E(APP_NAME, "Sensor %s GPIO setting error", sensor->name);
  128. free(instance);
  129. return false;
  130. }
  131. static uint8_t onewire_CRC_update(uint8_t crc, uint8_t b) {
  132. for(uint8_t p = 8; p; p--) {
  133. crc = ((crc ^ b) & 1) ? (crc >> 1) ^ 0b10001100 : (crc >> 1);
  134. b >>= 1;
  135. }
  136. return crc;
  137. }
  138. static bool onewire_CRC_check(uint8_t* data, size_t len) {
  139. uint8_t crc = 0;
  140. for(size_t i = 0; i < len; i++) {
  141. crc = onewire_CRC_update(crc, data[i]);
  142. }
  143. return !crc;
  144. }
  145. bool unitemp_OneWire_free(void* s) {
  146. Sensor* sensor = (Sensor*)s;
  147. free(sensor->instance);
  148. return true;
  149. }
  150. bool unitemp_OneWire_init(void* s) {
  151. OneWireSensor* instance = ((Sensor*)s)->instance;
  152. if(instance == NULL || instance->gpio == NULL) {
  153. FURI_LOG_E(APP_NAME, "Sensor pointer is null!");
  154. return false;
  155. }
  156. //Высокий уровень по умолчанию
  157. furi_hal_gpio_write(instance->gpio->pin, true);
  158. //Режим работы - OpenDrain, подтяжка включается на всякий случай
  159. furi_hal_gpio_init(
  160. instance->gpio->pin, //Порт FZ
  161. GpioModeOutputOpenDrain, //Режим работы - открытый сток
  162. GpioPullUp, //Принудительная подтяжка линии данных к питанию
  163. GpioSpeedVeryHigh); //Скорость работы - максимальная
  164. if(!oneWire_start(instance)) return false;
  165. oneWire_write(instance, 0x33); // Чтение ПЗУ
  166. uint8_t buff[8];
  167. oneWire_readBytes(instance, buff, 8);
  168. if(!onewire_CRC_check(buff, 8)) {
  169. return false;
  170. }
  171. FURI_LOG_D(APP_NAME, "%s family code: 0x%02X", ((Sensor*)s)->name, buff[0]);
  172. instance->familyCode = buff[0];
  173. if(instance->familyCode == FC_DS18B20 || instance->familyCode == FC_DS1822) {
  174. //Установка разрядности в 10 бит
  175. if(!oneWire_start(instance)) return false;
  176. oneWire_write(instance, 0xCC); // skip ROM
  177. oneWire_write(instance, 0x4E); // Запись в память
  178. buff[0] = 0x4B; //Значение нижнего предела
  179. buff[1] = 0x46; //Значение высшего предела
  180. buff[2] = 0x3F; //10 бит разрядность преобразования
  181. oneWire_writeBytes(instance, buff, 3);
  182. //Сохранение значений в EEPROM для автоматического восстановления после сбоев питания
  183. if(!oneWire_start(instance)) return false;
  184. oneWire_write(instance, 0xCC); // skip ROM
  185. oneWire_write(instance, 0x48); // Запись в EEPROM
  186. }
  187. return true;
  188. }
  189. bool unitemp_OneWire_deinit(void* s) {
  190. OneWireSensor* instance = ((Sensor*)s)->instance;
  191. if(instance == NULL || instance->gpio == NULL) return false;
  192. //Низкий уровень по умолчанию
  193. furi_hal_gpio_write(instance->gpio->pin, false);
  194. //Режим работы - аналог, подтяжка выключена
  195. furi_hal_gpio_init(
  196. instance->gpio->pin, //Порт FZ
  197. GpioModeAnalog, //Режим работы - аналог
  198. GpioPullNo, //Подтяжка выключена
  199. GpioSpeedLow); //Скорость работы - минимальная
  200. return true;
  201. }
  202. UnitempStatus unitemp_OneWire_update(void* s) {
  203. Sensor* sensor = (Sensor*)s;
  204. OneWireSensor* instance = ((Sensor*)s)->instance;
  205. if(sensor->status != UT_POLLING) {
  206. if(!oneWire_start(instance)) return UT_TIMEOUT;
  207. oneWire_write(instance, 0xCC); // skip ROM
  208. oneWire_write(instance, 0x44); // convert t
  209. return UT_POLLING;
  210. } else {
  211. if(!oneWire_start(instance)) return UT_TIMEOUT;
  212. oneWire_write(instance, 0xCC); // skip ROM
  213. oneWire_write(instance, 0xBE); // Read Scratch-pad
  214. uint8_t buff[9];
  215. oneWire_readBytes(instance, buff, 9);
  216. if(!onewire_CRC_check(buff, 9)) {
  217. return UT_BADCRC;
  218. }
  219. int16_t raw = buff[0] | ((int16_t)buff[1] << 8);
  220. if(instance->familyCode == FC_DS18S20) {
  221. sensor->temp = (float)raw / 2.0f;
  222. } else {
  223. sensor->temp = (float)raw / 16.0f;
  224. }
  225. }
  226. return UT_OK;
  227. }