Документация Engee
Notebook

Генерация кода для МИК32 (Измеритель освещенности)

В этом демонстрационном примере представлена разработка модели Engee для измерителя освещённости на фоторезисторе с последующей генерацией кода и выполнением на отладочной плате MIK32 NUKE V0.3.

Введение

Целевое устройство, используемое в этом демонстрационном примере - отладочная плата MIK32 NUKE V0.3 на базе микроконтроллера K1948ВК018 MIK32 Amur. В разрабатываемой в этом примере модели Engee осуществляется расчёт освещённости по имитируемому сигналу от аналого-цифрового преобразователя (АЦП) контроллера, а также подключается периферия контроллера. Компиляция и загрузка кода в микроконтроллер произведена из VS Code с расширением PlatformIO.

Аппаратная часть

Измерение освещенности в этом примере производится при помощи фоторезистора из семейства GL55. Входной сигнал АЦП - это падение напряжения на токоограничивающем резисторе в цепи фоторезистора. При высокой освещенности сопротивление фоторезистора $R_{LDR}$ уменьшается, а падение напряжения $V_{R_1}$ на токоограничивающем резисторе $R_1 = 83\ Ом$ увеличивается. Уровень питающего напряжения равен $V_{CC} = 3.3 В$. Схема соединения элементов приведена ниже.

mik32_lux_plate.png

Питание на схему подаётся от отладочной платы (контакты 3V3, GND). Получаемый от схемы аналоговый сигнал поступает на АЦП 4 микроконтроллера (ADC1.4), контакт P0.7.

Описание модели

Модель этого примера - mik32_adc_lux.engee. Для подключения и работы с периферией микроконтроллера используются блоки C Function. Блок времени моделирования Clock передаёт в блок ADC4 текущее время моделирования для имитации измеренного на резисторе $R_1$ падения напряжения в процессе моделирования.

mik32_lux_model.png

Для расчёта освещенности в модели присутствует подсистема расчёта сопротивления фоторезистора Get_LDR_Resistance и блок приближенной одномерной функции illuminance_from_resistance.

Подключение периферии

Для работы с периферией МИК32 в модели используются следующие блоки C Function: systemClockConfig, EnableInterrupts, ADC4 и USART1_print. Каждый из этих блоков подключает заголовочный файл для соответствующей периферии из библиотеки MIK32 HAL. Блок EnableInterrupts помимо прочего подключает заголовочный файл с функцией обработки прерываний, а USART1_print - заголовочный файл stdlib.h стандартной библиотеки Си для преобразования целочисленного формата в строку.
Подключаемые заголовочные файлы содержатся в директории include/ примера. Ниже приведен пример подключения заголовочного файла HAL-библиотеки в блоке systemClockConfig.

mik32_lux_include.png

В таблице ниже дана информация о назначении блоков C Function и подключаемых ими файлах библиотеки MIK32 HAL.

Блок C Function Назначение Подключаемые файлы заголовков
systemClockConfig Инициализация библиотеки HAL, настройка подсистемы тактирования и монитора частоты МК mik32_hal.h
EnableInterrupts Включение аппаратных прерываний, подключение функции обработки прерываний mik32_hal_irq.h mik32_hal_adc_isr.h
ADC4 Настройка АЦП и получение новых значений mik32_hal_adc.h
USART1_print Настройка USART и передача в него сообщений mik32_hal_usart.h

Более подробное описание принципов работы кода в блоках C Function дано в комментариях к коду.

Расчёт освещенности

Встроенные АЦП МИК32 имеют 12-битовую разрядность, в связи с чем получаемый от АЦП сигнал ADCvalue принимает значения в диапазоне [0, 4095]. Как говорилось ранее, этот сигнал соответствует падению напряжения $V_{R_1}$ на токоограничивающем резисторе в цепи фоторезистора в диапазоне [0, 1.2] В. В блоке Get_LDR_Resistance модели на основании этого сигнала производится расчёт сопротивления фоторезистора $R_{LDR}$ по формуле

$$R_{LDR} = \left( \frac{V_{CC}}{V_{R_{1}}} - 1 \right ) \cdot R_1 = \left( \frac{11261}{V_{R_{1}}} - 1 \right ) \cdot 83$$

На основании полученного сигнала Ohm блок 1-D Lookup Table illuminance_from_resistance формирует выходной сигнал освещенности Lux. Примерная функция, параметризуемая блоком illuminance_from_resistance и связывающая освещенность и сопротивление, определяется по следующим точкам:

