12

Оптический модуль MTF-02

Современные робототехнические системы, дроны и автоматизированные устройства требуют точного определения перемещения в пространстве. Один из ключевых компонентов для этой задачи — Оптический модуль визуальной инерциальной навигации, такой как MTF02. Этот компактный и энергоэффективный сенсор позволяет устройствам "чувствовать" движение даже без GPS или внешних ориентиров.

Оптический датчик MTF-02

Оптический датчик MTF-02

В конструкции датчика MTF-02 интегрированы две ключевые подсистемы:

  • ToF motion sensor (Time-of-Flight) для получения точечного расстояния;

  • Сенсор оптического потока (Optical flow) для отслеживания движения поверхности.

Основные характеристики

  • Напряжение питания:4 - 5.5В, потребление ~200мВт;

  • Размеры/вес: ~25x10x4,5мм 1,5г;

  • Оптический поток: 42° - при освещенности 60 Lux;

  • Минимальная высота: ≥ 8см;

  • Максимальная скорость: до 7м/c на высоте 1 метр;

  • FoV-камера: до 2,5 м @ 90% отражения и 600 Lux, мертвая зона FoV-камеры после 2см;

  • Длина волны ToF: 940нм.

Процесс работы MTF-02:

  1. ToF motion sensor — технология измерения расстояния до объекта с помощью времени задержки отраженного сигнала (лазерного или ИК-импульса). Точечные датчики измеряют дистанцию до одной точки.

  2. Optical flow - датчик захватывает изображение поверхности вниз и вычисляет относительное движение при частоте ~50 Гц, работает начиная с высоты 8см и далее для алгоритмов стабилизации движения при полете или перемещении в помещении.

Это похоже на то, как компьютерная мышь определяет свое перемещение, но с более высокой точностью.

Интерфейсы и протоколы

  • UART, LVTL 3.3В;

  • поддерживаемые протоколы: Micolink, Mavlink (APM +PX4), MSP(iNav):

  • Частота передачи: 50 Гц.

Применение:

Дроны и квадрокоптеры

  • Стабилизация в помещении без GPS;

  • Точное позиционирование при посадке.

Роботы-пылесосы

  • Построение карты помещения;

  • Контроль пройденного пути.

Мобильная робототехника

  • Навигация автономных роботов;

  • Избегание столкновений.

Локализация и колижионирование

интеграция оптического потока и ToF

Аналитика движения

определение скорости движения по поверхности

Мое личное применение:

Задача стоит следующая: мне необходимо разработать такую систему, которая способна сканировать в пространстве над поверхностью т.е. по "воздуху".

Для решения поставленной задачи, был выбран датчик MTF-02, обладающий необходимыми характеристиками для одновременного определения пройденного пути, координат перемещения в плоскости (X, Y) и оценки высоты объекта.

Благодаря встроенномуToF motion sensor, обеспечивающей точное измерение расстояния, а также модулю оптического потока, MTF-02 способен адаптироваться к условиям, когда отсутствует прямая опора или контрольный фон, это делает его особенно эффективным в задачах, где важно отслеживать перемещение объекта в подвешенном состоянии или при движении над неровной/неоднородной поверхностью.

Схема подключения датчика MTF-02

Сигнал TX датчика MTF-02 подключается к STM32F103(PA10-31 контакт - RX), а так же +5В и GND

Сигнал TX датчика MTF-02 подключается к STM32F103(PA10-31 контакт - RX), а так же +5В и GND

Для более стабильного напряжения питания можно использовать следующую схему, в которой работает понижающий преобразователь MP231, но необходим источник +12В, в моем случае используется аккумуляторная сборка (NiMH/Pb +12В).

Вид осциллограммы передаваемых данных модуля MTF-02 по интерфейсу USART (линия TX)

Настройка микроконтроллера STM32F103 в CubeIDE

Настройка интерфейса USART в микроконтроллере STM32F103

Настройка интерфейса USART в микроконтроллере STM32F103

  • В пункте [ 1 ] настраиваю скорость (Baud Rate [115200]), остальные параметры без изменений;

  • В пункте [ 2 ] заходим в параметр "DMA Settings" и включаем его на примем данных;

