Датчик оптического потока PAT9125

Датчик оптического потока PAT9125

Современные компьютерные мыши, тачпады, сенсорные панели и мобильная робототехника, обязаны своей точностью и отзывчивостью миниатюрным системам движения. Одним из таких является PAT9125 - это высокоточный двухосевой оптический датчик, способный с невероятной точностью отслеживать перемещение по различным поверхностям.

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

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

  • Количество осей: 2 (X и Y);

  • Разрешение: до 1200 CPI (Counts Per Inch);

  • Интерфейсы связи: I2C и SPI;

  • Скорость кадров: до 2300 FPS (кадров в секунду);

  • Рабочее расстояние: около 1.2мм ± 0.2мм от поверхности.


Применение и обработка данных

Считывание данных с датчика по I2C и SPI - интерфейсам, дает доступ к приращениям по осям X и Y. Эти значения можно использовать для расчета абсолютного перемещения, а при необходимости - перевести в сантиметры или метры, учитывая установленное разрешение (CPI), Таким образом, PAT9125 может эффективно выполнять роль оптического энкодера, позволяя измерять расстояние, путь и даже направление движения.

Виды отслеживания оптического датчика

Датчик оптического потока PAT9125

Пример схемы электрической принципиальной, подключение к микроконтроллеру STM32F103 по интерфейсу I2C.

Датчик оптического потока PAT9125
Датчик оптического потока PAT9125

Реализация программного кода (Настройка, прием данных, конвертация) PAT9125 и микроконтроллера STM32F103.

Настройка в CubeIDE

Выберем I2C и выставим параметры:

  • I2C Speed Mode: Standard Mode;

  • I2C Speed Frequency(KHz): 100.

Датчик оптического потока PAT9125

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

#define PAT9125_I2C_ADDR (0x79<<1) // Адрес датчика (если ID_SEL = NC) (0x79<<1) (0x73 << 1) #define REG_PRODUCT_ID 0x00 // Регистр идентификатора продукта #define REG_MOTION_BURST 0x02 // Регистр для чтения движения Режим BURST чтения #define REG_DELTA_X_LO 0x03 // 8-битный формат #define REG_DELTA_Y_LO 0x04 // 8-битный формат #define REG_DELTA_XY_HI 0x12 // 12-битный формат #define REG_X_CPI 0x0D // регистр CPI по X #define REG_Y_CPI 0x0E // регистр CPI по Y #define NOISE_THRESHOLD_CM 0.01f // Фильтр шума (1 мм) #define CPI 700.0f // Разрешение датчика (Counts Per Inch) 720 #define INCH_TO_MM 25.4f // 1 дюйм = 25.4 мм #define INCH_TO_CM 2.54f // 1 дюйм = 2.54 см #define USE_12BIT_FORMAT // 12-битный формат #define I2C_RX_BUFFER_SIZE 16//Основной буфер для данных Нужно 5 байт: [MOTION, Delta_X_LO, Delta_Y_LO, SQUAL, Delta_XY_HI] uint8_t i2c_rx_buffer[I2C_RX_BUFFER_SIZE]={0,}; int32_t total_x = 0; // отсчеты по х int32_t total_y = 0; // отсчеты по y int32_t motion_flag =0; static uint16_t delta_x_lo =0; static uint16_t delta_y_lo =0; static uint16_t delta_xy_hi =0; float delta_x_cm = 0.0f; //Данные по x в см float delta_y_cm = 0.0f; //Данные по y в см float flow_vel_x_cop_ab = 0.0f;//Данные по x в мм float flow_vel_y_cop_ab = 0.0f;//Данные по y в мм float beta_rad = 0.0f; //Угловая скорость в радианах

Метод PAT9125_Init

В данном методе производится инициализация датчика:

  • Считывание ID и проверка доступности устройства;

  • Установление разрешения CPI, через метод PAT9125_SetCpi().

