SmartTape: лазерная рулетка на STM32 и VL53L4CX

Перевод статьи How to Build a Smart Laser Distance Meter Using STM32 and VL53L4CX — Circuit Digest.
Мерить расстояние обычной рулеткой просто — ровно до того момента, когда результат нужно ещё и посчитать, записать или снять из неудобного положения. Цифровая рулетка снимает большую часть этой ручной работы, объединяя измерение расстояния, вычисления и компактный интерфейс.
SmartTape — карманный лазерный измерительный инструмент с питанием от аккумулятора, построенный вокруг этой идеи. Он измеряет расстояние, считает площадь и объём, определяет высоту косвенным методом по углу наклона, отслеживает максимум и минимум дистанции и работает как электронный уровень. Всё это управляется единственной подпружиненной поворотной ручкой и выводится на 1,3-дюймовый OLED.

Две системы измерения: дальномер и инклинометр
Из чего это собрано#
В основе — STM32G491CEU6, микроконтроллер Arm Cortex-M4F на 170 МГц. Он обслуживает дальномер, инклинометр, OLED, поворотный энкодер, мониторинг батареи, управление лазером, энергонезависимые настройки и конечный автомат приложения.
Расстояние измеряет ST VL53L4CX — Time-of-Flight датчик, который в режиме LONG берёт до 6 метров; для домашних и мастерских задач этого хватает. Углы даёт трёхосевой инклинометр Murata SCL3300-D01-10, благодаря которому прошивка умеет считать высоту косвенным методом.
Проект принципиально не собран из отладочных плат и готовых модулей: под него разведена собственная плата. Оптика вынесена на отдельную маленькую дочернюю плату, а на основной живут STM32, схема питания, интерфейс дисплея, органы управления и отладочный разъём. Прошивка тоже написана с нуля на встраиваемом C: интерфейс, алгоритмы фильтрации, расчёты, хранение настроек во Flash и графический движок OLED сделаны специально под это железо.

STM32G491, VL53L4CX и SCL3300 — три главных микросхемы
| Компонент | Обозначение | Назначение |
|---|---|---|
| Микроконтроллер | STM32G491CEU6, QFN-48 | основной процессор и логика приложения |
| ToF-датчик | ST VL53L4CX, LGA-12 | лазерное измерение расстояния |
| Инклинометр | Murata SCL3300-D01-10 | прецизионное измерение углов по трём осям |
| Дисплей | SH1106 1,3″ 128 × 64 | основной графический вывод |
| Лазерный диод | ROHM RLD65NZN5, 650 нм | видимая метка прицеливания |
| Драйвер лазера | ON Semiconductor CAT4002A | источник тока для лазера |
| Стабилизатор 3,3 В | ST LD39200PU33R | основное питание |
| Зарядное устройство | LTC4057ES5-4.2 | заряд Li-Ion/LiPo |
| P-MOSFET | AO3401A | аппаратная коммутация питания |
| Энкодер | Hongyan RS11 / Bourns PEC11R | навигация и ввод |
| Кварц | 24 МГц | тактирование МК |
Как работает измерение#
VL53L4CX излучает инфракрасный свет и определяет расстояние по времени возврата отражённого сигнала. Видимый красный лазер к системе дальнометрии отношения не имеет — он нужен только как указатель, чтобы пользователь видел, куда именно целится.
STM32 непрерывно принимает данные дальномера и оценивает качество каждого измерения. Сырые ToF-измерения иногда дают выбросы и становятся менее стабильными на больших дистанциях, поэтому прошивка применяет двухступенчатую фильтрацию: скользящую медиану, а за ней экспоненциальное сглаживание с коэффициентом, зависящим от дистанции.
SCL3300 даёт углы, нужные в режимах HEIGHT и LEVEL. В режиме HEIGHT устройство измеряет наклонную дистанцию до цели и вместе с измеренным углом тангажа вычисляет вертикальную составляющую.

ToF-датчик вынесен на отдельную оптическую плату
Датчик общается с STM32 по I²C1 на 400 кГц, адрес 0x29. Плюс две линии GPIO: XSHUT для аппаратного выключения и INT — сигнал готовности нового результата. Для дальних измерений прошивка использует режим LONG с бюджетом времени 200 мс и включает компенсацию перекрёстных засветок от защитного стекла.
Оптическая плата подключена к основной семью боковыми металлизированными полуотверстиями. Такое решение позволяет расположить оптику независимо от остальной электроники и корпуса, а заодно уводит VCSEL и область SPAD-приёмника подальше от цифровых сигналов основной платы.

SCL3300 общается по SPI кадрами по 32 бита с контролем CRC-8
SCL3300 подключён по SPI1 на частоте около 5,3 МГц. Интерфейс использует фиксированные 32-битные кадры с проверкой целостности по CRC-8. Разрешение по углу — примерно 0,0055°, чего достаточно и для функции уровня, и для тригонометрии в режиме измерения высоты. Инклинометр заодно отдаёт температуру, которая показывается в интерфейсе уровня.

Лазер питается стабилизированным током около 32 мА
Лазерный диод RLD65NZN5 на 650 нм подключён не напрямую к GPIO, а через драйвер постоянного тока CAT4002A. Ток задаётся резистором 3,74 кОм:
I_LASER = (1,2 В / 3740 Ом) × 100 ≈ 32 мА
Вход EN/DIM драйвера заведён на STM32, так что прошивка включает и выключает лазер по необходимости. Сам диод стоит на оптической плате рядом с дальномером, а апертура коллимирующей линзы совмещена с отверстием в корпусе.
Режимы измерения#
Прошивка организует функции в карусель из восьми режимов. Переключение — щелчками ручки, выбор — нажатием.

Восемь режимов в одном меню
| Режим | Функция | Что делает |
|---|---|---|
| DIST | Дальномер | непрерывное измерение с индикаторами тангажа и крена |
| LEVEL | Уровень | полноэкранный электронный пузырьковый уровень с углами и температурой |
| HEIGHT | Косвенная высота | считает вертикальную высоту по наклонной дистанции и углу |
| AREA | Площадь | берёт длину и ширину, считает площадь |
| VOLUME | Объём | берёт длину, ширину и высоту |
| CYLINDER | Объём цилиндра | считает объём бака или трубы по диаметру и высоте |
| MAXMIN | Границы | отслеживает максимум и минимум дистанции |
| MEMORY | Журнал | последние десять сохранённых измерений |
Единицы — сантиметры, миллиметры, метры или дюймы; выбранная единица сохраняется во внутренней Flash STM32 и переживает выключение.

Режим DIST

Режим CYLINDER — объём бака по диаметру и высоте

Режим LEVEL с тангажом и креном
Питание: USB-C, заряд и 3,3 В#
Путь питания начинается с разъёма USB Type-C. SmartTape заявлен как потребитель (sink) резисторами 5,1 кОм на CC1 и CC2 — этого достаточно, чтобы брать питание от обычной зарядки USB-C без контроллера Power Delivery.
Дальше VBUS проходит через диод Шоттки, защищающий от обратного тока, когда устройство питается от аккумулятора при подключённом кабеле.
Зарядом занимается LTC4057ES5-4.2. Ток заряда задаётся резистором 1,65 кОм на выводе PROG:
I_CHG = (1000 × 1,0 В) / 1650 Ом ≈ 0,606 А
Весь процесс CC/CV микросхема ведёт сама, без участия прошивки.
Главный выключатель сделан на P-канальном MOSFET AO3401A: физический ползунковый переключатель управляет затвором, а не пропускает через себя весь ток нагрузки. Подтяжка 100 кОм держит транзистор закрытым при разомкнутом переключателе.
Напряжение батареи стабилизируется до 3,3 В стабилизатором LD39200PU33R — он выдаёт до 2 А и имеет малое падение, так что схема продолжает работать по мере разряда литиевого аккумулятора.
Заряд батареи ещё и контролируется: делитель 100 кОм / 100 кОм уменьшает напряжение вдвое и подаёт его на канал 1 ADC3 (вывод PB1). Прошивка восстанавливает напряжение как
V_BAT = 2 × (ADC_RAW / 4095) × 3,30 В
и фильтрует результат перед выводом индикатора заряда.
Дисплей и единственная ручка#
Дисплей — монохромный OLED SH1106 128 × 64 на I²C2 (400 кГц, адрес 0x3C). Прошивка не относится к нему как к текстовому экрану: она держит полный закадровый фреймбуфер. У SH1106 в памяти 132 колонки против 128 у привычного SSD1306, и этот запас используется, чтобы собирать кадр целиком и отправлять его на дисплей разом. Для анимированного интерфейса это принципиально: экран не «перерисовывается по кусочкам» на глазах у пользователя.
Весь интерфейс работает через одну подпружиненную ручку в стиле Hongyan RS11 / Bourns PEC11R. Она не крутится непрерывно, как обычный энкодер: её щёлкают влево или вправо, после чего она возвращается в центр. Обе фазы заведены на GPIO с подтяжками 10 кОм и RC-цепочками подавления дребезга на 0,1 мкФ. Встроенная кнопка даёт выбор, а также жесты «долгое нажатие», «двойное нажатие» и «нажать и повернуть» — так один орган управления закрывает и навигацию по режимам, и съём измерения, и настройки.
Плата, сборка и корпус#

Двухслойная плата в Altium Designer
Плата — компактная двухслойная. Поскольку в маленьком корпусе соседствуют оптика, прецизионная инерциалка, USB, питание от батареи и быстрый микроконтроллер, размещению компонентов уделено много внимания. Тепловая площадка QFN-48 у STM32G491 посажена на сплошной полигон земли на нижнем слое. Кварц на 24 МГц с конденсаторами 8 пФ стоит вплотную к выводам PF0/PF1, линии D+ и D− USB разведены согласованной дифференциальной парой с TVS-защитой у разъёма, а аналоговая дорожка измерения батареи разведена подальше от SPI и I²C.

Почти всё — поверхностный монтаж
Сборку начинают с мелкой пассивки, затем идут корпуса SOT-23 и более сложные, а кварц, энкодер, OLED и разъёмы ставят в последнюю очередь, чтобы не мешали паять. Отдельного внимания требует LDO LD39200 в корпусе DFN-6: его нижняя площадка должна нормально прилегать к плате и по теплу, и по электрике. Перед подачей питания плату стоит осмотреть под увеличением и проверить на замыкания между VBAT, VDD, VBUS и землёй, а затем прозвонить SWD с помощью ST-Link — и только потом подключать аккумулятор.

Двухстворчатый корпус под печать из PLA или PETG
Корпус — двухстворчатая «раковина» из двух половин, удерживающих плату, аккумулятор, дисплей, энкодер и оптику. В верхней половине окно под OLED и утопленная площадка вокруг ручки, оптическая плата расположена так, чтобы лазер смотрел в круглое отверстие спереди. В нижней — отсек батареи и фиксация платы; вырез под USB-C позволяет заряжать устройство не разбирая. Рекомендуемая печать — PLA или PETG, слой 0,2 мм, заполнение около 20%.
Прошивка#
Прошивка написана на встраиваемом C в STM32CubeIDE с использованием HAL для STM32G4 и драйвера ST VL53L4CX Ultra-Lite. RTOS нет: приложение построено вокруг главного цикла с периодом примерно 30 мс. Модель исполнения получается простой, а частоты обновления хватает и для отзывчивого управления, и для анимации. Внутри прошивка делится на инициализацию железа, сбор данных с датчиков, обработку сигналов, конечный автомат приложения, отрисовку графики, управление питанием и телеметрию.
Для отладки на плате разведён шестиконтактный разъём SWD с сигналами SWDIO, SWCLK, NRST, SWO, 3,3 В и GND, а также тестовые площадки USART3 TX/RX для логов во время разработки.
Схемы, прошивка и гербера опубликованы в репозитории проекта — ссылки есть в оригинальной статье.