В рамках реализации приема данных по интерфейсу(USART) была задействована технология прямого доступа к данным (DMA), что позволило существенно снизить нагрузку на центральный процессор.

Для этого приемный сигнал USART(USART_RX) был сконфигурирован на работу в режиме DMA, при котором поступающие данные автоматически записываются в выделенный участок оперативной памяти без участия ядра.

  • В пункте [ 3 ] заходим в параметр "NVIC Settings" и включаем глобальное прерывание.

    Для отслеживания состояния интерфейса USART и обработки важных событий (например, завершения приема или ошибки), в разделе NVIC Settings было включено глобальное прерывание USART, это обеспечивает возможность немедленного реагирования со стороны микроконтроллера на изменения состояния периферии без постоянного опроса регистров.

Реализация программного кода(настройка и прием данных)

Создание переменных и макросов

********************************************************************************************************

extern volatile uint8_t uartRxFullIRDone; //сработало прерывание по полному буферу
extern volatile uint8_t uartRxHalfIRDone; //сработало прерывание по половине буфера
extern short status_UART;

#define UART_RX_BUFFER_SIZE 96//основной буфер
uint8_t uart_rx_buffer_MTF[UART_RX_BUFFER_SIZE]={0,};
uint8_t uart_rx_buffer_MTF_copy[UART_RX_BUFFER_SIZE]={0,};


#define SIZEBUF_uart_rx_buf_mtf 64 //128 16
unsigned char uart_rx_buf_mtf[SIZEBUF_uart_rx_buf_mtf]={0,};
int size_uart_rx_buf_mtf=0;


MICOLINK_MSG_t msg;
MICOLINK_PAYLOAD_RANGE_SENSOR_t payload;

//буфер для сборки строки
#define SIZEBUF_result 96
char uart_rezult_buf1[SIZEBUF_result]={0,};
char uart_rezult_buf2[SIZEBUF_result]={0,};
char* uart_rezult_buf=uart_rezult_buf1;
short uart_rezult_buf_i=0;//индекс
char* uart_bufRow=uart_rezult_buf1;//буфер с целой строкой
//E N D буфер для сборки строки
//E N D для составления строк

//Данные полученные от структуры
float distance_m=0.0f;
int16_t flow_vel_x_cop=0;
float flow_vel_x_cop_ab=0.0f;
int16_t flow_vel_y_cop=0;
float flow_vel_y_cop_ab=0.0f;
uint32_t time_ms_s = 0;
float distance_global =0.0f;
//E N D данные полученные от структуры

//Данные после преобраз.сглаживания
float smoothed_x = 0.0f; // Сглаженная скорость по X (см/с)
float smoothed_y = 0.0f; // Сглаженная скорость по Y (см/с)
float smoothed_distance = 0.0f; // Сглаженная дистанция (м)
float total_velocity = 0.0f; // Общая скорость из сглаж. линейных скор. и дистанции (см/с)
//E N D Данные после преобраз.сглаживания

static float total_path_m = 0.0f; // Пройденный путь (метры)
float total_path_m_cop = 0.0f;
long total_path_m_cop_long =0; //тест
static float position_x_m = 0.0f; // Положение по X (в метрах)
float position_x_m_cop = 0.0f;
long position_x_m_cop_long= 0;
static float position_y_m = 0.0f; // Положение по Y (в метрах)
float position_y_m_cop = 0.0f;
long position_y_m_cop_long= 0;
float beta_rad = 0.0f;

// Буферы для сглаживания данных
#define BUFFER_SIZE 5 // Размер буфера для сглаживания, если необходимо еще медленее, уменьшать размер
float flow_vel_x_buffer[BUFFER_SIZE] = {0}; // Буфер для flow_vel_x
float flow_vel_y_buffer[BUFFER_SIZE] = {0}; // Буфер для flow_vel_y
float distance_buffer[BUFFER_SIZE] = {0}; // Буфер для дистанции
uint8_t buffer_index = 0; // Индекс текущего положения в буфере
// E N D Буферы для сглаживания данных

