Наборы LEGO с электрикой уже давно перестали быть просто игрушкой.  Современная серия устройств Powered Up — это небольшая модульная робототехническая платформа: smart-устройства, моторы, датчики, подсветка, управляемые по Bluetooth, с возможностью программирования поведения моделей, что ранее было доступно только в специализированных наборах (LEGO Mindstorms, Education).

Как же получить данные из smart-устройства, ведь это открывает новые возможности по использованию электронных LEGO наборов.

Официальное приложение LEGO PoweredUp предлагает визуальный блоковый редактор программирования и виртуальных пультов управления. Можно логически объединять до четырёх хабов (большие «интеллектуальные кубики» LEGO с портами ввода-вывода), настраивать взаимодействие устройств и собирать достаточно сложные алгоритмы — от роботов, до беспилотного грузовика, автоматизированной установки или управления железной дорогой.

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

К счастью, экосистема Powered Up (знакомство с ней https://youtu.be/8F44vVdfK_A) основана на открытых технологиях: устройства работают по BLE (Bluetooth Low Energy), а LEGO официально опубликовала протокол взаимодействия — LWP3 (LEGO® Wireless Protocol v3, https://lego.github.io/lego-ble-wireless-protocol-docs/).

Это открыло путь сторонним разработчикам ПО создавать свои инструменты для программирования и управления хабами LEGO. И одним из удачных решений, на мой взгляд, является PyBricks.

PyBricks (https://pybricks.com/ это альтернативная прошивка для хабов серии Powered Up, созданная командой энтузиастов, решившая «раскрыть» весь потенциал LEGO-электроники. Вместе с прошивкой предоставляется веб-IDE: редактор кода, загрузчик и BLE-коммуникатор — всё работает прямо в браузере.

PyBricks
PyBricks

Программировать можно на MicroPython (бесплатный режим) или в блочном редакторе, доступном по подписке. PyBricks полностью заменяет штатную прошивку и превращает хаб в автономный микроконтроллер со встроенным интерпретатором Python, код запускается прямо на устройстве. При этом всегда можно вернуться на родную прошивку: официальное приложение LEGO PoweredUp перепрошьёт хаб при первом подключении. И кроме того, у этого ПО хорошая документация, можно без труда разобраться, что не скажешь о приложении LEGO – там информации практически нет.

В этой статье мы хотели поделиться опытом передачи данных с LEGO-хаб  в ПК, показать, как это работает и какие открываются новые возможности.

Что мы сделали:

1. Прошили LEGO Technic Hub альтернативной прошивкой PyBricks.

2. Создали простую LEGO-установку с обратной связью

3. Написали программу для хаба, которая периодически отправляет данные

4. На ПК с помощью библиотеки Bleak подключили хаб к компьютеру 

5. Получили данные с хаба и применили их.

Было решено сделать простую установку с обратной связью. На вал мотора установили небольшую «качель», на неё – датчик наклона от набора LEGO WeDo 2.0. Этот датчик измеряет угол от -45 до 45 градусов (точнее два угла, по тангажу и крену, нам нужен первый).

Установка. Белый кубик слева - датчик наклона.
Установка. Белый кубик слева - датчик наклона.

Далее нужно написать программу на PyBricks, загрузить её в перепрошитый хаб и отсоединится — код будет работь автономно. Программа постоянно считывает угол наклона и управляет мотором так, чтобы выставить качель в горизонтальное положение. Скорость вращения двигателя рассчитывается пропорционально отклонению — классический пропорциональный регулятор.

Вот такая программа получилась в Pybricks.

from pybricks.hubs import TechnicHub
#from pybricks.hubs import CityHub
from pybricks.pupdevices import Motor, TiltSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# создаём хаб и устройства
hub = TechnicHub()
#hub = CityHub()
motor = Motor(Port.A)
tilt = TiltSensor(Port.B)

angle_0 = 0 # целевой угол

#Kp коэффициент пропорционального усиления (КПУ)
Kp = 3
# Увод качели от равновесия перед началом
motor.run(30)
wait(1000)
    
K = 0 # счетчик попыток найти равновесие

while True:
        # угол наклона в градусах: 0 = горизонт, -2 = погрешность экземпляра
        angle = tilt.tilt()[0]-2   # [0]=тангаж, [1]=крен 
        # отклонение
        error = angle - angle_0
    # скорость, управляющее воздействие
        speed = Kp*error
    # ограничим скорость
        speed = max(min(speed, 75), -75)

        motor.run(speed)
        K+=1
#        print(f"{angle},{speed}") 
        print(angle) # Вывод для передачи данных

        # определение достижения целевого угла
        if abs(angle) ==angle_0:
                angle = 0
                for i in range(10):
                    angle += tilt.tilt()[0]-2
                    wait(100)
                    if angle != angle_0 * (i+1):
                        break
                if angle == angle_0 * (i+1):
                    print("РОВНО, K=", K)
                    break
        wait(50)

Двигатель запускается командой motor.run(speed) – движение с постоянной скорость в град/с. При маленьких скоростях движение реализовано рывками, но для нашей задачи это не принципиально.

Установка в действии.
Установка в действии.

После отладки, когда система заработала стабильно, стало интересно провести эксперимент, точнее серию экспериментов и посмотреть, как изменяются динамика и устойчивость при разных значениях коэффициента пропорциональности. А чтобы наблюдать процесс во времени, хаб должен передать угол наклона. Для этого в коде оставили один-единственный print(), который и будет передавать на ПК значение текущего угла.

Принимать и визуализировать данные будет программа, которую мы напишем и запустим на ПК. Для связи с хабом используем Bleak.

Bleak (https://pypi.org/project/bleak/) — это кроссплатформенная библиотека Python для работы с BLE. Она позволяет: находить BLE-устройства и подключаться к ним, читать и писать их характеристики, подписываться на уведомления — именно через них PyBricks будет передавать строки, отправленные командой print().

Алгоритм работы следующий: запускаем нашу программу на ПК, включаем хаб (индикатор должен мигать), и Bleak находит его по имени. После появления сообщения «— Приём данных…» нужно нажать кнопку хаба ещё раз — это запускает загруженную программу PyBricks, и в этот момент он начинает отправлять телеметрию.

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

Скрытый текст

В программе на ПК для работы необходимо найти хаб. Сканирование инициализируется вызовом
await BleakScanner.discover(timeout=8)
Среди найденных устройств выбирается с именем «HUBPB».
После подключения программа подписывается на специальную BLE-характеристику (можно взять из описания LWP3), которая в прошивке PyBricks выполняет роль виртуального UART (универсальный асинхронный приёмопередатчик).
Это позволяет оставленной нами команде print() в PyBricks не просто выводит текст «в никуда», а отправлять строку по BLE-каналу уведомлений (notify characteristic) — то есть устройство, подписанное на эту характеристику (в нашем случае — ПК с Bleak), получает каждую строку, которую хаб «напечатал». Подписка выглядит как
client.start_notify(CHAR_UUID, callback),
где callback — это наша функция обработчик данных. Следующей строчкой надо вывести сообщение об ожидании данных (например "— Приём данных…")
Данные, приходящие из PyBricks, выглядят как обычные текстовые строки, иногда с управляющими символами. Поэтому в обработчике сначала делаем data.decode(...).strip(), а затем фильтруем всё, что не является цифрой или знаком числа. В итоге у нас остаётся значение, которое можно преобразовать в float и использовать дальше.
Каждый принятый замер мы сопровождаем меткой времени t (time.time()) и уже в таком виде отправляем в очередь межпроцессного обмена:
queue.put((t, value)).
Это единственная точка соприкосновения двух процессов, она позволяет полностью развести Bluetooth-код и графику, чтобы они не мешали друг другу.
Графическая часть работает отдельно — она выполняется в собственном процессе, запущенном через
multiprocessing.Process(target=plotter).
Внутри него создаётся окно matplotlib, включается интерактивный режим (plt.ion()), и начинается простой цикл: чтение очередной точки, добавление в массивы, обновление линии и вызов plt.pause(0.01) для перерисовки. Получается «живой график», который визуализирует поток данных в момент их получения, без задержек.
В финальном управляющем блоке (if name == "__main__":) необходимо создать очередь, запустить процесс с графиком и отдать управление BLE-части. При завершении или нажатии Ctrl+C в программе необходимо корректно завершить подпроцесс, чтобы не оставлять зависших окон.

Таким образом, print() в PyBricks фактически становится каналом телеметрии: всё, что программа на хабе выводит в консоль, уходит по BLE в нашу программу на ПК.

Работа установки. Передача данных. График угла от времени. Zoom графика.
Работа установки. Передача данных. График угла от времени. Zoom графика.

Передавать можно несколько значений в print(), через запятую. Соответственно на стороне ПК эту строку приёма надо разделить и преобразовать во float.

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

Угол состояния качели во времени при различных коэфициентов пропорциональности.
Угол состояния качели во времени при различных коэфициентов пропорциональности.

На полученном графике можно даже заметить «физику процесса». Цветом выделены области различных значений коэффициента пропорциональности, для каждого значения проведены серии из трёх тестов. Длинные пики вниз — это исходное положение качели примерно 30°, откуда начинается выравнивание, начало теста.

Картина получается показательная: коэффициент Kₚ = 2 обеспечивает самое быстрое и стабильное время сходимости. При более высоких значениях постепенно появляется заметная перерегулировка — система начинает «размахиваться» и тратит больше времени на сходимость.

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

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

Сегодня же нам хотелось показать главное: LEGO-электроника с прошивкой PyBricks и библиотекой Bleak в сочетании с фантазией превращается из игрушки в инструмент для экспериментов и получения навыков исследователя. Причём всё это работает не на дорогих комплектах LEGO Education, а на вполне доступных наборах Technic и City с электрикой. Наша установка была собрана на Technic Hub (Control+), но мы попробовали перепрошить более простой CITY Hub (88009) — и он без проблем заработал.

Надеемся, эта статья кому-то подскажет как использовать компоненты знакомого всем конструктора по-новому. Поможет увидеть широкие возможности у простой на первый взгляд системы.

Комментарии (2)


  1. XelaVopelk
    24.11.2025 08:33

    А это работает для Kazi?


    1. Amir_Aizatulin Автор
      24.11.2025 08:33

      У Kazi нет таких устройств.