void PAT9125_Init() { uint8_t product_id = PAT9125_ReadReg(REG_PRODUCT_ID); if (product_id != 0x31) { // Ожидаемый ID датчика printf("%s", message_test_1); } else { /* * Значение 0x7F (127) ≈ 500 CPI (базовое значение). Значение 0xBC (188) ≈ 1000 CPI. Значение 0xDE (222) ≈ 1500 CPI. Значение 0xFF (255) ≈ 2000 CPI (максимальное).*/ PAT9125_SetCPI(0xBC);// Установлено 1000 CPI printf("%s", message_test_2); } }

Метод PAT9125_SetCPI

Данный метод, устанавливает заданный CPI в регистры X[0x0D] и Y[0x0E], считывает один байт из регистра датчика PAT9125 по I2C, (выставлено 1000 CPI, что эквивалентно 0.0254 мм/отсчет).

void PAT9125_SetCPI(uint16_t cpi_value){ uint8_t data[2]; // Устанавливаем X-CPI data[0] = REG_X_CPI; data[1] = cpi_value; HAL_I2C_Master_Transmit(&hi2c1, PAT9125_I2C_ADDR, data, 2, HAL_MAX_DELAY); // Устанавливаем Y-CPI data[0] = REG_Y_CPI; HAL_I2C_Master_Transmit(&hi2c1, PAT9125_I2C_ADDR, data, 2, HAL_MAX_DELAY); }

Метод PAT9125_ReadReg

Считывает один байт из регистра датчика PAT9125 по I2C (используется для чтения текущих значений (идентификатора устройства, данных движения и т.д.)).

uint8_t PAT9125_ReadReg(uint8_t reg) { uint8_t data = 0;// от функции PAT9125_ReadReg HAL_I2C_Master_Transmit(&hi2c1, PAT9125_I2C_ADDR, &reg, 1, HAL_MAX_DELAY); HAL_I2C_Master_Receive(&hi2c1, PAT9125_I2C_ADDR, &data, 1, HAL_MAX_DELAY); return data; }

Метод PAT9125_WriteReg

Данный метод, записывает значение value в регистр reg датчика PAT9125, используется для настройки параметров датчика, например (Установка CPI-разрешения).

void PAT9125_WriteReg(uint8_t reg, uint8_t value) { uint8_t data[2] = {reg, value}; HAL_I2C_Master_Transmit(&hi2c1, PAT9125_I2C_ADDR, data, 2, HAL_MAX_DELAY); }

Метод PAT9125_ReadMotion

Данный метод, считывает информацию о перемещении по осям X и Y из датчика (режим Burst Read), так же обновляет общее смещение total_x, total_y, и вызывает функцию обновления общего пройденного пути, простыми словами (используется каждый раз, когда нужно получить новые данные движения с датчика).

Поддерживает форматы:

  • 8-битный формат и 12-битный (определяется макросом USE_12BIT_FORMAT), для работы в 8-битном формате, просто закоментируйте макрос(#define USE_12BIT_FORMAT)
  • в режиме 12-бит, данные собираются из старших и младших байтов и расширяются до знакового значения.
void PAT9125_ReadMotion(int16_t *delta_x, int16_t *delta_y) { uint8_t reg = REG_MOTION_BURST; // Отправляем команду BURST READ if (HAL_I2C_Master_Transmit(&hi2c1, PAT9125_I2C_ADDR, &reg, 1, HAL_MAX_DELAY) != HAL_OK) { printf("Ошибка передачи I2C!\n"); return; } // Читаем сразу 5 байт данных (MOTION, Delta_X_LO, Delta_Y_LO, SQUAL, Delta_XY_HI) if (HAL_I2C_Master_Receive(&hi2c1, PAT9125_I2C_ADDR, i2c_rx_buffer, I2C_RX_BUFFER_SIZE, HAL_MAX_DELAY) != HAL_OK) { printf("Ошибка приёма I2C!\n"); return; } delta_x_lo = i2c_rx_buffer[1]; // Delta_X (младший байт) delta_y_lo = i2c_rx_buffer[2]; // Delta_Y (младший байт) delta_xy_hi = i2c_rx_buffer[4]; // Delta_XY_Hi (старшие 4 бита X и Y) #ifdef USE_12BIT_FORMAT // Если используем 12-битный формат delta_xy_hi = PAT9125_ReadReg(REG_DELTA_XY_HI); // Формируем 12-битные значения *delta_x = (int16_t)(((delta_xy_hi & 0xF0) << 4) | delta_x_lo); *delta_y = (int16_t)(((delta_xy_hi & 0x0F) << 8) | delta_y_lo); // Расширяем знаковый бит для 12-битного числа (если отрицательное) if (*delta_x & 0x0800) *delta_x |= 0xF000; if (*delta_y & 0x0800) *delta_y |= 0xF000; #else // 8-битный формат (если нужно) *delta_x = (int8_t)delta_x_lo; *delta_y = (int8_t)delta_y_lo; #endif total_x += *delta_x; total_y += *delta_y; UpdateTotalDistance(total_x,total_y); }

Метод ProcessMotionData

Данный метод является основным обработчиком движения, вызывает метод PAT9125_ReadMotion, обрабатывает данные и формирует строки для вывода по UART.

void ProcessMotionData(void) { HAL_Delay(1);//чтобы HAL_GetTick() не выдавал ноль uint32_t ms = HAL_GetTick(); PAT9125_ReadMotion(&dx, &dy); /** Данные после выполнения метода PAT9125_ReadMotion * total_x - Отсчеты по x * total_y - Отсчеты по y * delta_x_cm - данные по x в см * delta_x_cm - данные по y в см * total_distance_cm - общий пройденный путь в см */ //-------------В данном куске кода работа предназначена для CartScan--------------- float time_sec = ms/1000.0f;//перевод в секунды flow_vel_x_cop_ab = delta_x_cm * 10.0f; flow_vel_y_cop_ab = delta_y_cm * 10.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); total_path_m_cop = total_distance_cm*10.0f; total_path_m_cop_long = (long)roundf(total_path_m_cop); beta_rad = calculateBetaRadians(delta_x_cm, delta_y_cm)*10.0f;//получение угла в радианах }

Метод UpdateTotalDistance

Данный метод вычисляет прирост пройденного пути на основе новых данных смещения и обновляет общий путь total_distance_cm

void UpdateTotalDistance(int32_t delta_x, int32_t delta_y) { // Переводим X и Y в см delta_x_cm = convert_to_cm(delta_x, CPI); delta_y_cm = convert_to_cm(delta_y, CPI); // Фильтруем шум (игнорируем слишком маленькие изменения) if (fabsf(delta_x_cm) < NOISE_THRESHOLD_CM) delta_x_cm = 0; if (fabsf(delta_y_cm) < NOISE_THRESHOLD_CM) delta_y_cm = 0; // Проверяем, изменились ли данные bool is_moving = (delta_x != last_delta_x || delta_y != last_delta_y); // Вычисляем пройденный путь (Только если датчик двигается) if (is_moving) { float delta_distance = sqrtf(delta_x_cm * delta_x_cm + delta_y_cm * delta_y_cm); total_distance_cm += delta_distance/720.0f; } last_delta_x = delta_x; last_delta_y = delta_y; }

Метод convert_to_cm

Преобразует значение смещения из отсчетов в сантиметры, используя установленное разрешение CPI

float convert_to_cm(int32_t delta, float cpi) { return (float)delta * INCH_TO_CM / cpi; }

Метод calculateBetaRadians

Данный метод вычисляет угол направления движения по данным X и Y

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

Главный метод

Запускается в главном цикле while.

void proj_main() { HAL_Delay(1);//чтобы HAL_GetTick() не выдавал ноль PAT9125_Init(); while (1){ ProcessMotionData(); }//while (1) }

Вывод

Это полноценный драйвер + обработчик данных с датчика PAT9125, включающий:

  • Считывание и обработку данных о движении;
  • Перевод в физические единицы (см, мм, радианы);
  • Калибровка чувствительности.

Ссылка на скачивание исходного кода [ #исскуствомк_исходный_код -оптический_датчик_PAT9125]

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

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

Начать дискуссию