Measurement setup

To verify the working of my own receiver I tested some transmitters and the LEGO receiver. Below are some results from measurements.

All measurements of IR data were made using a TSOP4136 receiver and viewing the output on my scope.


Which transmitter uses which commands?

8879 (dual jog)

This remote uses ‘increment PWM’ and ‘decrement PWM’ commands from Single Channel Mode when jog wheels are turned. when only one ‘stop’ button is pressed this is sent using the ‘Brake Then Float’ command from Single Channel Mode (PWM mode), when both ‘stop’ buttons are pressed  Combo Direct Mode is used with both channels set as ‘Brake Then Float’.

1 0 11 | 0 100 | 1000 | 1000
Toggle 1
Escape 0
Channel 4 (11)
Address 0
Mode 100 (Single output mode, PWM)
Data 1000 (Brake then float)
LRC 1000 (1011 ^ 0100 ^ 1000 = 0111 -> ^0xF = 1000)

1 0 11 | 0 110 | 0100 | 0110
Toggle 1
Escape 0
Channel 4 (11)
Address 0
Mode 110 (Single output Mode, Clear Set Toggle)
Data 0100 (Increment PWM)
LRC 0110 (1011 ^ 0110 ^ 0100 = 1001 -> ^0xF = 0110)
0 0 01 | 0 001 | 1111 | 0000
Toggle 0
Escape 0
Channel 2 (01)
Address 0
Mode 001 (Combo Direct Mode)
Data 1111 -> Brake then float output A (11xx), Brake then float output B (xx11)
LRC 0000

8885 (dual joystick)

This remote uses Combo Direct Mode for all commands. This remote sends the joystick state continuously if one of the joysticks is used. I found it remarkable that it sent the command ‘float’ to the output when the joystick was released, as this is the default action if a timeout happens (i.e. when no joystick is pressed or when IR reception is interrupted).

Edit: at first I assumed that missing one IR message would cause a timeout. Then Philo  pointed out that it takes more than a second to timeout, so the float command DOES make sense!

0 0 00 | 0 001 | 0010 | 1100 (rood)
Toggle 0
Escape 0
Channel 1
Address 0
Mode 001 (ComboDirect Mode)
Data : 0010 -> Backward output A
1 0 00 | 0 001 | 0000 | 0110 (red stop)
Toggle 1
Escape 0
Channel 1
Address 0
Mode 001 (ComboDirect Mode)
Data : 0000 -> Float both
0 0 00 | 0 001 | 0110 | 1000 (red + blue)
Toggle 0
Escape 0
Channel 1
Address 0
Mode 001 (ComboDirect Mode)
Data : 0110 -> Backward output A, Forward output B


IR Transmission timing

On the last page of the LEGO IR specification a lot of figures and text is dedicated to a very nice timing schedule where the outputs of different transmitters do not overlap in time when several channels transmit at the same time (see the spec for a clearer choice of words 😉 ) . Although this scheme is very nice, it is not implemented in both measured PowerFunction transmitters.

Upper drawing: from norm. Lower drawing: how LEGO remotes are implemented (not to scale, just illustrating the difference in timing principle)


The time between messages is increasing at higher channel numbers, but the delay is fixed; the spec describes a different time delay between message 1-2, 2-3 and message 3-4,4-5 and 5  to subsequent messages. Only one delay time is used in the ‘real’ transmitters. At first I thought the delay between messages would dictate the timeout time for the receiver (some functions have timeout, which means that if no IR messages arrive anymore, the output is turned off). My assumption was that missing one message would ‘time out’ the receiver, but later I found that the timeout  is given as 1.2s. This also clarifies the transmission of ‘output float’ by the joystick transmitter, that makes the receiver more responsive that waiting for a timeout.

Values below were measured from startbit to startbit for both power functions transmitters.

channel delay
1 110ms
2 148ms
3 189ms
4 230ms

 Characterization IR Receiver

