No Image

Ds18b20 несколько датчиков на одну линию

СОДЕРЖАНИЕ
799 просмотров
10 марта 2020

Продолжаем работу с датчиком температуры DS18B20, который подключается посредством однопроводной шины 1-WIRE. Вернее не с датчиком, а с несколькими датчиками, подключенными на один провод. А точнее не с несколькими, а с двумя, потому что больше у меня нет.

Данный урок был очень востребован, и, как я и обещал в занятии по данному датчику, он не заставил себя долго ждать.

Первый датчик у нас уже был подключен на макетной плате, правда я её заменил на меньшего размера, а второй датчик у меня несколько в другом исполнении — в экране и на проводе. Такие варианты также существуют в широкой продаже и используются в более тяжёлых условиях (незащищённых от атмосферных и иных воздействий).

Теперь наша схема выглядит следующим образом (нажмите на картинку для увеличения изображения):

Второй датчик подключен полностью параллельно первому (все три вывода).

Начнём теперь потихоньку разбираться, как же можно на одном проводе давать команды и получать данные одновременно из двух датчиков. Как известно, для этого существует уникальный серийный 64-битный код, который нам и предстоит сегодня считать с обоих датчиков для того, чтобы по этим кодам раздельно к ним и обращаться.

Проект создадим полностью на основе проекта DS18B20 урока 92 и присвоем ему имя DS18B20_MORE_SENSORS.

Откроем наш проект в Cube MX и, ничего в нём не трогая, сгенерируем проект для Keil и также откроем его там. Настроим программатор на автоперезагрузку, включим уровень оптимизации 1, подключим файл ds18b20.c и будем думать, как нам считать этот серийный идентефикатор. Оказывается, это не совсем просто. Есть команда Read ROM с кодом 0x33, которая читает серийный код, она не сложная. Мы отправляем её датчику и датчик нам выдаёт 8 заветных байтов. Но есть одна небольшая проблемка: данная команда работает только при условии, что у нас будет подключен только один датчик. Можно подключить датчики по очереди, считать с них данные коды и потом подключить их вместе и по этим кодам обращаться, но, согласитесь, для рядового пользователя, для которого мы разрабатываем устройство, это будет, мягко говоря, трудновато. Поэтому есть другая команда, которая считывает идентификаторы со всех датчиков, подключенных одновременно. Это команда Search Rom с кодом 0xF0. Но тут тоже не всё так просто, Придётся написать очень нелёгкий алгоритм, так как с первого раза данная команда не работает. Вот этим мы и займёмся сегодня. Поэтому и был для этого написан отдельный урок.

Также, чтобы узнать подробно, как работает команда поиска идентификатора, существует уже другая документация, разработанная не отдельно для нашего датчика, а для интерфейса 1-WIRE по технологии iButton. Application Note 937. При желании узнать ещё больше, чем вам здесь дам я, вы можете данную книгу найти без труда.

Разбираться с этим поиском мы будем постепенно. А пока создадим для этого функцию в файле ds18b20.c над функцией инициализации датчика

uint8_t ds18b20_SearhRom( uint8_t *Addr)

uint8_t id_bit_number;

uint8_t last_zero, rom_byte_number, search_result;

uint8_t id_bit, cmp_id_bit;

uint8_t rom_byte_mask, search_direction;

//проинициализируем переменные

last_zero = 0;

rom_byte_number = 0;

rom_byte_mask = 1;

search_result = 0;

return search_result;

В функции мы создали и проинициализировали ряд переменных, которые нам потребуются в дальнейшем в данной функции. В качестве входного аргумента мы будем передавать адрес восьмибайтного массива, в который функция будет записывать очередной серийный код определённого датчика.

Добавим две глобальные переменные в файл main.c

uint8_t Dev_ >

uint8_t Dev_Cnt;

Одна переменная будет для хранения нескольких серийных номеров (я думаю больше восьми датчиков мы не будем подключать, а если будем, то изменим первую размерность), а вторая — для количества датчиков на шине, которое мы затем определим программно.

Также добавим несколько глобальных переменных в файл ds18b20.c, а также подключим две переменные, добавленные выше

uint8_t LastDeviceFlag;

uint8_t LastDiscrepancy;

uint8_t LastFamilyDiscrepancy;

uint8_t ROM_NO[8];

extern uint8_t Dev_ID[8][8];

