Сообщество Engee

Arduino: быстрый старт

Автор
avatar-alexevsalexevs
Notebook

Пакет поддержки Arduino: быстрый старт

Первый пример из серии для начала работы с микроконтроллерами Arduino из Engee без погружения в код. В примере пошагово объясняется, как настроить подключение, собрать и запустить на контроллере свою первую модель.

Введение

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

  1. "Экспорт алгоритма" (пример):
    • пользователь разрабатывает алгоритм в модели
    • автоматизированно генерируется код C из модели
    • пользователь скачивает файлы
    • файлы добавляются в проект во внешней IDE
    • пользователь интегрирует код алгоритма и код периферии микроконтроллера
    • пользователь программирует контроллер
  2. "Периферийные блоки" (пример):
    • пользователь разрабатывает алгоритм в модели
    • пользователь переносит код периферии
    • автоматизированно генерируется код C из модели
    • пользователь скачивает файлы
    • файлы добавляются в проект во внешней IDE
    • пользователь программирует контроллер

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

Для исключения погружения в код С пользователи Engee могут воспользоваться пакетами поддержки встраиваемых систем. Они открывают ещё два совершенно новых сценария:

  1. "Независимое выполнение"
    • пользователь разрабатывает алгоритм в модели
    • пользователь добавляет специализированные блоки из пакета поддержки микроконтроллера
    • автоматизированно запускается программирование контроллера
  2. "Интерактивное выполнение"
    • пользователь разрабатывает алгоритм в модели
    • пользователь добавляет специализированные блоки из пакета поддержки микроконтроллера
    • автоматизированно запускается программирование контроллера
    • пользователь может управлять моделью, выполняемой на микроконтроллере, менять её параметры и визуализировать сигналы модели.

Подготовка и работа этих сценариев на микроконтроллере Arduino и будет освещена далее.

Шаг 1: Arduino и его Toolchain

Для этого примера нам понадобится:

  1. Микроконтроллер Arduino (Uno, Mega или другой с чипом AVR)
  2. Кабель USB
  3. Установленные на ПК драйвера микроконтроллера
  4. Toolchain Arduino - ArduinoCLI

Arduino подключим к ПК, убедимся, что драйвера установлены, ПК распознаёт микроконтроллер. На этом этапе сразу определим порт, к которому подключен наш микроконтроллер:

img1.png

В нашем случае - это Arduno Uno R3, на порте COM10.

Загрузим ArduinoCLI - этот инструмент в дальнейшем будет вызван из Engee автоматически для программирования микроконтроллера. Удобнее всего будет расположить его в определённой директории. В случае этого и последующих примеров его путь определён как "D:\targets\arduino-cli.exe". Запомним его для дальнейшего использования.

Получим полное имя нашей платы при помощи ArduinoCLI. Для этого перейдём в её директорию, откроем в ней терминал и вызовем, например, в PowerShell команду .\arduino-cli.exe board list

img10.png

Так мы получим список подключенных по COM устройств. Из вывода командной строки видно, что на COM10 подключена плата Arduino Uno с полным именем (FBQN) arduino:avr:uno - оно также нам далее понадобится.

Доступные FQBN можно получить, например, вызвав команду .\arduino-cli.exe board listall

img11.png

Шаг 2: Платформа Engee.Интеграции

Соединение между целевым устройством и ПК установлено, теперь установим соединение между Engee и ПК. Для этого нам понадобится:

  1. Установить Engee.Интеграции
In [ ]:
engee.package.install("Engee-Device-Manager") 
Ссылка для подключения: engee.com/prod/user/demo54365638-alexevs
Установите клиентскую программу:
https://dl.kpm-ritm.ru/repo/Host-Device-Manager-v0.98-Windows.zip - Для Windows
https://dl.kpm-ritm.ru/repo/Host-Device-Manager-v0.98-Linux.zip - Для Linux
Для получения примеров выполните: engee.package.getdemos("Engee-Device-Manager")
Для запуска серверной программы выполните: engee.package.start("Engee-Device-Manager")
Пакет поддержки 'Engee-Device-Manager' версии 'v0.98' успешно установлен.
  1. Скачать архив с клиентской программой, разархивировать и запустить её. В случае этого примера клиентская программа для удобства расположена в той же директории, что и ArduinoCLI:

    img2.png
  1. Установить соединение между Engee и ПК. Нужно вставить полученную ранее ссылку в клиентскую программу и нажать "Подключиться":
img3.png

Соединение между ПК и Engee установлено, можно переходить непосредственно к разработке модели и программированию микроконтроллера.

В дополнение, если хотите - можно получить/обновить папку примеров, там можно найти тестовые примеры для работы с внешними устройствами, периферией и микроконтроллерами.

In [ ]:
engee.package.getdemos("Engee-Device-Manager")
Out[0]:
"/user/Engee-Device-Manager-demos"

Шаг 3: Модель примера

Пример "Hello World!" для Arduino - это программа мигания светодиодом. Вот, как она будет выглядеть в модели Engee:

img4.png

Алгоритм модели заключается в одном блоке - Pulse Generator. Его настройки:

Тип импульса - На основе шагов расчёта; Амплитуда - 1; Период (количество шагов расчета) - 50; Ширина импульса (количество шагов расчета) - 25; Задержка перед первым импульсом (количество шагов расчёта) - 0, Период дискретизации - 0.02.

Блок формирует меандр с частотой 1 Гц и D = 50%.

Сигнал LED на выходе блока передаётся на блок периферии контроллера Arduino-digitalWrite - цифровой выход GPIO 13. На каждом шаге расчёта модели блок вызывает стандартную функцию записи в цифровой выход digitalWrite() из библиотеки Arduino.

Пин 13 - выход, к которому подключен встроенный на отладочной плате светодиод.

Блок EDM-Target-Arduino необходим для установления связи с микроконтроллером и его Toolchain. Вот, как определены настройки блока в текущем примере:

img5.png
  • Порт - имя последовательного порта, к которому подключен наш микроконтроллер. Его можно определить следующим образом:
    • COM10 - для Windows, такое значение мы получили для микроконтроллера в нашем примере.
    • /dev/tty/USB0 - пример имени последовательного порта для Linux.
    • <auto> - если подключен один микроконтроллер, Engee определит его порт самостоятельно.
  • Полное имя платы - FQBN платы, который мы получили ранее. Здесь возможны варианты:
    • arduino:avr:uno / arduino:avr:mega / arduino:avr:leonardo / … - в зависимости от того, какая плата подключена.
    • <auto> - если подключен один микроконтроллер, Engee определит его имя самостоятельно.
  • Путь к ArduinoCLI - полный путь к ArduinoCLI
    • "D:\targets\arduino-cli.exe" - такое значение мы скопировали в контекстном меню проводника Windows в нашем примере.
    • "D:\targets\arduino-cli" / D:\targets\arduino-cli.exe / D:\targets\arduino-cli - также допустимые варианты указания пути в Windowa
    • /home/Targets/Arduino/arduino-cli - вариант указания пути к ArduinoCLI в Linux
    • <auto> - в таком случае Engee будет автоматически искать ArduinoCLI в соответствии со следующими приоритетами:
      • пути, добавленные в переменную окружения PATH;
      • текущая директория клиентской программы;
      • C:\Program Files\;
      • C:\Program Files (x86)\.
  • Директория моделей - путь для расположения папки со скетчем .ino модели относительно расположения клиентской программы. В нашем примере - это .\arduino_examples, эта папка будет создана автоматически, а итоговая структура папки targets этого примера будет выглядеть следующим образом:
PS D:\targets> tree /f
Структура папок
Серийный номер тома: 4040-B539
D:.
│   arduino-cli.exe
│   engee-device-manager.exe
│
└───arduino_examples
    └───arduino_quick_start
            arduino_quick_start.ino

Шаг 4: Моделирование

Модель примера собрана и, прежде чем загружать её на микроконтроллер, естественно, её необходимо проверить путём моделирования в Engee. Это можно сделать и в графическом интерфейсе и автоматизированно в скрипте при помощи программного управления моделированием.

In [ ]:
cd(@__DIR__)
name = "arduino_quick_start"
try
    engee.close(name, force=true) # закрытие модели 
catch err # в случае, если нет модели, которую нужно закрыть и engee.close() не выполняется, то будет выполнена её загрузка после catch
    m = engee.load(name*".engee") # загрузка модели
end;
try
    engee.run(m) # запуск модели
catch err # в случае, если модель не загружена и engee.run() не выполняется, то будут выполнены две нижние строки после catch
    m = engee.load(name*".engee") # загрузка модели
    engee.run(m) # запуск модели
end
Out[0]:
SimulationResult(
    run_id => 29,
    "LED" => WorkspaceArray{Float64}("arduino_quick_start/LED")

)

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

In [ ]:
data = collect(simout[name*"/LED"])
t = data.time
LED = data.value

gr(format=:png)

plot(t, LED; label = :none)
Out[0]:
No description has been provided for this image

На графике наблюдается меандр с частотой 1 Гц, D = 50% и амплитудой = 1. Этап моделирования в Engee пройден успешно, добавлены блоки из пакета поддержки, а также установлено соединение с микроконтроллером. Теперь можно перейти к выполнению модели по двум запланированным сценариям.

Шаг 5: Независимое выполнение

В первую очередь переключим целевую платформу: вместо Engee в выпадающем списке выберем Target Hardware:

gif1.gif

Нажмём на кнопку "Запуск в независимом режиме". Это приведёт к тому, что сгенерируется автономное приложение реального времени и запустится на целевой платформе независимо от Engee. Информация о сборке и загрузке модели видна в окне диагностики.

В процессе сборки модели можно наблюдать, как Engee автоматически запускает ArduinoCLI для сборки проекта, его компиляции и загрузки на микроконтроллер. О ходе процесса загрузки также свидетельствует мигание светодиодов RX/TX на плате Arduino. О выполнении модели свидетельствует мигание светодиода L на плате.

Выполнение в этом режиме на Arduino приводит к тому, что приложение реального времени, сгенерированное из модели, работает на микроконтроллере независимо от Engee. После запуска приложения в Engee мы видим только информацию о затраченном времени на генерацию кода и загрузку на устройство, а также уведомление о запуске модели.

Шаг 6: Интерактивное выполнение

В интерактивном режиме реализован двусторонний обмен данными между Target Hardware и Engee. Для выполнения модели в этом режиме нажмём на кнопку "Запустить модель на железе" - также происходит вызов ArduinoCLI, приложение загружается, а в окне диагностики модели выводятся соответствующие сообщения.

Однако сразу после запуска приложения можно наблюдать, что модель выполняется и на Arduino, и в Engee. О передачи данных из микроконтроллера в Engee свидетельствует периодическое мигание светодиода TX на плате, графики записываемых сигналов можно наблюдать в окне визуализации сигналов.

Кроме этого, сохраняется возможность управления приложением на Arduino - в нужный момент можно, например, остановить выполнение модели на железе.

Для удобства мониторинга модели можно увеличить время - в этом режиме модель выполняется уже не 10 секунд, а 100. Для неограниченного времени выполнения в строку конца интервала моделирования можно вписать Inf.

Дополнение: Инспектор данных

Ещё один удобный инструмент для мониторинга данных, получаемых от Arduino - это встроенное приложение Engee "Инспектор данных". В интерактивном режиме откроем приложение:

Благодаря этому инструменту появляется возможность анализа сигналов на различных прогонах модели даже в процессе её выполнения.

Дополнение: Результаты работы пакета поддержки

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

In [ ]:
path = "/user/codegen_target"
folders = filter(f -> isdir(joinpath(path, f)), readdir(path))
if !isempty(folders)
    latest_folder = last(sort(folders, by=f -> stat(joinpath(path, f)).ctime))
    println("Последняя созданная папка: \n"*latest_folder)
end
println("\nЕё содержимое:")
readdir(joinpath(path,latest_folder)) .|> println;
Последняя созданная папка: 
0eb920ef-a28a-4037-9630-6ff17de8908a

Её содержимое:
arduino_quick_start.c
arduino_quick_start.h
codeinfo.json
main.c

В этой папке:

  • файлы .h, .c - код модели на языке Си, который можно скачать и использовать в сценарии экспорта кода.
  • файл codeinfo.json - описание интерфейсов кода модели в формате JSON. Здесь приводятся имена функций, структур данных - состояний, настраиваемых параметров, а также метаданные модели.

Вот, что представляет из себя содержимое этого файла в нашем случае:

In [ ]:
for line in eachline(joinpath(path,latest_folder,"codeinfo.json"))
    println(line)