After I implemented the firmware for my own receiver I wanted to check some properties of the LEGO IR Receiver. One of Tkkrlab‘s members owns the 8884 LEGO receiver so I was able to see what exactly the LEGO receiver is doing. This was very interesting; the LEGO norm is sometimes not completely clear in how things should be implemented. Verifying with the ‘original’ receiver showed some inconsitensies, and raised some questions.

PWM, frequency, duty cycle and number of steps

The first step was looking at the output PWM frequency. I monitored the ‘C1’ and ‘C2’ signals which drive the motor

PWM, channel 1 is C1, channel 2 is C2

The used PWM frequency is 1150Hz. I’m using 13kHz myself (necessary to enable servo control from same timer), I’ll have to see if this gives any change in power efficiency.

DutyCycle, jog remote control

Next, I used the 8879 ‘speed remote control’ to step through the PWM cycles. First, a bit of background info. I read the LEGO protocol document, and in all PWM descriptions the description ‘PWM 1’ to ‘PWM 7’ are used between stop and full throttle. These are PWM values (duty cycles) I recorded when moving the jog forward / backward

1:  26.4%
2:  37.9%
3:  49.4%
4:  63.2%
5:  74.7%
6:  87.4%
full throttle

Now this is weird; first of all, we’re seeing that only 6 levels of PWM are used. This is not only unexpected from the documentation, it is also giving less resolution for control to the users. Secondly, the PWM is starting at 26%. Why? I plotted the percentages, and it seems that the fist step (13%) seems to be missing, for some reason. Weird.

Edit:  Philo pointed out that in large builds the friction in the motor +  attached drive chain might be too large. To be sure that the motor doesn’t stall at low PWM values this first step might  have been skipped. In my receiver I do not skip it, I’m guessing that lighter loads will be used, and I’d like to be able to give more control of PWM or servo position with the original remote.

Edit 2: Indeed I found that with lower voltages (7V) the first step of PWM generation gives very little torque. BUT: when you return from a higher PWM ratio, it gives you the possibility to let the motor ‘coast’ for a while.

“Brake then Float”

In the protocol, two ways of disabling the motor are mentioned: ‘float’ and ‘Brake then float’. With an H-bridge motor controller, both ‘float’ and ‘brake’ can easily be implemented, but the timing for ‘brake then float’ was not described in the protocol. I struggled a bit myself with this feature, because all other messages (PWM, direct pin control, float, full forward / backward) can be turned into output signals to the H-bridge without memorizing previous states. The ‘brake then float’ state should take care that the receiver first brakes, then floats. But then again,  how long should you brake? Also, when floating and receiving a ‘brake then float’ command (red button on 8879 remote), should you brake again? Questions, questions. I connected a 5V supply to the C1 and C2 connections, current limited by 2 12kOhm resistors. Now, the receiver could pull low, drive high, and float. ‘Float’ would mean both outputs were going to 5V, brake would mean both outputs would be going to GND.

I captured a series of remote control actions in one picture to show what happens.

  1. we’re coming from a ‘brake’ situation
  2. Gradually moving forward and backward with jog knob, motor keeps running forward. PWM details are lost in the limited scope resolution
  3. Transition from going forward to backward; here the receiver ‘floats’ the output, it is neither pulled to GND nor pulled to battery voltage!
  4. Gradually moving forward and backward with jog knob, motor keeps running backward
  5. Again transition to running forward, floating
  6. Running forward in PWM
  7. Stop button pressed-> braking, and NOT going to float!
  8. Going backward with 8885 remote control; full throttle
  9. Release joystick, output is floating
  10. Going forward with 8885 remote control; full  throttle
  11. Release joystick, output is floating

Now what have we learned? The LEGO engineers were probably confused themselves aswell by the protocol description and did not implement a float action after a brake. You don’t need a scope to verify this, given that you’ve got both remotes -> try to rotate the axle of a (LEGO) motor after stopping; in ‘float’  it rotates with less friction than in ‘brake’. For your information, my remote receiver DOES implement a brake, and then a float <grudge mode on>because I didn’t know the LEGO implementation in advance and spent quite some time programming this…<grudge mode off>.