extern uint8_t Dev_Cnt;

Вернёмся в нашу функцию ds18b20_SearhRom и напишем следующее условие

if (!LastDeviceFlag)

ds18b20_Reset();

ds18b20_WriteByte(0xF0);

В тело данного условия мы попадём если флаг последнего устройства у нас не будет установлен. Мы здесь перезагрузим наши датчики и отправим в них во все команду Search Rom.

Ну а теперь давайте немного разберёмся, как происходит процесс поиска серийных номеров. Всё это описано в вышеупомянутой книге, но я постараюсь донести это как-то вкратце и постепенно, оформляя также полученные знания в код.

После отправки команды Search Rom (0xF0) все устройства будут последовательно формировать на шине состояние и 1, соответствующее значению их фактического бита в ROM. Процесс чтения начинается с самого младшего бита кода и проходит в два такта времени. Если все устройства на шине в очередном считываемом бите содержат , то будет последовательно присутствовать на шине 01. Если оба устройства будут содержать 1, то результат будет 10. Всё это имеет место, если у всех устройств одинаковые биты в данной позиции. А если будет хотя бы у одного устройства результат другой, то это приведёт к результату 00, указывая на конфликт. Далее в следующем (в третьем) такте контроллер передаёт 0 или 1, чтобы отобрать устройства, у которых совпадёт данный бит с битом содержащимся в его идентификаторе. Устройства, у которых бит не совпадёт, перейдут в состояние ожидания и будут в нём находиться до тех пор, пока не получат импульс сброса (перезагрузки). Затем идёт следующий аналогичный цикл из трёх тактов для следующего бита. Итого таких циклов будет 64, а тактов получается 192, в течении которых контроллер определит код одного из устройств, остальные будут обязательно находиться в режиме ожидания, на то он и уникальный — этот код. По этому коду контроллер сможет спокойно затем обращаться к данному устройству. То есть оставшиеся циклы уже будут проходить без конфликтов и будут уже иметь определённый результат.

Далее у нас остаются ещё устройства, у которых мы код пока не считали. Поэтому мы повторяем данную процедуру сначала и должны дойти до того цикла, когда контроллер последний раз поймал конфликт, но отправим мы уже в следующем цикле не 0, а 1, что приведёт в режим ожидания уже другое устройство, это будет именно то устройство, код которого мы и считали в первой процедуре.

Далее мы процедуру повторяем заново до очередного последнего конфликта (ну или предпоследнего, если считать предыдущий последним) и ведём себя таким же образом, как и при считывании кода второго устройства и это действие приведёт в режим ожидания оба устройства, коды которых мы считали во втором этапе.

И таким образом мы поступаем, повторяя процедуры до тех пор, пока конфликтов не будет вообще.

Конечно без практики, я понимаю, данный процесс не понять. Поэтому в документации приведён был конкретный пример, в котором идентифицировались 4 устройства на шине 1-WIRE

Для простоты все биты идентификаторов не показываются и старшие биты обозначены символами x.

Процесс чтения, как я уже и говорил, происходит с самого малдшего байта. Поторим вышенаписанное на данном примере.

1. Контроллер формирует импульс сброса, на что все устройства отвечают импульсом присутствия.

2. Контроллер отправляет команду 0xF0 (Search ROM).

3. Контроллер читает один бит с шины, на что устройства ответят 00, что позволяет говорить о разрядном конфликте, означающем, что устройства в данном разряде имеют разное состояние.

Читайте также:  Что дает прошивка планшета

4. Контроллер отправляет бит в шину, что приведёт устройства 2 и 3 в состояние ожидания и также к тому, что при всех следующих операциях до сброса данные устройства уже не будут откликаться.

5. Контроллер читает следующий бит, получая 01, так как результат у 1 и 4 устройства, которые остались способными откликаться на команды биты одинаковые и равны 0.

6. Контроллер отправляет бит в шину для того, чтобы оба устройства остались в активном режиме, не отключать же их все.

7. Контроллер снова читает следующий бит, используя два такта чтения и получает 00, что соответствует разрядному конфликту, опять же позволяющему судить о том, что биты у устройств разные.

8. Контроллер снова отправляет бит в шину, что приведёт устройство 1 к переходу в режим ожидания и в результате этого у нас способным откликаться останется только одно устройство. Но то, что оно одно, мы просто знаем заведомо. А на практике нам это ещё не известно. Поэтому продолжаем чтение до самого старшего 63 бита.

9. Остальные все циклы чтения не приведут к конфликтам, так как у нас уже не будет разных битов на шине, так как устройство у нас только одно, тем самым мы считаем один идентификатор до конца.

10. Теперь мы должны прочитать идентификатор следующего устройства, для чего должны повторить шаги от 1 до 7, соответственно активируя заново все устройства.

11. В самой старшей позиции, в которой контроллер после обнаружения последнего конфликта писал 0, контроллер уже пишет 1. Это уже приведёт к переходу в режим ожидания уже устройство 4, что даст нам дочитать код ROM устройства 1.

12. Читаем код устройства 1 до конца.

13. Далее нам требуется считать ROM следующего устройства (одного из устройств 2 или 3). Для этого мы уже повторяем шаги только с 1 до 3.

14. В самой старшей позиции, в которой контроллер после обнаружения последнего конфликта в проходе втором писал 0, контроллер уже пишет 1. Это приведёт к переходу в режим ожидания устройства 1 и 4.

15. Дальше читаем следующий бит, получая 00, что означает, что биты у устройств 2 и 3 разные.

16. Контроллер посывает в шину , что приведёт к отключению устройство 3, оставляя устроство 2, как единственное активное.

17. Читаем код устройства 2 до конца.

18. Далее мы должны считать код идентификации последнего устройства 3, выполняя шаги 13 — 15.

19. В самой старшей позиции, в которой контроллер после обнаружения последнего конфликта в проходе третьем писал 0, контроллер уже пишет 1. Это приведёт к переходу в режим ожидания устройство 2, оставляя устройство 3 активным.

20. Читаем код ROM устройства 3 до конца.

Теперь у нас считаны коды всех 4 устройств. Если устройств на шине будет больше, то проходов тоже будет больше и шагов, следовательно, тоже.

Надеюсь, что теперь вам процесс считывания кодов стал более понятен.

Также у нас будет возможность это ещё раз закрепить, когда мы будем выдумывать алгоритм при написании кода функции поиска кодов, также ещё закрепляя визуально, поглядывая на результаты логического анализа на шине.

В следующей части урока мы напишем полностью функцию поиска идентификаторов датчиков и считаем уникальные коды со всех датчиков температуры.

Отладочную плату можно приобрести здесь STM32F103C8T6

Датчик температуры в экране с проводом можно приобрести здесь DS18B20 в экране с проводом

Переходник USB to TTL можно приобрести здесь ftdi ft232rl

Смотреть ВИДЕОУРОК (нажмите на картинку)

Продолжаем работу с датчиком температуры DS18B20, который подключается посредством однопроводной шины 1-WIRE. Вернее не с датчиком, а с несколькими датчиками, подключенными на один провод. А точнее не с несколькими, а с двумя, потому что больше у меня нет.

Данный урок был очень востребован, и, как я и обещал в занятии по данному датчику, он не заставил себя долго ждать.

Первый датчик у нас уже был подключен на макетной плате, правда я её заменил на меньшего размера, а второй датчик у меня несколько в другом исполнении — в экране и на проводе. Такие варианты также существуют в широкой продаже и используются в более тяжёлых условиях (незащищённых от атмосферных и иных воздействий).

Теперь наша схема выглядит следующим образом (нажмите на картинку для увеличения изображения):

Второй датчик подключен полностью параллельно первому (все три вывода).

Начнём теперь потихоньку разбираться, как же можно на одном проводе давать команды и получать данные одновременно из двух датчиков. Как известно, для этого существует уникальный серийный 64-битный код, который нам и предстоит сегодня считать с обоих датчиков для того, чтобы по этим кодам раздельно к ним и обращаться.

Проект создадим полностью на основе проекта DS18B20 урока 92 и присвоем ему имя DS18B20_MORE_SENSORS.

