Skip to content

Модуль библиотеки для обмена данными с рабочим пространством Matlab Simulink

License

Notifications You must be signed in to change notification settings

Casonka/1224l-matlab-serial-stm32

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Библиотека для обмена с окружением Maltab Simulink

В этом репозитории содержится программный код библиотеки для отправки данных различного типа в рабочее пространства Simulink для реализации исследований, процессов калибровки и настройки, отладки, а также реализации интерфейса Hardware-in-the-Loop. На данный момент реализация включает отправку, прием находится в процессе тестирования и будет добавлен в следующем обновлении

Актуальность проекта: апрель 2024 года Над репозиторием работал: Программист РЦР ДГТУ Назаров Александр (@casonka)

Структура библиотеки

В основе проекта лежит следующая структура :

1224l-matlab-serial-stm32:
|
|
|--inc:
|   |--matlab_serial.h
|
|--src:
	|--matlab_serial.c

matlab_serial.h - заголовочный файл, содержащий шаблоны функций библиотеки
matlab_serial.c - файл с реализацией функций библиотеки

Как работает библиотека

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

- uint8_t
- int8_t
- uint16_t
- int16_t
- uint32_t
- int32_t
- float

Методы библиотеки содержат необходимый минимум защиты от аргументов, ссылающихся на NULL, несоответствия вызываемому типу данных с инициализированным и ошибки динамического выделения памяти.

Благодаря такой реализации удалось получить функции с упрощенным подобием динамической типизации и уменьшить количество требуемых аргументов функции. Подробная информация и примеры реализации библиотеки смотри в следующем разделе.

Инструкция по взаимодействию

Для минимальной работы драйвера связи с пространством Simulink необходимо выполнение как минимум двух функций:

matlab_serial_init(obj, interface, pointer, start_symbol, end_symbol);

Функция инициализации сериализатора, содержит следующие аргументы:

  • obj - объект типа matlab_serial_t, необходимый для организации обмена;
  • interface - объект типа UART_HandleTypeDef необходимый для привязки к объекту сериализации;
  • pointer - переменная, которую необходимо передать в рабочее пространство;
  • start_symbol - значение стартового байта пакета, передаваемого в Matlab;
  • end_symbol - значение двухбайтового конца пакета, передаваемого в Matlab;

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

Для инициализации передачи массивов реализована следующая функция инициализации:

matlab_serial_init_array(obj, interface, pointer, start_symbol, end_symbol);

Список аргументов повторяется с первым вариантом функции и кроме другого названия из параметра pointer используется ссылка не на параметр, а на нулевой элемент массива _Generic((&pointer[0]),\ поэтому при инициализации убедитесь, что в аргумент передается одномерный массив.

Для передачи отслеживаемых переменных используют функцию передачи:

matlab_serial_send(matlab_serial_t *object,uint32_t timeout);

Помимо передачи объекта, вторым аргументом указывается таймаут передачи информационных пакетов.

Результат выполнения функций можно отслеживать при помощи переменной типа status_t, ниже приведен список результатов выполнения, по которым можно определить ключевые состояния работы функций библиотеки:

typedef  enum {
STATUS_OK = 0x0, // Успешное выполнение функции
OBJECT_NULL = 0x1, // Передан аргумент с ссылкой на NULL
INVALID_DATA_TYPE = 0x2, // Несоответствие передаваемого типа с инициализованным
UNDEFINED_DATA_TYPE = 0x3, // Тип данных не был инициализирован
SENDING_ERROR = 0x4, // Ошибка отправки данных
RECEIVING_ERROR = 0x5, // Ошибка приема данных
ALLOCATE_ERROR = 0x6, // Ошибка при выделении динамической памяти
END_FUNCTION_WITH_ERROR = 0xF, // Функция завершена с ошибкой (не используется)
}status_t; 

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

matlab_serial_finish(matlab_serial_t *object);

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

// создание объекта матлаб сериализатора
matlab_serial_t object;

// создание отслеживаемой переменной 
float value = 0.4;

/*! инициализация сериализатора для отслеживания float переменной
*	huart1 может быть заменен на любой другой интерфейс UART, сгенерированный 
*	в вашем Cube MX или CubeIDE проекте
*/
matlab_serial_init(object, huart1, value, 0x3A, 0x0D0A);

// loop
// объявление передачи данных с таймаутом 100 миллисекунд
matlab_serial_send(&object, 100);

// При необходимости завершаем работу с объектом, освобождая занимаемую память
matlab_serial_finish(&object);

Для получения дополнительной информации рекомендуется обратиться к заголовочному файлу matlab_serial.h .

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

float value = 0.0;
void foo(void)
{
    // ОШИБКА приводящая к утечке памяти
    matlab_serial_t object;
    matlab_serial_init(object, huart1, value, 0x3A, 0x0D0A);
	
	matlab_serial_send(object, 100);
}

int main(void)
{
    // Выполнения инициализации, настройка регистров микроконтроллера
    while(1)
    {
        foo();
    }
}

В приведенном фрагмента matlab_serial_t переменная инициализируется в качестве локальной переменной, объект инициализируется и сразу же отправляет данные, в процессе завершения выполнения функция очищает локальную переменную, однако выделяемая в таком случае динамическая память объекта остается и занимает место, поэтому многократное выполнение функции влечет за собой утечку памяти и скорейший переход в HardFault.

В качестве возможных вариантов исправление ошибки будет указывание объекта глобальной переменной, а функцию инициализации проделать однократно:

float value = 0.0;
matlab_serial_t object;
void foo(void)
{
	matlab_serial_send(object, 100);
}

int main(void)
{
    // Выполнения инициализации, настройка регистров микроконтроллера
    matlab_serial_init(object, huart1, value, 0x3A, 0x0D0A);
    while(1)
    {
	    foo();
    }
}

В таком случае запись считается корректной и может быть использована разработчиком как шаблон. Допускается запись инициализации в локальном пространстве в следующем виде:

float value = 0.0;
matlab_serial_t object;
void foo(void)
{
	matlab_serial_init(object, huart1, value, 0x3A, 0x0D0A);
	matlab_serial_send(object, 100);

	matlab_serial_finish(&object);
}

int main(void)
{
	// Выполнения инициализации, настройка регистров микроконтроллера
	while(1)
	{
		foo();
	}
}

Таким образом память освобождается и объект может быть инициализирован снова.

Работа с окружением Matlab Simulink

Настройка Simulink программы является одним из основных шагов для успешного обмена с микроконтроллером. Инструкция по её настройке была написана на основе этого репозитория. Переходите по ссылке для получения дополнительной информации по настройке Simulink.

Для организации передачи используются блоки расширения Embedded Coder. Расположение блоков может быть реализовано, как на приведенном ниже рисунке.

Данный шаблон можно использовать как пример для реализации своих Simulink проектов. Для соединения используется блок Serial Configuration с указанием COM порта и настроенной скорости в бодах. Для примера в приведенных ниже рисунках демонстрируется настройка для приема одного байта (рисунок слева) и массива трех байт (рисунок справа) информации.

Блок Cast необходим для преобразования значения к необходимому типу и необходим в том случае, если вы пытаетесь передать float переменную. В таком случае параметр принимаемой переменной в блоке Serial Receive необходимо изменить на single, а блоке Cast указать double, этого будет достаточно для успешного приема float переменной. Настройка преобразования приведена в рисунке, приведенном ниже.

Todo лист (дорожная карта) ближайших обновлений

  • Добавить функции для приема данных с Matlab Simulink на микроконтроллер;
  • Добавить реализацию инициализации режима Hardware-in-the-Loop;
  • Добавить дополнительные функции для повышения вариативности выполнения функций отправки (по таймеру, внешнему событию);
  • Расширить транспорт, добавив реализацию обмена при помощи DMA;

Спасибо за внимание! Если репозиторий помог тебе в разработке и исследовании, мне было бы приятно получить от тебя star, это мотивирует меня продолжать наполнение библиотеки.

About

Модуль библиотеки для обмена данными с рабочим пространством Matlab Simulink

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C 100.0%