2. Работа с датчиком температуры DS18B20 для STM32 на языке ДРАКОН

DS18B20 + STM32 + ДРАКОН
DS18B20 + STM32 + ДРАКОН
DS18B20 + STM32 + ДРАКОН

Учим микроконтроллер определять адреса датчиков и читать температуру.

Я рисовал функции исходя из своего опыта, а он мне четко говорит - редко в проекте один датчик температуры, обычно их несколько. В моем случае, в одном из медицинских проборов над которым работал, DS18B20 было 5 штук.
И второе важное правило – менять датчики должно быть легко и быстро.
Механически сломать датчик не сложно. Найти другой для замены не проблема, проблема если их в системе несколько. Его же нужно автоматически определить и вставить на своё место в алгоритме (у датчика имеется уникальный адрес). Надо сделать так, чтобы при замене не приходилось перепрограммировать устройство. Есть разные способы решить эту задачу, я покажу один из них.

Все что тут написано является только лишь моим мнением. Я ни к чему не призываю, ничему не учу, а только делюсь своим опытом.

Инструментарий.

Программы:
ИС ДРАКОН (выпуск от 5.04.2020),
STM32CubeMX (v6.0.0),
STM32CubeIDE (v1.4.0),
Notepad++ (v7.9.1).

Железо:
китайская плата на STM32F401CCU6 (RAM 64KB, FLASH 256KB),
китайский программатор ST-Link V2 со шлейфом 4-pin,
3 цифровых датчика температуры DS18B20,
2 резистора 4.7к, провода и разъёмы.

Эта блок-схема поясняет зачем два порта 1-Wire и как мы будем с ними работать. Это просто блок-схема (не программа) и кода внутри икон не содержит. Чтобы детально рассмотреть можно правой клавишей мыши "Открыть картинку в новой вкладке".
Эта блок-схема поясняет зачем два порта 1-Wire и как мы будем с ними работать. Это просто блок-схема (не программа) и кода внутри икон не содержит. Чтобы детально рассмотреть можно правой клавишей мыши "Открыть картинку в новой вкладке".
Эта блок-схема поясняет зачем два порта 1-Wire и как мы будем с ними работать. Это просто блок-схема (не программа) и кода внутри икон не содержит. Чтобы детально рассмотреть можно правой клавишей мыши "Открыть картинку в новой вкладке".

Пояснение к алгоритму замены датчиков.
Пока в памяти микроконтроллера не прописано ни одного адреса датчиков DS18B20 мы делаем так: подключаем датчик к первой 1-Wire шине, подаем питание на микроконтроллер, ждем световой индикации и снимаем питание. То же проделываем с остальными двумя датчиками (предварительно нацарапав на них номера).

2. Работа с датчиком температуры DS18B20 для STM32 на языке ДРАКОН

Если же в процессе работы у нас вышел из строя одни из датчиков, то мы его выпаиваем и повторяем процедуру выше уже с новым датчиком (при этом не отключая от второй шины оставшиеся в работе датчики). А после этой процедуры припаиваем новый датчик на место неисправного.

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

Таким образом мы автоматизировали процесс замены датчиков при поломках (реализация этого алгоритма в блок-схеме ДРАКОН и коде будет в следующей статье.

Реализация работы с датчиком DS18B20 для STM32 на языке ДРАКОН.

Будем использовать уже готовые блок-схемы из предыдущей статьи, где описана реализация 1-Wire шины для STM32. Блок-схемы доработаю по принципу «добавить только то, что нужно».
А нужно будет два порта 1-Wire.

Пойдем простым путем – добавим в функции «Сигнал сброса шины 1-Wire», «Передача БАЙТА по 1-Wire», «Получение БАЙТА по 1-Wire» и «Передача/получение бита по 1-Wire (тайм-слот)» еще по одному принимаемому параметру. Если это «1» то работаем с первой шиной 1-Wire, а если «2» – со второй.

В функцию «Сигнал сброса шины 1-Wire» вводим еще один входящий параметр и делаем дополнительную развилку, чтобы понимать с какой шиной будем работать. Часть блок-схемы просто дублируем (методом копи-паста) и только изменяем код внутри иконок. Также меняем тип блок-схемы с «Примитив» на «Силуэт». Это для того, чтобы вся схема помещалась по высоте. При таком подходе навигация по всем функциям будет только влево-вправо (мы исключим вертикальную прокрутку).
В функцию «Сигнал сброса шины 1-Wire» вводим еще один входящий параметр и делаем дополнительную развилку, чтобы понимать с какой шиной будем работать. Часть блок-схемы просто дублируем (методом копи-паста) и только изменяем код внутри иконок. Также меняем тип блок-схемы с «Примитив» на «Силуэт». Это для того, чтобы вся схема помещалась по высоте. При таком подходе навигация по всем функциям будет только влево-вправо (мы исключим вертикальную прокрутку).
В функцию «Сигнал сброса шины 1-Wire» вводим еще один входящий параметр и делаем дополнительную развилку, чтобы понимать с какой шиной будем работать. Часть блок-схемы просто дублируем (методом копи-паста) и только изменяем код внутри иконок. Также меняем тип блок-схемы с «Примитив» на «Силуэт». Это для того, чтобы вся схема помещалась по высоте. При таком подходе навигация по всем функциям будет только влево-вправо (мы исключим вертикальную прокрутку).

Аналогично поступаем с оставшимися функциями (вводим еще один входящий параметр и изменяем код внутри иконок). В результате получаем новый код четырех функций для работы с 1-Wire [1].

Далее не забываем включить в CubeMX поддержку второго USART и сгенерировать main.c заново.

Теперь надо узнать прописанные в датчиках DS18B20 адреса (64 бита, т. е. 8 БАЙТ).

Самый простой способ - это использовать команду READ ROM (0x33) подключая датчики к шине 1-Wire по одному.

Функция принимает номер шины для работы и возвращает адрес подключенного датчика в виде 64-битной переменной (типа uint64_t).
Функция принимает номер шины для работы и возвращает адрес подключенного датчика в виде 64-битной переменной (типа uint64_t).
Функция принимает номер шины для работы и возвращает адрес подключенного датчика в виде 64-битной переменной (типа uint64_t).

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

Адрес в HEX формате: 0xFC00000A250FAD28.
Адрес в HEX формате: 0xFC00000A250FAD28.
Адрес в HEX формате: 0xFC00000A250FAD28.

Если написать наш адрес в виде массива из БАЙТ в десятичном виде (начиная с младших), то получится следующее:

uint8_t addr [8]={40,173,15,37,10,0,0,252};

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

Эта функция принимает номер шины и дает команду всем датчикам начать внутри себя преобразование температуры и занесение во внутреннюю память.
Эта функция принимает номер шины и дает команду всем датчикам начать внутри себя преобразование температуры и занесение во внутреннюю память.
Эта функция принимает номер шины и дает команду всем датчикам начать внутри себя преобразование температуры и занесение во внутреннюю память.
Эта функция принимает адрес датчика (к которому хотим обратиться), номер шины для работы и возвращает температуру в формате float.
Эта функция принимает адрес датчика (к которому хотим обратиться), номер шины для работы и возвращает температуру в формате float.
Эта функция принимает адрес датчика (к которому хотим обратиться), номер шины для работы и возвращает температуру в формате float.

Теперь мы можем считывать адреса датчиков и температуры.
Проверяем.

Там, где мы объявили дефайны и функции, добавим две глобальные переменные.
Там, где мы объявили дефайны и функции, добавим две глобальные переменные.
Там, где мы объявили дефайны и функции, добавим две глобальные переменные.
Перед бесконечным циклом напишем вызов функции считывания адреса. А в бесконечном цикле будем читать показания температуры по считанному адресу DS18B20 и давать команду на преобразование температуры, и так циклично с задержкой 1с.
Перед бесконечным циклом напишем вызов функции считывания адреса. А в бесконечном цикле будем читать показания температуры по считанному адресу DS18B20 и давать команду на преобразование температуры, и так циклично с задержкой 1с.
Перед бесконечным циклом напишем вызов функции считывания адреса. А в бесконечном цикле будем читать показания температуры по считанному адресу DS18B20 и давать команду на преобразование температуры, и так циклично с задержкой 1с.

Подключаем датчик к первой шине 1-Wire и запускаем отладку (жмём зеленого жука).

Видим, что адрес нашего датчика занесен в переменную addr_temp. Отображение значений стоит в HEX формате.
Видим, что адрес нашего датчика занесен в переменную addr_temp. Отображение значений стоит в HEX формате.
Видим, что адрес нашего датчика занесен в переменную addr_temp. Отображение значений стоит в HEX формате.

Теперь вытянем датчик из разъёма первой шины и вставим в разъем второй шины 1-Wire.

Переключаем режим отображения в Default и видим значение температуры.
Переключаем режим отображения в Default и видим значение температуры.
Переключаем режим отображения в Default и видим значение температуры.

Наши функции работают как надо.

Далее на базе проделанной работы можно реализовать устройство, которое будет мониторить температуру по трем датчикам и записывать это в свою энергонезависимую память. Своего рода микро-станция наблюдения для накопления информации за последние 2-3 месяца. В следующей статье будет описана работа с FLASH памятью микроконтроллера STM32F401CCU6, а также вывод данных на ПК через виртуальный com-порт (разъем USB на плате).

Это устройство (микро-станция наблюдения) всего лишь подготовительный этап для более серьезного проекта. Но об этом в свое время.

Предыдущая статья 1. Шина 1-Wire для STM32 на языке ДРАКОН.

[1] Файл с полным кодом и блок схема для программы «ИС ДРАКОН»