Откроем наш проект в Cube MX и, ничего в нём не трогая, сгенерируем проект для Keil и также откроем его там. Настроим программатор на автоперезагрузку, включим уровень оптимизации 1, подключим файл ds18b20.c и будем думать, как нам считать этот серийный идентефикатор. Оказывается, это не совсем просто. Есть команда Read ROM с кодом 0x33, которая читает серийный код, она не сложная. Мы отправляем её датчику и датчик нам выдаёт 8 заветных байтов. Но есть одна небольшая проблемка: данная команда работает только при условии, что у нас будет подключен только один датчик. Можно подключить датчики по очереди, считать с них данные коды и потом подключить их вместе и по этим кодам обращаться, но, согласитесь, для рядового пользователя, для которого мы разрабатываем устройство, это будет, мягко говоря, трудновато. Поэтому есть другая команда, которая считывает идентификаторы со всех датчиков, подключенных одновременно. Это команда Search Rom с кодом 0xF0. Но тут тоже не всё так просто, Придётся написать очень нелёгкий алгоритм, так как с первого раза данная команда не работает. Вот этим мы и займёмся сегодня. Поэтому и был для этого написан отдельный урок.

Также, чтобы узнать подробно, как работает команда поиска идентификатора, существует уже другая документация, разработанная не отдельно для нашего датчика, а для интерфейса 1-WIRE по технологии iButton. Application Note 937. При желании узнать ещё больше, чем вам здесь дам я, вы можете данную книгу найти без труда.

Разбираться с этим поиском мы будем постепенно. А пока создадим для этого функцию в файле ds18b20.c над функцией инициализации датчика

uint8_t ds18b20_SearhRom( uint8_t *Addr)

uint8_t id_bit_number;

uint8_t last_zero, rom_byte_number, search_result;

uint8_t id_bit, cmp_id_bit;

uint8_t rom_byte_mask, search_direction;

//проинициализируем переменные

last_zero = 0;

rom_byte_number = 0;

rom_byte_mask = 1;

search_result = 0;

return search_result;

В функции мы создали и проинициализировали ряд переменных, которые нам потребуются в дальнейшем в данной функции. В качестве входного аргумента мы будем передавать адрес восьмибайтного массива, в который функция будет записывать очередной серийный код определённого датчика.

Добавим две глобальные переменные в файл main.c

uint8_t Dev_ >

uint8_t Dev_Cnt;

Одна переменная будет для хранения нескольких серийных номеров (я думаю больше восьми датчиков мы не будем подключать, а если будем, то изменим первую размерность), а вторая — для количества датчиков на шине, которое мы затем определим программно.

Читайте также:  Убрать известковый налет с нержавейки

Также добавим несколько глобальных переменных в файл ds18b20.c, а также подключим две переменные, добавленные выше

uint8_t LastDeviceFlag;

uint8_t LastDiscrepancy;

uint8_t LastFamilyDiscrepancy;

uint8_t ROM_NO[8];

extern uint8_t Dev_ID[8][8];

extern uint8_t Dev_Cnt;

Вернёмся в нашу функцию ds18b20_SearhRom и напишем следующее условие

if (!LastDeviceFlag)

ds18b20_Reset();

ds18b20_WriteByte(0xF0);

В тело данного условия мы попадём если флаг последнего устройства у нас не будет установлен. Мы здесь перезагрузим наши датчики и отправим в них во все команду Search Rom.

Ну а теперь давайте немного разберёмся, как происходит процесс поиска серийных номеров. Всё это описано в вышеупомянутой книге, но я постараюсь донести это как-то вкратце и постепенно, оформляя также полученные знания в код.

После отправки команды Search Rom (0xF0) все устройства будут последовательно формировать на шине состояние и 1, соответствующее значению их фактического бита в ROM. Процесс чтения начинается с самого младшего бита кода и проходит в два такта времени. Если все устройства на шине в очередном считываемом бите содержат , то будет последовательно присутствовать на шине 01. Если оба устройства будут содержать 1, то результат будет 10. Всё это имеет место, если у всех устройств одинаковые биты в данной позиции. А если будет хотя бы у одного устройства результат другой, то это приведёт к результату 00, указывая на конфликт. Далее в следующем (в третьем) такте контроллер передаёт 0 или 1, чтобы отобрать устройства, у которых совпадёт данный бит с битом содержащимся в его идентификаторе. Устройства, у которых бит не совпадёт, перейдут в состояние ожидания и будут в нём находиться до тех пор, пока не получат импульс сброса (перезагрузки). Затем идёт следующий аналогичный цикл из трёх тактов для следующего бита. Итого таких циклов будет 64, а тактов получается 192, в течении которых контроллер определит код одного из устройств, остальные будут обязательно находиться в режиме ожидания, на то он и уникальный — этот код. По этому коду контроллер сможет спокойно затем обращаться к данному устройству. То есть оставшиеся циклы уже будут проходить без конфликтов и будут уже иметь определённый результат.

Далее у нас остаются ещё устройства, у которых мы код пока не считали. Поэтому мы повторяем данную процедуру сначала и должны дойти до того цикла, когда контроллер последний раз поймал конфликт, но отправим мы уже в следующем цикле не 0, а 1, что приведёт в режим ожидания уже другое устройство, это будет именно то устройство, код которого мы и считали в первой процедуре.

Далее мы процедуру повторяем заново до очередного последнего конфликта (ну или предпоследнего, если считать предыдущий последним) и ведём себя таким же образом, как и при считывании кода второго устройства и это действие приведёт в режим ожидания оба устройства, коды которых мы считали во втором этапе.

И таким образом мы поступаем, повторяя процедуры до тех пор, пока конфликтов не будет вообще.

Конечно без практики, я понимаю, данный процесс не понять. Поэтому в документации приведён был конкретный пример, в котором идентифицировались 4 устройства на шине 1-WIRE

Для простоты все биты идентификаторов не показываются и старшие биты обозначены символами x.

Процесс чтения, как я уже и говорил, происходит с самого малдшего байта. Поторим вышенаписанное на данном примере.

1. Контроллер формирует импульс сброса, на что все устройства отвечают импульсом присутствия.

2. Контроллер отправляет команду 0xF0 (Search ROM).

3. Контроллер читает один бит с шины, на что устройства ответят 00, что позволяет говорить о разрядном конфликте, означающем, что устройства в данном разряде имеют разное состояние.

4. Контроллер отправляет бит в шину, что приведёт устройства 2 и 3 в состояние ожидания и также к тому, что при всех следующих операциях до сброса данные устройства уже не будут откликаться.

5. Контроллер читает следующий бит, получая 01, так как результат у 1 и 4 устройства, которые остались способными откликаться на команды биты одинаковые и равны 0.

6. Контроллер отправляет бит в шину для того, чтобы оба устройства остались в активном режиме, не отключать же их все.

7. Контроллер снова читает следующий бит, используя два такта чтения и получает 00, что соответствует разрядному конфликту, опять же позволяющему судить о том, что биты у устройств разные.

8. Контроллер снова отправляет бит в шину, что приведёт устройство 1 к переходу в режим ожидания и в результате этого у нас способным откликаться останется только одно устройство. Но то, что оно одно, мы просто знаем заведомо. А на практике нам это ещё не известно. Поэтому продолжаем чтение до самого старшего 63 бита.

9. Остальные все циклы чтения не приведут к конфликтам, так как у нас уже не будет разных битов на шине, так как устройство у нас только одно, тем самым мы считаем один идентификатор до конца.

10. Теперь мы должны прочитать идентификатор следующего устройства, для чего должны повторить шаги от 1 до 7, соответственно активируя заново все устройства.

11. В самой старшей позиции, в которой контроллер после обнаружения последнего конфликта писал 0, контроллер уже пишет 1. Это уже приведёт к переходу в режим ожидания уже устройство 4, что даст нам дочитать код ROM устройства 1.

12. Читаем код устройства 1 до конца.

13. Далее нам требуется считать ROM следующего устройства (одного из устройств 2 или 3). Для этого мы уже повторяем шаги только с 1 до 3.

14. В самой старшей позиции, в которой контроллер после обнаружения последнего конфликта в проходе втором писал 0, контроллер уже пишет 1. Это приведёт к переходу в режим ожидания устройства 1 и 4.

15. Дальше читаем следующий бит, получая 00, что означает, что биты у устройств 2 и 3 разные.

16. Контроллер посывает в шину , что приведёт к отключению устройство 3, оставляя устроство 2, как единственное активное.

17. Читаем код устройства 2 до конца.

18. Далее мы должны считать код идентификации последнего устройства 3, выполняя шаги 13 — 15.

19. В самой старшей позиции, в которой контроллер после обнаружения последнего конфликта в проходе третьем писал 0, контроллер уже пишет 1. Это приведёт к переходу в режим ожидания устройство 2, оставляя устройство 3 активным.

20. Читаем код ROM устройства 3 до конца.

Теперь у нас считаны коды всех 4 устройств. Если устройств на шине будет больше, то проходов тоже будет больше и шагов, следовательно, тоже.

Надеюсь, что теперь вам процесс считывания кодов стал более понятен.

Также у нас будет возможность это ещё раз закрепить, когда мы будем выдумывать алгоритм при написании кода функции поиска кодов, также ещё закрепляя визуально, поглядывая на результаты логического анализа на шине.

В следующей части урока мы напишем полностью функцию поиска идентификаторов датчиков и считаем уникальные коды со всех датчиков температуры.

Отладочную плату можно приобрести здесь STM32F103C8T6

Датчик температуры в экране с проводом можно приобрести здесь DS18B20 в экране с проводом

Читайте также:  Создать qr код для инстаграм

Переходник USB to TTL можно приобрести здесь ftdi ft232rl

Смотреть ВИДЕОУРОК (нажмите на картинку)

Подробно про датчики температуры DS18B20 и работу с библиотекой DallasTemperature.

Характеристики датчика:

  • Диапазон температур: –55 … 125°C ±2.0, –10 … 85°C ±0.5
  • Разрешение: от 9 до 12 Бит, до 0.0625 °C
  • Напряжение питания: от 3.0 В до 5.5 В. Возможно фантомное питание (питание по линии данных)
  • Связь по 1-Wire. Каждый датчик имеет уникальный 64 битный серийный номер, по которому происходит общение с датчиком на шине.
  • Тревожный сигнал, передает адрес датчика, если температуры вышла за заданные пределы.

Схема подключения датчиков:

Назначение выводов:

Также существует герметичная версия DS18B20, в таких датчиках смотрим на цвета проводов.

PIN Цвет TO-92 8-PIN SOIC ОПИСАНИЕ
GND Черный 1 5 Масса
DQ Желтый, Белый или Синий 2 4 Линия данных интерфейса 1-Wire.
VDD Красный 3 3 Вход внешнего питания.

Подключение одного датчика:

Датчик (ногу DQ) можно подключать на любой свободный выход arduino, в данном случаи датчик подключен к аналоговому А1 (он же 15 цифровой). В коде, при необходимости, можно задать любой другой, на котором будет сконфигурирована шина 1-Wire.

Также необходимо притянуть линию данных к питанию резистором на 4,7к. Питание у датчика 5 вольт.

Подключение нескольких датчиков:

Дополнительные датчики подключаются параллельно.

Подключение датчика с фантомным питанием:

Не рекомендуется, без крайней необходимости подключать датчик подобным образом, это плохо сказывается на быстродействии и стабильности работы датчика.

Для работы с датчиками необходима библиотека OneWire, скачать можно тут или тут, благодаря которой можно работать со всей линейкой устройств от Maxim/Dallas с однопроводной шиной (1-Wire), включая DS18B20.

Также, для удобства работы с датчиками DS18B20, рекомендуется использовать библиотеку DallasTemperature, особенно если датчиков на шине несколько, можно скачать тут или тут, она работает поверх библиотеки OneWire. Библиотека обширная, возможно будет тяжела для освоения начинающим, особенно по примерам из комплекта.

Пример работы с одним датчиком, без DallasTemperature:

Открываем пример DS18x20_Temperature.pde из библиотеки OneWire.

Далее в 10 строке указываем пин к которому подключен датчик, изначально там указан 10 пин, а в нашем случаи это A1, то есть, меняем «OneWire ds(10);» на «OneWire ds(A1);» и загружаем в arduino. Открываем «монитор порта» в мониторе каждую секунду приходят следующие данные.

ROM = 28 A8 3E F9 5 0 0 12 — Адрес датчика на шине в HEX формате.
Chip = DS18B20 — Тип датчика, вычисляется из адреса датчика.
Data = 1 C0 1 4B 46 3F FF 10 10 6F CRC=6F — Данные о температуре в HEX формате.
Temperature = 28.00 Celsius, 82.40 Fahrenheit — Температура в двух системах.

Алгоритм получения данных с датчика:

Получение температуры в примере DS18x20_Temperature.pde, происходит в три этапа.

Первым нужно узнать адрес датчика на шине и подключен ли он вообще,

за это отвечает код выше и функция ds.search(addr), которая, если найдет устройство, положит его адрес в массив addr. Можно эту процедуру опустить, если адрес датчика заранее известен.

Вторым отправляется команда на датчик, чтобы он прочитал температуру и положил данные в регистр.