end
{
    "entrypoints": [
        {
            "type": "INIT",
            "name": "init",
            "cname": "arduino_quick_start_init"
        },
        {
            "type": "STEP",
            "name": "step",
            "cname": "arduino_quick_start_step",
            "sample_time": "0.02",
            "inputs": [],
            "outputs": [],
            "states": [
                {
                    "cname": "arduino_quick_start_S",
                    "ctype": "Ext_arduino_quick_start_S",
                    "fields": []
                }
            ],
            "timings": []
        },
        {
            "type": "TERMINATE",
            "name": "term",
            "cname": "arduino_quick_start_term"
        }
    ],
    "tunable_params": null,
    "logging_signals": {
        "cname": "arduino_quick_start_B",
        "ctype": "Ext_arduino_quick_start_B",
        "fields": [
            {
                "name": "Pulse Generator",
                "cname": "LED",
                "ctype": "double",
                "mtype": "double",
                "dims": [],
                "uuid": "1ee02607-0cf8-4001-9989-3751fa191965",
                "sample_time": "0.02"
            }
        ]
    },
    "metadata": {
        "codegen_version": "release-1.1.30",
        "model_uuid": "",
        "model_name": "arduino_quick_start",
        "target": "c",
        "model_config": {
            "Codegen": {
                "EnableMultiTasking": false,
                "GenerateComments": true,
                "CreateCFunction": false,
                "DefaultParameterBehavior": "Inlined",
                "TargetHardware": "C"
            },
            "Solver": {
                "AbsTol": "auto",
                "FixedStep": "0.02",
                "InitialStep": "auto",
                "MaxStep": "auto",
                "MinStep": "auto",
                "OutputOption": "false",
                "OutputTimes": "1e-2",
                "RelTol": "auto",
                "SolverName": "Euler",
                "SolverType": "fixed-step",
                "StartTime": "0.0",
                "StopTime": "100",
                "SaveSignalsAtEvents": true,
                "ZcThreshold": "1e-10",
                "MaxConsecutiveMinStep": "10"
            },
            "SimulationMode": "normal",
            "RITM": {
                "ritmDetectOverruns": true,
                "ritmOVRMode": "Terminate",
                "ritmOVRtoignore": 1,
                "ritmCalculateTET": true,
                "ritmProfile": false,
                "ritmProfilePoints": 400,
                "ritmCompilerFastRun": false,
                "ritmExtModeNoWait": false
            },
            "DataSource": {
                "DataSourceType": "BaseWorkspace",
                "DataDictionary": null,
                "HasAccessToBaseWorkspace": true
            }
        }
    }
}

Сгенерированные при помощи ArduinoCLI исходные файлы приложения можно найти в директории по пути:

C:\Users\<username>\AppData\Local\arduino\sketches\<sketch_id>

В случае текущего примера - это последняя сгенерированная папка

C:\Users\alexevs\AppData\Local\arduino\sketches\B63B153BB37714FCC764F0C5FC795996 со следующим содержимым:

PS C:\Users\alexevs\AppData\Local\arduino\sketches\B63B153BB37714FCC764F0C5FC795996> tree /f
Структура папок тома Windows
Серийный номер тома: C03A-F53E
C:.
│   .last-used
│   arduino_quick_start.ino.eep
│   arduino_quick_start.ino.elf
│   arduino_quick_start.ino.hex
│   arduino_quick_start.ino.with_bootloader.bin
│   arduino_quick_start.ino.with_bootloader.hex
│   build.options.json
│   compile_commands.json
│   includes.cache
│   libraries.cache
│
├───core
├───libraries
│   └───TimerOne
│           TimerOne.cpp.d
│           TimerOne.cpp.o
│
└───sketch
    │   arduino_quick_start.ino.cpp
    │   arduino_quick_start.ino.cpp.d
    │   arduino_quick_start.ino.cpp.o
    │
    └───src
            arduino_quick_start.c
            arduino_quick_start.c.d
            arduino_quick_start.c.o
            arduino_quick_start.h
            ext_mode_types.h
            ext_types.h
            ext_work.h
            rtiostream.h
            rtiostream_uart.cpp
            rtiostream_uart.cpp.d
            rtiostream_uart.cpp.o
            rtwtypes.h
            rtw_extmode.h

Заключение

В этом примере мы освоили начало работы с пакетом поддержки Arduino в Engee: прошли по шагам в процессе установки соединения, подготовки окружения, разработки модели и выполнения модели в независимом и интерактивном режимах на Arduino.