Please read the general section first!

MattzoTrainController for Power Functions (MTC4PF)


The MattzoTrainController for Power Functions (MTC4PF) acts as a controller for LEGO Power Function Train Motors (or compatible) or other Power Function motors, e.g. the XL motor for the Emerald Express.

The MTC4PF also switches train lights on and off.

The MTC4PF can control Power Functions motors directly, or it can relay the logical commands to “virtual” motor shields like the LEGO Infrared Receiver 8884 or 4DBrix WiFi Train Receivers. When using virutal motor shields, it can even control multiple trains at the same time.

Functional Description

When Rocrail wants to make a train go into a certain direction, it communicates this as a “loco” command via the MQTT broker.

The MTC4PF receives the loco command and checks, if the command is relevant for the controller by comparing the loco id of the Rocrail command with the loco id or loco ids stored in the controller. If the loco is controlled by the controller, the desired speed and direction are translated into the correct power setting for the LEGO train motor.

Up to two motors can be directly attached to the MTC4PF, one on each output of the motor shield. In the source code, you can configure the sense of rotation for both motors individually. A typical setup of two motors under a single train would usually be forward/reverse.

Please note that you must not connect more than one motor to a single output of the L9110 motor shield. Attaching two or more motor to a single output of the motor shield will overloaded it and eventually make it burn off.

Besides the directly connected motor shields, the MTC4PF can also act as a command relay module and pass the Rocrail commands on to trains with a LEGO Infrared Receiver 8884 on board. It is possible to install the MTC4PF 1) somewhere on the layout, or 2) in the train. By installing it in the train close to the IR receiver, you can make sure that the train is always in contact with the IR LED on the controller. This enables routes through different rooms and through tunnels. Multiple trains with IR receiver can be controlled by a single MTC4PF. Trains can have more than IR receiver on board, which will be controlled synchronously by the MTC4PF. The turning direction of the individual motors can be set individually.

The MTC4PF can also relay Rocrail commands to 4DBrix WiFi Train Receivers. Multiple trains with 4DBrix WiFi Train Receivers can be controlled by a single MTC4PF. Trains can have more than 4DBrix WiFi Train Receiver on board, which will be controlled synchronously by the MTC4PF. The turning direction of the individual motors can be set individually.

You can also attach LED lights to the controller. They can be switches on and off with the function keys on the loco control panel in Rocrail. You may use all unused pins of the controller for extra lights. Rocrail supports up to 32 functions.

The controller continuously monitors its power supply. We plan to adapt the motor power to the decreasing voltage of the battery in future versions of the firmware.


The following sketch shows the wiring of the controller with a directly attached motor shield L9110, 2 train motors and 2 LEDs:

MattzoTrainController for Power Functions with two train motors and two LED lights.

Required components:

  • I/O board with micro controller. We have used a NodeMCU Amica Modul V2 ESP8266 ESP-12F. Similar modules should work as well.
  • Motor shield L9110
    • 2 channel motor shield.
    • Max. 12V.
    • ~800mA maximum continuous current.
    • 2A max. peak current (this is about the blocking current of a LEGO train motor).
  • LEGO power functions cable, cut in two halfs.
  • Power supply, around 9V. Some options are:
    • Non-rechargeable batteries
      • 6 AA or AAA batteries
      • 9V block battery
    • Rechargeable batteries
      • 8 rechargeable AA or AAA batteries
      • rechargeable 9V block battery
    • If the loco provides enough space, we always try to use 8 rechargeable AA batteries.
  • Basic stuff like bread board, resistors, wires etc.

The following picture shows a MTC4PF with typically required components and cables:

MattzoTrainController for Power Functions with 1 attached train motor and 2 LEDs

The voltage of the power supply is monitored using the analog input pin A0 of the controller. Please be aware that the reference voltage of the analog input pin A0 of the micro controller is usually 3.3V. If you attach more than 3.3V to this pin, you will destroy your micro controller. Use the voltage divider as depicted on the wiring diagram to reduce the voltage that reaches the A0 pin.

From firmware version 0.2, voltage monitoring is already supported in the firmware, but no action is derived from it yet. That means, that you don’t necessarily need to build the resistors and cables attached to the A0 pin yet at this time as there is no practical application for it yet.


Case for MTC4PF

We will publish instructions of how to build a superb box for the MTC4PF soon. This will include the files required to print a beautiful box with a 3D printer soon.

The dimensions of the case match precisely the size of a standard LEGO power functions battery box.


For general setup instructions please refer to the “General” section.

Before uploading the firmware, make sure that you have configured the network configuration files as described in the general section, and the specific configuration file for the MTC4PU (MTC4PU_Configuration.h).


Configure the locomotives that the controller shall control. The meaning of the parameters are self-explanatory or explained in the configuration file.

The controller can control multiple locomotives only when using motor shields that are not directly connected to the controller, like Lego Infrared Receivers 8884 or 4D Brix WiFi Train Receivers.

Motor Shields

Configure the Motor Shields that the controller shall control. There are different types motor shields:

  • Directly connected motor shields (L298N, L9110). These motor shields are wired directly to the controller.
  • Remote or virtual motor shields like the Lego Infrared Receiver 8884 or 4D Brix WiFi Train Receivers.

Controler Wiring Specifics

In this section, you need to configure the wiring characteristics of the controller:

  • Motor shield type of the directly connected motor shield and the pins used (details see code).
  • Configuration of connected motors and lights for the Infrared “motor shield” including the pin used for the IR LED.
  • Number of connected LEDs and used pins.
  • Indication if status LED is installed and on which pin.

Number of (light) functions and to which loco they belong.

You can also enable of disable the Auto Light feature, which automatically turns lights on and off according to the movement of the loco.

If a status LED is installed, you can enable it and assign the pin on which it is installed.

Network settings

In this section, you set if the ebreak is triggered when the controller looses connection to MQTT.

Syslog settings

Here you can change the name for syslog entries submitted by this controller.

Configuration examples

Let’s have a look at some configuration examples.

A loco with L9110 and multi color headlights

A loco with L9110 motor shields and a multi color LED as headlight. The LED is lighting white when operating forward, and red when operating in reverse mode.

const int NUM_LOCOS = 1;


locoConf[0] = (MattzoLocoConfiguration) {
     .locoName = "Sante Fe",
     .locoAddress = 13043,
     .accelerationInterval = 100,
     .accelerateStep = 2,
     .brakeStep = 2


const int NUM_MOTORSHIELDS = 1;


msConf[0] = (MattzoMotorShieldConfiguration) {
       .motorShieldName = "SFE",
       .motorShieldType = MotorShieldType::L9110,
       .minArduinoPower = MIN_ARDUINO_POWER,
       .maxArduinoPower = MAX_ARDUINO_POWER,
       .configMotorA = -1,
       .configMotorB = 0,
       .locoAddress = 13043

The loco is called “Sante Fe”, has the address 13043 in RocRail. Every 100ms (0,1 seconds), it will accelerate by 2% of the maximum power (20% per second) or brake with 3% of the maximum power (30% per second).

The motor shield is a L9110 type. A train motor is connected to port A in reverse turning direction (-1). No device is connected on port B.

Let’s have a look at the light configuration:

const int NUM_FUNCTIONS = 3;
uint8_t FUNCTION_PIN[NUM_FUNCTIONS] = { D0, D1, D2 };
const bool AUTO_LIGHTS = true;

3 functions are defined, which correspond to the F1, F2 and F3 buttons on the loco control pad in Rocrail. The relevant three pins of the multi-color LED are connected to D0, D1 and D2 on the controller. As there is only one loco defined for this controller (which is the usual case), the assignment of the functions is simply “0” for each of the functions, which means “all trains”.

Auto Lights are switched on. By default, functions with even numbers are switched on when the train moves forward and vice versa. All LEDs are switched off on stop. For changing the behaviour of the auto light function, you need to modify the source code in MTC4PF.ino. Search for the void lightEvent() function and modify the source code in way, that all functions are switched on when going forward, and only the red part of the LED is switched on when going in reverse:

case LightEventType::FORWARD:
  functionCommand[i] = true;
case LightEventType::REVERSE:
  functionCommand[i] = (i == 0);

If you want to leave the lights in the last state when stopping, comment out the following statement just a bit above:

case LightEventType::STOP:
  // do nothing!
  // functionCommand[i] = false;

In future version of the firmware, auto lights will be configurable more easily.

A loco with infrared receiver and Power Functions light

A single loco, “motor shield” is a LEGO Infrared Receiver 8884, one train motor and a Power Functions light are connected.

const int NUM_LOCOS = 1;


locoConf[0] = (MattzoLocoConfiguration) {
     .locoName = "L7938",
     .locoAddress = 7938,
     .accelerationInterval = 100,
     .accelerateStep = 2,
     .brakeStep = 2

const int NUM_MOTORSHIELDS = 1;


msConf[0] = (MattzoMotorShieldConfiguration) {
       .motorShieldName = "L7938",
       .motorShieldType = MotorShieldType::LEGO_IR_8884,
       .minArduinoPower = MIN_ARDUINO_POWER,
       .maxArduinoPower = MAX_ARDUINO_POWER,
       .configMotorA = 1,
       .configMotorB = 0,
       .locoAddress = 7938


const MotorShieldType MOTORSHIELD_TYPE = MotorShieldType::NONE;


#define IR_LED_PIN D5
#define IR_CHANNEL 0
#define IR_PORT_RED 1
#define IR_PORT_BLUE 0


const int NUM_FUNCTIONS = 1;
const bool AUTO_LIGHTS = true;

The loco is called “L7938” and has the address 7938 in RocRail. Every 100ms (0,1 seconds), it will accelerate by 2% of the maximum power (20% per second) or brake with 2% of the maximum power (20% per second).

The loco operates by sending commands to the LEGO Infrared Receiver 8884 via an infrared LED. One motor is installed on the red port (.configMotorA = 1). The infrared is installed on pin D5 (IR_LED_PIN).

Please note that the constant MOTORSHIELD_TYPE must be set to MotorShieldType::NONE, as this motor shield is not directly attached to the controller.

One function is defined (F1 in Rocrail). Note that the “virtual” pin IR_LIGHT_BLUE is used as identifier for the pin on the controller. Using this pin, the controller will not switch a pin on the controller directly, but instead signal the light command to the LEGO IR Receiver 8884, who in turn does the actual job.

Auto lights are switched off. By default, lights will be switched on automatically when going forward, and switched off when stopping or going in reverse. How to change this behaviour, see above.

3 locos with 5 4DBrix WiFi Train Receivers

Check out the example file (MTC4PF_Configuration_Example_4DBrix.h) which is part of the firmware download! In this example, the MTC4PF controls 3 locos with 5 4DBrix WiFi Train Receivers in total. If you have understood the examples above, you should be able to fetch the whereabout of this configuration file as well.

Setup in Rocrail

To set-up a train controller in Rocrail, open Rocview and navigate to menu Tables / Locomotives. Choose the locomotive that you want to configure or create a new one.

Navigate to tab “Interface” and configure the loco address as specified in the firmware configuration file above. Then set the “Decoder Steps” value to 255:

Navigate to the “Speed” tab, and choose “Percent”. Enter useful motor power values for the different speed levels (trial and error):

Defining speed in Rocrail is a complex matter. More information about this topic can be found here.

There is a lot of additional configuration options for trains in Rocrail. Please refer to the Rocrail documentation for more information.


Leave a Reply

Your email address will not be published. Required fields are marked *