Skip to content

H0 Locomotive Motor Simulation with bEMF Control

This document describes how to simulate standard H0 model railroad locomotive motors (brushed DC) and implement Back-Electromotive Force (bEMF) load compensation using the XIAO Seeed RP2040 and Renode.

Overview

In model railroading, maintaining a constant speed as a locomotive climbs a grade or pulls a heavy consist is a key feature of high-quality decoders. This is achieved by measuring the bEMF voltage generated by the motor during the "OFF" portion of the PWM cycle.

Motor Physics Model

A brushed DC motor can be modeled with the following electrical and mechanical equations:

  1. Voltage Equation: \(V_{in} = I \cdot R + L \frac{di}{dt} + V_{bemf}\)
  2. Back-EMF Equation: \(V_{bemf} = K_e \cdot \omega\)
  3. Torque Equation: \(\tau = K_t \cdot I = J \frac{d\omega}{dt} + B\omega + \tau_{load}\)

Variables Breakdown

For beginners, here is what each term represents:

  • \(V_{in}\) (Input Voltage): The voltage applied to the motor terminals, controlled by the PWM duty cycle from the RP2040.
  • \(I\) (Current): The electrical current flowing through the motor windings, measured in Amperes.
  • \(R\) (Resistance): The internal electrical resistance of the motor coils (Ohms). It causes energy loss as heat.
  • \(L\) (Inductance): The property of the coils that resists changes in current (Henries).
  • \(\frac{di}{dt}\) (Change in Current): How fast the current is changing over time. This term (\(L \frac{di}{dt}\)) represents the voltage drop due to inductance.
  • \(V_{bemf}\) (Back-EMF): The "internal" voltage generated by the motor as it spins, acting against the input voltage.
  • \(K_e\) (Back-EMF Constant): A physical constant of the motor that relates its speed to the voltage it generates.
  • \(\omega\) (Angular Velocity): The rotational speed of the motor (usually radians per second).
  • \(\tau\) (Torque): The rotational force produced by the motor.
  • \(K_t\) (Torque Constant): Relates the current flowing through the motor to the torque it produces. In many units, \(K_t\) is numerically equivalent to \(K_e\).
  • \(J\) (Inertia): The resistance of the rotor (and attached wheels/gears) to changes in its rotational speed.
  • \(\frac{d\omega}{dt}\) (Angular Acceleration): How fast the motor's speed is increasing or decreasing.
  • \(B\) (Viscous Friction): Internal friction that increases as the motor spins faster.
  • \(\tau_{load}\) (Load Torque): External forces resisting the motor, such as a locomotive pulling heavy cars or climbing a steep grade.
  • \(V_{start}\) (Start Voltage): The minimum voltage required to overcome static friction (stiction) and start the motor turning from a standstill.
  • \(V_{stop}\) (Stop Voltage): The voltage level below which the motor's internal friction and load will cause it to stop turning. Usually lower than \(V_{start}\) due to the transition from static to kinetic friction.

Equation Breakdown

1. The Voltage Equation

\[V_{in} = I \cdot R + L \frac{di}{dt} + V_{bemf}\]

This equation describes how the input voltage is "used up" inside the motor. It says the total voltage you provide (\(V_{in}\)) equals the sum of: - The voltage dropped across the internal resistance (\(I \cdot R\)). - The voltage used to overcome inductance when current changes (\(L \frac{di}{dt}\)). - The Back-EMF generated by the spinning motor (\(V_{bemf}\)).

2. The Back-EMF Equation

\[V_{bemf} = K_e \cdot \omega\]

This is the most important equation for bEMF control. It shows that the internal voltage generated by the motor is directly proportional to its speed. If you double the speed, you double the Back-EMF. This allows us to calculate the motor's speed just by measuring this voltage.

3. The Torque Equation

\[\tau = K_t \cdot I = J \frac{d\omega}{dt} + B\omega + \tau_{load}\]

This equation relates the electrical current to the physical movement. It tells us: - The motor produces torque proportional to the current (\(K_t \cdot I\)). - This torque is used to accelerate the rotor (\(J \frac{d\omega}{dt}\)), overcome internal friction (\(B\omega\)), and fight against external loads (\(\tau_{load}\)).

bEMF Control Logic

The bEMF voltage is directly proportional to the motor speed. By measuring \(V_{bemf}\), the firmware can determine the actual speed of the locomotive and adjust the PWM duty cycle to match the desired speed.

Measurement Cycle

  1. PWM ON: Power is applied to the motor.
  2. PWM OFF: The motor is disconnected from power. The inductance causes a flyback current, which must decay before measurement.
  3. Sampling Window: Once the flyback current has subsided, the voltage at the motor terminals is purely the bEMF.
  4. ADC Read: The RP2040 ADC samples the voltage.
  5. PID Update: The error between target bEMF (speed) and measured bEMF is fed into a PID controller to update the PWM duty cycle.

Renode Configuration

To simulate this in Renode, we use the MotorModel peripheral (Phase 8.1).

REPL Example

motor: Peripherals.Motor.MotorModel @ sysbus
    kv: 1000            // RPM per Volt
    resistance: 10      // Ohms
    inductance: 0.001   // Henries
    inertia: 0.0001     // kg*m^2
    voltageInput: pwm0.slice0_chB
    velocityOutput: adc.channel0

Note: In the simulation, the velocityOutput is scaled to represent the bEMF voltage seen by the ADC.

Firmware Implementation

ADC/PWM Synchronization

To capture the bEMF accurately, the ADC must be triggered exactly during the PWM OFF period.

// Example: Trigger ADC on PWM Wrap (End of cycle)
void setup_pwm_and_adc() {
    // Configure PWM
    pwm_config config = pwm_get_default_config();
    pwm_config_set_wrap(&config, 2500); // 20kHz at 50MHz
    pwm_init(slice_num, &config, true);

    // Enable PWM Wrap Interrupt
    pwm_set_irq_enabled(slice_num, true);
    irq_set_exclusive_handler(PWM_IRQ_WRAP, on_pwm_wrap);
    irq_set_enabled(PWM_IRQ_WRAP, true);
}

void on_pwm_wrap() {
    pwm_clear_irq(slice_num);
    // Start ADC conversion after a short delay (to allow flyback to decay)
    // In a real system, use a timer or PWM compare to trigger ADC
    adc_select_input(0);
    uint16_t result = adc_read();

    // Process bEMF value...
}

Typical H0 Motor Parameters

Standard H0 motors (like those from Mabuchi, Mashima, or modern CAN motors) typically have:

Parameter Value Range
Operating Voltage 0 - 12V / 14V DC
Start Voltage (\(V_{start}\)) 0.5V - 4.5V
Stop Voltage (\(V_{stop}\)) 0.2V - 2.5V
No-load Speed 8,000 - 15,000 RPM
Stall Current 0.5A - 2.0A
Terminal Resistance 5 - 25 Ohms

By configuring these in LOCO_SIM.md, developers can test their PID tuning for different locomotive types (e.g., a fast passenger engine vs. a high-torque switcher) entirely in simulation.