
Современные робототехнические системы, дроны и автоматизированные устройства требуют точного определения перемещения в пространстве. Один из ключевых компонентов для этой задачи — Оптический модуль инерциальной навигации, такой как MTF02. Этот компактный и энергоэффективный сенсор позволяет устройствам «чувствовать» движение даже без GPS или внешних ориентиров.
В конструкции датчика 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 метр;
-
ToF motion sensor: до 2,5 м @ 90% отражения и 600 Lux, мертвая зона ToF-камеры после 2см;
-
Длина волны ToF: 940нм.
Процесс работы MTF-02:
-
ToF motion sensor — технология измерения расстояния до объекта с помощью времени задержки отраженного сигнала (лазерного или ИК-импульса). Точечные датчики измеряют дистанцию до одной точки.
-
Оптический поток (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
Для более стабильного напряжения питания можно использовать следующую схему, в которой работает понижающий преобразователь MP231, но необходим источник +12В, в моем случае используется аккумуляторная сборка (NiMH/Pb +12В).
Вид осциллограммы передаваемых данных модуля MTF-02 по интерфейсу USART (линия TX)

Настройка микроконтроллера STM32F103 в CubeIDE
-
В пункте [ 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 Буферы для сглаживания данных
Структуры 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; } }
Главный метод
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.
ссылка на оригинал статьи https://habr.com/ru/articles/935300/
Добавить комментарий