In [ ]:
Освещенность = [4624,1895,1412,1129,929,773,646,538,445,363,290,223,162,107,55,7];
Сопротивление = [1,50,100,150,200,250,300,350,400,450,500,550,600,650,700,750];

using Plots, LaTeXStrings
gr( size = (400, 400), legend=:top, format=:svg )

plot(Сопротивление, Освещенность;
     label = L"Lux = f(R_{LDR})", marker = (:circle, 3, :blue),
     xaxis = ("Сопротивление фотодиода, Ом"), yaxis = ("Освещенность, Лк"))
Out[0]:

Эти точки выведены из паспортных данных к фоторезисторам семейства GL55.

Результаты моделирования

Для моделирования измерителя освещенности загрузим и запустим модель mik32_adc_lux.engee:

In [ ]:
if "mik32_adc_lux" in [m.name for m in engee.get_all_models()]
    m = engee.open( "mik32_adc_lux" );
else
    m = engee.load( "$(@__DIR__)/mik32_adc_lux.engee" );
end

данные = engee.run(m);

Из полученных данных моделирования построим графики сигналов: значения, полученного от АЦП (имитация синусоидального изменения падения напряжения) и рассчитанной освещенности. Так как в блоке 1-D Lookup Table выбран метод приближения "nearest", освещенность в результате расчётов будет принимать исключительно те значения, которые были внесены в таблицу блока.

In [ ]:
gr( size = (800, 300), legend=:top, format=:svg )
plot(данные["ADCvalue"].time, данные["ADCvalue"].value;
     label = "Данные АЦП", lw = 2)
plot!(данные["Lux"].time, данные["Lux"].value*4;
      label = "Освещенность, 4⋅лк", st = :step, lw = 2)
Out[0]:

Как видно из полученных графиков, изменение сигнала от АЦП приводит к соответствующих изменениям рассчитываемого сигнала освещенности.

Генерация кода

Сгенерируем код из модели для последующей загрузки разработанного в модели алгоритма в микроконтроллер:

In [ ]:
engee.generate_code( "$(@__DIR__)/mik32_adc_lux.engee",
                     "$(@__DIR__)/mik32_adc_lux_code")
[ Info: Generated code and artifacts: /user/testing_room/mik32_adc_lux/mik32_adc_lux_code

Созданные в папке mik32_adc_lux_code файлы - заголовочный mik32_adc_lux.h и исходный mik32_adc_lux.c мы и используем далее при сборке проекта. Сгенерированный файл основной программы main.c в проекте использоваться не будет, для выполнения кода в среде разработки подготовлен main.cpp, расположенной в корневой папке mik32_adc_lux примера.

Подготовка проекта в среде разработки

Среда разработки, через которую ведётся сборка проекта и его загрузка в целевое устройство - VS Code с надстройкой PlatformIO. Конфигурации среды и подключения в этом примере не рассматриваются, так как они подробно изложены на ресурсах) разработчика контроллера.
Из директории примера перенесём в проект PlatformIO сгенерированные файлы, main.cpp, mik32_hal_adc_isr.h и файл конфигурации platformio.ini.

mik32_lux_platfotmio_2.png

После этого можно перейти к сборке проекта и загрузке программы.

Выполнение кода на МИК32

Подключим отладочную плату MIK32 NUKE V0.3 к USB-порту компьютера, после чего в PlatformIO можем наблюдать подключенное устройство. Для корректной идентификации подключения этой платы требуется USB драйвер. В примере используется драйвер libusbK.

После успешного подключения перейдём к сборке проекта:
“PLATFORMIO -> PROJECT TASKS -> mik32v2 -> General -> Build”.
При отсутствии ошибок сборки загрузим скомпилированный код в микроконтроллер:
“PLATFORMIO -> PROJECT TASKS -> mik32v2 -> General -> Upload”.

Для вывода результатов расчёта используем графопостроитель из программы SerialPlot, получающий данные из последовательного порта.

mik32_lux_2.gif

При изменении освещенности на фотодиоде (светя на него фонариком или затеняя), в последовательный порт выводится соответствующее уровню значение освещенности из блока Lookup Table модели.

Заключение

В данном примере мы рассмотрели разработку модели Engee для программы расчёта освещённости на основании сигнала АЦП и вывода полученного значения в последовательный порт на микроконтроллере K1948ВК018 MIK32 Amur в составе отладочной платы MIK32 NUKE V0.3. Разработанная модель встроена сгенерированными файлами в проект среды PlatformIO для VS Code с последующей сборкой, загрузкой и исполнением на целевом устройстве.

Блоки, использованные в примере