Skip to content

Instantly share code, notes, and snippets.

@laurivosandi
Last active April 6, 2025 08:05
Show Gist options
  • Save laurivosandi/a0a263ebd3c54a40d628c1355788622f to your computer and use it in GitHub Desktop.
Save laurivosandi/a0a263ebd3c54a40d628c1355788622f to your computer and use it in GitHub Desktop.
LEGO Power Functions IR control with HIP badge
from esp32 import RMT
from machine import Pin, Timer
button3 = Pin(9, Pin.IN, Pin.PULL_UP)
button4 = Pin(10, Pin.IN, Pin.PULL_UP)
ir = Pin(2, Pin.OUT)
rmt = RMT(0, pin=ir, clock_div=191, tx_carrier=(38000, 50, 1))
tim = Timer(3)
def send_command(nibble1, nibble2, nibble3):
nibble4 = 0xF ^ nibble1 ^ nibble2 ^ nibble3 # LRC nibble
command = (nibble1 << 12) | (nibble2 << 8) | (nibble3 << 4) | nibble4
pulses = []
pulses.append(6)
pulses.append(39)
for shift in range(15, -1, -1):
pulses.append(6)
bit = (command >> shift) & 1
pulses.append(19 if bit else 10)
pulses.append(6)
pulses.append(39)
rmt.write_pulses([11*j for j in pulses], 1)
def speed_to_nibble(v):
if v < 0:
return (-v) | 0b1000
elif v > 0:
return v
else:
return 0b1000
def set_speed(channel, red, blue):
send_command(
(channel & 0b11) | 0b100,
speed_to_nibble(red) & 0b1111,
speed_to_nibble(blue) & 0b1111)
red = 0
blue = 0
def irq_handler(*args):
global red, blue
red = 1 - button3.value()
blue = 1 - button4.value()
set_speed(0, red, blue)
red = 1 - button3.value()
blue = 1 - button4.value()
if red or blue:
# Retransmit after 500ms if any of the buttons is still pressed
tim.init(period=200, mode=Timer.ONE_SHOT, callback=irq_handler)
else:
set_speed(0, 0, 0)
button3.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=irq_handler)
button4.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=irq_handler)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment