Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр Собирайте фишки

Волшебный особняк

Казуальные, Три в ряд, Головоломки

Играть

Топ прошлой недели

  • AlexKud AlexKud 38 постов
  • Animalrescueed Animalrescueed 36 постов
  • Oskanov Oskanov 7 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
0 просмотренных постов скрыто
11
ChipCraft
ChipCraft
22 дня назад

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

Оптический модуль MTF-02 Программа, Инженер, Статья, Arduino, Тестирование, Длиннопост

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

Оптический модуль MTF-02 Программа, Инженер, Статья, Arduino, Тестирование, Длиннопост

Оптический датчик 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

Оптический модуль MTF-02 Программа, Инженер, Статья, Arduino, Тестирование, Длиннопост

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

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

Оптический модуль MTF-02 Программа, Инженер, Статья, Arduino, Тестирование, Длиннопост

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

Оптический модуль MTF-02 Программа, Инженер, Статья, Arduino, Тестирование, Длиннопост

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

Оптический модуль MTF-02 Программа, Инженер, Статья, Arduino, Тестирование, Длиннопост

Настройка интерфейса 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.

Показать полностью 6
[моё] Программа Инженер Статья Arduino Тестирование Длиннопост
2
120
Aleks2
23 дня назад

Ответ на пост «Операция “Толстая жопа” или хомячий фитнесс-трекер своими руками»⁠⁠2

Питать такой девайс от зарядки - моветон! У меня мышь, бегая в самодельном колесе, сама вырабатывала электричество и питала яркий светодиод. В качестве генератора был использован моторчик постоянного тока. Однажды я подумал - чего добру пропадать, и решил подключить вместо светодиода аккумулятор, что бы она его заряжала. Взял батарейку от убитой звонилки и подключил ее к проводкам моторчика… Я как-то совсем подзабыл, что моторчик - он хоть, и работает генератором, все же в первую очередь моторчик. Нужно было поставить между ним и батарейкой диод, что бы ток тёк только от "генератора" в батарейку, но было уже поздно: колесо под лапками несчастной мышки начало вращаться в обратную сторону, она упала на живот и колесо начало раскручивать ее с бешеной скоростью! Я от неожиданности не сразу сообразил отключить провода и бедная мышь, повращавшись в этой бешеной центрифуге, выпрыгнула на ходу, взлетев в самый верх клетки, и, упав на дно, убежала в свою норку. К колесу она больше ни разу не подходила…

Джунгарский хомяк Своими руками Arduino Длиннопост Ответ на пост Текст
4
6841
R.Melvin
R.Melvin
Пересказываю всякое простыми словами, с мемами, и вот это вот всё.
23 дня назад

Операция “Толстая жопа” или хомячий фитнесс-трекер своими руками⁠⁠2

Сидели с хомяком, скучали.

Я посмотрел на Бусю, в этот раз удержавшись от шуток про ее лишний вес, и кивнул на колесо.

- Ты хоть бегаешь?

- Конечно, бегаю! – возмутилась она. – Каждую ночь.

Я скептически хмыкнул. Ну вот сложно мне поверить в ежедневные кардионагрузки при таком шарообразном телосложении. Хоть она и пыталась что-то там про пушистую кость рассказывать.

Буся – джунгарский хомяк. Днем она всячески спит, тюленится и предается прочим хомячьим утехам. Изображает бурную деятельность только по ночам. А поскольку колесо у нее практически бесшумное, то я не знаю, действительно ли она там бегает, как утверждает. Пару раз я ее застукал, резко включив свет, но она тут же стыдливо слезала с колеса.

1/2

Бусеница

Тут-то мне и пришла в голову идея проекта: а что если запилить на ардуино простенький девайс, считывающий обороты колеса? Зная его диаметр, можно легко высчитать и общий километраж, и скорость.

Первым делом, я пошел в интернеты смотреть велокомпьютеры. Цена, конечно же, не обрадовала. Да и не хотелось мне покупать готовое. Я ведь мамкин инженер, у меня две руки, хоть и из жопы, но прямые. Есть 3D принтер и скромные навыки моделирования. Писать код для ардуино я, конечно же, не умею, но для этого есть Чат ПТ.

Решено. Сели с Бусей и стали разрабатывать проект. Долго спорили, но в итоге решили заказать всю мелочевку на Али. Хоть и дольше, но Ардуино и прочая мишура там дешевле раза в два.

Операция “Толстая жопа” или хомячий фитнесс-трекер своими руками Джунгарский хомяк, Своими руками, Arduino, Длиннопост, Фитнес-трекер, Счетчик

После недолгого напряжения мозговых мыщц были выбраны:

  • Китайский Ардуино Nano 3.0 контроллер CH340

  • Экранчик OLED дисплей SISJQRR 0.91 дюйма 128x64

  • И магнитный герконовый переключатель

Обошлось это в 390р.

Кнопка нашлась дома, метизов тоже наскреблось по сусекам, а корпус замоделю сам и напечатаю.

Идея была такая: на колесо клеим маленький магнитик, с каждым оборотом колеса он проходит возле геркона. Тот отправляет сигнал на Ардуино, который в уме считает и выводит на экран все показатели. Тут-то мы и выводим хомяка на чистую воду.

Операция “Толстая жопа” или хомячий фитнесс-трекер своими руками Джунгарский хомяк, Своими руками, Arduino, Длиннопост, Фитнес-трекер, Счетчик

Буся явно представляла себе проект как-то так. Я не стал переубеждать.

Покупка оформлена, и две недели можно и дальше ничего не делать, пока идет посылка.

Буся в это время в отместку придумала способ меня ткнуть носом в свои занятия спортом. Она стала в колесо затаскивать какую-то хрень, которая сильно гремела в процессе бега. Мол, хотел бега, вот тебе бег, кожаный ублюдок. Утром источник звука пропадал из колеса, а Буся, как ни в чем ни бывало, спала себе без задних лап. Т.е. буквально. Их не видно под толстой жопой.

Наконец-то мне поступил звонок с неизвестного номера. Китайская баба-робот отрапортовала в трубку, что посылка доставлена. Я почти в ту же минуту сорвался с места и, полный счастья, побежал ее забирать. Ну не совсем в ту же, конечно, дня через 4 только собрался с силами и поперся к постамату.

За это время, путем долгих переговоров с чатом ГПТ, был написан код для Ардуино. Забегая вперед, мы его 7 раз переписывали, пока я не получил то, что хотел. А причина была в том, что я и сам толком не знал, чего хотел, а ГПТ слишком хорошо воспитан, чтобы послать меня в пешее со своими доработками.

Операция “Толстая жопа” или хомячий фитнесс-трекер своими руками Джунгарский хомяк, Своими руками, Arduino, Длиннопост, Фитнес-трекер, Счетчик

Прошил плату, пользуясь гайдом от того же ГПТ. Без него я бы вообще не справился, ибо возникали ошибки, и я, продолжая делать вид, что все держу под контролем, шел обратно к ГПТ и говорил: «Не работает! Памаги!»

После первой сборки на соплях меня ожидало потрясение. Вот от кого не ожидал удара в спину, так от китайцев. Мелкий подлый китаец, наверняка злобно хихикая по-китайски, отправил мне нерабочий экран. Плата завелась и прошилась, а вот экран был черен, как душа того китайца. Мольба и проклятия не сработали – экран так и не завелся. Разбираться с продавцом ради ста рублей и ждать опять две недели мне было неохота. Пришлось лезть на православный и духоскрепный Озон. Цены там, конечно, не радуют, по сравнению с Китаем, но Буся каждый день поторапливала.

Выбрал Дисплей LCD1602C СИНИЙ с I2C за 252р. Гулять так гулять на все деньги. Выбирал по картинке и конечно же лоханулся. Экран был огромен по сравнению с китайским и в несколько раз больше самой Ардуино. Зато была и хорошая новость – больше экрана – больше данных он сможет отобразить. Поэтому я сделал вид, что так и задумано, и все по-прежнему под контролем.

Операция “Толстая жопа” или хомячий фитнесс-трекер своими руками Джунгарский хомяк, Своими руками, Arduino, Длиннопост, Фитнес-трекер, Счетчик

Новый экран

Фотографий процесса сборки я делать не додумался, уж извините.

Будучи опытным мамкиным инженером с большим стажем, я учел прошлые ошибки и не стал ничего замерять при разработке корпуса. Кому это нужно? Ну как, плату и экран-то я, конечно, измерил, иначе вообще вышло бы глупо, а вот расстояние до колеса от прутьев клетки, расстояние между прутьями и предполагаемое место установки не стал. Этому была объективная причина: внутренности лежали у меня перед носом, а до клетки надо было поднимать задницу и идти. Пусть и пару шагов, но все-таки. Да и чутье меня почти никогда не подводило.

Замоделил корпус

Операция “Толстая жопа” или хомячий фитнесс-трекер своими руками Джунгарский хомяк, Своими руками, Arduino, Длиннопост, Фитнес-трекер, Счетчик

На этом скрине видно габариты экрана и платы (на дне 4 пенька для платы)

Из-за особенностей 3D печати решил собрать две половинки на винты. Всякие защелки – это, конечно, круто и эстетично, но не люблю я поддержки при печати и сложные модели. Я предпочитаю топорный минимализм. Даже скругления и овалы портят его брутальную атмосферу. Я так всегда себе говорю, когда представляю, что моделировать что-то сложное своими прямыми ручками из задницы я буду в 10 раз дольше, чем обычные люди.

Сборка простая: Ардуино лежит на дне корпуса, а экран на стойках для печатных плат, к которым корпус и притянут винтами с двух сторон. Сзади я заложил две гайки, чтобы потом болтами прикрутить девайс к решетке. И оставил отверстие для геркона. Отверстие было с запасом, потому что чутье мне подсказывало, что нужно будет еще доделать некую трубку с герконом внутри до колеса с магнитом. Эту мысль я оставил на тот момент, когда удосужусь все-таки померить реальное расстояние, а пока корпус напечатал просто с отверстием. Естественно, чутье меня подвело, и расстояния там особого не было. Поэтому геркон стыдливо выглядывает из корпуса на пол-шишечки, а отверстие с запасом – это, значит, для вентиляции. Ну, я так и хотел.