********************************************************************************************************

Cтруктуры MICOLINK_MSG_t msg и MICOLINK_PAYLOAD_RANGE_SENSOR_t

Реализацию структур я взял с официального сайта [ https://micoair.com/docs/decoding-micolink-messages-from-mtf-01/ ]

********************************************************************************************************

#define MICOLINK_MSG_HEAD 0xEF
#define MICOLINK_MAX_PAYLOAD_LEN 64
#define MICOLINK_MAX_LEN MICOLINK_MAX_PAYLOAD_LEN + 7
enum
{
MICOLINK_MSG_ID_RANGE_SENSOR = 0x51, // Range Sensor
};
/*
Message Structure Definition
*/
typedef struct
{
uint8_t head;
uint8_t dev_id;
uint8_t sys_id;
uint8_t msg_id;
uint8_t seq;
uint8_t len;
uint8_t payload[MICOLINK_MAX_PAYLOAD_LEN];
uint8_t checksum;

uint8_t status;
uint8_t payload_cnt;
} MICOLINK_MSG_t;

// Range Sensor
typedef struct
{
uint32_t time_ms; // System time in ms
uint32_t distance; // distance(mm), 0 Indicates unavailable
uint8_t strength; // signal strength
uint8_t precision; // distance precision
uint8_t dis_status; // distance status
uint8_t reserved1; // reserved
int16_t flow_vel_x; // optical flow velocity in x
int16_t flow_vel_y; // optical flow velocity in y
uint8_t flow_quality; // optical flow quality
uint8_t flow_status; // optical flow status
uint16_t reserved2; // reserved
} MICOLINK_PAYLOAD_RANGE_SENSOR_t;

********************************************************************************************************

Метод uart_Handler_MTF

Данный метод отвечает за получение, предварительную обработку и подготовку к использованию данных, поступающих от датчика MTF-02.

Основные задачи метода
Приём данных с датчика
Метод реагирует на прерывания DMA — по заполнению первой или второй половины приёмного буфера. Это позволяет работать с потоком данных непрерывно, без потерь.

Буферизация и переключение кадров
Используются два чередующихся буфера (uart_rezult_buf1 и uart_rezult_buf2), чтобы приём новых данных и обработка предыдущих шли параллельно.

Декодирование пакета
Полученные байты передаются в функцию micolink_decode, которая разбирает пакет и выделяет физические величины:

flow_vel_x_cop — линейная скорость по оси X

flow_vel_y_cop — линейная скорость по оси Y

distance_m — дистанция до поверхности

Сглаживание данных
Для уменьшения шумов значения проходят через циклический буфер и усредняются функцией calculate_average. Это даёт стабильные показания скорости и расстояния.

Интегрирование скорости в путь
На основе сглаженных скоростей выполняется интегрирование (update_position) для получения пройденного пути по осям X и Y.
Параллельно рассчитывается общая длина пути и угол движения (calculateBetaRadians).

Подготовка данных для передачи
Формируются готовые строки (sprintf) с данными в удобном текстовом формате для отладки, логирования или передачи в другие системы.

void uart_Handler_MTF(void)
{
HAL_Delay(1);//чтобы HAL_GetTick() не выдавал ноль
uint32_t ms = HAL_GetTick();
// uint32_t time_sec = ms / 1000;
char isData=0;
char* pData=(char*)uart_rx_buffer_MTF;

if(uartRxFullIRDone){
uartRxFullIRDone = 0;
// Указатель на вторую половину основного буфера DMA
pData=(char*)&uart_rx_buffer_MTF[UART_RX_BUFFER_SIZE/2];
isData=1;
}
if(uartRxHalfIRDone){
uartRxHalfIRDone = 0;
// Указатель на первую половину основного буфера DMA
pData = (char*)uart_rx_buffer_MTF;
isData=1;
}
if(isData)
{
isData=0;

if(uart_rezult_buf==uart_rezult_buf1){
memcpy(uart_rezult_buf1, pData, UART_RX_BUFFER_SIZE / 2);
uart_bufRow=uart_rezult_buf1;
uart_rezult_buf=uart_rezult_buf2;

}else{
memcpy(uart_rezult_buf2, pData, UART_RX_BUFFER_SIZE / 2);
uart_bufRow=uart_rezult_buf2;
uart_rezult_buf=uart_rezult_buf1;

}
memcpy(uart_rx_buffer_MTF_copy,(uint8_t*)uart_bufRow,UART_RX_BUFFER_SIZE);
micolink_decode(uart_rx_buffer_MTF_copy,UART_RX_BUFFER_SIZE);

//Сглаженные значения
flow_vel_x_buffer[buffer_index] = flow_vel_x_cop;
flow_vel_y_buffer[buffer_index] = flow_vel_y_cop;
distance_buffer[buffer_index] = distance_m;
buffer_index = (buffer_index + 1) % BUFFER_SIZE; // Циклический буфер
// Рассчитываем сглаженные значения

smoothed_x = calculate_average(flow_vel_x_buffer);
smoothed_y = calculate_average(flow_vel_y_buffer);
smoothed_distance = calculate_average(distance_buffer);
//E N D Сглаженные значения
float time_sec = ms/1000.0f;//перевод в секунды

update_position(smoothed_x,smoothed_y,ms);//интегрирование линейной скорости для расчёта пройденного пути, с учётом фильтрации малых шумов.

update_motion(smoothed_x,smoothed_y,smoothed_distance, ms);//расчёт общей скорости и пройденного пути

//делаю копию потому что position_x_m,y и total_path_m static (если одтать в буфер staic, то работать система не будет)
position_x_m_cop = position_x_m;
position_y_m_cop = position_y_m;
total_path_m_cop = total_path_m*1000.0f;
total_path_m_cop_long = (long)roundf(total_path_m_cop);

flow_vel_x_cop_ab=position_x_m_cop * 1000.0f;//перевод в мм
flow_vel_y_cop_ab=position_y_m_cop * 1000.0f;
position_x_m_cop_long = (long)roundf(flow_vel_x_cop_ab);
position_y_m_cop_long = (long)roundf(flow_vel_y_cop_ab);
//E N D

beta_rad = calculateBetaRadians(flow_vel_x_cop_ab, flow_vel_y_cop_ab);//получение угла в радианах

size_uart_rx_buf_mtf = sprintf((char*)&uart_rx_buf_mtf[0], "%ld %ld %.6f %ld %.3f %d %d>",
position_x_m_cop_long, position_y_m_cop_long,beta_rad, total_path_m_cop_long, time_sec, 1,0);//отправка пакета UART ведущему устройству

}
}

********************************************************************************************************

Метод update_motion

Данный метод отвечает за расчёт общей скорости и пройденного пути, он выполняет ключевую навигационную задачу — на основе данных от MTF-02 вычисляет, с какой скоростью движется объект и какое расстояние он прошёл с момента старта измерений.

Принцип работы
Измерение времени между кадрами
Функция хранит момент предыдущего вызова (last_time_ms) и определяет, сколько секунд прошло между текущим и прошлым измерением (delta_time_s). Это позволяет интегрировать движение по времени.

Вычисление мгновенной скорости

Используются проекции скорости по осям X и Y (flow_vel_x, flow_vel_y).

Их векторная сумма (sqrtf(...)) даёт модуль скорости в плоскости.

Результат умножается на измеренное датчиком расстояние до поверхности (distance_m), что учитывает масштаб оптического потока.

Деление на 100 применяется, если исходные скорости приходят в сантиметрах в секунду (приведение к м/с).

Интегрирование для получения пути
Общая скорость умножается на интервал времени — это даёт приращение пути за данный шаг.
Приращение накапливается в переменной total_path_m, которая отражает суммарное пройденное расстояние с начала работы системы.

Обновление времени
В конце функция сохраняет текущее время вызова, чтобы при следующем измерении корректно вычислить delta_time_s.

Простыми словами
Метод update_motion — это шагомер с точностью до миллиметров, но не по количеству шагов, а по точным данным от оптического датчика.
Он измеряет скорость движения, умножает её на прошедшее время и складывает результат в копилку пройденного пути

// Функция расчёта общей скорости и пройденного пути
void update_motion(float flow_vel_x, float flow_vel_y, float distance_m,uint32_t time_ms) {

static uint32_t last_time_ms = 0; // Время предыдущего измерения

float delta_time_s = (time_ms - last_time_ms) / 1000.0f; // Время в секундах

if (delta_time_s > 0) {
// Рассчитываем общую скорость (м/с)
float total_velocity_m_per_s =distance_m * sqrtf(flow_vel_x * flow_vel_x + flow_vel_y * flow_vel_y)/100.0f;// деление на 100 если скорости передаются в см/c если в м/то не надо делить
// Интегрируем скорость для расчёта пути
total_path_m += total_velocity_m_per_s * delta_time_s;
}
last_time_ms = time_ms; // Обновляем время последнего измерения
}

Метод update_position

Данный метод отвечает за то, чтобы перевести показания датчика MTF-02 из скоростей в координаты — то есть понять, где сейчас находится объект относительно точки старта.

Как это работает
Определение времени между измерениями
Метод вычисляет, сколько секунд прошло с момента предыдущего вызова (delta_time_s).
Это нужно, чтобы правильно учесть, на какое расстояние мог сдвинуться объект.

Отсев шумов
Если скорость по X или Y слишком мала (меньше 0,01 см/с), она считается шумом и приравнивается к нулю. Это предотвращает накопление ошибок из-за микроколебаний или дрожания датчика.

Перевод в метры в секунду
Показания датчика приходят в сантиметрах в секунду, поэтому они делятся на 100, чтобы работать в метрической системе (м/с).

Интегрирование — путь из скорости

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

Полученное приращение добавляется к текущим координатам position_x_m и position_y_m.

Таким образом, шаг за шагом накапливается точка текущего положения в метрах.

Обновление времени
Сохраняется момент последнего измерения, чтобы при следующем вызове правильно рассчитать delta_time_s.

Простыми словами
update_position — это математический «следопыт»:
он берёт скорости, отбрасывает шум, переводит их в пройденное расстояние и складывает с предыдущими координатами.
В результате получается текущая позиция объекта в двухмерном пространстве.

********************************************************************************************************

//интегрирование линейной скорости для расчёта пройденного пути, с учётом фильтрации малых шумов.
void update_position(float flow_vel_x, float flow_vel_y,uint32_t time_ms){

static uint32_t last_time_ms = 0;// Время последнего измерения (мс)

// Вычисляем разницу во времени между измерениями в секундах
float delta_time_s = (time_ms - last_time_ms) / 1000.0f;
if (delta_time_s > 0.0f) {

// Проверка на малые скорости и шумы
if (fabsf(flow_vel_x) < 0.01f) flow_vel_x = 0.0f; // Игнорируем шум по X
if (fabsf(flow_vel_y) < 0.01f) flow_vel_y = 0.0f; // Игнорируем шум по Y

// Переводим скорости из см/с в м/с
float velocity_x_mps = flow_vel_x / 100.0f; // Линейная скорость по X (м/с)
float velocity_y_mps = flow_vel_y / 100.0f; // Линейная скорость по Y (м/с)

// Интегрируем скорости для обновления положенияx`
position_x_m += velocity_x_mps * delta_time_s; // Путь = Скорость * Время
position_y_m += velocity_y_mps * delta_time_s;
}
// Обновляем время последнего измерения
last_time_ms = time_ms;
}

********************************************************************************************************

Метод calculateBetaRadians перевод угла в радианы

float calculateBetaRadians(float flow_vel_x, float flow_vel_y)
{
return atan2(flow_vel_y, flow_vel_x); // Угол в радианах
}

Метод calculate_average вычисление среднего значения из буфера, необходи для сглаживания данных поступающих от датчика MTF-02


float calculate_average(float *buffer) {
float sum = 0.0;
for (int i = 0; i < BUFFER_SIZE; i++) {
sum += buffer[i];
}
return sum / BUFFER_SIZE;
}
//E N D функция вычисления среднего значения из буфера

********************************************************************************************************

Обработка и расшифровка данных MicoLinkВ

В работе с датчиком MTF-02 информация передаётся в виде бинарных сообщений по протоколу MicoLink. Этот набор функций выполняет полный цикл приёма — от поимки первого байта до получения готовых чисел скорости и высоты.

1. Метод micolink_parse_char, осуществляет приём и разбор данных, обрабатывает поток входящих байтов, поступающих от датчика.

Каждый байт проходит через «машину состояний»:

Заголовок — признак начала пакета.

ID устройства и системы — кому адресовано сообщение.

ID сообщения — тип передаваемых данных (например, показания дальномера).

Длина полезной нагрузки — сколько байт занимает полезная информация.

Полезная нагрузка — сами измеренные значения (скорости, дистанция).

Контрольная сумма — защита от ошибок в передаче.

Если всё прошло успешно и контрольная сумма совпала — пакет считается принятым.

2. Метод micolink_check_sum, осуществляет проверку целостности
Каждое сообщение содержит контрольную сумму — специальное число, рассчитанное по всем байтам пакета.

Если расчёт на приёмной стороне совпадает с переданным значением, значит, данные достоверны.

Этот шаг защищает от искажений, которые могут возникнуть в линии связи.

3. Метод micolink_decode, осуществляет декодирование,после успешного приёма пакет разбирается по смыслу.

В случае с MICO_LINK_MSG_ID_RANGE_SENSOR из него извлекаются:

time_ms — отметка времени измерения;

distance_m — высота над поверхностью, в метрах;

flow_vel_x и flow_vel_y — линейные скорости по осям X и Y (см/с).

Эти значения затем используются для расчёта скорости, перемещения и построения траектории движения.

// Функция обработки данных uint8_t* data, size_t size
void micolink_decode(uint8_t* data, size_t size)
{
//static MICOLINK_MSG_t msg;

if (micolink_parse_char(&msg,data,size) == false) {
return;
}

switch (msg.msg_id) {
case MICOLINK_MSG_ID_RANGE_SENSOR: {
//MICOLINK_PAYLOAD_RANGE_SENSOR_t payload;
memcpy(&payload, msg.payload, msg.len);

// Обработка данных датчика
uint32_t time_ms = payload.time_ms;
time_ms_s = time_ms;

uint32_t distance = payload.distance;
distance_m =(float)distance/1000.0f;//перевел мм в метры // высота

int16_t flow_vel_x = payload.flow_vel_x;
flow_vel_x_cop = (float)flow_vel_x;
int16_t flow_vel_y = payload.flow_vel_y;
flow_vel_y_cop = (float)flow_vel_y;

break;
}
default:
// Обработка других сообщений
break;
}
}

// Проверка контрольной суммы
bool micolink_check_sum(MICOLINK_MSG_t* msg) {
uint8_t length = msg->len + 6; // Длина сообщения
uint8_t temp[MICOLINK_MAX_LEN];
uint8_t checksum = 0;

memcpy(temp, msg, length);

for (uint8_t i = 0; i < length; i++) {
checksum += temp[i];
}

return (checksum == msg->checksum);
}
********************************************************************************************************
// Парсинг входящего байта
bool micolink_parse_char(MICOLINK_MSG_t* msg, uint8_t* data, size_t size) {//uint8_t data
for (size_t i = 0; i < size; i++) {
uint8_t byte = data[i]; // Получаем очередной байт из буфера
switch (msg->status) {
case 0: // Ожидание заголовка
if (byte == MICOLINK_MSG_HEAD) {
msg->head = byte;
msg->status++;
}
break;

case 1: // ID устройства
msg->dev_id = byte;
msg->status++;
break;

case 2: // ID системы
msg->sys_id = byte;
msg->status++;
break;

case 3: // ID сообщения
msg->msg_id = byte;
msg->status++;
break;

case 4: // Номер последовательности
msg->seq = byte;
msg->status++;
break;

case 5: // Длина полезной нагрузки
msg->len = byte;
if (msg->len == 0) {
msg->status += 2;
} else if (msg->len > MICOLINK_MAX_PAYLOAD_LEN) {
msg->status = 0; // Сброс из-за ошибки
} else {
msg->status++;
}
break;

case 6: // Прием полезной нагрузки
msg->payload[msg->payload_cnt++] = byte;
if (msg->payload_cnt == msg->len) {
msg->payload_cnt = 0;
msg->status++;
}
break;

case 7: // Контрольная сумма
msg->checksum = byte;
msg->status = 0; // Сброс статуса

if (micolink_check_sum(msg)) {

return true; // Сообщение успешно принято
}
break;

default:
msg->status = 0;
msg->payload_cnt = 0;
break;
}
}
return false;
}

********************************************************************************************************

Метод uart_startRecieving_MTF

После вызова данного метода MTF-02 начинает передавать пакеты данных по UART, а контроллер непрерывно принимает их в выделенный буфер, не тратя ресурсы на побайтовую обработку. Когда буфер наполняется наполовину или полностью, срабатывают соответствующие обработчики (uartRxHalfIRDone и uartRxFullIRDone), и начинается разбор протокола MicoLink.

********************************************************************************************************

void uart_startRecieving_MTF(void)
{
status_UART=1;//1=startRecieving 2=RxHalf 3=RxCplt

memset(uart_rx_buffer_MTF,0,sizeof(uart_rx_buffer_MTF));

HAL_UART_Receive_DMA(&huart2, (uint8_t*)uart_rx_buffer_MTF, UART_RX_BUFFER_SIZE);//начинаю прием данных от mtf_02 на uart2
}

Обработчики прерывания на прием

Данная реализация обработчиков конкретно у меня, находится в другом классе.

********************************************************************************************************

void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) //(перывание на прием от MTF)
{
if(huart == &huart2){//MTF_02
status_UART=2;//1=startRecieving 2=RxHalf 3=RxCplt //отладка
uartRxHalfIRDone = 1; //сработало прерывание по половине
}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) //Callback от UART RX (перывание на прием от MTF)
{
if(huart == &huart2){//MTF_02
status_UART=3;//1=startRecieving 2=RxHalf 3=RxCplt //отладка
uartRxFullIRDone = 1; //сработало прерывание по полному буферу
}
}

