Каждый, кто работает с профессиональным инструментом Makita, знает, что их аккумуляторы — это не просто "банки" с энергией. Внутри скрывается сложная система управления (BMS), которая хранит массу полезной информации: от количества циклов заряда до напряжения на каждой ячейке. Однако получить эти данные без специального оборудования невозможно.
Несколько лет назад сообщество энтузиастов подарило нам проект OBI (Open Battery Interface) — решение на базе Arduino и Python, которое впервые позволило заглянуть "под капот" этих батарей. Это был настоящий прорыв, который послужил отправной точкой и для моего проекта. Но, как и у любой технологии, у него были свои ограничения. Я поставил перед собой цель создать более современное, удобное и полностью автономное устройство. Эта статья — история его разработки, от идеи до финальной реализации.

Глава 1. Оригинальный проект Arduino OBI: Мощная, но громоздкая основа
Оригинальный OBI имел двухкомпонентную архитектуру:
Аппаратная часть: Плата Arduino, выступавшая в роли простого USB-моста.
Программная часть: Приложение на Python с интерфейсом на Tkinter, которое выполняло всю логику.
Arduino лишь транслировала команды, полученные по USB, в 1-Wire протокол для BMS и отправляла "сырой" ответ обратно. Вся обработка, парсинг и отображение данных происходили на компьютере. Это было функционально, но требовало привязки к ПК, установки Python и библиотек, что создавало высокий порог входа для обычного пользователя.
Глава 2. Новое видение: Автономность, Wi-Fi и Веб-интерфейс
Я решил, что современное устройство должно быть полностью автономным. Выбор пал на ESP32 — мощный микроконтроллер со встроенным Wi-Fi, способный взять на себя все задачи: от общения с батареей до хостинга полноценного веб-сервера.
Ключевые цели проекта:
Полная автономность: Вся логика должна выполняться на одном устройстве.
Беспроводной доступ: Использовать Wi-Fi для подключения.
Универсальный интерфейс: Веб-интерфейс, доступный из любого браузера на любом устройстве.
Современный UX/UI: Создать наглядный, адаптивный и интуитивно понятный интерфейс.
Глава 3. Погружение в код: Нюансы протокола и архитектура
Перенос логики с Python на C++ для ESP32 был нетривиальной задачей, полной подводных камней.
Backend: Логика на C++ (ESP32)
Вся логика работы с аккумулятором инкапсулирована в классе MakitaBMS. Это "мозг" устройства.
Нюансы реализации протокола:
Протокол общения с BMS оказался сложнее, чем просто "отправил-получил". Существует как минимум два основных типа контроллеров (условно "STANDARD" и "F0513"), которые требуют разного подхода.
Команды
0xCCи0x33: Общение идет через две базовые команды 1-Wire. Команда0xCCиспользуется для простых запросов (например, получить модель), а0x33— для более сложных, двухшаговых операций, таких как вход в сервисный режим или чтение статических данных. Мои функцииcmd_and_read_ccиcmd_and_read_33реализуют эти базовые транзакции.Проблема "просыпания" и транзисторный ключ: Как оказалось, для активации пина
Enableна BMS требуется +5В, а ESP32 выдает лишь 3.3В. Это приводило к нестабильной работе. Решением стал NPN-транзисторный ключ, который использует 3.3В сигнал от ESP32 для управления 5-вольтовой линией. Когда ESP32 подаетLOW(0В), транзистор закрывается, и подтягивающий резистор (4.7 кОм) надежно подает +5В наEnable. Когда ESP32 подаетHIGH(3.3В), транзистор открывается и "сажает"Enableна землю.-
Разные протоколы для разных батарей: Самое интересное открытие ждало меня при работе с динамическими данными.
Батареи "STANDARD" ожидают, что питание будет подано один раз, после чего можно отправлять одну длинную команду (
0xD7) и получать все данные о ячейках и температуре одним пакетом.Батареи "F0513" оказались гораздо капризнее. Они требуют, чтобы каждый отдельный запрос (напряжение ячейки 1, напряжение ячейки 2 и т.д.) сопровождался полным циклом сброса по питанию.
Для решения этой проблемы в функции
readDynamicDataбыла реализована специальная lambda-функцияexec_f0513_cmd, которая оборачивает каждую команду для F0513 в последовательность:ВКЛЮЧИТЬ ПИТАНИЕ -> ВЫПОЛНИТЬ КОМАНДУ -> ВЫКЛЮЧИТЬ ПИТАНИЕ. Это и стало ключом к стабильной работе с этим типом контроллеров.
Взаимодействие с веб-интерфейсом (main.cpp):
Веб-сервер: Я использовал библиотеку
ESPAsyncWebServer, которая создает асинхронный веб-сервер, не блокирующий основную программу.Файловая система SPIFFS: Все файлы веб-интерфейса (
index.html,style.css,app.js) хранятся во внутренней памяти ESP32. Сервер просто отдает их браузеру по запросу.WebSocket: Для мгновенной двусторонней связи используется WebSocket. Когда пользователь нажимает кнопку в браузере, JavaScript отправляет JSON-сообщение на ESP32. ESP32 обрабатывает команду и отправляет в ответ JSON с данными или статусом.
Парсинг и отправка данных: Библиотека
ArduinoJsonиспользуется для создания и разбора JSON-сообщений. Например, после считывания данных, они упаковываются в JSON-объект и отправляются всем подключенным клиентам черезws.textAll(output).
Frontend: Веб-интерфейс (HTML, CSS, JavaScript)
Структура и логика (app.js):
Весь интерфейс — это одностраничное приложение (SPA), управляемое JavaScript.
WebSocket-клиент: Скрипт устанавливает WebSocket-соединение с ESP32. Реализована логика автоматического переподключения (
connect(),reconnectInterval) в случае потери связи.Обработка сообщений: Функция
handleWebSocketMessage— это центральный диспетчер. Она получает JSON от ESP32, смотрит на полеtypeи решает, что делать: обновить статус, показать ошибку, отрисовать статические или динамические данные.Сохранение состояния (
lastData): Чтобы не запрашивать статические данные каждый раз, они сохраняются в глобальном объектеlastData. Когда приходят динамические данные, они не заменяют, а дополняют этот объект (lastData = { ...lastData, ...msg.data}), после чего интерфейс перерисовывается с полным набором данных.Динамический рендеринг: Функции
renderData,renderCellsиrenderAlertsотвечают за "отрисовку" данных. Они не перезагружают страницу, а динамически создают и изменяют HTML-элементы, вставляя в них полученные значения.Расчет SOC: Для расчета уровня заряда используется нелинейный алгоритм на основе таблицы соответствия напряжений (
socTable). Это гораздо точнее, чем простая линейная зависимость, так как учитывает особенности разряда Li-ion аккумуляторов.Визуализация на CSS: Сама схема батареи (контейнеры, клеммы, провода) отрисована полностью на CSS. JavaScript лишь меняет цвет фона ячеек (
backgroundColor) и добавляет классы (.imbalanced,.dead-cell) в зависимости от полученных напряжений. Это делает отрисовку быстрой и адаптивной.
Глава 4. Преимущества новой версии
В итоге, мы получили не просто аналог, а совершенно новый по своей философии продукт:
Параметр |
Оригинальный Arduino OBI |
Моя версия на ESP32 |
|---|---|---|
Платформа |
Arduino + Компьютер (Python) |
ESP32 (автономно) |
Подключение |
Проводное (USB) |
Беспроводное (Wi-Fi) |
Интерфейс |
Десктопное приложение (Tkinter) |
Веб-интерфейс |
Доступ |
С одного ПК, где все установлено |
С любого устройства в сети Wi-Fi |
Визуализация |
Табличные данные |
Интерактивная графическая схема |
Аналитика |
Отображение "сырых" данных |
Автоматический расчет SOC, детекция дисбаланса, мертвых ячеек |
Заключение
Путь от идеи до готового устройства был полон вызовов, связанных с аппаратными нюансами и особенностями протоколов. Но благодаря мощи ESP32 и гибкости веб-технологий, удалось создать действительно современный и удобный инструмент. Он не требует от конечного пользователя никаких специальных знаний, работает "из коробки" и предоставляет исчерпывающую информацию о состоянии аккумулятора в самом наглядном виде.
Проект размещен в открытом доступе на https://github.com/Belik1982/esp32-makita-bms-reader, и я буду рад любому фидбэку и предложениям по его дальнейшему развитию.
Комментарии (8)

