3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН

3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН
3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН

Речь пойдет об устройстве, которое каждые 10 минут измеряет температуру с трех датчиков и записывает показания в энергонезависимую память, добавляя при этом дату и время замера.
Диапазон измерений -55 до +125 °C, для диапазона от -10 до +85 °C погрешность не превышает 0.5 °C, шаг измерений 0.0625 °C.
При используемом микроконтроллере устройство может записать непрерывно показания за 85 суток (далее можно очистить память и писать заново). Данные передаются на ПК через USB Type-C соединение по виртуальному COM порту.
Затраты на изготовление устройства около 500 руб. (7$).

Для чего мне понадобилось такое устройство?

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

Измерения происходят по трём направлениям. Датчики DS18B20 установлены:
1-й на улице,
2-й в комнате,
3-й на батарее отопления в самом её горячем месте.

Мозгом является микроконтроллер STM32F401CCU6 с минимальной обвязкой. Он же накапливает данные измерений в свою FLASH память (в ту её часть которая остаётся свободной от прошивки).

Устройство не имеет внешнего интерфейса управления. Если подключены датчики, то идет сбор информации и запись. Если датчики отключены, то устройство пытается передать все накопленные данные на ПК (через USB Type-C разъём). На плате всего один светодиод (кроме светодиода питания) который загорается и горит постоянно если произошла программная ошибка. Либо мигает, когда идет запись во FLASH. В обычном рабочем режиме погашен.

А вот как выглядит накопленная за 6 суток информация в программе Excel.
А вот как выглядит накопленная за 6 суток информация в программе Excel.
А вот как выглядит накопленная за 6 суток информация в программе Excel.

На видео работающее устройство.

Учитывая, что ранее была проведена работа в программе «ИС ДРАКОН» по подключению датчиков DS18B20 к микроконтроллеру STM32 (статьи [1] и [2]), мне осталось только написать основной алгоритм. На него ушло 3 дня. Не хочу сказать что это быстро, а также что сам алгоритм оптимален. Однако для человека, который ранее вообще не знал как работать с stm32, думаю результат удовлетворительный.

Измерения температуры мы будем сохранять во FLASH память микроконтроллера. А вернее в ту ее часть, которая остаётся незадействованной кодом прошивки. В микроконтроллерах ATmega, которые устанавливают на платы Arduino есть отдельно память EEPROM. В STM32 тоже такая есть, но не во всех микроконтроллерах. Однако мы можем использовать основную FLASH память (обычно ее остаётся много, если прошивка небольшая).
Например, моя программа будет занимать не более 64КБ, а всего в STM32F401CCU6 256КБ. Таким образом под свои нужды мне доступно 256-64 = 192КБ, что довольно неплохо, учитывая что в топовой Arduino Mega (ATmega2560) всего 4КБ EEPROM.

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

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

Программы:
ИС ДРАКОН (выпуск от 5.04.2020),
STM32CubeIDE (v1.4.0),
STM32CubeProgrammer (v2.5.0),
Notepad++ (v7.9.1),
Termite (v3.4).

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

Подключаем нашу плату к ПК и запускаем программу STM32CubeProgrammer.

Нажимаем кнопку Connect -> вкладка со стрелкой. Видим конфигурацию памяти нашего микроконтроллера: четыре сектора по 16КБ, один на 64 и один на 128КБ. Наш код прошивки будет занимать первые четыре сектора по 16КБ. А вот с пятого (адрес 0х08010000) мы можем записывать данные.
Нажимаем кнопку Connect -> вкладка со стрелкой. Видим конфигурацию памяти нашего микроконтроллера: четыре сектора по 16КБ, один на 64 и один на 128КБ. Наш код прошивки будет занимать первые четыре сектора по 16КБ. А вот с пятого (адрес 0х08010000) мы можем записывать данные.
Нажимаем кнопку Connect -> вкладка со стрелкой. Видим конфигурацию памяти нашего микроконтроллера: четыре сектора по 16КБ, один на 64 и один на 128КБ. Наш код прошивки будет занимать первые четыре сектора по 16КБ. А вот с пятого (адрес 0х08010000) мы можем записывать данные.
Интерфейс для просмотра памяти, который нам предлагает программа STM32CubeProgrammer (вкладка с карандашом).
Интерфейс для просмотра памяти, который нам предлагает программа STM32CubeProgrammer (вкладка с карандашом).
Интерфейс для просмотра памяти, который нам предлагает программа STM32CubeProgrammer (вкладка с карандашом).

Выберем адрес 0x08000000, установим прочесть 0x40000 (262 144 DEC) и нажмем кнопку «Read» (прочтем всю FLASH память микроконтроллера доступную нам).

Опустимся в самый низ и посмотрим адрес нашей последней четырёхбайтной ячейки. Это адрес 0x0803FFFC. Запишем вручную этот адрес в программе (# define ADDR_FLASH_END 0x0803FFFC). Этот дефайн пригодится нам если мы будем менять микроконтроллер на другой (с большим или меньшим кол-вом памяти).
Опустимся в самый низ и посмотрим адрес нашей последней четырёхбайтной ячейки. Это адрес 0x0803FFFC. Запишем вручную этот адрес в программе (# define ADDR_FLASH_END 0x0803FFFC). Этот дефайн пригодится нам если мы будем менять микроконтроллер на другой (с большим или меньшим кол-вом памяти).
Опустимся в самый низ и посмотрим адрес нашей последней четырёхбайтной ячейки. Это адрес 0x0803FFFC. Запишем вручную этот адрес в программе (# define ADDR_FLASH_END 0x0803FFFC). Этот дефайн пригодится нам если мы будем менять микроконтроллер на другой (с большим или меньшим кол-вом памяти).
Хранить будем наши восьмибайтные адреса датчиков температуры DS18B20 как показано на рисунке (помечено красными выделением). А если необходимо изменить адреса, то мы старые ячейки затираем в 0x00000000, смещаемся влево (ближе к началу) на три восьмибайтные позиции и записываем новые адреса (помечено зеленым выделением).
Хранить будем наши восьмибайтные адреса датчиков температуры DS18B20 как показано на рисунке (помечено красными выделением). А если необходимо изменить адреса, то мы старые ячейки затираем в 0x00000000, смещаемся влево (ближе к началу) на три восьмибайтные позиции и записываем новые адреса (помечено зеленым выделением).
Хранить будем наши восьмибайтные адреса датчиков температуры DS18B20 как показано на рисунке (помечено красными выделением). А если необходимо изменить адреса, то мы старые ячейки затираем в 0x00000000, смещаемся влево (ближе к началу) на три восьмибайтные позиции и записываем новые адреса (помечено зеленым выделением).

Такой алгоритм позволяет обойтись без дополнительного стирания памяти. Стирать можно только целыми блоками, что не удобно. А записывать можно только в ячейку, в которой значение 0xFFFFFFFF. Если в ячейке уже есть какие-либо данные, то запись приведет к непредсказуемому результату. Но можно полностью обнулять (приводить значение ячейки к 0x00000000).

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

Всю остальную доступную память будем использовать для записи данных.

Теперь основываясь на материалах двух предыдущих статей ([1] и [2]) к уже имеющимся добавим необходимые функции (блок-схема алгоритма для программы «ИС ДРАКОН» и ею же сгенерированный код Си [3]).

Для удобства я создал две функции void pre_drakon() и void drakon() которые располагаются соответственно до бесконечного цикла while(1) и в нем.

Функция «Основная функция перед циклом while(1)» анализирует состояние памяти, считывает записанные в ней адреса датчиков, а также принимает решение о том переходить ли в рабочий режим измерений или только выдать данные через виртуальный СОМ порт.
Функция «Основная функция перед циклом while(1)» анализирует состояние памяти, считывает записанные в ней адреса датчиков, а также принимает решение о том переходить ли в рабочий режим измерений или только выдать данные через виртуальный СОМ порт.
Функция «Основная функция перед циклом while(1)» анализирует состояние памяти, считывает записанные в ней адреса датчиков, а также принимает решение о том переходить ли в рабочий режим измерений или только выдать данные через виртуальный СОМ порт.
Функция «Основная функция бесконечного цикла while(1)» производит измерения температуры и вносит их во FLASH память (добавив дату и время) каждые 10 минут. А также отслеживает события заполнения памяти и отключения шлейфа с датчиками (чтобы не писать понапрасну пустые значения).
Функция «Основная функция бесконечного цикла while(1)» производит измерения температуры и вносит их во FLASH память (добавив дату и время) каждые 10 минут. А также отслеживает события заполнения памяти и отключения шлейфа с датчиками (чтобы не писать понапрасну пустые значения).
Функция «Основная функция бесконечного цикла while(1)» производит измерения температуры и вносит их во FLASH память (добавив дату и время) каждые 10 минут. А также отслеживает события заполнения памяти и отключения шлейфа с датчиками (чтобы не писать понапрасну пустые значения).

Также есть 5 вспомогательных функций для работы основного алгоритма. Далее я просто покажу их без объяснений.

3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН
3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН

3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН
3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН

3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН
3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН

3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН
3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН

3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН
3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН

В конечном виде алгоритм выглядит следующим образом.

3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН
3. Трехканальный термометр на STM32 с выводом данных через USB на языке ДРАКОН

Выводы.

Язык ДРАКОН в связке с STM32CubeIDE вполне успешно можно применять для программирования микроконтроллеров STM32. При разработке алгоритма в виде блок-схем ДРАКОН в дальнейшем значительно упрощается модификация уже созданных алгоритмов под новые задачи (справедливо для разработчика, который проектировал алгоритм). Так как все связи в алгоритме прорисованы линиями, допустить грубую алгоритмическую ошибку становится трудно, и как правило алгоритм начинает работать сразу после трансляции в код.

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

Картинка из просторов интернета.
Картинка из просторов интернета.
Картинка из просторов интернета.

[1] 1. Шина 1-Wire для STM32 на языке ДРАКОН

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

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