Как пользоваться STM32CubeMonitor (графики, приборы) и зачем нужно

Краткое описание программы

Новая
хрень, внезапно, полезная от
STMicroelectronics взамен устаревшей STM Studio. Программное обеспечение STM32CubeMonitor позволяет очень удобно и наглядно выводить значение глобальных переменных (по сути считывая значение с ОЗУ) в виде графиков с применением различных функций и возможностью удобной записи
.
Как смотреть переменную (строить график)?
Первое что нужно – это программа с глобальными переменными, у меня это элементы структуры для значения ускорения датчика ADXL345:

Открываем STM32CubeMonitor и сначала добавляем блок получение выход (acq_out):

Подключаем ST-LINK к STM32 и далее к ПК:

Проверка: Win + R -> devmgmt.msc -> Universal Serial Bus devices -> STM32 STLink

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

Проверить связь легко нажатием на лампочку:

Светодиод на отладчике должен помигать:

Находим папку с проектом, в STM32CubeIDE это можно сделать из дерева проектов:

Далее находим файл ProjectName.elf и копируем адрес папки, где он находится:

Сейчас добавляем блок переменных ( variables), двойное нажатие на него и теперь вставляем ранее скопированный адрес, выбираем файл с расширением .elf и отмечаем нужные переменные для просмотра (у меня этого элементы структуры Adxl345.x, Adxl345.y, Adxl345.z):

После соединения/редактирования блоков нужно будет нажать развернуть ( Deploy) и далее приборная панель (Dashboard).

Далее жмем на кнопку Start и всё должно работать. Выбрав показывать точки ( Show Points) легко просматриваются значения на кривой вместе с временем:

Также график можно увеличивать, а если STLINK отвалится, то придется заново нажимать кнопку запуска:

Добавление аналоговых индикаторов (Gauge)
Можно сделать свою приборную панель, для этого после блока переменных нужно добавить блок единичного значения (Single value) и только потом блок измерителя (Gauge).

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

Кроме обычного стрелочного прибора есть еще и другие показометры:

Отображение переменных в виде текста
Если нужно просто вывести переменные, то делается это следующим образом:

В настройках задается отображение и текст, сопровождающий переменную:

Готово, работает


Добавление светодиода в STM32CubeMonitor
Использую проект с датчиком ускорения ADXL345, от которого получаю ускорение,

Как и ранее, сначала добавляются нужные переменные в блок переменных (Variables node), адреса и имена извлекаются из .elf файла, который находится в папке Debug проекта:

В блоке обработки переменных (Processing node) можно ничего не менять, если не нужны дополнительные операции:

В блоке единичного значения (Single Value) пишем любое имя (Name), а в строке переменной (Variable) четко пишем название переменной (такое же как в программе и как выбрано ранее):

В блоке Изменения (Change Node) нужно добавить установку (Set) значения msg.payload (сделал как в источнике):

Также добавил текстовый вывод (Text node), которая раньше уже использовалась для отображения значения переменной, а сейчас будет отображать то, что выходит после блока Изменения (Change Node):

И последнее, блок светодиода имеем самые простые настройки, изменил размер и цвет (красный - false, зеленый - true):

Все готово, развертываем (Deploy) и заходим на приборную панель (Dashboard):

Штука на самом деле очень удобна, особенно если нужно следить на несколькими процессами, достаточно подписать светодиод и виртуальная приборная панель становится как настоящая! 

На основе: https://community.st.com/s/question/0D53W00000DJ49tSAD/simple-led-blink-with-stm32cubemonitor
Обновление от 05.08.2022
Запись данных (логгирование)
Для регистрации всех получаемых значений достаточно выбрать Log All Values:

После этого при каждой сессии данные будут записываться и их потом можно удобно по всей красе посмотреть:

Использование триггера
Здесь есть возможность начать запись по переднему/заднему фронту с предварительной установкой нужного порога для выбранной переменной:

Теперь построение графика начнется тогда, когда Adxl345.z превысит 200.

Что может оказаться очень удобным, по меньшей мере хранить кучу лишних данных не придётся:

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

побитных, тригонометрических, логических:

и статистических функций:

Среднее значение
Использование среднего скользящего позволяет избавиться от шума, в устройствах на МК это часто используется для обработки значений с АЦП. Здесь есть встроенная функция среднего, посмотрим как сработает для сглаживаний значений ускорения с датчика ADXL345:

Получилось хорошо, но, увы, здесь нельзя изменять порядок фильтра, поэтому при резких изменениях сглаженная кривая не поспевает.

? Установка (Запись) переменной через STM32CubeMonitor
Обновление от 08.04.2023
Конечно, кроме чтение возможна и запись данных в МК, и это крайне полезно и нужно, чтобы чем-то управлять. Самый простой способ - это использовать встроенный блок (узел) панели записи (write panel).

Его нужно разместить между узлом с переменными (myVariables) и выходом отладчика (myProbe_Out)

Значащих настроек этот блок не имеет:

После развертки (DEPLOY) заходим в приборную панель (DASHBOARD) и начинаем получение данных нажатием на START Acquisition, только после этого добавленные переменные (их список в блоке myVariables) высветятся и будут доступны для записи:

В поле, где также отображается тип переменной записываем число и нажимаем кнопку записать (WRITE) и напечатанное значение отправляется в ОЗУ микроконтроллера (что хорошо видно по графику, куда происходит вывод этой же переменной):

Таким образом можно легко что-то включать/выключать через STM32CubeMonitor и сразу же вести комплексную проверку и отладку вместе с регистрацией (логгированием; см. предыдущую главу). А вот весь код JSON этих блоков (для импорта нажмите Ctrl + i):
{
"id": "89903e71a0f08de5",
"type": "tab",
"label": "Flow 1",
"disabled": false,
"info": "",
"env": []
},
{
"id": "19e6cbb7d092d2a1",
"type": "ui_chartst",
"z": "89903e71a0f08de5",
"group": "f9c34dde.1e2f4",
"name": "myChart",
"order": 4,
"width": 15,
"height": 9,
"chartType": "line",
"curveType": "linear",
"duration": "15",
"ymin": "",
"ymax": "",
"x": 680,
"y": 340,
"wires": []
},
{
"id": "40e8524f1649a5fc",
"type": "acquisition out",
"z": "89903e71a0f08de5",
"name": "myProbe_Out",
"probeconfig": "d8f080bf556b5a58",
"x": 820,
"y": 200,
"wires": []
},
{
"id": "d2220fb5a6c1872b",
"type": "acquisition in",
"z": "89903e71a0f08de5",
"name": "myProbe_In",
"probeconfig": "114771b6ed2c2cfa",
"x": 190,
"y": 340,
"wires": [
[
"a74bab37b15e7eb7"
],
[]
]
},
{
"id": "30256467cedaa806",
"type": "variables",
"z": "89903e71a0f08de5",
"groupname": "myVariables",
"accesspoint": 0,
"execonfig": "aaf8e169bc5a02ba",
"variablelist": [],
"triggerstartmode": "manual",
"triggername": "setBuzzerFreq",
"triggerthreshold": "30000",
"frequency": "",
"frequencyType": "0",
"snapshotheader": "",
"mode": "direct",
"lastImportedTime": 1680974212034,
"openStatus": true,
"x": 430,
"y": 200,
"wires": [
[
"40e8524f1649a5fc",
"836a3e90ed3167d4"
],
[]
]
},
{
"id": "e13a339edca89ec5",
"type": "ui_button",
"z": "89903e71a0f08de5",
"name": "",
"group": "f9c34dde.1e2f4",
"order": 3,
"width": 5,
"height": 1,
"passthru": false,
"label": "Clear Graphs",
"tooltip": "",
"color": "",
"bgcolor": "",
"icon": "",
"payload": "",
"payloadType": "str",
"topic": "clear",
"x": 190,
"y": 440,
"wires": [
[
"19e6cbb7d092d2a1"
]
]
},
{
"id": "015c58a5befd6de2",
"type": "ui_button",
"z": "89903e71a0f08de5",
"name": "",
"group": "f9c34dde.1e2f4",
"order": 1,
"width": 5,
"height": 1,
"passthru": false,
"label": "START Acquisition",
"tooltip": "",
"color": "",
"bgcolor": "",
"className": "",
"icon": "",
"payload": "",
"payloadType": "str",
"topic": "start",
"topicType": "str",
"x": 210,
"y": 160,
"wires": [
[
"30256467cedaa806"
]
]
},
{
"id": "79d6288865062524",
"type": "ui_button",
"z": "89903e71a0f08de5",
"name": "",
"group": "f9c34dde.1e2f4",
"order": 2,
"width": 5,
"height": 1,
"passthru": true,
"label": "STOP Acquisition",
"tooltip": "",
"color": "",
"bgcolor": "",
"className": "",
"icon": "",
"payload": "",
"payloadType": "str",
"topic": "stop",
"topicType": "str",
"x": 210,
"y": 240,
"wires": [
[
"30256467cedaa806"
]
]
},
{
"id": "a74bab37b15e7eb7",
"type": "processing",
"z": "89903e71a0f08de5",
"groupname": "myVariables",
"groupid": "806262801786c334",
"expressions": [],
"statistics": [],
"logmode": "no",
"logformat": "stcm",
"x": 450,
"y": 340,
"wires": [
[
"19e6cbb7d092d2a1"
],
[]
]
},
{
"id": "836a3e90ed3167d4",
"type": "ui_write",
"z": "89903e71a0f08de5",
"group": "f9c34dde.1e2f4",
"name": "",
"order": 8,
"width": 0,
"height": 0,
"x": 650,
"y": 120,
"wires": [
[
"40e8524f1649a5fc"
]
]
},
{
"id": "f9c34dde.1e2f4",
"type": "ui_group",
"name": "Chart",
"tab": "17d09b07.741a55",
"order": 1,
"disp": true,
"width": "15",
"collapse": false
},
{
"id": "d8f080bf556b5a58",
"type": "probe",
"probeid": "53FF68064882575124392487",
"probename": "ST-Link v2 (...92487)",
"protocol": "SWD",
"frequency": "1.8 MHz - Default",
"probeproperty": "{\"SWD\":[\"4.6 MHz\",\"1.8 MHz - Default\",\"950 kHz\",\"400 kHz\",\"150 kHz\"],\"JTAG\":[\"18 MHz\",\"9 MHz\",\"4.5 MHz\",\"2.25 MHz\",\"1.12 MHz - Default\",\"560 kHz\",\"280 kHz\",\"140 kHz\"]}",
"probeversion": "ST Link firmware version V2.J40",
"connectionType": "p2p"
},
{
"id": "114771b6ed2c2cfa",
"type": "probe",
"probeid": "53FF68064882575124392487",
"probename": "ST-Link v2 (...92487)",
"protocol": "SWD",
"frequency": "1.8 MHz - Default",
"probeproperty": "{\"SWD\":[\"4.6 MHz\",\"1.8 MHz - Default\",\"950 kHz\",\"400 kHz\",\"150 kHz\"],\"JTAG\":[\"18 MHz\",\"9 MHz\",\"4.5 MHz\",\"2.25 MHz\",\"1.12 MHz - Default\",\"560 kHz\",\"280 kHz\",\"140 kHz\"]}",
"probeversion": "ST Link firmware version V2.J39",
"connectionType": "p2p"
},
{
"id": "aaf8e169bc5a02ba",
"type": "exe-config",
"name": "Buzzer",
"exefile": "D:\\STM32\\Buzzer-STM32-HAL\\Debug\\Buzzer-STM32-HAL.elf",
"exefolder": "D:\\STM32\\Buzzer-STM32-HAL\\Debug",
"exevariablelist": [
{
"address": "0x080029c0",
"name": "AHBPrescTable[0]",
"type": 1
},
{
"address": "0x20000080",
"name": "Buz.Freq[0]",
"type": 5
},
{
"address": "0x2000007f",
"name": "Buz.Help",
"type": 1
},
{
"address": "0x200000a0",
"name": "Buz.htim",
"type": 5
},
{
"address": "0x200000a8",
"name": "Buz.PWM_Channel",
"type": 5
},
{
"address": "0x2000007e",
"name": "Buz.Tick",
"type": 1,
"checked": false
},
{
"address": "0x200000a4",
"name": "Buz.TIM_TypeDef",
"type": 5
},
{
"address": "0x2000007a",
"name": "Buz.Tout",
"type": 3,
"checked": false
},
{
"address": "0x2000007c",
"name": "Buz.ToutSave",
"type": 3
},
{
"address": "0x20000078",
"name": "Buz.Type",
"type": 2
},
{
"address": "0x20000044",
"name": "htim11.Channel",
"type": 2
},
{
"address": "0x2000006a",
"name": "htim11.ChannelNState[0]",
"type": 2
},
{
"address": "0x20000066",
"name": "htim11.ChannelState[0]",
"type": 2
},
{
"address": "0x2000006e",
"name": "htim11.DMABurstState",
"type": 2
},
{
"address": "0x20000048",
"name": "htim11.hdma[0]",
"type": 5
},
{
"address": "0x20000040",
"name": "htim11.Init.AutoReloadPreload",
"type": 5
},
{
"address": "0x20000038",
"name": "htim11.Init.ClockDivision",
"type": 5
},
{
"address": "0x20000030",
"name": "htim11.Init.CounterMode",
"type": 5
},
{
"address": "0x20000034",
"name": "htim11.Init.Period",
"type": 5
},
{
"address": "0x2000002c",
"name": "htim11.Init.Prescaler",
"type": 5
},
{
"address": "0x2000003c",
"name": "htim11.Init.RepetitionCounter",
"type": 5
},
{
"address": "0x20000028",
"name": "htim11.Instance",
"type": 5
},
{
"address": "0x20000064",
"name": "htim11.Lock",
"type": 2
},
{
"address": "0x20000065",
"name": "htim11.State",
"type": 2
},
{
"address": "0x20000070",
"name": "setBuzzerFreq",
"type": 5,
"checked": true
},
{
"address": "0x20000000",
"name": "SystemCoreClock",
"type": 5
},
{
"address": "0x20000074",
"name": "uwTick",
"type": 5
},
{
"address": "0x20000008",
"name": "uwTickFreq",
"type": 2
},
{
"address": "0x20000004",
"name": "uwTickPrio",
"type": 5
}
],
"expand": false,
"filename": "Buzzer-STM32-HAL.elf",
"exeModifiedTime": 1680900178165,
"configLastUpdate": 1680966721298
},
{
"id": "17d09b07.741a55",
"type": "ui_tab",
"name": "Home",
"icon": "dashboard",
"disabled": false,
"hidden": false
}
]
? Но есть еще более удобный способ, это использовать слайдер, который работает по сути как ползунковый переменный резистор, что сильно облегчает тонкую настройку и регулировку (напряжения, свечения, звука), когда нужно в действительности ощутить и оценить действие самостоятельно, получив при этом нужную оптимальную цифру.
Еще запись с датчика ускорения
Не могу не сделать график зависимости ускорения с вибромоторчиком:

Получается весьма интересно:

Можно по-бырому записать что нужно, а потом детально рассмотреть:

А вот вам еще проверка
светодиодного проверяльщика (дорабатывается
):
Он уже работает и здесь очень быстро возрастает выходное напряжение, а после прекращения преобразования экспоненциально уменьшается, т.к. конденсатор разряжается.

Дополнительные возможности
Есть еще куча возможностей, в частности различные элементы интерфейса:

Получаемые данные можно пихать куда угодно через: MQTT, HTTP, websocket, TCP, UDP, Serial.

Купить на Aliexpress 
Из-за трудности достать по нормальной цене микроконтроллеры STM32 (и другие) советую обратить внимание на плату с STM32F401 с USB Type-C, которая всё еще доступна и имеет отличные параметры (84MHz, 64k RAM, 256k ROM, 3*SPI, 3*UART, 8*TIM...).
?️ STM32F401 Module (3.50?): https://ali.ski/T9_RBe
?️ STM32F401 Black Pill USB C(3.88?):
https://ali.ski/wvygW
?️ STM32F401 DevBoard Type-C (3.46?): https://ali.ski/SvrJ8d

Видос
Итого
Штука прикольная, не скажу что эти блоки мне понравились, но само ПО выглядит модно и графики строит красиво и легко вести запись значений.
STM32CubeMonitor отлично подойдет для отладки устройства на расстоянии или отлова непредсказуемо возникающих зависаний/вылетом в обработчик ошибок (Hard Fault). Скачать и попробовать можно на оф. сайте или прямо здесь (старую версию) : STM32CubeMonitor.zip
Или новую 1.4.0 в телеграм-канале: https://t.me/cxemka_com/10
Жаль только то, что не поддерживается бичевый JLINK, который работает через SWD.


Спасибо. Очень информативно