tormozedison
06.11.2025 17:56Не по теме. Встречал информацию, что в батареях дешёвых шуруповёртов иногда нет балансира. А ещё встречал обзор малогабаритного балансира с дисплеем, без скидки он не очень дёшев, но в дни, когда скидка есть, более чем доступен. Можно на таких батареях устанавливать разъём для подключения этого балансира, а потом подключать его по очереди то к одной батарее, то к другой, в зависимости от того, какая сейчас заряжается.

010011011000101110101
06.11.2025 17:56балансир требует подключения к каждому элементу батареи, а их даже в самых малых 5шт, в остальных кратно пяти. Эти контакты, естественно не выводятся наружу. А подключаться к ним слишком хлопотно.

tormozedison
06.11.2025 17:56Я про те шуруповёрты, где в батарее три элемента последовательно. Чтобы приделать к ней разъём для периодического подключения этой штуковины, достаточно всего 4 ног.

ruraic
06.11.2025 17:56Так уже есть недорогие активные балансиры на разное количество элементов, недавно брал на 5s и на 3s. Цена выходит около 5-6$ На пятёрку уже поставил. Вот пример Из минусов - если батарею оставить очень на долго (в зависимости от емкость наверное пол-года - год) - балансир её высадит. Но думаю если аккумуляторы очень редко используются, то и балансир там не особо нужен.

010011011000101110101
06.11.2025 17:56речь идёт про родные макиты? или про миллион макита-совместимых клонов?

Belik1982 Автор
06.11.2025 17:56это относится только к оригинальным батареям, у клонов нет проблем с програмной блокировкой

jouilk23
06.11.2025 17:56Для диагностики в мастерской вещь удобная, но в производственной среде я бы не стал полагаться на Wi-Fi и SPIFFS. Всё же провод и стабильное питание надежнее
alcotel
А что за чип BMS в этих аккумах стоит? Не увидел никаких ссылок его в репозиториях.