********************************************************************************************************

Обработчик ошибок

********************************************************************************************************

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART2 && enResetUART) { //MTF
/* Сброс ошибок и восстановление работы */
HAL_UART_DeInit(huart);
HAL_UART_Init(huart);
uartRxFullIRDone = 0;
uartRxHalfIRDone = 0;
}
}

********************************************************************************************************

Ссылка на скачивание исходного кода [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_исходный_код -Исходный код для датчика MTF-02]

Вывод

Датчик MTF-02 — это отличное решение для проектов, требующих точного измерения перемещения без сложных навигационных систем. Его простота, низкая цена и энергоэффективность делают его популярным в робототехнике, дронах и умных устройствах.

Главная функция

void proj_main()
{
volatile const char *ch = ";V-F-BIN;ver: "VER_PROG(VER_a,VER_b,VER_c);(void)ch;//0x8008b00


HAL_Delay(1);//чтобы HAL_GetTick() не выдавал ноль

uart_startRecieving_MTF();//Начинаю принимать данные от mtf_02

while (1){

//хэндлеры
uart_Handler_MTF();
}//while (1)
}

********************************************************************************************************

Ссылка на скачивание исходного кода [ https://t.me/ChipCraft В закрепленном сообщении [ #исскуствомк_исходный_код -Исходный код для датчика MTF-02]

Вывод

Датчик MTF-02 — это отличное решение для проектов, требующих точного измерения перемещения без сложных навигационных систем. Его простота, низкая цена и энергоэффективность делают его популярным в робототехнике, дронах и умных устройствах.


Заключение

Если статья показалась Вам интересной, буду рад выпустить для Вас еще множество статей исследований по всевозможным видам устройств, так что, если не хотите их пропустить – буду благодарен за подписку на мой ТГ-канал: https://t.me/ChipCraft.

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества