Analog control (RCPWM et al)#

This tutorial demonstrates how to set up the analog control interface in different modes. It is not meant to provide an exhaustive description of all of the features of the auxiliary I/O because the respective chapter of the reference manual already covers that adequately.


  • Telega-based motor controller.

  • Motor, unless it is part of an integrated drive.

  • DC power supply.

  • An electric motor test bench, such as Zubax Heidy, a propeller stand, or a similar rig depending on the intended application.

  • Network interface adapter, such as Zubax Babel.

  • Arbitrary waveform generator (recommended), an RCPWM tester, or some equivalent equipment that can generate the analog signal for controlling the drive.

Configure the motor controller#

The motor controller should be configured for use with the connected motor. If the velocity control mode is of interest, then the velocity controller should be configured. These initial steps may be as simple as connecting the motor and running the automatic motor identification procedure; for details, please consult other tutorials that may apply in your case, such as “Yakut CLI tool”.

Once the controller is operational, prepare a configuration file template that we will be working with in the subsequent steps by simply dumping all the configuration parameters into a YAML file and removing all the registers that are not related to the auxiliary I/O interface. It can be done either with Yukon by clicking through the register view GUI, or using Yakut as follows (assuming that the node-ID of the motor controller is 125):

y rl 125 | y --yaml rb 125 --only=mp > analog_ctl.yaml

Then open analog_ctl.yaml in any text editor (preferably with YAML syntax highlighting) and remove all parameters except those that are related to the to the auxiliary I/O interface. You should end up with something roughly like this:

aux.power_output:               false
aux.pull:                       0

aux.ctl.dead0:                  false
aux.ctl.mode:                   ""      # None, analog control disabled.
aux.ctl.type:                   0       # Selects one of the demodulators below, 0 to disable.

aux.ctl.1_rcpwm.rev_mid_fwd:    [0.001, 0.0015, 0.002]
aux.ctl.1_rcpwm.deadband:       0.0001

aux.ctl.2_voltage.rev_mid_fwd:  [0.0, 1.65, 3.3]
aux.ctl.2_voltage.deadband:     0.15

When you modify the file, you can apply it to the controller (or several) using the Yukon GUI or by invoking the following Yakut command:

y rb 120-126 < analog_ctl.yaml  # Apply to nodes 120,121,122,123,124,125 (change this to match your case).
y cmd 120-126 restart           # Do not forget to restart the node(s) afterward.

If you are using Yukon or some other GUI solution, you can avoid this configuration file business completely and just edit the registers directly in the GUI. However, it is often more convenient to keep all configuration parameters related to some particular function of the device in a separate file which can be deployed when necessary. For instructional purposes, we will stick to the file-based approach in this tutorial. Feel free to ignore it and just edit the registers directly if you prefer.

Velocity control via RCPWM#

In this section, we will set up the drive in the velocity control mode directed by a RCPWM signal supplied to the auxiliary input.

Suppose that we want the RCPWM pulse duration to translate to the velocity setpoint as follows, with some deadband around the midpoint where the drive is to remain disengaged:


Pulse duration

-300 radian/second

1 ms


1.5±0.05 ms

+300 radian/second

2 ms


Modify analog_ctl.yaml as follows:

aux.ctl.dead0:                  false
aux.ctl.mode:                   "dv 300.0"      # Drive-Velocity, ±300 radian/second
aux.ctl.type:                   1
aux.ctl.1_rcpwm.rev_mid_fwd:    [0.001, 0.0015, 0.002]  # See the table.
aux.ctl.1_rcpwm.deadband:       50.0e-6

Apply the new configuration and restart the controller. The drive will remain in the standby mode as long as no RCPWM signal is detected or the pulse duration is within the configured deadband off the midpoint.

Connect the RCPWM signal source and set the pulse duration to 1.5 ms; the controller will remain idle. Setting the pulse duration to 1.7 ms will command the controller to spin up in the forward direction and maintain the angular velocity of +120 radian/second. Reversal is possible by sending pulses shorter than 1.5 ms. The system status register contains information on the setpoint value passed to the motor control core from the analog control front-end:

y r 125 sys.status

Unipolar, non-reversible control can be configured by setting the middle and negative reference points to the same value. The following configuration is implemented next:


