Каждый, кто работает с профессиональным инструментом Makita, знает, что их аккумуляторы — это не просто "банки" с энергией. Внутри скрывается сложная система управления (BMS), которая хранит массу полезной информации: от количества циклов заряда до напряжения на каждой ячейке. Однако получить эти данные без специального оборудования невозможно.

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

Глава 1. Оригинальный проект Arduino OBI: Мощная, но громоздкая основа

Оригинальный OBI имел двухкомпонентную архитектуру:

  1. Аппаратная часть: Плата Arduino, выступавшая в роли простого USB-моста.

  2. Программная часть: Приложение на Python с интерфейсом на Tkinter, которое выполняло всю логику.

Arduino лишь транслировала команды, полученные по USB, в 1-Wire протокол для BMS и отправляла "сырой" ответ обратно. Вся обработка, парсинг и отображение данных происходили на компьютере. Это было функционально, но требовало привязки к ПК, установки Python и библиотек, что создавало высокий порог входа для обычного пользователя.

Глава 2. Новое видение: Автономность, Wi-Fi и Веб-интерфейс

Я решил, что современное устройство должно быть полностью автономным. Выбор пал на ESP32 — мощный микроконтроллер со встроенным Wi-Fi, способный взять на себя все задачи: от общения с батареей до хостинга полноценного веб-сервера.

Ключевые цели проекта:

  1. Полная автономность: Вся логика должна выполняться на одном устройстве.

  2. Беспроводной доступ: Использовать Wi-Fi для подключения.

  3. Универсальный интерфейс: Веб-интерфейс, доступный из любого браузера на любом устройстве.

  4. Современный UX/UI: Создать наглядный, адаптивный и интуитивно понятный интерфейс.

Глава 3. Погружение в код: Нюансы протокола и архитектура

Перенос логики с Python на C++ для ESP32 был нетривиальной задачей, полной подводных камней.

Backend: Логика на C++ (ESP32)

Вся логика работы с аккумулятором инкапсулирована в классе MakitaBMS. Это "мозг" устройства.

Нюансы реализации протокола:
Протокол общения с BMS оказался сложнее, чем просто "отправил-получил". Существует как минимум два основных типа контроллеров (условно "STANDARD" и "F0513"), которые требуют разного подхода.

  1. Команды 0xCC и 0x33: Общение идет через две базовые команды 1-Wire. Команда 0xCC используется для простых запросов (например, получить модель), а 0x33 — для более сложных, двухшаговых операций, таких как вход в сервисный режим или чтение статических данных. Мои функции cmd_and_read_cc и cmd_and_read_33 реализуют эти базовые транзакции.

  2. Проблема "просыпания" и транзисторный ключ: Как оказалось, для активации пина Enable на BMS требуется +5В, а ESP32 выдает лишь 3.3В. Это приводило к нестабильной работе. Решением стал NPN-транзисторный ключ, который использует 3.3В сигнал от ESP32 для управления 5-вольтовой линией. Когда ESP32 подает LOW (0В), транзистор закрывается, и подтягивающий резистор (4.7 кОм) надежно подает +5В на Enable. Когда ESP32 подает HIGH (3.3В), транзистор открывается и "сажает" Enable на землю.

  3. Разные протоколы для разных батарей: Самое интересное открытие ждало меня при работе с динамическими данными.

    • Батареи "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)


  1. alcotel
    06.11.2025 17:56

    А что за чип BMS в этих аккумах стоит? Не увидел никаких ссылок его в репозиториях.


  1. tormozedison
    06.11.2025 17:56

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


    1. 010011011000101110101
      06.11.2025 17:56

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


      1. tormozedison
        06.11.2025 17:56

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


    1. ruraic
      06.11.2025 17:56

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


  1. 010011011000101110101
    06.11.2025 17:56

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


    1. Belik1982 Автор
      06.11.2025 17:56

      это относится только к оригинальным батареям, у клонов нет проблем с програмной блокировкой


  1. jouilk23
    06.11.2025 17:56

    Для диагностики в мастерской вещь удобная, но в производственной среде я бы не стал полагаться на Wi-Fi и SPIFFS. Всё же провод и стабильное питание надежнее