1/2

Корпус в сборе

Ну вот и приблизился конец квеста. Магнит я сдернул с кабеля для зарядки телефона, с магнитным коннектором. Приклеил на суперклей к колесу. Покрутил. Поматерился, отодрал и приклеил заново на нужном месте.

Девайс очень удобно крепился к решетке двумя болтами, отверстия для которых удачно попали между прутьями. Ч – чутье, мать его.

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

1/3

Шайтан машина установлена

Питается все это дело от зарядки для телефона.

Итак, что показывает экран:

  • Кр – кол-во кругов.

  • Км – пробег в километрах.

  • Время с последнего сброса.

  • Км/h – максимальная скорость.

Единственная кнопка включает экран, т.к. тот гаснет после 20 секунд, а долгое зажатие этой же кнопки обнуляет все счетчики.

Операция “Толстая жопа” или хомячий фитнесс-трекер своими руками Джунгарский хомяк, Своими руками, Arduino, Длиннопост, Фитнес-трекер, Счетчик

Сам девайс я назвал Бусенизатор 3000.

Преисполненный гордости, я ткнул Бусю в мягкие телеса и сказал торжественно: «Беги!». Она, естественно, на колесе вертела весь этот торжественный момент и до ночи просила ее не тревожить. Пришлось ждать утра.

Утром гордая толстая жопа спала после ночной смены. Бусенизатор 3000 показал, что ее хомячество пробежало 5 км за ночь. 11564 круга, максимальная скорость 10км/ч.

Операция “Толстая жопа” или хомячий фитнесс-трекер своими руками Джунгарский хомяк, Своими руками, Arduino, Длиннопост, Фитнес-трекер, Счетчик

Вроде неплохо, я даже присвистнул. Но потом загуглил нормы ГТО для ее возраста и был несколько разочарован, о чем не преминул сообщить Бусе. Гугл подсказал, что джунгарики могут пробегать и 9 км.

Моя догадка подтвердилась. Кто-то много ест и ленится делать кардио.

Пристыженная Буся на следующую ночь показала уже 6 км. Нам есть еще куда расти.

Спасибо всем, кто смог дочитать этот опус до конца, а я пойду пожру что-нибудь.

Показать полностью 14
[моё] Джунгарский хомяк Своими руками Arduino Длиннопост Фитнес-трекер Счетчик
380
3
ardublock
ardublock
23 дня назад
ArduBlock

Интернет время - Wemos Uno ESP 8266 12⁠⁠

Интернет время - Wemos Uno ESP 8266 12 Arduino, Видео ВК, Вертикальное видео, Робототехника, Самоделки, Программа, Новинки, Ardublock, Видео, Короткие видео
Показать полностью 1
[моё] Arduino Видео ВК Вертикальное видео Робототехника Самоделки Программа Новинки Ardublock Видео Короткие видео
2
7
ardublock
ardublock
23 дня назад
ArduBlock

Интернет время - ESP 8266 12F NodeMDU⁠⁠

Интернет время - ESP 8266 12F NodeMDU Arduino, Вертикальное видео, Видео ВК, YouTube, Ardublock, Видео, Короткие видео
Показать полностью 1
[моё] Arduino Вертикальное видео Видео ВК YouTube Ardublock Видео Короткие видео
0
7
ardublock
ardublock
23 дня назад
ArduBlock

ArduBlock - Интернет часы - Wemos D1 Mini ESP 8266 12⁠⁠

ArduBlock - Интернет часы - Wemos D1 Mini ESP 8266 12 Arduino, Вертикальное видео, Видео ВК, YouTube, Ardublock, Видео, Короткие видео
Показать полностью 1
[моё] Arduino Вертикальное видео Видео ВК YouTube Ardublock Видео Короткие видео
0
4
ardublock
ardublock
24 дня назад
ArduBlock

ArduBlock - Интернет часы - ESP 8266 01⁠⁠

ArduBlock - Интернет часы - ESP 8266 01 Arduino, Видео ВК, Вертикальное видео, YouTube, Ardublock, Видео, Короткие видео, Длиннопост
Показать полностью 1 1
[моё] Arduino Видео ВК Вертикальное видео YouTube Ardublock Видео Короткие видео Длиннопост
0
165
A.Kristina
A.Kristina
24 дня назад
Arduino & Pi

Цветовой сенсор⁠⁠

Высокочувствительный модуль цвета TCS3472, который способен определять RGB цвета (красный, зеленый, синий), и светить именно тем светом, цвет предмета которого был поднесён к датчику, потребляя при этом доли миллиампер и имеет широкую область применения. Кстати, стоит такой 138 руб. Ссылка на него

Сенсор Датчик Arduino Робототехника Программирование Своими руками Электроника Видео Короткие видео Реклама
33
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии