Motion Control Module

This module provides a Service (motion_control_service) to perform Torque/Velocity/Position control. This Service is recommended to be running at 100MHz Reference Clock Frequency. After running this service, the user can select the controlling mode (either torque, velocity, or position control mode). Depending on the selected mode, motion_control_service will call the corresponding function from module_controllers to calculate the proper reference value of the torque, and calculated values of reference torque will be sent to torque control service.

How to use


We assume that you are using SOMANET Base and your app includes the required board support files for your SOMANET device.

See also

You might find the app_demo_motion_control example apps useful, which illustrate the use of this module:

  • BLDC Motion Control Demo
  1. In your app, modify your Makefile so that looks like this:

    # The TARGET variable determines what target system the application is
    # compiled for. It either refers to an XN file in the source directories
    # or a valid argument for the --target option when compiling
    # Possible SOMANET targets:
    # SOMANET-CoreC22
    # SOMANET-CoreC21
    # SOMANET-CoreC21-rev-b
    # SOMANET-CoreC2X
    # The APP_NAME variable determines the name of the final .xe file. It should
    # not include the .xe postfix. If left blank the name will default to
    # the project name
    APP_NAME = app_demo_motion_control
    # The USED_MODULES variable lists other module used by the application.
    USED_MODULES = configuration_parameters lib_bldc_torque_control lib_limited_torque_position_control module_adc module_autotune module_biss_encoder module_board-support module_controllers module_encoder_rem_14 module_encoder_rem_16mt module_filters module_hall_sensor module_incremental_encoder module_motion_control module_position_feedback module_profiles module_pwm module_serial_encoder module_shared_memory module_spi_master module_utils module_watchdog
    # The flags passed to xcc when building the application
    # You can also set the following to override flags for a particular language:
    # If the variable XCC_MAP_FLAGS is set it overrides the flags passed to
    # xcc for the final link (mapping) stage.
    XCC_FLAGS_Release = -g -O3
    # The XCORE_ARM_PROJECT variable, if set to 1, configures this
    # project to create both xCORE and ARM binaries.
    # The VERBOSE variable, if set to 1, enables verbose output from the make system.
    VERBOSE = 0
    XMOS_MAKE_PATH ?= ../..
    -include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
  2. Add config.xscope (located in sc_somanet-base) to your project.

  3. Properly instantiate a Torque Control Service.

  4. Include the Motion Control Service header motion_control_service.h in your app.

  5. Inside your main function, instantiate the interfaces array for the Service-Clients communication.

  6. Outside your IF2 tile, instantiate the Service. For that, first you will have to fill up your Service configuration and provide interfaces to your position feedback sensor Service and Torque Control Service.

  7. Now you can perform calls to the Motion Control Service through the interfaces connected to it. You can do this at whichever other core.

    #include <CoreC2X.bsp>               //Board Support file for SOMANET Core C2X device
    #include <Drive1000-rev-c4.bsp>  //Board Support file for SOMANET Drive module
                                     //(select your board support files according to your device)
     #include <pwm_service.h>
     #include <hall_service.h>
     #include <watchdog_service.h>
     #include <motorcontrol_service.h>
     #include <motion_control_service.h> // step 3
     PwmPortsGeneral pwm_ports = SOMANET_DRIVE_PWM_PORTS_GENERAL;
             WatchdogPorts wd_ports = SOMANET_DRIVE_WATCHDOG_PORTS;
             FetDriverPorts fet_driver_ports = SOMANET_DRIVE_FET_DRIVER_PORTS;
             ADCPorts adc_ports = SOMANET_DRIVE_ADC_PORTS;
             SPIPorts spi_ports = SOMANET_DRIVE_SPI_PORTS;
             HallEncSelectPort hall_enc_select_port = SOMANET_DRIVE_ENCODER_PORTS_INPUT_MODE_SELECTION;
             port ? qei_hall_port_1 = SOMANET_DRIVE_ENCODER_1_PORT;
             port ? qei_hall_port_2 = SOMANET_DRIVE_ENCODER_2_PORT;
             port ?gpio_port_0 = SOMANET_DRIVE_GPIO_D0;
             port ?gpio_port_1 = SOMANET_DRIVE_GPIO_D1;
             port ?gpio_port_2 = SOMANET_DRIVE_GPIO_D2;
             port ?gpio_port_3 = SOMANET_DRIVE_GPIO_D3;
    int main(void)
                 // Motor control interfaces
                 interface WatchdogInterface i_watchdog[2];
                 interface UpdatePWMGeneral i_update_pwm;
                 interface UpdateBrake i_update_brake;
                 interface ADCInterface i_adc[2];
                 interface TorqueControlInterface i_torque_control[2];
                 interface MotionControlInterface i_motion_control[3];
                 interface PositionFeedbackInterface i_position_feedback_1[3];
                 interface PositionFeedbackInterface i_position_feedback_2[3];
                 interface shared_memory_interface i_shared_memory[3];               //step 4
             on tile[APP_TILE]:
                  demo_motion_control(i_motion_control[0]); // step 6
             on tile[APP_TILE_2]:
                 //step 5
                 MotionControlConfig motion_ctrl_config;
                 motion_ctrl_config.min_pos_software_limit =               MIN_POSITION_SOFTWARE_LIMIT;
                 motion_ctrl_config.max_pos_software_limit =               MAX_POSITION_SOFTWARE_LIMIT;
                 motion_ctrl_config.min_pos_range_limit    =               MIN_POSITION_RANGE_LIMIT;
                 motion_ctrl_config.max_pos_range_limit    =               MAX_POSITION_RANGE_LIMIT;
                         motion_ctrl_config.max_motor_speed =                      MOTOR_MAX_SPEED;
                         motion_ctrl_config.polarity =                             POLARITY;
                         motion_ctrl_config.enable_profiler =                      ENABLE_PROFILER;
                         motion_ctrl_config.max_acceleration_profiler =            MAX_ACCELERATION_PROFILER;
                         motion_ctrl_config.max_deceleration_profiler =            MAX_DECELERATION_PROFILER;
                         motion_ctrl_config.max_speed_profiler =                   MAX_SPEED_PROFILER;
                         motion_ctrl_config.position_control_strategy =            POSITION_CONTROL_STRATEGY;
                         motion_ctrl_config.position_kp =                          POSITION_Kp;
                         motion_ctrl_config.position_ki =                          POSITION_Ki;
                         motion_ctrl_config.position_kd =                          POSITION_Kd;
                         motion_ctrl_config.position_integral_limit =              POSITION_INTEGRAL_LIMIT;
                         motion_ctrl_config.velocity_kp =                          VELOCITY_Kp;
                         motion_ctrl_config.velocity_ki =                          VELOCITY_Ki;
                         motion_ctrl_config.velocity_kd =                          VELOCITY_Kd;
                         motion_ctrl_config.velocity_integral_limit =              VELOCITY_INTEGRAL_LIMIT;
                         motion_ctrl_config.enable_velocity_auto_tuner =           ENABLE_VELOCITY_AUTO_TUNER;
                 motion_ctrl_config.enable_compensation_recording =        ENABLE_COMPENSATION_RECORDING;
                 motion_ctrl_config.cogging_compensation_state =           COGGING_COMPENSATION_STATE;
                 motion_ctrl_config.enable_cogging_compensation =          ENABLE_COGGING_COMPENSATION;
                         motion_ctrl_config.enable_open_phase_detection =          ENABLE_OPEN_PHASE_DETECTION;
                         motion_ctrl_config.position_kp_l =                        GAIN_SCHEDULING_POSITION_Kp_0;
                         motion_ctrl_config.position_ki_l =                        GAIN_SCHEDULING_POSITION_Ki_0;
                         motion_ctrl_config.position_kd_l =                        GAIN_SCHEDULING_POSITION_Kd_0;
                         motion_ctrl_config.position_kp_h =                        GAIN_SCHEDULING_POSITION_Kp_1;
                         motion_ctrl_config.position_ki_h =                        GAIN_SCHEDULING_POSITION_Ki_1;
                         motion_ctrl_config.position_kd_h =                        GAIN_SCHEDULING_POSITION_Kd_1;
                         motion_ctrl_config.velocity_kp_l =                        GAIN_SCHEDULING_VELOCITY_Kp_0;
                         motion_ctrl_config.velocity_ki_l =                        GAIN_SCHEDULING_VELOCITY_Ki_0;
                         motion_ctrl_config.velocity_kd_l =                        GAIN_SCHEDULING_VELOCITY_Kd_0;
                         motion_ctrl_config.velocity_kp_h =                        GAIN_SCHEDULING_VELOCITY_Kp_1;
                         motion_ctrl_config.velocity_ki_h =                        GAIN_SCHEDULING_VELOCITY_Ki_1;
                         motion_ctrl_config.velocity_kd_h =                        GAIN_SCHEDULING_VELOCITY_Kd_1;
                         motion_ctrl_config.velocity_lo_l =                        GAIN_SCHEDULING_VELOCITY_THRESHOLD_0;
                         motion_ctrl_config.velocity_hi_l =                        GAIN_SCHEDULING_VELOCITY_THRESHOLD_1;
                         motion_ctrl_config.brake_release_strategy =               BRAKE_RELEASE_STRATEGY;
                         motion_ctrl_config.brake_release_delay =                  BRAKE_RELEASE_DELAY;
                         //select resolution of sensor used for motion control
                             motion_ctrl_config.resolution  =                          SENSOR_2_RESOLUTION;
                         } else {
                             motion_ctrl_config.resolution  =                          SENSOR_1_RESOLUTION;
                         motion_ctrl_config.dc_bus_voltage=                        DC_BUS_VOLTAGE;
                         motion_ctrl_config.pull_brake_voltage=                    PULL_BRAKE_VOLTAGE;
                         motion_ctrl_config.pull_brake_time =                      PULL_BRAKE_TIME;
                         motion_ctrl_config.hold_brake_voltage =                   HOLD_BRAKE_VOLTAGE;
                         motion_control_service(motion_ctrl_config, i_torque_control[0], i_motion_control, i_update_brake); //5
     on tile[IF2_TILE]:
             /* PWM Service */
                 if (!isnull(fet_driver_ports.p_esf_rst_pwml_pwmh) && !isnull(fet_driver_ports.p_coast))
                 pwm_service_general(pwm_ports, i_update_pwm, GPWM_FRQ_15, DEADTIME_NS);
              /* ADC Service */
                 adc_service(adc_ports, i_adc /*ADCInterface*/, i_watchdog[1], IF2_TILE_USEC, SINGLE_ENDED);
             /* Watchdog Service */
                 watchdog_service(wd_ports, i_watchdog, IF2_TILE_USEC);
             /* Motor Control Service */
                 MotorcontrolConfig motorcontrol_config;
                 motorcontrol_config.dc_bus_voltage =  DC_BUS_VOLTAGE;
                 motorcontrol_config.phases_inverted = MOTOR_PHASES_CONFIGURATION;
                 motorcontrol_config.torque_P_gain =  TORQUE_Kp;
                 motorcontrol_config.torque_I_gain =  TORQUE_Ki;
                 motorcontrol_config.torque_D_gain =  TORQUE_Kd;
                 motorcontrol_config.pole_pairs =  MOTOR_POLE_PAIRS;
                 motorcontrol_config.max_torque =  MOTOR_MAXIMUM_TORQUE;
                 motorcontrol_config.phase_resistance =  MOTOR_PHASE_RESISTANCE;
                 motorcontrol_config.phase_inductance =  MOTOR_PHASE_INDUCTANCE;
                 motorcontrol_config.torque_constant =  MOTOR_TORQUE_CONSTANT;
                 motorcontrol_config.current_ratio =  CURRENT_RATIO;
                 motorcontrol_config.voltage_ratio =  VOLTAGE_RATIO;
                 motorcontrol_config.temperature_ratio =  TEMPERATURE_RATIO;
                 motorcontrol_config.rated_current =  MOTOR_RATED_CURRENT;
                 motorcontrol_config.rated_torque  =  MOTOR_RATED_TORQUE;
                 motorcontrol_config.percent_offset_torque =  APPLIED_TUNING_TORQUE_PERCENT;
                 motorcontrol_config.protection_limit_over_current =  PROTECTION_MAXIMUM_CURRENT;
                 motorcontrol_config.protection_limit_over_voltage =  PROTECTION_MAXIMUM_VOLTAGE;
                 motorcontrol_config.protection_limit_under_voltage = PROTECTION_MINIMUM_VOLTAGE;
                 motorcontrol_config.protection_limit_over_temperature = TEMP_BOARD_MAX;
                 for (int i = 0; i < 1024; i++)
                     motorcontrol_config.torque_offset[i] = 0;
                 torque_control_service(motorcontrol_config, i_adc[0], i_shared_memory[2],
                         i_watchdog[0], i_torque_control, i_update_pwm, IF2_TILE_USEC, /*gpio_port_0*/null);
             /* Shared memory Service */
             [[distribute]] shared_memory_service(i_shared_memory, 3);
              /* Position feedback service */
                 PositionFeedbackConfig position_feedback_config;
                 position_feedback_config.sensor_type = SENSOR_1_TYPE;
                 position_feedback_config.resolution  = SENSOR_1_RESOLUTION;
                 position_feedback_config.polarity    = SENSOR_1_POLARITY;
                 position_feedback_config.velocity_compute_period = SENSOR_1_VELOCITY_COMPUTE_PERIOD;
                 position_feedback_config.pole_pairs  = MOTOR_POLE_PAIRS;
                 position_feedback_config.tile_usec   = IF2_TILE_USEC;
                 position_feedback_config.max_ticks   = SENSOR_MAX_TICKS;
                 position_feedback_config.offset      = HOME_OFFSET;
                 position_feedback_config.sensor_function = SENSOR_1_FUNCTION;
                 position_feedback_config.biss_config.multiturn_resolution = BISS_MULTITURN_RESOLUTION;
                 position_feedback_config.biss_config.filling_bits = BISS_FILLING_BITS;
                 position_feedback_config.biss_config.crc_poly = BISS_CRC_POLY;
                 position_feedback_config.biss_config.clock_frequency = BISS_CLOCK_FREQUENCY;
                 position_feedback_config.biss_config.timeout = BISS_TIMEOUT;
                 position_feedback_config.biss_config.busy = BISS_BUSY;
                 position_feedback_config.biss_config.clock_port_config = BISS_CLOCK_PORT;
                 position_feedback_config.biss_config.data_port_number = BISS_DATA_PORT_NUMBER;
                 position_feedback_config.biss_config.data_port_signal_type = BISS_DATA_PORT_SIGNAL_TYPE;
                 position_feedback_config.rem_16mt_config.filter = REM_16MT_FILTER;
                 position_feedback_config.rem_14_config.hysteresis              = REM_14_SENSOR_HYSTERESIS;
                 position_feedback_config.rem_14_config.noise_settings          = REM_14_SENSOR_NOISE_SETTINGS;
                 position_feedback_config.rem_14_config.dyn_angle_error_comp    = REM_14_DYN_ANGLE_ERROR_COMPENSATION;
                 position_feedback_config.rem_14_config.abi_resolution_settings = REM_14_ABI_RESOLUTION_SETTINGS;
                 position_feedback_config.qei_config.number_of_channels = QEI_SENSOR_NUMBER_OF_CHANNELS;
                 position_feedback_config.qei_config.signal_type        = QEI_SENSOR_SIGNAL_TYPE;
                 position_feedback_config.qei_config.port_number        = QEI_SENSOR_PORT_NUMBER;
                 position_feedback_config.qei_config.ticks_lost_threshold = QEI_SENSOR_TICKS_LOST;
                 position_feedback_config.hall_config.port_number = HALL_SENSOR_PORT_NUMBER;
                 position_feedback_config.gpio_config[0] = GPIO_CONFIG_1;
                 position_feedback_config.gpio_config[1] = GPIO_CONFIG_2;
                 position_feedback_config.gpio_config[2] = GPIO_CONFIG_3;
                 position_feedback_config.gpio_config[3] = GPIO_CONFIG_4;
                 //setting second sensor
                 PositionFeedbackConfig position_feedback_config_2 = position_feedback_config;
                 position_feedback_config_2.sensor_type = 0;
                 if (SENSOR_2_FUNCTION != SENSOR_FUNCTION_DISABLED) //enable second sensor
                     position_feedback_config_2.sensor_type = SENSOR_2_TYPE;
                     position_feedback_config_2.polarity    = SENSOR_2_POLARITY;
                     position_feedback_config_2.resolution  = SENSOR_2_RESOLUTION;
                     position_feedback_config_2.velocity_compute_period = SENSOR_2_VELOCITY_COMPUTE_PERIOD;
                     position_feedback_config_2.sensor_function = SENSOR_2_FUNCTION;
                 position_feedback_service(qei_hall_port_1, qei_hall_port_2, hall_enc_select_port, spi_ports, gpio_port_0, gpio_port_1, gpio_port_2, gpio_port_3,
                         position_feedback_config, i_shared_memory[0], i_position_feedback_1,
                         position_feedback_config_2, i_shared_memory[1], i_position_feedback_2);


    return 0;





Maximum possible value for pid constants for both velocity and position controllers.


threshold in ticks to re-enable the position controler if the limit reached.


Period for the control loop [microseconds].


Period for the control loop [seconds].


Threshold to detect brake release in ticks.


Brake release duration in milliseconds.


Time to wait when updating the brake config in milliseconds.

It is because the pwm service needs time to stop.

Global Types


doxygenstruct: Cannot find struct “MotionControlStrategies” in doxygen xml output


Structure definition for a Motion Control Loop Service configuration.

Structure Members:

int position_control_strategy

Parameter for selecting between defferent types of position or velocity controllers.

int motion_profile_type

Parameter for selecting between different types of profilers (including torque/velocity/posiiton controllers.

int min_pos_software_limit

Parameter for setting the minimum software position range.

int max_pos_software_limit

Parameter for setting the maximum software position range.

int min_pos_range_limit

Parameter for setting the minimum position range.

int max_pos_range_limit

Parameter for setting the maximum position range.

int max_speed

Parameter for setting the maximum application speed.

int max_motor_speed

Parameter for setting the maximum motor speed.

int torque_ref_limit

Upper limit of torque reference in milli-Nm.

int enable_profiler

Parameter for enabling/disabling the profiler.

int max_acceleration_profiler

Parameter for setting the maximum acceleration in profiler mode.

int max_deceleration_profiler

Parameter for setting the maximum deceleration in profiler mode.

int max_speed_profiler

Parameter for setting the maximum speed in profiler mode.

int max_torque_rate_profiler

Parameter for setting the maximum torque in profiler mode.

int torque_kp

Parameter for torque controller P-constant.

int torque_ki

Parameter for torque controller I-constant.

int torque_kd

Parameter for torque controller D-constant.

int offset_compensation_constant

(optional) difference between measured and real electrical angle at 1000 rpm in software.

please notice that [0-360] degree range is mapped to [0-4095] range inside the software. Default value is 0

int field_weakening_status

field_weakening 1-> enabled, 0-> disabled

int field_weakening_percentage

field_weakening percentage.

This parameter changes between 0 and 100, and represents the reduction percentage of rotor magnetic field

int field_weakening_starting_range

speed in which field weakening will start (in rpm)

int field_weakening_ending_range

speed in which field weakening will end (in rpm)

float position_kp

Parameter for position controller P-constant.

float position_ki

Parameter for position controller I-constant.

float position_kd

Parameter for position controller D-constant.

int position_integral_limit

Parameter for integral limit of position pid controller.

int rise_time_freedom_percent_autotune

This value helps the tuner to find out whether the ki is high enough or not.

By default set this value to 300, and if the tuner is not able to find proper values (and the response is having oscillations), increase this value to 400 or 500.

float velocity_kp

Parameter for velocity controller P-constant.

float velocity_ki

Parameter for velocity controller I-constant.

float velocity_kd

Parameter for velocity controller D-constant.

int velocity_integral_limit

Parameter for integral limit of velocity pid controller.

int enable_velocity_auto_tuner

Parameter for enabling/disabling auto tuner for velocity controller.

int enable_compensation_recording

Parameter for enabling/disabling the cogging torque compensator recording.

int cogging_compensation_state

Parameter for tracking the status of the cogging compensation recording 0 -> NO DATA, 1 -> IN PROGRESS, 2 -> RECORDING_SAVING, 3 -> DATA EXISTS.

int enable_cogging_compensation

Parameter for enabling/disabling the cogging torque compensation algorithm.

int enable_sensor_evaluation

Parameter for enabling/disabling the sensor evaluation procedure.

CommutationOffsetData co_parameters

Structure for the the commutation offset detection procedure.

int enable_open_phase_detection

Parameter for enabling/disabling the online open phase detection functionality.

int resolution

Parameter for setting the resolution of position sensor [ticks/rotation].

MotionPolarity polarity

Parameter for setting the polarity of the movement.

int brake_release_strategy

Parameter for setting different brake release strategies, e.g., shaking.

int brake_release_delay

Parameter for setting the delay between removing voltage from the brake and disabling the control.

int dc_bus_voltage_actual

Measured value of dc-link.

int pull_brake_voltage

Parameter for setting the voltage for pulling the brake out!

int pull_brake_time

Parameter for setting the time of brake pulling.

int hold_brake_voltage

Parameter for setting the brake voltage after it is pulled.

float position_kp_l

Parameter for gain scheduling position controller P-constant for low velocities.

float position_ki_l

Parameter for gain scheduling position controller I-constant for low velocities.

float position_kd_l

Parameter for gain scheduling position controller D-constant for low velocities.

float position_kp_h

Parameter for gain scheduling position controller P-constant for high velocities.

float position_ki_h

Parameter for gain scheduling position controller I-constant for high velocities.

float position_kd_h

Parameter for gain scheduling position controller D-constant for high velocities.

float velocity_kp_l

Parameter for gain scheduling velocity controller P-constant for low velocities.

float velocity_ki_l

Parameter for gain scheduling velocity controller I-constant for low velocities.

float velocity_kd_l

Parameter for gain scheduling velocity controller D-constant for low velocities.

float velocity_kp_h

Parameter for gain scheduling velocity controller P-constant for high velocities.

float velocity_ki_h

Parameter for gain scheduling velocity controller I-constant for high velocities.

float velocity_kd_h

Parameter for gain scheduling velocity controller D-constant for high velocities.

int velocity_lo_l

Parameter for setting the low velocity threshold for gain scheduling controller.

int velocity_hi_l

Parameter for setting the high velocity threshold for gain scheduling controller.


doxygenstruct: Cannot find struct “MotionPolarity” in doxygen xml output

Motion Control Service

void motion_control_service(MotionControlConfig &motion_ctrl_config, interface TorqueControlInterface client i_torque_control, interface MotionControlInterface server i_motion_control[3], client interface UpdateBrake i_update_brake, client interface i2c_master_if i2c)

Service to perform position or velocity control.

You will need a Motor Control Stack running parallel to this Service, have a look at Torque Control Service for more information.

  • motion_ctrl_config – structure for motion control configuration
  • i_torque_control – communication class to the torque control service
  • i_motion_control[3] – array of MotionControlInterfaces to communicate with up to 3 clients
  • i_update_brake – class to update brake configuration in PWM service
  • i2c – communication class for logging of errors


Motion Control Interface

interface MotionControlInterface

Interface type to communicate with the Motion Control Service.

void disable()

disables the motion control service

void enable_position_ctrl(int mode)

enables the position controler

  • mode – position control mode
void enable_velocity_ctrl(void)

enables the velocity controller

void enable_torque_ctrl()

enables the torque controller

void set_torque(int target_torque)

sets the reference value of torque in torque control mode

  • target_torque – torque reference in mNm
MotionControlConfig get_motion_control_config()

Getter for current configuration used by the Service.

Returns:current service configuration.
void set_motion_control_config(MotionControlConfig in_config)

Setter for new configuration in the Service.

  • in_config – new service configuration
void set_motorcontrol_config(MotorcontrolConfig in_config)

Setter for new configuration in the Motorcontrol Service.

  • in_config – new service configuration.
MotorcontrolConfig get_motorcontrol_config()

Getter for current configuration used by the torque control service.

Returns:current service configuration
void set_brake_status(int brake_status)

Sets brake status to ON (no movement) or OFF (possible to move)

  • brake_status – release if 1, block if 0
void update_brake_configuration()

updates the new brake configuration in pwm service

MotorcontrolConfig start_offset_detection_procedure()

Enables the offset detection process.

Returns:torque control configuration
void reset_faults()

Send a reset fault command to the motion control.

void set_safe_torque_off_enabled()

Enables the safe-torque-off mode.

int get_position()

getter of actual position

int get_velocity()

getter of actual velocity

int open_phase_detection()

return the open phase error (0 = phase A, 1 = phase B, 2 = phase C, 4 = no error)

void pid_reset()
UpstreamControlData update_control_data(DownstreamControlData downstreamcontroldata)

responsible for data communication between torque controller and higher level controllers

  • downstreamcontroldata – structure including the commands for torque/velocity/position controller

structure of type UpstreamControlData structure including the actual parameters (measurements, ...) from torque controller to higher controlling levels

[[clears_notification]] int get_last_error(ErrItem_t &ErrItem)

Pop last error item from error buffer.

  • Error – item
[[notification]] slave void new_error(void)

Notification of new error.

Cogging Torque Feature


This software also includes a cogging torque compensation feature, which enables you to remove the magnetic disturbances between the motor shaft and the stator. Those disturbances are in the form of a periodic load applied to the rotor (the cogging torque). This load is positive when the magnets are reppelled by the stator, and negative when they are attracted to it. The disturbances are most present at low speed and can induce a jitter in the control of the motor.

The compensation can be done in two steps :

  • First the controller must perform a calibration process, in which the torque necessary to remove is measured. This part uses a position control of the motor at low speed (10 RPM). To work properly controller should be well tuned. During this process, the motor will run for ten rotations in each direction. Recorded table is used to improve the quality of control in the second run. Process is repeated one more time to record a final table.
  • Then, if the compensation is enabled, the controller will add an offset to the torque command given to the torque control service. Since the cogging torque is periodic, the offset is equal to the one measured at the same angle of the rotor.

How to use

1- The calibration process uses the position controller in profile mode. The first step is to enable the position controller with the interface enable_position_ctrl() and the profiler by setting the variable enable_profiler to 1 in the structure Motion Control Config.

2- Start the recording of the cogging torque of your motor by setting the variable enable_compensation_recording to 1 in the structure Motion Control Config.

3- At the end of the measurement process, the variable enable_compensation_recording is automatically set to 0. You can then enable/disable the compensation of the cogging torque by setting the variable enable_cogging_compensation in the structure Motion Control Config to 1 or 0.


Before the calibration process, make sure that the position PID parameters are set for a stable control at 10 RPM To tune the controller, feel free to use the Tuning application. (Bad tuning means the motor turns visibly step by step, stopping from time to time)

Once the cogging torque is calibrated for a motor, the calibration table is saved into the flash memory. It is possible to enable/disable the compensation without doing the calibration another time.

Before doing the calibration, be sure that the compensation is disabled, otherwise the measures will be altered.

Status of the recording procedure can be observed with a variable cogging_compensation_state in the structure Motion Control Config. If there’s no table recorded, variable equals 0. During the recording procedure, it equals 1. After the recording is done, it equals 2. After the recorded table is saved to the memory and procedure is completed, it equals 3. If the user wants to cancel the recording procedure, he is able to perform the quick stop.


void cogging_torque_compensation(client interface MotionControlInterface i_motion_control)
    DownstreamControlData downstream_control_data = {0};

    MotionControlConfig motion_ctrl_config = i_motion_control.get_motion_control_config();

    // 1) First step : Calibration //
    i_motion_control.enable_position_ctrl();                            //the calibration process uses the position controller

    motion_ctrl_config = i_motion_control.get_motion_control_config();
    motion_ctrl_config.enable_compensation_recording = 1;                               //set the flag to 'enable'
    motion_control_config.enable_cogging_compensation = 0;                      // cogging compensation must be disabled while doing recording procedure

    while (motion_ctrl_config.enable_compensation_recording)            //check regularly if the flag is set to '0', which indicates the end of the process
    {                                                                   //do not give other commands to the motor that would risk to influence the measurement
        motion_ctrl_config = i_motion_control.get_motion_control_config();

    // 2) Second step : Compensation //
    motion_ctrl_config = i_motion_control.get_motion_control_config();
    motion_ctrl_config.enable_cogging_compensation = 1;                 //use the previous calibration to compensate the cogging torque
    downstream_control_data.torque_cmd = 0;