Pulse duration


less than 1.05 ms

+300 radian/second

2 ms

Modify analog_ctl.yaml as follows:

aux.ctl.dead0:                  false
aux.ctl.mode:                   "dv 300.0"
aux.ctl.type:                   1
aux.ctl.1_rcpwm.rev_mid_fwd:    [0.001, 0.001, 0.002]  # "rev" and "mid" are the same.
aux.ctl.1_rcpwm.deadband:       50.0e-6

In this configuration, a pulse duration of 1.5 ms will run the motor forward at 150 radian/second.

Torque control via analog voltage#

In this section, we will set up the drive in the ratiometric torque control mode directed by the voltage applied at the auxiliary input. This kind of control is often used in simple micromobility vehicles, where the voltage is modulated by a variable resistor installed on the handlebars connected between the ground and some positive voltage, often around +4 V.

Suppose that we want the analog voltage applied at the auxiliary I/O pin to map to the ratiometric torque setpoint as follows, with some deadband around zero:



-100% (braking during forward rotation, motoring during reverse rotation)

0.1 V

0% (freewheeling)

1.0±0.1 V

+100% (motoring during forward rotation, braking during reverse rotation)

3.0 V

Modify analog_ctl.yaml as follows:

aux.ctl.dead0:                  false
aux.ctl.mode:                   "dtr"           # Drive-Torque-Ratiometric
aux.ctl.type:                   2
aux.ctl.2_voltage.rev_mid_fwd:  [0.1, 1.0, 3.0] # See the table.
aux.ctl.2_voltage.deadband:     0.1

Connect the source of the analog signal (e.g., an arbitrary waveform generator or a variable resistor between the ground and some voltage source) to the auxiliary input pin and set it to 1.0 V, apply the new configuration, and restart the controller. It is important to ensure that the signal source is connected first because if the input is allowed to float, the behavior of the drive will be unpredictable.

Once the controller is restarted, increase the voltage to 1.2 V and observe the motor to run forward at 10% torque. Set the voltage to 0.8 V to brake the motor at -22% torque and then run in the reverse direction at -22% torque. Use diagnostic registers to check the input voltage and the computed setpoint:

y r 125 sys.status  # See the setpoint value passed to the motor control core from the analog control front-end.
y r 125 aux.voltage # Voltage measured at the input pin.

In applications like sensorless generators or sensorless micromobility drives, the sensorless passive spinup mode is often useful, where the drive will keep the motor in the freewheeling mode regardless of the commanded setpoint until the motor is accelerated by an external force to some threshold velocity where the drive can be engaged and act upon the received setpoint. This mode is often useful with the aux.ctl.dead0 option, which will keep the drive active — tracking the motor state — while the analog control signal resides inside the deadband zone. The deadband zone itself can be disabled in this mode, depending on the application. Set it up as follows:

aux.ctl.dead0:                  true            # !!!
aux.ctl.mode:                   "dtr"
aux.ctl.type:                   2
aux.ctl.2_voltage.rev_mid_fwd:  [0.1, 1.0, 3.0]
aux.ctl.2_voltage.deadband:     0.1             # Can be set to zero.
# New options for the drive command:
drive.runner.type:                      1
drive.runner.1_passive.velocity_off_on: [5, 10]

Apply the configuration and restart the controller. The motor may hum or emit a weak sizzling noise while standing still as the controller tracks the state of the rotor in sensorless mode. If you display the estimated mechanical position (e.g., plot it as explained in other tutorials) and spin the motor by hand, you will see the estimated position change accordingly.

Control by current#

The auxiliary I/O port contains an optional strong pull resistor \(R_\text{pull}\) that can be used to measure the control current sinking into the port as \(u_\text{aux} = i_\text{control} \, R_\text{pull}\), where \(u_\text{aux}\) is the voltage observed at the analog input pin. The pull resistor can be tied to the ground by setting aux.pull to -1 (minus one). For example, one common configuration is \(R_\text{pull} = 1200 \Omega\) (consult with the hardware datasheet for this information), in which case the dynamic range of the control current is 0 to 2.75 mA.

If aux.pull is set to +1 (plus one), the current will be sourced by the controller and the voltage function will be inverted.