на это датчику требуется относительно много времени, порядка 750мс.

Третьем даем команду на чтение данных из регистра и в цикле считываем ответ в массив

и попутно отправляем его в «монитор порта» для отладки, ниже конвертируем в привычные нам Цельсии или Фаренгейты.

Пример целиком, на всякий случай

Работа с библиотекой DallasTemperature:

Получать температуру с датчиков библиотекой DallasTemperature можно разными методами, у каждого метода есть свои особенности, но по порядку.

Работа с датчиками по индексу:

Родными примерами из библиотеки пользоваться не будем, разберем упрощенную версию, что ниже. Датчик температуры все также подключен ко входу А1.

Пример крайне упрощен и по сути не отличается от кода из примера «DS18x20_Temperature.pde» библиотеки OneWire.

При инициализации просиходит поиск устройств на шине и каждому устройству назначается свой «индекс» по номеру которого, функцией getTempCByIndex(0), можно достать температуру из датчика. Перед считыванием нужно вызвать функцию requestTemperatures() которая дает команды на подключенные датчики считать температуру и положить её в регистр для считвания.

Метод не стабилен при работе с несколькими датчиками, ибо если будут проблемы с обнаружением одного из нескольких датчиков на шине, индексы перестроятся и будем получать ошибочные показания. Также такой метод, не всегда имеет смысл использовать при работе с одним датчиком, зачем использовать тяжелую библиотеку, если достаточно одной функции в коде?

Еще один пример работы с датчиками по индексу, этот пример использоватся в видео. Он отправляет в «монитор порта» температуру со всех подключенных датчиков. Для получения количества подключенных датчиков, вызывается функция getDeviceCount(), которая возвращает значение в переменную qty. В loop, также даем команду датчикам, вызывая функцию requestTemperatures(), а ниже, в цикле for, используя количество подключенных датчиков, отпраляем в монитор порта температуру со всех подключенных датчиков.

Работа с датчиками по ID:

В данном случаи обращаемся к датчику не по назначенному библиотекой «индексу», а по серийному номеру датчика, заданного в коде,

и в данном случаи мы исключаем возможность считать температуру с неправельного датчика, но нужно зарание задать серийный номер. Если задавать его в коде, то устройство будет привязано к конкретному датчику, что осложнит замену датчика при его неисправности.

В коде объяевленны два массива sensor1 и sensor2 в которых хранятся 8 битный серийный номер датчика. В loop после вызова функции requestTemperatures() считываем температуру функцией getTempC(sensor1) передавая ей массив с серийным номером датчика, функция возвращает значение температуры с датчика, которую отправляем в «монитор порта», в случаи если датчика с таким серийным номером на шине не окажится, функция вернет -127.0

Еще один пример из видео, работающий по такому принципу ниже. Он отображает полученную температуру с датчика на LCD сшилде.

Работа с ID:

И заключительный простой пример, в данном случаи, при включении микроконтроллера и всего прочего, вызываем функцию getDeviceCount() которая возвращает количество найденых датчиков на шине, это количество отправляем в «монитор порта» но правельее сделать проверку на наличие датчиков и остановку устройства если датчики не найдены.

Следом вызываем функцию getAddress(sensor0, 0), в функцию передаем массив sensor0 который в нашем случаи объявлен в 7 строке кода и индекс датчика, адрес которого функция присвоит в sensor0.

Следом, в цикле for отправляем в монитор порта содержимое массива sensor0, в котором должен содержатся серийный номер датчика, если все прошло успешно

В функции setResolution(sensor0, 11) устанавливаем разрешение получаемой с датчика sensor0 температуры по его серийному номеру, может быть 9, 10, 11, 12 бит, данный параметр не влияет на точность датчика.

в loop, как и в примере выше, отправляем значение температуры с датчика в «монитор порта» по серийному номеру

Зачем нужен этот пример? если с таким же успехом, можно написать ds.getTempCByIndex(0), с одним датчиком так и нужно, а если их много? серийный номер датчика можно записать в EEPROM с привязкой к конкретной задачи, отслеживать получение верных данных с конкретного датчика, все это повышает надежность устройства.

Купить DS18B20:

можно на али, тут, в герметичном исполнении тут.

Видео:

Комментировать
799 просмотров
Комментариев нет, будьте первым кто его оставит

Это интересно
Adblock
detector