DIY sensor compatível com LEGO Powered Up
Enviado: 23 mar 2025, 14:57
Andava já há uns tempos com a ideia de tentar uma coisa destas mas como sabia que ia dar trabalho fui adiando.
Até que um tipo viu um video meu no Youtube e perguntou se era possível ligar um 'reed switch" a um hub Powered Up e usar Pybricks para ler o estado (um 'reed switch' é um interruptor magnético, uma ampola pequena de vidro com uma bola lá dentro e 2 contactos, quando se aproxima um íman a bola move-se e fecha o circuito eléctrico entre os 2 contactos, pode ser útil por exemplo para detectar se uma janela está aberta ou fechada có colando um íman à janela).
Ser possível é: pega-se num Tilt Sensor do WeDo2 que já tem lá dentro duas coisas parecidaa e "hackeia-se".
Ou pega-se num microcontrolador e implementa-se o protocolo da LEGO e cria-se de raiz um dispositivo novo. De vez em quando aparecem na net algumas coisas assim, muito mal ou nada mesmo documentadas.
Por isso fui finalmente à procura de como fazer isto e deixar documentado para os próximos.
Porquê um microcontrolador?
Porque de há uns tempos para cá é tudo com microcontroladores. Nos tempos dourados do ZX Spectrum e Commodore C64, havia uma porta de expansão onde podiamos ligar os nossos próprios circuitos e fazer coisas relativamente simples que depois o Basic do computador conseguia entender. Não havia cá "drivers".
Por uns tempos o PC ainda teve isso. Mas ligar uma cena ao bus ISA do PC era de loucos (ainda fiz isso no meu trabalho de final de curso) e obrigava a fazer drivers. Uma forma de contornar isso era usar a porta da impressora (Centronics) ou do rato (RS-232) e usar drivers já existentes. Mas isso tudo acabou, agora um PC só tem USB (nenhum doido se mete a fazer placas PCI ou PCI-X).
Os bricks inteligentes da LEGO também evoluíram (se consideramos isso uma evolução) do mesmo modo e se o MINDSTORMS EV3 ainda tinha USB directo e UART/I2C indirecto (pelas fichas de I/O) o Powered UP já só tem.. bem... "aquilo": uma forma básica de UART não documentada que usa um protocolo LPF2 mal documentado, no mínimo incompleto.
Mas é o que temos.
O melhor que há por aí de documentação é ainda o projecto Pybricks, com uma página dedicada ao protocolo da LEGO:
https://github.com/pybricks/technical-i ... rotocol.md
Mas sem indicações concretas de como fazer um dispositivo.
Depois há por aí alguns projectos soltos, também raramente bem documentados. O melhor que encontrei foi o MyOwnBricks:
https://github.com/ysard/MyOwnBricks
uma library para Arduino (portanto em qualquer coisa parecida com C++) justamente para construir os seus próprios sensores compatíveis com LEGO Powered Up. Com alguns exemplos concretos de como fazer sensores que imitam sensores já existentes (nomeadamente o Tilt Sensor e o Color and Distance Sensor).
E com uma nota de agradecimento à minha pessoa por ter contribuído para o reverse engineering do protocolo (eu que mal pesco um boi do protocolo!) bem como ao Philo (que ele sim, com um Analisador Lógico, conseguiu alguma coisa).
Bem, eu ao lado do Philo... vamos ter de fazer alguma coisa para justificar tamanha honra
Instalei a library dele, tentei emular um Tilt Sensor com um ESP32 (que não sendo um Arduino é um dos milhentos controladores que podem ser usados como se fossem Arduino) e deu-me um erro de permissões, eu que não percebo nada de C++ lá descobri que uma das classes ou coisa parecida num dos ficheiros tinha de ser declarado como Public para poder ser usado, ultrapassei o problema para depois não ter nada a sair pela porta série (UART).
Isto deu um pouco mais de trabalho, a resposta a um comentário feito pelo Anton Vanhoucke há ano e meio ajudou - o tipo fez o projecto dele para uma arquitectura diferente do ESP32, baseada no Atmega32u4 que tem duas UART - ele usou uma para comunicar com o hub LEGO (Serial1), a outra para debug (Serial0). O ESP32 tem três UARTS mas a que ele usou para comunicar com o hub é internamente usada para comunicar com memória flash, tem de ser remapeada para outros pinos, lá descobri como fazer isto e pronto, temos o nosso primeiro Tilt Sensor a funcionar.
Ele implementa apenas o modo 0 do Tilt Sensor, que envia dois valores (dois ângulos de inclinação). Eu só queria ler um interruptor portanto um valor bastava-me. E queria o meu próprio sensor (com um nome e um ID diferentes de sensores da LEGO, para evitar confusões). Por isso tive de analisar o código e experimentar muitas combinações até conseguir.
Criei assim um Custom Sensor, que se identifica com o ID 36 (que não corresponde a nenhum dispositivo conhecido) e diz ao Hub que tem um modo apenas chamado MYOWNSWITCH que fornece valores de um byte apenas (mais concretamente signed int8).
Com o Pybricks é possível usar este dispositivo com a classe PUPDevice, que identica o dispositivo e expõe os modos disponíveis:
Neste caso o dispositivo tem o ID36 (nenhum da LEGO) e um modo apenas ('MYOWNSWITH que é o modo zero) que permite ler um valor do tipo 0 (que é o int8).
O que significa que pode ser acedido com a função 'read()' usando como argumento '0' (zero, o modo)
E com este código no Pybricks consigo ativar um motor quando primo um botão no ESP32:
[media] [/media]
Agora vou limpar o que fiz e sugerir ao autor do MyOwnBricks as alterações para a library dele funcionar com ESP32 e se ele achar por bem adicionar a minha classe CustomSensor ao projecto dele.
To be continued...
Até que um tipo viu um video meu no Youtube e perguntou se era possível ligar um 'reed switch" a um hub Powered Up e usar Pybricks para ler o estado (um 'reed switch' é um interruptor magnético, uma ampola pequena de vidro com uma bola lá dentro e 2 contactos, quando se aproxima um íman a bola move-se e fecha o circuito eléctrico entre os 2 contactos, pode ser útil por exemplo para detectar se uma janela está aberta ou fechada có colando um íman à janela).
Ser possível é: pega-se num Tilt Sensor do WeDo2 que já tem lá dentro duas coisas parecidaa e "hackeia-se".
Ou pega-se num microcontrolador e implementa-se o protocolo da LEGO e cria-se de raiz um dispositivo novo. De vez em quando aparecem na net algumas coisas assim, muito mal ou nada mesmo documentadas.
Por isso fui finalmente à procura de como fazer isto e deixar documentado para os próximos.
Porquê um microcontrolador?
Porque de há uns tempos para cá é tudo com microcontroladores. Nos tempos dourados do ZX Spectrum e Commodore C64, havia uma porta de expansão onde podiamos ligar os nossos próprios circuitos e fazer coisas relativamente simples que depois o Basic do computador conseguia entender. Não havia cá "drivers".
Por uns tempos o PC ainda teve isso. Mas ligar uma cena ao bus ISA do PC era de loucos (ainda fiz isso no meu trabalho de final de curso) e obrigava a fazer drivers. Uma forma de contornar isso era usar a porta da impressora (Centronics) ou do rato (RS-232) e usar drivers já existentes. Mas isso tudo acabou, agora um PC só tem USB (nenhum doido se mete a fazer placas PCI ou PCI-X).
Os bricks inteligentes da LEGO também evoluíram (se consideramos isso uma evolução) do mesmo modo e se o MINDSTORMS EV3 ainda tinha USB directo e UART/I2C indirecto (pelas fichas de I/O) o Powered UP já só tem.. bem... "aquilo": uma forma básica de UART não documentada que usa um protocolo LPF2 mal documentado, no mínimo incompleto.
Mas é o que temos.
O melhor que há por aí de documentação é ainda o projecto Pybricks, com uma página dedicada ao protocolo da LEGO:
https://github.com/pybricks/technical-i ... rotocol.md
Mas sem indicações concretas de como fazer um dispositivo.
Depois há por aí alguns projectos soltos, também raramente bem documentados. O melhor que encontrei foi o MyOwnBricks:
https://github.com/ysard/MyOwnBricks
uma library para Arduino (portanto em qualquer coisa parecida com C++) justamente para construir os seus próprios sensores compatíveis com LEGO Powered Up. Com alguns exemplos concretos de como fazer sensores que imitam sensores já existentes (nomeadamente o Tilt Sensor e o Color and Distance Sensor).
E com uma nota de agradecimento à minha pessoa por ter contribuído para o reverse engineering do protocolo (eu que mal pesco um boi do protocolo!) bem como ao Philo (que ele sim, com um Analisador Lógico, conseguiu alguma coisa).
Bem, eu ao lado do Philo... vamos ter de fazer alguma coisa para justificar tamanha honra
Instalei a library dele, tentei emular um Tilt Sensor com um ESP32 (que não sendo um Arduino é um dos milhentos controladores que podem ser usados como se fossem Arduino) e deu-me um erro de permissões, eu que não percebo nada de C++ lá descobri que uma das classes ou coisa parecida num dos ficheiros tinha de ser declarado como Public para poder ser usado, ultrapassei o problema para depois não ter nada a sair pela porta série (UART).
Isto deu um pouco mais de trabalho, a resposta a um comentário feito pelo Anton Vanhoucke há ano e meio ajudou - o tipo fez o projecto dele para uma arquitectura diferente do ESP32, baseada no Atmega32u4 que tem duas UART - ele usou uma para comunicar com o hub LEGO (Serial1), a outra para debug (Serial0). O ESP32 tem três UARTS mas a que ele usou para comunicar com o hub é internamente usada para comunicar com memória flash, tem de ser remapeada para outros pinos, lá descobri como fazer isto e pronto, temos o nosso primeiro Tilt Sensor a funcionar.
Ele implementa apenas o modo 0 do Tilt Sensor, que envia dois valores (dois ângulos de inclinação). Eu só queria ler um interruptor portanto um valor bastava-me. E queria o meu próprio sensor (com um nome e um ID diferentes de sensores da LEGO, para evitar confusões). Por isso tive de analisar o código e experimentar muitas combinações até conseguir.
Criei assim um Custom Sensor, que se identifica com o ID 36 (que não corresponde a nenhum dispositivo conhecido) e diz ao Hub que tem um modo apenas chamado MYOWNSWITCH que fornece valores de um byte apenas (mais concretamente signed int8).
Com o Pybricks é possível usar este dispositivo com a classe PUPDevice, que identica o dispositivo e expõe os modos disponíveis:
Código: Selecionar todos
{'id': 36, 'modes': (('MYOWNSWITCH', 1, 0),)}O que significa que pode ser acedido com a função 'read()' usando como argumento '0' (zero, o modo)
E com este código no Pybricks consigo ativar um motor quando primo um botão no ESP32:
Código: Selecionar todos
from pybricks.hubs import TechnicHub
from pybricks.pupdevices import Motor
from pybricks.parameters import Port
from pybricks.tools import wait
from pybricks.iodevices import PUPDevice
hub = TechnicHub()
myOwnSensor = PUPDevice(Port.A)
mot = Motor(Port.B)
print('\n')
print(myOwnSensor.info())
while(True):
if myOwnSensor.read(0)[0] == 100:
print('ON')
mot.run(360)
else:
print('OFF')
mot.stop()
wait(100)
Agora vou limpar o que fiz e sugerir ao autor do MyOwnBricks as alterações para a library dele funcionar com ESP32 e se ele achar por bem adicionar a minha classe CustomSensor ao projecto dele.
To be continued...




