4.10. Motion Control API (MCAPI)

MCAPI provides a set of high-level interfaces that can be used by an application to control the motor and obtain feedback information from it while requiring no underlying knowledge of MCAF and its inner-workings.

../_images/mcapi-block-diagram.svg

Figure 4.15 Block diagram showing MCAPI relative to MCAF and the application

4.10.1. Overview

MCAPI provides the following interfaces for an application to use:

  1. Public functions to interact with MCAF — defined in mcapi.h
  2. enum and struct typedefs to work with these MCAPI functions — defined in mcapi_types.h

All MCAPI functions are designed with following goals:

  • Minimize CPU execution time
  • Non-blocking implementation
  • Do not need to be called at any particular rate and do not require any timing reference
  • Do not require access to any of the device peripherals

4.10.2. API Description

All MCAPI functions that are defined in mcapi.h also include doc comments with relevant information. The table below shows a list of these functions and a brief summary of their description.

Top-level API feature API description
Start the motor Starts the specified motor. There will be no change if the motor is already running. If there is an active MCAF fault, this function will have no effect.
Stop the motor Stops the specified motor. There will be no change if the motor is already in fault, stopped or stopping states.
Set velocity reference

Uses the specified value to update velocity reference for the motor. Input value is a signed Q15 number that has the same scaling factor for velocity as used within MCAF. Sign of the input value will determine the direction of rotation.

Changes in velocity command when the motor is not in MCAPI_MOTOR_RUNNING state will be saved and will take effect only when the motor reaches this state.

Before this function is called for the first time after initialization, the set value of velocity reference is either zero, or equal to the minimum value of velocity reference that is valid for MCAF.

Note:

  • There are slew rate limits within MCAF that will limit step changes in reference from taking effect on the motor on an immediate basis.
  • Also, changes in the direction of rotation at runtime is not currently supported by MCAF. There is a band of velocity reference around zero that is considered as invalid input for MCAF.
  • Invalid values of velocity reference will be limited to the minimum velocity parameter that is defined in MCAF.
Get velocity reference

Returns a signed Q15 value of velocity reference for the motor. The return value will exactly match the set value set by “set velocity” function and have the same scaling factor for velocity as used within MCAF. Sign of the return value will determine the direction of rotation.

Before the “set velocity” function is called for the first time after initialization, the return value of velocity reference is either zero, or equal to the minimum value of velocity reference that is valid for MCAF.

Get motor velocity Returns a signed Q15 value of velocity for the motor as measured by an estimator in MCAF. The return value will have the same scaling factor for velocity as used within MCAF. Sign of the return value will determine the direction of rotation.
Get magnitude of current

Returns a signed Q15 value that represents the amplitude of current in the motor. The return value is scaled in terms of the same scaling factor for full-scale current as used in MCAF.

Since this value is derived from signals with low pass filtering, this is not an instantaneous value and will have some delay compared to the actual current in the motor. The filter time constant used in this case can be changed in the Customize page of motorBench® Development Suite.

Get fault status Returns a MCAPI_FAULT_FLAGS type bit-field with individual flags for each fault type.
Clear fault status Clears the specified fault flag or a given set of fault flags. This function does not implicitly start the motor after clearing all pending faults.
Get motor status Returns MCAPI_MOTOR_STATE type motor status.
Get current Iq

Returns a signed Q15 value that represents the q-axis current in the motor. This return value is scaled in terms of the same scaling factor for full-scale current as used in MCAF.

Since this value is derived from signals with low pass filtering, this is not an instantaneous value and will have some delay compared to the actual current in the motor. The filter time constant used in this case can be changed in the Customize page of motorBench® Development Suite.

Get float value of full-scale current Returns a floating point formatted full-scale value of current that is being used by MCAF.
Get float value of full-scale voltage Returns a floating point formatted full-scale value of voltage that is being used by MCAF.
Get float value of full-scale torque

Returns a floating point formatted full-scale value of electromagnetic torque for the given hardware system being used with MCAF.

Factors such as reluctance torque, iron saturation and changes in magnet flux due to temperature can impact the accuracy of this scaling factor. Hence, this is to be consumed by the application on a “for indication only” basis.

Get float value of full-scale velocity Returns a floating point formatted full-scale value of velocity that is being used by MCAF.
Pre-ADC ISR function

This is a place-holder implementation of the pre-ADC ISR function that will get called at the beginning of ADC ISR that is used by MCAF.

This interface is intended to support the need for functional safety features that check for periodicity of interrupts and execute some test cases.

Post-ADC ISR functions

This is a place-holder implementation of the post-ADC ISR function that will get called at the end of ADC ISR that is used by MCAF.

This interface is intended to support the need for functional safety features that check for periodicity of interrupts and execute some test cases.

Get DC link voltage Returns a signed Q15 value that represents DC link voltage in the system. This return value is scaled in terms of the same scaling factor for full-scale voltage as used in MCAF.
Get upper current saturation limit Returns a signed Q15 value that represents upper bound of the current saturation limit that is implemented in MCAF.
Get lower current saturation limit Returns a signed Q15 value that represents lower bound of the current saturation limit that is implemented in MCAF.
Get maximum value of velocity reference Gets the maximum command value of velocity reference that is currently supported in the given configuration of MCAF.
Get minimum value of velocity reference Gets the minimum command value of velocity reference that is currently supported in the given configuration of MCAF.

4.10.3. Usage Notes

This guidance is available for application developers accessing MCAF through MCAPI functions.

  1. Do not use any of the interfaces defined in mcapi_internal.h.
  2. Do not use the types MCAPI_MOTOR_DATA or MCAPI_FEEDBACK_SIGNALS or access their contents.
  3. After device startup, call MCAPI_Initialize() once before calling any MCAPI functions from the application.
  4. All MCAPI functions have certain latency limits. Latency for a setter function or command function is the time delay between the beginning of MCAPI function call and the instant the corresponding MCAF control variable is set (note that because of interaction between main thread and ISR, this change may not take effect until some time after MCAPI function call has completed). Latency for a getter function or feedback function is the time delay between the instant MCAF ISR samples a value from its internal state, and the instant MCAPI returns that value as a result of MCAPI function call.
  5. Despite this latency limitation, calling one of the get functions immediately after calling its counterpart set function will promptly return the set value. In this case, the return value from get function represents the request and not necessarily the state of the motor.
  6. Latency limits of MCAPI functions are not bounded in MCAF R6. However, latency for both getter and setter functions are typically within 2 ISR cycles.
  7. Calling one or more MCAPI functions in quick succession, for instance, less than 1 ms apart, can cause latency to increase. Similarly, calling one of the MCAPI functions within a while() loop without any delay will cause MCAPI to lose synchronization with MCAF.
  8. Since MCAPI interacts with sections of MCAF that execute from an interrupt, the application cannot assume the motor state to be unchanged in between successive calls to the MCAPI.

See Main Application for a description of an example application that is included with MCAF.

4.10.4. Implementation Notes

4.10.4.1. MCAPI Architecture

../_images/mcapi-arch-diagram.svg

Figure 4.16 Block diagram showing MCAPI implementation architecture

MCAPI uses a single data buffer approach in MCAPI motor data in order to reliably communicate in between the application, which is asynchronous to the ADC ISR, and MCAF routines that execute from the ADC ISR.

  • On the application-facing side of MCAPI: all MCAPI functions that are called by the application write to and read from MCAPI motor data.
  • On the MCAF-facing side of MCAPI: an API service routine that is called from the ADC ISR synchronizes MCAPI motor data with control variables within MCAF motor data.

4.10.4.1.1. MCAPI Data Access

MCAPI motor data, defined by the type MCAPI_MOTOR_DATA, is allocated within the MCAF motor structure of type MCAF_MOTOR_DATA.

MCAF ADC ISR accesses MCAPI motor data structure through MCAPI internal function, MCAF_ApiServiceIsr(), from a function call in isr.c.

The application should use one of the public MCAPI functions to indirectly access MCAPI motor data structure using the pointer &motor.apiData. This should be treated as an opaque data structure, and the application should not access its contents directly.

Listing 4.6
MCAF_MOTOR_DATA motor;

int main(void)
{
    MCAPI_Initialize(&motor.apiData);

    ...

    MCAPI_MOTOR_STATE motorState = MCAPI_OperatingStatusGet(&motor.apiData);
    switch (motorState)
    {
        case MCAPI_MOTOR_STOPPED:
            # do something

        ...

    }

    ...

    return 1;
}

4.10.4.1.2. Handling Concurrency

The application may execute at some arbitrary rate, with calls to MCAPI that are asynchronous to the ADC ISR. Shared MCAPI motor data that is used in both MCAPI function calls and the ADC ISR must be protected against unsynchronized concurrent memory access, known as a data race.

For example, the following sequence of events could occur within MCAPI function MCAPI_FaultStatusClear(), which sets a series of bit flags in motor.apiData.faultClearFlags to request clearing faults:

  1. The application calls MCAPI_FaultStatusClear(&motor.apiData, 2)
  2. MCAPI_FaultStatusClear() reads a preexisting value of 8 (bit 3 is set) from faultClearFlags in MCAPI motor data
  3. MCAPI_FaultStatusClear() is interrupted by the ADC ISR and MCAF_ApiServiceIsr() clears bit 3, writing faultClearFlags to 0
  4. MCAPI_FaultStatusClear() calculates a value of 10 from 8 OR 2
  5. MCAPI_FaultStatusClear() writes the value 10 to faultClearFlags

In this case, the write made by the ADC ISR was lost.

To prevent data races, MCAPI functions use the apiBusy flag to claim ownership of MCAPI motor data structure while they are executing a critical section of code. The API service routine is designed to skip execution when it sees that the apiBusy flag is set.

4.10.4.2. MCAPI errata

  • MCAPI will not individually clear MCAPI_FAULT_FLAG_OVERCURRENT fault or MCAPI_FAULT_FLAG_MOTOR_DRIVE fault if there are other active faults. (DB_MC-3012; Applicability: MCAF R6)

    For example, if there are three active faults at a given instance of time:

    • MCAPI_FAULT_FLAG_OVERCURRENT fault
    • MCAPI_FAULT_FLAG_MOTOR_DRIVE fault
    • MCAPI_FAULT_FLAG_OVERVOLTAGE fault

    Then, in this case the following code snippet will not clear MCAPI_FAULT_FLAG_OVERCURRENT fault or MCAPI_FAULT_FLAG_MOTOR_DRIVE fault.

    Listing 4.7
    void APP_ApplicationStep(volatile MCAPI_MOTOR_DATA *api)
    {
        ...
        MCAPI_FaultStatusClear(api, MCAPI_FAULT_FLAG_OVERCURRENT);
        ...
        MCAPI_FaultStatusClear(api, MCAPI_FAULT_FLAG_MOTOR_DRIVE);
        ...
    }
    

    Application can workaround this issue by clearing all faults in one attempt as shown in the code snippet below.

    Listing 4.8
    void APP_ApplicationStep(volatile MCAPI_MOTOR_DATA *api)
    {
      ...
      uint16_t faultFlags = MCAPI_FaultStatusGet(api);
      MCAPI_FaultStatusClear(api, faultFlags);
      ...
    }
    
  • MCAPI may drop fault events from MCAF under certain corner-cases. (DB_MC-2978; Applicability: MCAF R6)

    This issue may occur if these two events occur in the same ADC interrupt:

    1. MCAPI clears a particular fault condition.
    2. MCAF raises another instance of the same fault condition.

    In the existing implementation of MCAPI, the application does not have a workaround for this issue.

4.10.4.3. Modules

Module Files Description Comments
parameters/mcapi_params
parameters/mcapi_params.h
mcapi
mcapi.c
mcapi.h
mcapi_types.h
MCAPI source
mcapi_internal
mcapi_internal.h
MCAPI routines internal to MCAF