This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Instapin_motion problem with a 2-pole pair motor

Other Parts Discussed in Thread: DRV8301, MOTORWARE, BOOSTXL-DRV8301, DAC8562, TMS320F2812, DRV8302

Maxon EC-2 (2 pole pairs) won't move in lab12a,b with USER_MOTOR_NUM_POLE_PAIRS = 2 ( the correct value since the motor is a 4 pole)

There was an error in USER_IQ_FULL_SCALE_FREQ_Hz from the beginning that prevented system enable, corrected now.

The curious thing is that if I set the motor pole pairs to  4 the motor moves but with wrong speed.

Lab 13x don't work either with the correct pole pairs entry.

If the encoder was wrong connected the motor should not run att all with the worng pole pairs setting or ?

Everything works fine with the 4-pole pairs Teknic motor.

Any ideas ?

  • Ingemar,

    What value are you setting for USER_MOTOR_ENCODER_LINES?  This value should be the pre-quadrature resolution of the encoder.   

    Can you attach your user.h file?

  • This is an extract from user.h

    USER_PWM_FREQ_kHz (45), this might be too low ? 80kHz ?

    USER_MOTOR_FLUX_EST_FREQ_Hz (20 ,) this might also be to low ? 100 Hz ?

    The RMK3B (RLS AM8192B) decoder is set to 4096 (after quad) which should correspond to 1024 lines

    These are the entries for the Maxon EC-4 motor

    #elif (USER_MOTOR == Maxon_EC4_pole_22)

    #define USER_MOTOR_TYPE                 MOTOR_Type_Pm

    //#define USER_MOTOR_NUM_POLE_PAIRS       (4)     //Works, but gives doubled rpm

    #define USER_MOTOR_NUM_POLE_PAIRS       (2)

    #define USER_MOTOR_Rr                   (NULL)

    #define USER_MOTOR_Rs                   (0.2881)

    #define USER_MOTOR_Ls_d                 (0.0000529)

    #define USER_MOTOR_Ls_q                 (0.0000529)

    #define USER_MOTOR_RATED_FLUX           (0.027)

    #define USER_MOTOR_MAGNETIZING_CURRENT  (NULL)

    #define USER_MOTOR_RES_EST_CURRENT      (1.0)

    #define USER_MOTOR_IND_EST_CURRENT      (-1.0)

    #define USER_MOTOR_MAX_CURRENT          (3.0)

    #define USER_MOTOR_FLUX_EST_FREQ_Hz     (20.0)

    //#define USER_MOTOR_ENCODER_LINES        (2048.0)            //Doubled when motor run as four polepairs

    #define USER_MOTOR_ENCODER_LINES        (1024.0)

    #define USER_MOTOR_MAX_SPEED_KRPM       (6.0) //Gives 12krpm due to 2poles

    #define USER_SYSTEM_INERTIA             (0.03)

    #define USER_SYSTEM_FRICTION            (0.042)

  • It sounds like there is something that isn't configured quite correctly in your system. In doing the encoder math for the two cases they are equivalent, so I'm not sure why doubling the pole pairs & encoder lines allows the system to work. The produced electrical angles should be fine.

    Let's run this test in Lab 12a.

    1. Add "st_obj.vel.conv.Pos_erev" and "st_obj.vel.conv.Pos_mrev" into the watch window. These are both IQ24 variables.
    2. Set "gMotorVars.enableSys" to 1, but do not set "gMotorVars.Run_Identify" to 1
    3. Manually rotate the motor one revolution anti-clockwise
    4. Look at the value in "st_obj.vel.conv.Pos_mrev" it should be 1.0 and "st_obj.vel.conv.Pos_erev" should have gone from 0 to 1 equal to the number of pole pairs, which in your case should be 2.
  • #define USER_MOTOR_FLUX_EST_FREQ_Hz (20.0)
    for motor ID this is much too low. This looks to be a high speed motor so you should use proj_lab02c to run the ID. Try using
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (80.0)

    but this setting has no effect on run-time, just ID.

    It is strange that changing the pole pairs from 2 to 4 gives proper operation....(besides the RPM calculation being doubled).
  • We have done more tests now. My collegue writes this:

    I copied the latest user.h from instaspin_motion to instaspin_foc and tested lab2c several times. The motor (Maxon EC 4-pole 22, 24V) spins and the values were measured. Rs and flux were fairly the same as before (0.28 resp. 0.027) and stable between measurements. Ls varies between about 1.8E-5 and 2.3E-5 between measurements. Both Rs and Ls are about half of what is stated in the datasheet which says Rs=0.527ohm and Ls=5E-5H, which we assumed was a difference in definitions (phase to phase, i.e. two coils in the datasheet). I did not notice any big difference when I changed the values in user.h according to Ingemars recommendations below. I have updated user.h with Ls = 0.000025.

    When I try to run lab12a, the motor first starts to oscillate and after a few seconds starts to spin about 13000rpm. I thought the rpm may be limited by the USER_IQ_FULL_SCALE_FREQ_Hz which was set fairly high (1200) so I tried to reduce that to 400 just to check but it did’t make any difference.

    The encoder we are using is a RLS AM4096, see link below to device and datasheet. It is configured to 4096 resolution but from what we understand, this means we should set USER_MOTOR_ENCODER_LINES = 1024. This has been verified by measuring the period of the QEPA/B signals to appr. 56 us @1000rpm which is about the same as the Teknic_M2310PLN04K motor which has 1000 lines. The InstaSPIN_MOTION webapp was used during these tests (i.e. FAST estimator used). I have also checked that the phase of the A/B signals is the same as the Teknic.

    We have also aligned the QEPI signal from the encoder (which is external to the motor) so that it is placed the same way as in the Teknic motor when compared to the built in Hall sensors (centered in the high period of the B sensor) if this makes any difference. I don’t see how it could since the motor doesn’t spin a full turn which it may need if the QEPI were to be used to align the rotor with the encoder signals.

    www.rls.si/am4096-12-bit-rotary-magnetic-encoder-chip

    www.rls.si/.../download;file=custom%2Fupload%2FFile-1406277392.pdf

    I tried a few combinations of encoder settings with lab13b just to test and got the following result:
    USER_MOTOR_ENCODER_LINES = 1024: Starts to oscillate and after a few seconds starts to spin @13500rpm.
    USER_MOTOR_ENCODER_LINES = 1024 with encoder reconfigured for CCW operation: Motor “jumps around” in sporadic ways.
    USER_MOTOR_ENCODER_LINES = 4096: Holds position as it should, but does not spin when it is supposed to. gMotorVars.SpinTAC.PosMoveErrorID = 2


    In lab12a, the motor starts to run at 13000rpm and never stops, even though gMotorVars.SpinTAC.VelIdStatus = ST_VEL_ID_IDLE and gMotorVars.SpinTAC.VelIdErrorID = 0.

    In lab12b, the motor now runs as expected (!) when configured for as a two pole pair motor in user.h. I use an inertia value measured with the InstaSPIN_MOTION webapp (0.01). However, if I try to run at high speed, it does not go more than 13500rpm (and this does not seem to be limited by USER_IQ_FULL_SCALE_FREQ_Hz).

    Lab13b has previously been working as expected if we configure the motor as four pole pairs and the encoder as 2048, with the exception that the motor rotates twice the expected number of turns. I noticed that if USER_PWM_FREQ_KHz was set to 80, the motor started to oscillate for a few seconds when gMotorVars.Flag_Run_Identify was set. After a while, it stopped and the lab worked as usual. With the default value of 45, there was no oscillation.

    When I try to run lab13b with the motor and encoder configured for two poles, I get gMotorVars.SpinTAC.PosMoveErrorID = 14 as soon as I set gMotorVars.Flag_enableSys = 1. If I set gMotorVars.Flag_Run_Identify = 1, the motor tries to hold the position for a few seconds after which it stops holding and if I spin it slightly manually, it starts running at 13500rpm in whatever direction I started it manually.

    For your information the Maxon motor case is not grounded to the DRV830X. This might be a problem.
    The encoder wires are not screened.
    The encoder wires and the motor phase wires are about 1m each.
    The problems seems to appear when the encoder is used instead of FAST.

    Ingemar Dahlqvist
  • Ingemar,

    Ingemar Dahlqvist said:
    USER_MOTOR_ENCODER_LINES = 1024 with encoder reconfigured for CCW operation: Motor “jumps around” in sporadic ways.

    I think that the number of encoder lines configured as 1024 with CCW operation sounds like it could be close to being controlled.  What Bandwidth are you using in that configuration?

    Ingemar Dahlqvist said:
    USER_MOTOR_ENCODER_LINES = 4096: Holds position as it should, but does not spin when it is supposed to. gMotorVars.SpinTAC.PosMoveErrorID = 2

    When you have the number of lines configured as 4096, was it holding position where if you disturbed it, the motor would return to the setpoint or was the motor shaft locked?

    gMotorVars.SpinTAC.PosMoveErrorID = 2 indicates that the system maximum velocity is out of range.  It needs to be configured to be between 0 and 1.  This means that your USER_IQ_FULL_SCALE_FREQ_Hz needs to be increased so that USER_MOTOR_MAX_SPEED_KRPM < (USER_IQ_FULL_SCALE_FREQ_Hz * 60) / USER_MOTOR_NUM_POLE_PAIRS

    Ingemar Dahlqvist said:
    In lab12b, the motor now runs as expected (!) when configured for as a two pole pair motor in user.h. I use an inertia value measured with the InstaSPIN_MOTION webapp (0.01). However, if I try to run at high speed, it does not go more than 13500rpm (and this does not seem to be limited by USER_IQ_FULL_SCALE_FREQ_Hz).

    The other limitation could be from the encoder module, it might not be capable of reading the signal that fast.

    Ingemar Dahlqvist said:
    I noticed that if USER_PWM_FREQ_KHz was set to 80, the motor started to oscillate for a few seconds when gMotorVars.Flag_Run_Identify was set.

    That PWM frequency is too high, I think you are running out of processor.

    Ingemar Dahlqvist said:
    I get gMotorVars.SpinTAC.PosMoveErrorID = 14 as soon as I set gMotorVars.Flag_enableSys = 1.

    gMotorVars.SpinTAC.PosMoveErrorID = 14 indicates that the unit conversion is out of range [0.008, 1.0].  You need to ensure that USER_MOTOR_NUM_POLE_PAIRS / USER_IQ_FULL_SCALE_FREQ_Hz is within that range.

  • Hi,

    Now we have lab13b working with the settings in the following user.h file

    [
    #ifndef _USER_H_
    #define _USER_H_
    /* --COPYRIGHT--,BSD
    * Copyright (c) 2012, Texas Instruments Incorporated
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    *
    * * Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    *
    * * Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    *
    * * Neither the name of Texas Instruments Incorporated nor the names of
    * its contributors may be used to endorse or promote products derived
    * from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    * --/COPYRIGHT--*/

    //! \file solutions/instaspin_motion/boards/drv8301kit_revD/f28x/f2806xM/src/user.h
    //! \brief Contains the public interface for user initialization data for the CTRL, HAL, and EST modules
    //!
    //! (C) Copyright 2012, Texas Instruments, Inc.


    // **************************************************************************
    // the includes

    // modules
    #include "sw/modules/types/src/types.h"
    #include "sw/modules/motor/src/motor.h"
    #include "sw/modules/est/src/32b/est.h"
    #include "sw/modules/est/src/est_states.h"
    #include "sw/modules/est/src/est_Flux_states.h"
    #include "sw/modules/est/src/est_Ls_states.h"
    #include "sw/modules/est/src/est_Rs_states.h"
    #include "sw/modules/ctrl/src/32b/ctrl_obj.h"


    // platforms
    #include "sw/modules/fast/src/32b/userParams.h"

    //!
    //!
    //! \defgroup USER USER
    //!
    //@{


    #ifdef __cplusplus
    extern "C" {
    #endif

    // **************************************************************************
    // the defines


    //! \brief CURRENTS AND VOLTAGES
    // **************************************************************************
    //! \brief Defines the full scale frequency for IQ variable, Hz
    //! \brief All frequencies are converted into (pu) based on the ratio to this value
    //! \brief this value MUST be larger than the maximum speed that you are expecting from the motor
    #ifndef QEP
    #define USER_IQ_FULL_SCALE_FREQ_Hz (800.0) // 800 Example with buffer for 8-pole 6 KRPM motor to be run to 10 KRPM with field weakening; Hz =(RPM * Poles) / 120
    #else
    //#define USER_IQ_FULL_SCALE_FREQ_Hz (USER_MOTOR_NUM_POLE_PAIRS/0.008) // (4/0.008) = 500 Example with buffer for 8-pole 6 KRPM motor to be run to 6 KRPM; Hz = (RPM * Poles) / 120
    //#define USER_IQ_FULL_SCALE_FREQ_Hz (800.0) //Test w. Maxon 2 pole pair motor
    #define USER_IQ_FULL_SCALE_FREQ_Hz (400.0) //Test w. Maxon 2 pole pair motor
    #endif

    //! \brief Defines full scale value for the IQ30 variable of Voltage inside the system
    //! \brief All voltages are converted into (pu) based on the ratio to this value
    //! \brief WARNING: this value MUST meet the following condition: USER_IQ_FULL_SCALE_VOLTAGE_V > 0.5 * USER_MOTOR_MAX_CURRENT * USER_MOTOR_Ls_d * USER_VOLTAGE_FILTER_POLE_rps,
    //! \brief WARNING: otherwise the value can saturate and roll-over, causing an inaccurate value
    //! \brief WARNING: this value is OFTEN greater than the maximum measured ADC value, especially with high Bemf motors operating at higher than rated speeds
    //! \brief WARNING: if you know the value of your Bemf constant, and you know you are operating at a multiple speed due to field weakening, be sure to set this value higher than the expected Bemf voltage
    //! \brief It is recommended to start with a value ~3x greater than the USER_ADC_FULL_SCALE_VOLTAGE_V and increase to 4-5x if scenarios where a Bemf calculation may exceed these limits
    //! \brief This value is also used to calculate the minimum flux value: USER_IQ_FULL_SCALE_VOLTAGE_V/USER_EST_FREQ_Hz/0.7
    #define USER_IQ_FULL_SCALE_VOLTAGE_V (24.0) // 24.0 Example for drv8301_revd typical usage and the Anaheim motor
    //#define USER_IQ_FULL_SCALE_VOLTAGE_V (64.0) // 24.0 Example for drv8301_revd typical usage and the Anaheim motor

    //! \brief Defines the maximum voltage at the input to the AD converter
    //! \brief The value that will be represented by the maximum ADC input (3.3V) and conversion (0FFFh)
    //! \brief Hardware dependent, this should be based on the voltage sensing and scaling to the ADC input
    #define USER_ADC_FULL_SCALE_VOLTAGE_V (66.32) // 66.32 drv8301_revd voltage scaling

    //! \brief Defines the voltage scale factor for the system
    //! \brief Compile time calculation for scale factor (ratio) used throughout the system
    #define USER_VOLTAGE_SF ((float_t)((USER_ADC_FULL_SCALE_VOLTAGE_V)/(USER_IQ_FULL_SCALE_VOLTAGE_V)))

    //! \brief Defines the full scale current for the IQ variables, A
    //! \brief All currents are converted into (pu) based on the ratio to this value
    //! \brief WARNING: this value MUST be larger than the maximum current readings that you are expecting from the motor or the reading will roll over to 0, creating a control issue
    #define USER_IQ_FULL_SCALE_CURRENT_A (41.25) // 41.25 Example for drv8301_revd typical usage

    //! \brief Defines the maximum current at the AD converter
    //! \brief The value that will be represented by the maximum ADC input (3.3V) and conversion (0FFFh)
    //! \brief Hardware dependent, this should be based on the current sensing and scaling to the ADC input
    #define USER_ADC_FULL_SCALE_CURRENT_A (82.5) // 82.5 drv8301_revd current scaling

    //! \brief Defines the current scale factor for the system
    //! \brief Compile time calculation for scale factor (ratio) used throughout the system
    #define USER_CURRENT_SF ((float_t)((USER_ADC_FULL_SCALE_CURRENT_A)/(USER_IQ_FULL_SCALE_CURRENT_A)))

    //! \brief Defines the number of current sensors used
    //! \brief Defined by the hardware capability present
    //! \brief May be (2) or (3)
    #define USER_NUM_CURRENT_SENSORS (3) // 3 Preferred setting for best performance across full speed range, allows for 100% duty cycle

    //! \brief Defines the number of voltage (phase) sensors
    //! \brief Must be (3)
    #define USER_NUM_VOLTAGE_SENSORS (3) // 3 Required

    //! \brief ADC current offsets for A, B, and C phases
    //! \brief One-time hardware dependent, though the calibration can be done at run-time as well
    //! \brief After initial board calibration these values should be updated for your specific hardware so they are available after compile in the binary to be loaded to the controller
    #define I_A_offset (1.035423934)
    #define I_B_offset (1.027672052)
    #define I_C_offset (1.025883377)

    //! \brief ADC voltage offsets for A, B, and C phases
    //! \brief One-time hardware dependent, though the calibration can be done at run-time as well
    //! \brief After initial board calibration these values should be updated for your specific hardware so they are available after compile in the binary to be loaded to the controller
    #define V_A_offset (0.1651780009)
    #define V_B_offset (0.1657723784)
    #define V_C_offset (0.1657739282)


    //! \brief CLOCKS & TIMERS
    // **************************************************************************
    //! \brief Defines the system clock frequency, MHz
    #define USER_SYSTEM_FREQ_MHz (90.0)

    //! \brief Defines the Pulse Width Modulation (PWM) frequency, kHz
    //! \brief PWM frequency can be set directly here up to 30 KHz safely (60 KHz MAX in some cases)
    //! \brief For higher PWM frequencies (60 KHz+ typical for low inductance, high current ripple motors) it is recommended to use the ePWM hardware
    //! \brief and adjustable ADC SOC to decimate the ADC conversion done interrupt to the control system, or to use the software Que example.
    //! \brief Otherwise you risk missing interrupts and disrupting the timing of the control state machine
    #define USER_PWM_FREQ_kHz (45.0) //30.0 Example, 8.0 - 30.0 KHz typical; 45-80 KHz may be required for very low inductance, high speed motors
    //#define USER_PWM_FREQ_kHz (60.0) //Test w. Maxon 2 pp motor


    //! \brief Defines the maximum Voltage vector (Vs) magnitude allowed. This value sets the maximum magnitude for the output of the
    //! \brief Id and Iq PI current controllers. The Id and Iq current controller outputs are Vd and Vq.
    //! \brief The relationship between Vs, Vd, and Vq is: Vs = sqrt(Vd^2 + Vq^2). In this FOC controller, the
    //! \brief Vd value is set equal to USER_MAX_VS_MAG*USER_VD_MAG_FACTOR. Vq = sqrt(USER_MAX_VS_MAG^2 - Vd^2).
    //! \brief Set USER_MAX_VS_MAG = 1.0 for a pure sinewave with a peak at SQRT(3)/2 = 86.6% duty cycle. No current reconstruction is needed for this scenario.
    //! \brief Set USER_MAX_VS_MAG = 2/SQRT(3) = 1.1547 for a pure sinewave with a peak at 100% duty cycle. Current reconstruction will be needed for this scenario (Lab10a-x).
    //! \brief Set USER_MAX_VS_MAG = 4/3 = 1.3333 to create a trapezoidal voltage waveform. Current reconstruction will be needed for this scenario (Lab10a-x).
    //! \brief For space vector over-modulation, see lab 10 for details on system requirements that will allow the SVM generator to go all the way to trapezoidal.
    #define USER_MAX_VS_MAG_PU (1.0) // Set to 1.0 if a current reconstruction technique is not used. Look at the module svgen_current in lab10a-x for more info.


    //! \brief Defines the Pulse Width Modulation (PWM) period, usec
    //! \brief Compile time calculation
    #define USER_PWM_PERIOD_usec (1000.0/USER_PWM_FREQ_kHz)

    //! \brief Defines the Interrupt Service Routine (ISR) frequency, Hz
    //!
    #define USER_ISR_FREQ_Hz ((float_t)USER_PWM_FREQ_kHz * 1000.0 / (float_t)USER_NUM_PWM_TICKS_PER_ISR_TICK)

    //! \brief Defines the Interrupt Service Routine (ISR) period, usec
    //!
    #define USER_ISR_PERIOD_usec (USER_PWM_PERIOD_usec * (float_t)USER_NUM_PWM_TICKS_PER_ISR_TICK)


    //! \brief DECIMATION
    // **************************************************************************
    //! \brief Defines the number of pwm clock ticks per isr clock tick
    //! Note: Valid values are 1, 2 or 3 only
    #define USER_NUM_PWM_TICKS_PER_ISR_TICK (3)

    //! \brief Defines the number of isr ticks (hardware) per controller clock tick (software)
    //! \brief Controller clock tick (CTRL) is the main clock used for all timing in the software
    //! \brief Typically the PWM Frequency triggers (can be decimated by the ePWM hardware for less overhead) an ADC SOC
    //! \brief ADC SOC triggers an ADC Conversion Done
    //! \brief ADC Conversion Done triggers ISR
    //! \brief This relates the hardware ISR rate to the software controller rate
    //! \brief Typcially want to consider some form of decimation (ePWM hardware, CURRENT or EST) over 16KHz ISR to insure interrupt completes and leaves time for background tasks
    #define USER_NUM_ISR_TICKS_PER_CTRL_TICK (1) // 2 Example, controller clock rate (CTRL) runs at PWM / 2; ex 30 KHz PWM, 15 KHz control

    //! \brief Defines the number of controller clock ticks per current controller clock tick
    //! \brief Relationship of controller clock rate to current controller (FOC) rate
    #define USER_NUM_CTRL_TICKS_PER_CURRENT_TICK (1) // 1 Typical, Forward FOC current controller (Iq/Id/IPARK/SVPWM) runs at same rate as CTRL.

    //! \brief Defines the number of controller clock ticks per estimator clock tick
    //! \brief Relationship of controller clock rate to estimator (FAST) rate
    //! \brief Depends on needed dynamic performance, FAST provides very good results as low as 1 KHz while more dynamic or high speed applications may require up to 15 KHz
    #define USER_NUM_CTRL_TICKS_PER_EST_TICK (1) // 1 Typical, FAST estimator runs at same rate as CTRL;

    //! \brief Defines the number of controller clock ticks per speed controller clock tick
    //! \brief Relationship of controller clock rate to speed loop rate
    #define USER_NUM_CTRL_TICKS_PER_SPEED_TICK (15) // 15 Typical to match PWM, ex: 15KHz PWM, controller, and current loop, 1KHz speed loop

    //! \brief Defines the number of controller clock ticks per trajectory clock tick
    //! \brief Relationship of controller clock rate to trajectory loop rate
    //! \brief Typically the same as the speed rate
    #define USER_NUM_CTRL_TICKS_PER_TRAJ_TICK (15) // 15 Typical to match PWM, ex: 10KHz controller & current loop, 1KHz speed loop, 1 KHz Trajectory

    //! \brief Defines the controller frequency, Hz
    //! \brief Compile time calculation
    #define USER_CTRL_FREQ_Hz (uint_least32_t)(USER_ISR_FREQ_Hz/USER_NUM_ISR_TICKS_PER_CTRL_TICK)

    //! \brief Defines the estimator frequency, Hz
    //! \brief Compile time calculation
    #define USER_EST_FREQ_Hz (uint_least32_t)(USER_CTRL_FREQ_Hz/USER_NUM_CTRL_TICKS_PER_EST_TICK)

    //! \brief Defines the trajectory frequency, Hz
    //! \brief Compile time calculation
    #define USER_TRAJ_FREQ_Hz (uint_least32_t)(USER_CTRL_FREQ_Hz/USER_NUM_CTRL_TICKS_PER_TRAJ_TICK)

    //! \brief Defines the controller execution period, usec
    //! \brief Compile time calculation
    #define USER_CTRL_PERIOD_usec (USER_ISR_PERIOD_usec * USER_NUM_ISR_TICKS_PER_CTRL_TICK)

    //! \brief Defines the controller execution period, sec
    //! \brief Compile time calculation
    #define USER_CTRL_PERIOD_sec ((float_t)USER_CTRL_PERIOD_usec/(float_t)1000000.0)


    //! \brief LIMITS
    // **************************************************************************
    //! \brief Defines the maximum negative current to be applied in Id reference
    //! \brief Used in field weakening only, this is a safety setting (e.g. to protect against demagnetization)
    //! \brief User must also be aware that overall current magnitude [sqrt(Id^2 + Iq^2)] should be kept below any machine design specifications
    #define USER_MAX_NEGATIVE_ID_REF_CURRENT_A (-0.5 * USER_MOTOR_MAX_CURRENT) // -0.5 * USER_MOTOR_MAX_CURRENT Example, adjust to meet safety needs of your motor

    //! \brief Defines the low speed limit for the flux integrator, pu
    //! \brief This is the speed range (CW/CCW) at which the ForceAngle object is active, but only if Enabled
    //! \brief Outside of this speed - or if Disabled - the ForcAngle will NEVER be active and the angle is provided by FAST only
    #define USER_ZEROSPEEDLIMIT (1.0 / USER_IQ_FULL_SCALE_FREQ_Hz) // 0.002 pu, 1-5 Hz typical; Hz = USER_ZEROSPEEDLIMIT * USER_IQ_FULL_SCALE_FREQ_Hz

    //! \brief Defines the force angle frequency, Hz
    //! \brief Frequency of stator vector rotation used by the ForceAngle object
    //! \brief Can be positive or negative
    #define USER_FORCE_ANGLE_FREQ_Hz (USER_ZEROSPEEDLIMIT * USER_IQ_FULL_SCALE_FREQ_Hz) // 1.0 Typical force angle start-up speed

    //! \brief Defines the maximum current slope for Id trajectory during PowerWarp
    //! \brief For Induction motors only, controls how fast Id input can change under PowerWarp control
    #define USER_MAX_CURRENT_SLOPE_POWERWARP (0.3*USER_MOTOR_RES_EST_CURRENT/USER_IQ_FULL_SCALE_CURRENT_A/USER_TRAJ_FREQ_Hz) // 0.3*RES_EST_CURRENT / IQ_FULL_SCALE_CURRENT / TRAJ_FREQ Typical to produce 1-sec rampup/down

    //! \brief Defines the starting maximum acceleration AND deceleration for the speed profiles, Hz/s
    //! \brief Updated in run-time through user functions
    //! \brief Inverter, motor, inertia, and load will limit actual acceleration capability
    #define USER_MAX_ACCEL_Hzps (20.0) // 20.0 Default

    //! \brief Defines maximum acceleration for the estimation speed profiles, Hz/s
    //! \brief Only used during Motor ID (commission)
    #define USER_MAX_ACCEL_EST_Hzps (5.0) // 5.0 Default, don't change

    //! \brief Defines the maximum current slope for Id trajectory during estimation
    #define USER_MAX_CURRENT_SLOPE (USER_MOTOR_RES_EST_CURRENT/USER_IQ_FULL_SCALE_CURRENT_A/USER_TRAJ_FREQ_Hz) // USER_MOTOR_RES_EST_CURRENT/USER_IQ_FULL_SCALE_CURRENT_A/USER_TRAJ_FREQ_Hz Default, don't change

    //! \brief Defines the fraction of IdRated to use during rated flux estimation
    //!
    #define USER_IDRATED_FRACTION_FOR_RATED_FLUX (1.0) // 1.0 Default, don't change

    //! \brief Defines the fraction of IdRated to use during inductance estimation
    //!
    #define USER_IDRATED_FRACTION_FOR_L_IDENT (1.0) // 1.0 Default, don't change

    //! \brief Defines the IdRated delta to use during estimation
    //!
    #define USER_IDRATED_DELTA (0.00002)

    //! \brief Defines the fraction of SpeedMax to use during inductance estimation
    //!
    #define USER_SPEEDMAX_FRACTION_FOR_L_IDENT (1.0) // 1.0 Default, don't change

    //! \brief Defines flux fraction to use during inductance identification
    //!
    #define USER_FLUX_FRACTION (1.0) // 1.0 Default, don't change

    //! \brief Defines the PowerWarp gain for computing Id reference
    //! \brief Induction motors only
    #define USER_POWERWARP_GAIN (1.0) // 1.0 Default, don't change

    //! \brief Defines the R/L estimation frequency, Hz
    //! \brief User higher values for low inductance motors and lower values for higher inductance
    //! \brief motors. The values can range from 100 to 300 Hz.
    #define USER_R_OVER_L_EST_FREQ_Hz (300) // 300 Default


    //! \brief POLES
    // **************************************************************************
    //! \brief Defines the analog voltage filter pole location, Hz
    //! \brief Must match the hardware filter for Vph
    #define USER_VOLTAGE_FILTER_POLE_Hz (335.648) // 335.648, value for drv8301_revd hardware

    //! \brief Defines the analog voltage filter pole location, rad/s
    //! \brief Compile time calculation from Hz to rad/s
    #define USER_VOLTAGE_FILTER_POLE_rps (2.0 * MATH_PI * USER_VOLTAGE_FILTER_POLE_Hz)

    //! \brief Defines the software pole location for the voltage and current offset estimation, rad/s
    //! \brief Should not be changed from default of (20.0)
    #define USER_OFFSET_POLE_rps (20.0) // 20.0 Default, do not change

    //! \brief Defines the software pole location for the flux estimation, rad/s
    //! \brief Should not be changed from default of (100.0)
    #define USER_FLUX_POLE_rps (100.0) // 100.0 Default, do not change

    //! \brief Defines the software pole location for the direction filter, rad/s
    #define USER_DIRECTION_POLE_rps (6.0) // 6.0 Default, do not change

    //! \brief Defines the software pole location for the speed control filter, rad/s
    #define USER_SPEED_POLE_rps (100.0) // 100.0 Default, do not change

    //! \brief Defines the software pole location for the DC bus filter, rad/s
    #define USER_DCBUS_POLE_rps (100.0) // 100.0 Default, do not change

    //! \brief Defines the convergence factor for the estimator
    //! \brief Do not change from default for FAST
    #define USER_EST_KAPPAQ (1.5) // 1.5 Default, do not change

    // **************************************************************************
    // end the defines


    //! \brief USER MOTOR & ID SETTINGS
    // **************************************************************************

    //! \brief Defines the default bandwidth for SpinTAC Control
    //! \brief This value should be determined by putting SpinTAC Control through a tuning process
    #define USER_SYSTEM_BANDWIDTH_SCALE (5.0)

    //! \brief Define each motor with a unique name and ID number
    // BLDC & SMPM motors
    #define Estun_EMJ_04APB22 101
    #define Anaheim_BLY172S 102
    #define Teknic_M2310PLN04K 104
    #define Maxon_EC90 105
    #define Trinamic_QBL4208_41_04_006 106
    #define Maxon_EC4_pole_22 107
    #define Maxon_EC4_pole_22_4p 108
    #define Maxon_EC45_flat 109

    //! \brief Uncomment the motor which should be included at compile
    //! \brief These motor ID settings and motor parameters are then available to be used by the control system
    //! \brief Once your ideal settings and parameters are identified update the motor section here so it is available in the binary code
    //#define USER_MOTOR Estun_EMJ_04APB22
    //#define USER_MOTOR Anaheim_BLY172S
    //#define USER_MOTOR Teknic_M2310PLN04K
    //#define USER_MOTOR Belt_Drive_Washer_IPM
    //#define USER_MOTOR Marathon_5K33GN2A
    //#define USER_MOTOR Maxon_EC90
    //#define USER_MOTOR Maxon_EC45_flat
    #define USER_MOTOR Maxon_EC4_pole_22


    #if (USER_MOTOR == Estun_EMJ_04APB22) // Name must match the motor #define
    #define USER_MOTOR_TYPE MOTOR_Type_Pm // Motor_Type_Pm (All Synchronous: BLDC, PMSM, SMPM, IPM) or Motor_Type_Induction (Asynchronous ACI)
    #define USER_MOTOR_NUM_POLE_PAIRS (4) // PAIRS, not total poles. Used to calculate user RPM from rotor Hz only
    #define USER_MOTOR_Rr (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_Rs (0.2881201) // Identified phase to neutral resistance in a Y equivalent circuit (Ohms, float)
    #define USER_MOTOR_Ls_d (0.0000529231) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_Ls_q (0.0000529231) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_RATED_FLUX (0.0271403) // Identified TOTAL flux linkage between the rotor and the stator (V/Hz)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_RES_EST_CURRENT (1.0) // During Motor ID, maximum current (Amperes, float) used for Rs estimation, 10-20% rated current
    #define USER_MOTOR_IND_EST_CURRENT (-1.0) // During Motor ID, maximum current (negative Amperes, float) used for Ls estimation, use just enough to enable rotation
    #define USER_MOTOR_MAX_CURRENT (3.82) // CRITICAL: Used during ID and run-time, sets a limit on the maximum current command output of the provided Speed PI Controller to the Iq controller
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (20.0) // During Motor ID, maximum commanded speed (Hz, float), ~10% rated
    #define USER_MOTOR_ENCODER_LINES (1024.0) // Number of lines on the motor's quadrature encoder
    #define USER_MOTOR_MAX_SPEED_KRPM (3.0) // Maximum speed that the motor
    #define USER_SYSTEM_INERTIA (0.0271403) // Inertia of the motor & system, should be estimated by SpinTAC Velocity Identify
    #define USER_SYSTEM_FRICTION (-0.07862) // Friction of the motor & system, should be estimated by SpinTAC Velocity Identify
    // IPM motors
    // If user provides separate Ls-d, Ls-q
    // else treat as SPM with user or identified average Ls
    #define Belt_Drive_Washer_IPM 201

    // ACIM motors
    #define Marathon_5K33GN2A 301

    #elif (USER_MOTOR == Maxon_EC4_pole_22)
    #define USER_MOTOR_TYPE MOTOR_Type_Pm
    //#define USER_MOTOR_NUM_POLE_PAIRS (4) //Works, but gives doubled rpm
    #define USER_MOTOR_NUM_POLE_PAIRS (2)
    #define USER_MOTOR_Rr (NULL)
    #define USER_MOTOR_Rs (0.2881)
    //#define USER_MOTOR_Ls_d (0.0000177) //Measured
    //#define USER_MOTOR_Ls_q (0.0000177)
    #define USER_MOTOR_Ls_d (0.000025) //Datasheet / 2
    #define USER_MOTOR_Ls_q (0.000025)
    //#define USER_MOTOR_Ls_d (0.0000529) //Datasheet
    //#define USER_MOTOR_Ls_q (0.0000529)
    #define USER_MOTOR_RATED_FLUX (0.027)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL)
    #define USER_MOTOR_RES_EST_CURRENT (1.0)
    #define USER_MOTOR_IND_EST_CURRENT (-1.0)
    #define USER_MOTOR_MAX_CURRENT (3.0)
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (80.0)
    //#define USER_MOTOR_ENCODER_LINES (2048.0) //Doubled when motor run as four polepairs
    #define USER_MOTOR_ENCODER_LINES (1024.0)
    #define USER_MOTOR_MAX_SPEED_KRPM (10.0)
    //#define USER_SYSTEM_INERTIA (0.03)
    #define USER_SYSTEM_INERTIA (0.01)
    #define USER_SYSTEM_FRICTION (0.042)

    #elif (USER_MOTOR == Maxon_EC4_pole_22_4p)
    #define USER_MOTOR_TYPE MOTOR_Type_Pm
    #define USER_MOTOR_NUM_POLE_PAIRS (4)
    #define USER_MOTOR_Rr (NULL)
    #define USER_MOTOR_Rs (0.2881)
    #define USER_MOTOR_Ls_d (0.0000529)
    #define USER_MOTOR_Ls_q (0.0000529)
    #define USER_MOTOR_RATED_FLUX (0.027)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL)
    #define USER_MOTOR_RES_EST_CURRENT (1.0)
    #define USER_MOTOR_IND_EST_CURRENT (-1.0)
    #define USER_MOTOR_MAX_CURRENT (40.0)
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (20.0)
    #define USER_MOTOR_ENCODER_LINES (1024.0)
    #define USER_MOTOR_MAX_SPEED_KRPM (4.0)
    #define USER_SYSTEM_INERTIA (0.03)
    #define USER_SYSTEM_FRICTION (0.42)

    #elif (USER_MOTOR == Maxon_EC90) // Name must match the motor #define
    #define USER_MOTOR_TYPE MOTOR_Type_Pm // Motor_Type_Pm (All Synchronous: BLDC, PMSM, SMPM, IPM) or Motor_Type_Induction (Asynchronous ACI)
    #define USER_MOTOR_NUM_POLE_PAIRS (12) //Should be 12 // PAIRS, not total poles. Used to calculate user RPM from rotor Hz only
    #define USER_MOTOR_Rr (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_Rs (0.197) // Identified phase to neutral resistance in a Y equivalent circuit (Ohms, float)
    #define USER_MOTOR_Ls_d (0.00014) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_Ls_q (0.00014) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_RATED_FLUX (0.024) // Identified TOTAL flux linkage between the rotor and the stator (V/Hz)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_RES_EST_CURRENT (1.0) // During Motor ID, maximum current (Amperes, float) used for Rs estimation, 10-20% rated current
    #define USER_MOTOR_IND_EST_CURRENT (-1.0) // During Motor ID, maximum current (negative Amperes, float) used for Ls estimation, use just enough to enable rotation
    #define USER_MOTOR_MAX_CURRENT (40) // CRITICAL: Used during ID and run-time, sets a limit on the maximum current command output of the provided Speed PI Controller to the Iq controller
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (50.0) // During Motor ID, maximum commanded speed (Hz, float), ~10% rated
    #define USER_MOTOR_ENCODER_LINES (1024.0) //Should be 1024 // Number of lines on the motor's quadrature encoder
    #define USER_MOTOR_MAX_SPEED_KRPM (3.0) // Maximum speed that the motor
    #define USER_SYSTEM_INERTIA (0.57) // Inertia of the motor & system, should be estimated by SpinTAC Velocity Identify
    //med last #define USER_SYSTEM_FRICTION (1.14) // Friction of the motor & system, should be estimated by SpinTAC Velocity Identify
    #define USER_SYSTEM_FRICTION (0.29) // Friction of the motor & system, should be estimated by SpinTAC Velocity Identify

    #elif (USER_MOTOR == Maxon_EC45_flat) // Name must match the motor #define
    #define USER_MOTOR_TYPE MOTOR_Type_Pm // Motor_Type_Pm (All Synchronous: BLDC, PMSM, SMPM, IPM) or Motor_Type_Induction (Asynchronous ACI)
    #define USER_MOTOR_NUM_POLE_PAIRS (8) //Should be 12 // PAIRS, not total poles. Used to calculate user RPM from rotor Hz only
    #define USER_MOTOR_Rr (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_Rs (0.304) // Identified phase to neutral resistance in a Y equivalent circuit (Ohms, float)
    #define USER_MOTOR_Ls_d (0.00021) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_Ls_q (0.00021) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_RATED_FLUX (0.017) // Identified TOTAL flux linkage between the rotor and the stator (V/Hz)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_RES_EST_CURRENT (1.0) // During Motor ID, maximum current (Amperes, float) used for Rs estimation, 10-20% rated current
    #define USER_MOTOR_IND_EST_CURRENT (-1.0) // During Motor ID, maximum current (negative Amperes, float) used for Ls estimation, use just enough to enable rotation
    #define USER_MOTOR_MAX_CURRENT (3) // CRITICAL: Used during ID and run-time, sets a limit on the maximum current command output of the provided Speed PI Controller to the Iq controller
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (50.0) // During Motor ID, maximum commanded speed (Hz, float), ~10% rated
    #define USER_MOTOR_ENCODER_LINES (1024.0) //Should be 1024 // Number of lines on the motor's quadrature encoder
    #define USER_MOTOR_MAX_SPEED_KRPM (6.0) // Maximum speed that the motor
    #define USER_SYSTEM_INERTIA (0.075) // Inertia of the motor & system, should be estimated by SpinTAC Velocity Identify
    #define USER_SYSTEM_FRICTION (0.038) // Friction of the motor & system, should be estimated by SpinTAC Velocity Identify

    #elif (USER_MOTOR == Trinamic_QBL4208_41_04_006) // Name must match the motor #define
    #define USER_MOTOR_TYPE MOTOR_Type_Pm // Motor_Type_Pm (All Synchronous: BLDC, PMSM, SMPM, IPM) or Motor_Type_Induction (Asynchronous ACI)
    #define USER_MOTOR_NUM_POLE_PAIRS (4) // PAIRS, not total poles. Used to calculate user RPM from rotor Hz only
    #define USER_MOTOR_Rr (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_Rs (0.746) // Identified phase to neutral resistance in a Y equivalent circuit (Ohms, float)
    #define USER_MOTOR_Ls_d (0.0013) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_Ls_q (0.0013) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_RATED_FLUX (0.0344) // Identified TOTAL flux linkage between the rotor and the stator (V/Hz)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_RES_EST_CURRENT (1.0) // During Motor ID, maximum current (Amperes, float) used for Rs estimation, 10-20% rated current
    #define USER_MOTOR_IND_EST_CURRENT (-1.0) // During Motor ID, maximum current (negative Amperes, float) used for Ls estimation, use just enough to enable rotation
    #define USER_MOTOR_MAX_CURRENT (1) //Should be 5.4 according to motor datasheet // CRITICAL: Used during ID and run-time, sets a limit on the maximum current command output of the provided Speed PI Controller to the Iq controller
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (50.0) // During Motor ID, maximum commanded speed (Hz, float), ~10% rated
    #define USER_MOTOR_ENCODER_LINES (2048.0) //With AM4096 encoder configured for 2048 // Number of lines on the motor's quadrature encoder
    #define USER_MOTOR_MAX_SPEED_KRPM (3.0) // Maximum speed that the motor
    #define USER_SYSTEM_INERTIA (0.0162) // Inertia of the motor & system, should be estimated by SpinTAC Velocity Identify
    #define USER_SYSTEM_FRICTION (0.0270) // Friction of the motor & system, should be estimated by SpinTAC Velocity Identify


    #elif (USER_MOTOR == Estun_EMJ_04APB22) // Name must match the motor #define
    #define USER_MOTOR_TYPE MOTOR_Type_Pm // Motor_Type_Pm (All Synchronous: BLDC, PMSM, SMPM, IPM) or Motor_Type_Induction (Asynchronous ACI)
    #define USER_MOTOR_NUM_POLE_PAIRS (4) // PAIRS, not total poles. Used to calculate user RPM from rotor Hz only
    #define USER_MOTOR_Rr (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_Rs (0.2881201) // Identified phase to neutral resistance in a Y equivalent circuit (Ohms, float)
    #define USER_MOTOR_Ls_d (0.0000529231) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_Ls_q (0.0000529231) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_RATED_FLUX (0.0271403) // Identified TOTAL flux linkage between the rotor and the stator (V/Hz)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_RES_EST_CURRENT (1.0) // During Motor ID, maximum current (Amperes, float) used for Rs estimation, 10-20% rated current
    #define USER_MOTOR_IND_EST_CURRENT (-1.0) // During Motor ID, maximum current (negative Amperes, float) used for Ls estimation, use just enough to enable rotation
    #define USER_MOTOR_MAX_CURRENT (3.82) // CRITICAL: Used during ID and run-time, sets a limit on the maximum current command output of the provided Speed PI Controller to the Iq controller
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (20.0) // During Motor ID, maximum commanded speed (Hz, float), ~10% rated
    #define USER_MOTOR_ENCODER_LINES (1024.0) // Number of lines on the motor's quadrature encoder
    #define USER_MOTOR_MAX_SPEED_KRPM (3.0) // Maximum speed that the motor
    #define USER_SYSTEM_INERTIA (0.0271403) // Inertia of the motor & system, should be estimated by SpinTAC Velocity Identify
    #define USER_SYSTEM_FRICTION (-0.07862) // Friction of the motor & system, should be estimated by SpinTAC Velocity Identify

    #elif (USER_MOTOR == Anaheim_BLY172S)
    #define USER_MOTOR_TYPE MOTOR_Type_Pm
    #define USER_MOTOR_NUM_POLE_PAIRS (4)
    #define USER_MOTOR_Rr (NULL)
    #define USER_MOTOR_Rs (0.4110007)
    #define USER_MOTOR_Ls_d (0.0007092811)
    #define USER_MOTOR_Ls_q (0.0007092811)
    #define USER_MOTOR_RATED_FLUX (0.03279636)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL)
    #define USER_MOTOR_RES_EST_CURRENT (1.0)
    #define USER_MOTOR_IND_EST_CURRENT (-1.0)
    #define USER_MOTOR_MAX_CURRENT (5.0)
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (20.0)
    #define USER_MOTOR_ENCODER_LINES (2000.0)
    #define USER_MOTOR_MAX_SPEED_KRPM (4.0)
    #define USER_SYSTEM_INERTIA (0.02)
    #define USER_SYSTEM_FRICTION (0.01)

    #elif (USER_MOTOR == Teknic_M2310PLN04K)
    #define USER_MOTOR_TYPE MOTOR_Type_Pm
    #define USER_MOTOR_NUM_POLE_PAIRS (4)
    #define USER_MOTOR_Rr (NULL)
    #define USER_MOTOR_Rs (0.3918252)
    #define USER_MOTOR_Ls_d (0.00023495)
    #define USER_MOTOR_Ls_q (0.00023495)
    #define USER_MOTOR_RATED_FLUX (0.03955824)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL)
    #define USER_MOTOR_RES_EST_CURRENT (1.0)
    #define USER_MOTOR_IND_EST_CURRENT (-0.5)
    #define USER_MOTOR_MAX_CURRENT (7.0)
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (20.0)
    #define USER_MOTOR_ENCODER_LINES (1000.0)
    #define USER_MOTOR_MAX_SPEED_KRPM (4.0)
    #define USER_SYSTEM_INERTIA (0.027)
    #define USER_SYSTEM_FRICTION (0.2)


    #elif (USER_MOTOR == Belt_Drive_Washer_IPM)
    #define USER_MOTOR_TYPE MOTOR_Type_Pm
    #define USER_MOTOR_NUM_POLE_PAIRS (4)
    #define USER_MOTOR_Rr (NULL)
    #define USER_MOTOR_Rs (2.832002)
    #define USER_MOTOR_Ls_d (0.0115)
    #define USER_MOTOR_Ls_q (0.0135)
    #define USER_MOTOR_RATED_FLUX (0.5022156)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL)
    #define USER_MOTOR_RES_EST_CURRENT (1.0)
    #define USER_MOTOR_IND_EST_CURRENT (-1.0)
    #define USER_MOTOR_MAX_CURRENT (4.0)
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (20.0)

    #elif (USER_MOTOR == Marathon_5K33GN2A) // Name must match the motor #define
    #define USER_MOTOR_TYPE MOTOR_Type_Induction // Motor_Type_Pm (All Synchronous: BLDC, PMSM, SMPM, IPM) or Motor_Type_Induction (Asynchronous ACI)
    #define USER_MOTOR_NUM_POLE_PAIRS (2) // PAIRS, not total poles. Used to calculate user RPM from rotor Hz only
    #define USER_MOTOR_Rr (5.508003) // Identified phase to neutral in a Y equivalent circuit (Ohms, float)
    #define USER_MOTOR_Rs (10.71121) // Identified phase to neutral in a Y equivalent circuit (Ohms, float)
    #define USER_MOTOR_Ls_d (0.05296588) // For Induction, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_Ls_q (0.05296588) // For Induction, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_RATED_FLUX (0.8165*220.0/60.0) // sqrt(2/3)* Rated V (line-line) / Rated Freq (Hz)
    #define USER_MOTOR_MAGNETIZING_CURRENT (1.378) // Identified magnetizing current for induction motors, else NULL
    #define USER_MOTOR_RES_EST_CURRENT (0.5) // During Motor ID, maximum current (Amperes, float) used for Rs estimation, 10-20% rated current
    #define USER_MOTOR_IND_EST_CURRENT (NULL) // not used for induction
    #define USER_MOTOR_MAX_CURRENT (2.0) // CRITICAL: Used during ID and run-time, sets a limit on the maximum current command output of the provided Speed PI Controller to the Iq controller
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (5.0) // During Motor ID, maximum commanded speed (Hz, float). Should always use 5 Hz for Induction.
    #define USER_MOTOR_ENCODER_LINES (2048.0) // Number of lines on the motor's quadrature encoder
    #define USER_MOTOR_MAX_SPEED_KRPM (1.725) // Maximum speed that the motor
    #define USER_SYSTEM_INERTIA (0.02) // Inertia of the motor & system, should be estimated by SpinTAC Velocity Identify
    #define USER_SYSTEM_FRICTION (0.01) // Friction of the motor & system, should be estimated by SpinTAC Velocity Identify



    #else
    #error No motor type specified
    #endif

    #ifndef USER_MOTOR
    #error Motor is not defined in user.h
    #endif

    #ifndef USER_MOTOR_TYPE
    #error The motor type is not defined in user.h
    #endif

    #ifndef USER_MOTOR_NUM_POLE_PAIRS
    #error Number of motor pole pairs is not defined in user.h
    #endif

    #ifndef USER_MOTOR_Rr
    #error The rotor resistance is not defined in user.h
    #endif

    #ifndef USER_MOTOR_Rs
    #error The stator resistance is not defined in user.h
    #endif

    #ifndef USER_MOTOR_Ls_d
    #error The direct stator inductance is not defined in user.h
    #endif

    #ifndef USER_MOTOR_Ls_q
    #error The quadrature stator inductance is not defined in user.h
    #endif

    #ifndef USER_MOTOR_RATED_FLUX
    #error The rated flux of motor is not defined in user.h
    #endif

    #ifndef USER_MOTOR_MAGNETIZING_CURRENT
    #error The magnetizing current is not defined in user.h
    #endif

    #ifndef USER_MOTOR_RES_EST_CURRENT
    #error The resistance estimation current is not defined in user.h
    #endif

    #ifndef USER_MOTOR_IND_EST_CURRENT
    #error The inductance estimation current is not defined in user.h
    #endif

    #ifndef USER_MOTOR_MAX_CURRENT
    #error The maximum current is not defined in user.h
    #endif

    #ifndef USER_MOTOR_FLUX_EST_FREQ_Hz
    #error The flux estimation frequency is not defined in user.h
    #endif


    // **************************************************************************
    // the functions


    //! \brief Sets the user parameter values
    //! \param[in] pUserParams The pointer to the user param structure
    extern void USER_setParams(USER_Params *pUserParams);


    //! \brief Checks for errors in the user parameter values
    //! \param[in] pUserParams The pointer to the user param structure
    extern void USER_checkForErrors(USER_Params *pUserParams);


    //! \brief Gets the error code in the user parameters
    //! \param[in] pUserParams The pointer to the user param structure
    //! \return The error code
    extern USER_ErrorCode_e USER_getErrorCode(USER_Params *pUserParams);


    //! \brief Sets the error code in the user parameters
    //! \param[in] pUserParams The pointer to the user param structure
    //! \param[in] errorCode The error code
    extern void USER_setErrorCode(USER_Params *pUserParams,const USER_ErrorCode_e errorCode);


    //! \brief Recalculates Inductances with the correct Q Format
    //! \param[in] handle The controller (CTRL) handle
    extern void USER_softwareUpdate1p6(CTRL_Handle handle);


    //! \brief Updates Id and Iq PI gains
    //! \param[in] handle The controller (CTRL) handle
    extern void USER_calcPIgains(CTRL_Handle handle);


    //! \brief Computes the scale factor needed to convert from torque created by Ld, Lq, Id and Iq, from per unit to Nm
    //! \return The scale factor to convert torque from (Ld - Lq) * Id * Iq from per unit to Nm, in IQ24 format
    extern _iq USER_computeTorque_Ls_Id_Iq_pu_to_Nm_sf(void);


    //! \brief Computes the scale factor needed to convert from torque created by flux and Iq, from per unit to Nm
    //! \return The scale factor to convert torque from Flux * Iq from per unit to Nm, in IQ24 format
    extern _iq USER_computeTorque_Flux_Iq_pu_to_Nm_sf(void);


    //! \brief Computes the scale factor needed to convert from per unit to Wb
    //! \return The scale factor to convert from flux per unit to flux in Wb, in IQ24 format
    extern _iq USER_computeFlux_pu_to_Wb_sf(void);


    //! \brief Computes the scale factor needed to convert from per unit to V/Hz
    //! \return The scale factor to convert from flux per unit to flux in V/Hz, in IQ24 format
    extern _iq USER_computeFlux_pu_to_VpHz_sf(void);


    //! \brief Computes Flux in Wb or V/Hz depending on the scale factor sent as parameter
    //! \param[in] handle The controller (CTRL) handle
    //! \param[in] sf The scale factor to convert flux from per unit to Wb or V/Hz
    //! \return The flux in Wb or V/Hz depending on the scale factor sent as parameter, in IQ24 format
    extern _iq USER_computeFlux(CTRL_Handle handle, const _iq sf);


    //! \brief Computes Torque in Nm
    //! \param[in] handle The controller (CTRL) handle
    //! \param[in] torque_Flux_sf The scale factor to convert torque from (Ld - Lq) * Id * Iq from per unit to Nm
    //! \param[in] torque_Ls_sf The scale factor to convert torque from Flux * Iq from per unit to Nm
    //! \return The torque in Nm, in IQ24 format
    extern _iq USER_computeTorque_Nm(CTRL_Handle handle, const _iq torque_Flux_sf, const _iq torque_Ls_sf);


    //! \brief Computes Torque in lbin
    //! \param[in] handle The controller (CTRL) handle
    //! \param[in] torque_Flux_sf The scale factor to convert torque from (Ld - Lq) * Id * Iq from per unit to lbin
    //! \param[in] torque_Ls_sf The scale factor to convert torque from Flux * Iq from per unit to lbin
    //! \return The torque in lbin, in IQ24 format
    extern _iq USER_computeTorque_lbin(CTRL_Handle handle, const _iq torque_Flux_sf, const _iq torque_Ls_sf);


    #ifdef __cplusplus
    }
    #endif // extern "C"

    //@} // ingroup
    #endif // end of _USER_H_ definition
    ]
    Still lab12a does not work. Motor spinns but does not stop, no error codes.

    A other question is the possibility to combine the beginning a trapezoidal Curve with the end behaviour of a s-Curve ?

    Best Regards,
    Ingemar
  • Hi,
    We now have lab13b working.
    Lab 12a is not working. Motor spinns but never stops, no error code.

    The settings now is:
    USER_IQ_FULL_SCALE_FREQ_Hz (400.0)
    USER_PWM_FREQ_kHz (45.0) = default
    USER_MOTOR_MAX_SPEED_KRPM (10.0)

    An other questions is the possibility to combine the acceleration curve with the start of a trapezoid and the end of a s-curve ?
    Best Regards,
    Ingemar
  • Ingemar,

    You have the maximum speed set to 10krpm in your user.h.  If your motor capable of reaching that speed?  We use that speed in order to calculate the speed that we try to reach in lab 12a for the inertia identification.  If that speed cannot be reached, I would recommend reducing the gMotorVars.SpinTAC.VelIdGoalSpeed_krpm.  Does it only start spinning after you have set gMotorVars.SpinTAC.RunVelId to true?

    Ingemar Dahlqvist said:
    An other questions is the possibility to combine the acceleration curve with the start of a trapezoid and the end of a s-curve ?

    In the current software this is not possible.  The closest you could get to this is setting different acceleration and deceleration limits for a position change.

  • Hi Adam,
    I found the problem with lab12a.
    It was the lowpass filter cut-off frequency. This was set to 8000Hz which is to low for the Maxon EC-4 motor spinning at 10krpm and with an encoder with 1024 lines this will result in 17066 Hz.
    A more suitable value is around 20000 Hz.
    I have not figured out how steep the low pass filter cut-off is yet.
  • Ingemar,

    I thinking about the encoder setup, I don't think that cutoff frequency is actively used in the example labs.  But it did remind me about something else that could be the issue.  In MotorWare 14 we added GPIO qualification to the EQEP input lines to allow the EQEP module to work in noisier environments.  You should remove this functionality to see if this allows you to run lab 12a.  This functionality is in the hal.c file and the HAL_setupGpios function.  I've copied the code section that should be modified below:

      // Set Qualification Period for GPIO16-23, 22*2*(1/90MHz) = 0.48us
      GPIO_setQualificationPeriod(obj->gpioHandle,GPIO_Qual_A_PRD2,22);
    
      // SPIA SIMO
      GPIO_setMode(obj->gpioHandle,GPIO_Number_16,GPIO_16_Mode_SPISIMOA);
    
      // SPIA SOMI
      GPIO_setMode(obj->gpioHandle,GPIO_Number_17,GPIO_17_Mode_SPISOMIA);
    
      // SPIA CLK
      GPIO_setMode(obj->gpioHandle,GPIO_Number_18,GPIO_18_Mode_SPICLKA);
    
      // SPIA CS
      GPIO_setMode(obj->gpioHandle,GPIO_Number_19,GPIO_19_Mode_SPISTEA_NOT);
      
    #ifdef QEP
      // EQEP1A
      GPIO_setMode(obj->gpioHandle,GPIO_Number_20,GPIO_20_Mode_EQEP1A);
      GPIO_setQualification(obj->gpioHandle,GPIO_Number_20,GPIO_Qual_3Samples);
    
      // EQEP1B
      GPIO_setMode(obj->gpioHandle,GPIO_Number_21,GPIO_21_Mode_EQEP1B);
      GPIO_setQualification(obj->gpioHandle,GPIO_Number_21,GPIO_Qual_3Samples);
    
      // GPIO
      GPIO_setMode(obj->gpioHandle,GPIO_Number_22,GPIO_22_Mode_GeneralPurpose);
    
      // EQEP1I
      GPIO_setMode(obj->gpioHandle,GPIO_Number_23,GPIO_23_Mode_EQEP1I);
      GPIO_setQualification(obj->gpioHandle,GPIO_Number_23,GPIO_Qual_3Samples);
    #else

  • Hi Adam,
    I am quite sure that we are using the version 13 Motorware right now, but I will double check that.
    Shall we use version 14 instead, major imporvements ?
    We have 4 computers with motorware and it might not be the same version on them.
    But in the lab 12a there is a call to ENC_setup() line 228 with 8 kHz low pass cutoff.
    Best Regards,
    Ingemar
  • Ingemar,

    I would recommend it, there have been some improvements and new functionality release with MotorWare 14.

    I agree that the filter value is passed into ENC_setup, but I don't believe that it is used when calculating the encoder angle.
  • Hi Adam,

    I have some more questions about lab13c.

    We have found that if there is a load ( a little heavy) on the motor e.g. due to a gear box.

    The motor refuses to start when pos_plan_start is issued. No error is raised.

    How do the software know the rotor position from start ?

    Is the FAST still involved ?

    After performing a position sequence, what is the best way to lower the current until the next sequence is started.

    Best Regards,

    Ingemar

  • Ingemar,

    When the software does the Rs Recalibration on startup it will use the amount of current specified in USER_MOTOR_RES_EST_CURRENT in order to try and force the motor into alignment.  During this step is where we capture the encoder calibration.  I've copied the relevant code from lab 13c.

      // if we are forcing alignment, using the Rs Recalculation, align the eQEP angle with the rotor angle
      if((EST_getState(obj->estHandle) == EST_State_Rs) && (USER_MOTOR_TYPE == MOTOR_Type_Pm))
      {
    	  ENC_setZeroOffset(encHandle, (uint32_t)(HAL_getQepPosnMaximum(halHandle) - HAL_getQepPosnCounts(halHandle)));
      }

    If your motor has a heavy load on it then you will need to increase the amount of current to ensure that it can complete this alignment step.  I've used as much as USER_MOTOR_RATED_CURRENT in order to get this step to complete successfully.

  • Hi Adam,

    Last problem solved.

    I have some more questions (still lab13c).

    Setting ”USER_MOTOR_MAX_CURRENT” to 18A results in a externally measured current of 10A from DC power supply ( with Tektronix current probe)
    Increasing the ”USER_MOTOR_MAX_CURRENT” to 40A results in a current of 20A why is there such diference (DRB830x Rev D)
    Is the ”USER_MOTOR_MAX_CURRENT” not the max current drawn from the DC-bus ?

    Best Regards,
    Ingemar
  • Ingemar,

    The USER_MOTOR_MAX_CURRENT setting sets the output limit of the speed regulator.  So it doesn't directly relate to the DC bus current.  It will impact how much current the FOC will try to establish in the motor.  

    If you measure the phase current of the motor you should see it peak at 18A when you set USER_MOTOR_MAX_CURRENT to 18.0.

    Additionally, the USER_MOTOR_MAX_CURRENT setting is the maximum amount of current that the speed controller is allowed to request, so unless your system is putting enough load on the motor you won't see that current.

  • Hi Adam,

    I think that the discrepancy in the current figures might due to the fact that the DRV8301 board has a 660 uF capacitor bank.
    The torque demand in the mechanical prototype which the motor is connected to is quite short around 25 ms so I think that the capacitor bank can supply a part of the peak current.
    So the current measured (supplying the DRV8301) board by my collegue is lower than he think it should be. Actually he did not measure the phase current at all. I have asked him to measure the phase current at the same time as the current to DRV8301 together with the torque sensor signal.
    What do You think ?

    Best Regards,
    Ingemar
  • Ingemar,

    You are right that the capacitor bank will play a role in the current draw from your DC supply. Measuring the phase current will really be a good way to see how much current is being instantaneously applied to the motor.
  • Hi Adam,

    The phase currents are now measured and matches the "USER_MOTOR_MAX_CURRENT" settings.
    But now I am interested in plotting the measured currents iq and id from the PARK transform (Figure 1-3 in SPRUHJ1F) in CCS .
    However I have not figured out the name of these variables.
    Can you please tell me the names? where to be found in "control.c"

    Best Regards,
    Ingemar
  • Ingemar,

    The easiest way to access the PARK output variables would be to follow the example in proj_lab10b.  In the updateGlobalVariables_motor function it access the Id & Iq feedback (PARK output) and places them into global variables.  I've copied the relevant section of code below:

    // read Id and Iq vectors in amps
    gMotorVars.Id_A = _IQmpy(CTRL_getId_in_pu(ctrlHandle), _IQ(USER_IQ_FULL_SCALE_CURRENT_A));
    gMotorVars.Iq_A = _IQmpy(CTRL_getIq_in_pu(ctrlHandle), _IQ(USER_IQ_FULL_SCALE_CURRENT_A));
    
    // calculate vector Is in amps
    gMotorVars.Is_A = _IQsqrt(_IQmpy(gMotorVars.Id_A, gMotorVars.Id_A) + _IQmpy(gMotorVars.Iq_A, gMotorVars.Iq_A));

  • Hi Adam,

    Thanks!

    I added the code lines in lab13c. Not tested yet, Compiled without errors.

    Now I wonder if there is some ready made code for using the three 10-bit DAC's in the 2809M processor. Can't find any DAC support in HAL.
    What I would like do is to output for example the Iq, Id variables or just about any varaiable that would be of interest when the motor is coupled to the mechanics. DAC-output to Tektronix Ocilloscope for real time capture. A sync signal is also nice to have.

    Best Regards,
    Ingemar
  • Ingemar,

    The labs for the DRV8301 & BOOSTXL-DRV8301 show an example of using the PWM outputs combined with an RC filter to act as a DAC. You should be able to use that example code to create the output signals you are trying to read.
  • Hi Adam,

    I wonder how fast the XDS100 can supply data for graph in CCS6.
    E.g. the graph time resolution possible. Can I capture a position event less than 100ms ?

    Best Regards
    Ingemar
  • Ingemar,

    I don't think you would be able to log data that fast via the graph.  You would probably be better off using a software buffer on the IC to store your graph data.  See lab 05f for an example.

  • Hi Adam,

    I have been thinking about connection an external DAC ,SPI type to the J8 header on the DRV8301 board.
    What do you think about TI DAC8562/3 ?
    If this works I will have a realtime display on a TEK 4200 scope of any internal variable.

    Best Regards
    Ingemar
  • Hi Adam,

    Back to lab 12b some strange things happen.
    It works fine up to approx 5.5 krpm.

    However increasing motor speed to 5.8 krpm the control is lost and the motor spinns at 6.2 krpm.
    The only thing is to disable the system

    The parameters changed e.g. used follows here:
    gMotorVars.MaxVel_krpm = 5
    gMotorVars.PosStepInt_MRev = 4
    gMotorVars.PosStepFrac_MRev = 0.333
    gMotorVars.MaxAccel_krpmps = 120
    gMotorVars.MaxDecel_krpmps = 120
    gMotorVars.MaxJrk_krpmps2 = 2000
    gMotorVars.SpinTAC.PosMoveCurveType = ST_MOVE_CUR_STCRV

    #define USER_IQ_FULL_SCALE_FREQ_Hz (1000.0) //With Maxon 7 pole pair motor (ECi 40)

    #define USER_PWM_FREQ_kHz (60.0) //Test w. Maxon 7 pp motor -> max speed appr 5.65krpm

    #elif (USER_MOTOR == Maxon_ECi40_449470) // Name must match the motor #define
    #define USER_MOTOR_TYPE MOTOR_Type_Pm // Motor_Type_Pm (All Synchronous: BLDC, PMSM, SMPM, IPM) or Motor_Type_Induction (Asynchronous ACI)
    #define USER_MOTOR_NUM_POLE_PAIRS (7) //Should be 12 // PAIRS, not total poles. Used to calculate user RPM from rotor Hz only
    #define USER_MOTOR_Rr (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_Rs (0.404) // Identified phase to neutral resistance in a Y equivalent circuit (Ohms, float)
    #define USER_MOTOR_Ls_d (0.00032) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_Ls_q (0.00032) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_RATED_FLUX (0.021) // Identified TOTAL flux linkage between the rotor and the stator (V/Hz)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_RES_EST_CURRENT (1.0) // During Motor ID, maximum current (Amperes, float) used for Rs estimation, 10-20% rated current
    #define USER_MOTOR_IND_EST_CURRENT (-1.0) // During Motor ID, maximum current (negative Amperes, float) used for Ls estimation, use just enough to enable rotation
    #define USER_MOTOR_MAX_CURRENT (20) // CRITICAL: Used during ID and run-time, sets a limit on the maximum current command output of the provided Speed PI Controller to the Iq controller
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (50.0) // During Motor ID, maximum commanded speed (Hz, float), ~10% rated
    #define USER_MOTOR_ENCODER_LINES (1024.0) // Number of lines on the motor's quadrature encoder
    #define USER_MOTOR_MAX_SPEED_KRPM (6.0) // Maximum speed that the motor
    #define USER_SYSTEM_INERTIA (0.017) // Inertia of the motor & system, should be estimated by SpinTAC Velocity Identify
    #define USER_SYSTEM_FRICTION (0.018) // Friction of the motor & system, should be estimated by SpinTAC Velocity Identify

    Have any idea ?
    Seems like som calulations have run out of range.
    Reducing the user pwm frequency to 30kHz does not help.

    Best Regards,
    Ingemar
  • Ingemar,

    I think that DAC should be fine.  

    As far as potentially running out of calculations, that is easy to test.  Since you are running the PWMs at 60kHz, I'm assuming that USER_PWR_PER_ISR is set to 3, USER_CTRL_PER_ISR is set to 1, and USER_SPEED_PER_CTRL is set to 10.  This means that you are running the speed control loops at 3kHz.  If you set USER_SPEED_PER_CTRL to 30, this will run the speed loops at 1kHz.  

    Another thing that could be happening is that the pulses from your encoder are coming in too fast for the QEP hardware.  In MotorWare14, we added input qualification to help with filtering out noise coming in on the eQEP lines.  This is done in the HAL_setupGpios function.  You can try adjusting the setup of the GPIOs to see if that helps the issue.

  • Hi Adam,

    I have searced for "USER_SPEED_PER_CTRL", not found in any files.

    Did You mean "USER_NUM_ISR_TICKS_PER_CTRL_TICK" which seems to set the controler frequency ?

    Best Regards,
    Ingemar
  • Ingemar,

    Yes that is the parameter that I meant.  I was out of the office an unable to look up the exact right name.  I knew I was close.

  • Hi Adam,

    About the encoder SW.

    If we have an encoder with 1000 lines/turn, the resulting period times of chanel A, B is 10.9us at 5500rpm,
    Raising to 5800 rpms resuklts in a period time of 10.4 us.
    There is a call to ENC_setup() line 227 in lab12b with sample_period = 1.

    What does this mean?
    I asume that the sensor channels A,B,I are sampled but I have not figured out what this sample time is.
    The eQEP is interrupt driven ?
    The minium period time for an QEP input seems to be 2tc(SCO), tc(SCO) is 11-500ns for 28069M.
    Same clock as for ePWM? 22 ns ?

    Best Rehards,
    Ingemar
  • Ingemar,

    The eQEP is not separately interrupt driven.  It is queried for the encoder angle each PWM ISR.  

    Does this only occur when  you are running at that high speed?  If you are running at 1000 rpm (for example) for an extended period of time does this event occur?

    In the SpinTAC code, it needs at least three samples per electrical angle of the motor in order to control it.  I'm thinking that maybe you aren't getting three samples of the speed loop per electrical angle of the motor.

  • Hi Adam,
    I have tested lab12b with the Teknik motor and it works without any problems up to 6krpm which is the limit according to "USER_MOTOR_MAX_SPEED_KRPM" and the encoder lines are the same "1000"
    It seems that there might be some problem with the motor parameters:
    {
    gMotorVars.MaxVel_krpm = 5
    gMotorVars.PosStepInt_MRev = 4
    gMotorVars.PosStepFrac_MRev = 0.333
    gMotorVars.MaxAccel_krpmps = 120
    gMotorVars.MaxDecel_krpmps = 120
    gMotorVars.MaxJrk_krpmps2 = 2000
    gMotorVars.SpinTAC.PosMoveCurveType = ST_MOVE_CUR_STCRV

    #define USER_IQ_FULL_SCALE_FREQ_Hz (1000.0) //With Maxon 7 pole pair motor (ECi 40)

    #define USER_PWM_FREQ_kHz (60.0) //Test w. Maxon 7 pp motor -> max speed appr 5.65krpm

    #elif (USER_MOTOR == Maxon_ECi40_449470) // Name must match the motor #define
    #define USER_MOTOR_TYPE MOTOR_Type_Pm // Motor_Type_Pm (All Synchronous: BLDC, PMSM, SMPM, IPM) or Motor_Type_Induction (Asynchronous ACI)
    #define USER_MOTOR_NUM_POLE_PAIRS (7) //Should be 12 // PAIRS, not total poles. Used to calculate user RPM from rotor Hz only
    #define USER_MOTOR_Rr (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_Rs (0.404) // Identified phase to neutral resistance in a Y equivalent circuit (Ohms, float)
    #define USER_MOTOR_Ls_d (0.00032) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_Ls_q (0.00032) // For PM, Identified average stator inductance (Henry, float)
    #define USER_MOTOR_RATED_FLUX (0.021) // Identified TOTAL flux linkage between the rotor and the stator (V/Hz)
    #define USER_MOTOR_MAGNETIZING_CURRENT (NULL) // Induction motors only, else NULL
    #define USER_MOTOR_RES_EST_CURRENT (1.0) // During Motor ID, maximum current (Amperes, float) used for Rs estimation, 10-20% rated current
    #define USER_MOTOR_IND_EST_CURRENT (-1.0) // During Motor ID, maximum current (negative Amperes, float) used for Ls estimation, use just enough to enable rotation
    #define USER_MOTOR_MAX_CURRENT (20) // CRITICAL: Used during ID and run-time, sets a limit on the maximum current command output of the provided Speed PI Controller to the Iq controller
    #define USER_MOTOR_FLUX_EST_FREQ_Hz (50.0) // During Motor ID, maximum commanded speed (Hz, float), ~10% rated
    #define USER_MOTOR_ENCODER_LINES (1024.0) // Number of lines on the motor's quadrature encoder
    #define USER_MOTOR_MAX_SPEED_KRPM (6.0) // Maximum speed that the motor
    #define USER_SYSTEM_INERTIA (0.017) // Inertia of the motor & system, should be estimated by SpinTAC Velocity Identify
    #define USER_SYSTEM_FRICTION (0.018) // Friction of the motor & system, should be estimated by SpinTAC Velocity Identify
    }

    Lowering the "USER_PWM_FREQ_kHz " to 45kHz has no effect.
    Problem with "USER_IQ_FULL_SCALE_FREQ_Hz" value ?

    Using the formula in user.h line 79 gives "USER_IQ_FULL_SCALE_FREQ_Hz" 350 Hz
    and using the formula in line 81 gives "USER_IQ_FULL_SCALE_FREQ_Hz" 875Hz

    Shall the formula be different when using the eQEP ?

    Best Regards,
    Ingemar
  • Ingemar,

    I don't think the issue is with the mechanical speed.  I think the issue is the electrical speed.  I'm assuming that your timing in the user.h is as follows:

    USER_PWM_FREQ_kHz - 60.0
    USER_NUM_PWM_TICKS_PER_ISR_TICK - 3
    USER_NUM_ISR_TICKS_PER_CTRL_TICK - 1
    USER_NUM_CTRL_TICKS_PER_SPEED_TICK - 15

    This results in the speed loop being called at 0.75ms.  Since the Position Converter requires at least 3 samples per electrical angle, this means that the maximum frequency it can support is 1/(3 * 0.00075) = 444 Hz.  This electrical speed can be converted into mechanical speed based on the number of pole pairs in your motor.  So for the Teknic 444 Hz is (444 * 60) / 4 = 6660 rpm.  For your motor 444 Hz is (444 * 60) / 7 = 3805 rpm

    The way to increase this is to run the speed loop faster.  You can do that by decreasing USER_NUM_CTRL_TICKS_PER_SPEED_TICK.  If you were to set that to 5, the math would work out so that the maximum speed of your motor would be 11428rpm.  

  • Hi Adam,

    Thanks!

    I was not aware of the factor "3" in the Position Converter, the rest I did understand.

    But now I have some more questions.

    Question 1.

    Is it possible to load the software using the CAN interface without an external flashmemory or MRAM ?

    Question 2.

    Would it be possible to port the software to a TMS320F2812. I know that this device lacks FPU, CLA and the enhanced periferials.

    Best Regards,
    Ingemar
  • Ingemar,

    Yeah, we need to do a better job of documenting the impact of that on high pole pair motors.

    Ingemar Dahlqvist said:
    Is it possible to load the software using the CAN interface without an external flashmemory or MRAM ?

    It should be possible, but I don't know if there is an example software that does this.  You would probably need to ask the C2000 specific experts over here: 

    Ingemar Dahlqvist said:
    Would it be possible to port the software to a TMS320F2812. I know that this device lacks FPU, CLA and the enhanced periferials.

    It isn't possible to port the InstaSPIN software to that platform.  This is because part of the InstaSPIN software is located in masked ROM on the device.  So without the ROM IP code you cannot run InstaSPIN.

  • Hi Adam,

    I have some more questions about lab13c.c.

    In Assigniing "velMax =" there is a mulitiplication with  ST_SPEED_PU_PER_KRPM this ends up to a value = 2  for a 7 pole-pair motor and 10krpm.

    I quite do not understand the purpose of this factor.

    We have some problems getting the the speed up. setting the USER_IQ_FULL_SCALE_FREQ_Hz = 1300 results in th emotor spinning at max 6200.

    Best Regards,

    Ingemar

  • Ingemar,

    The ST_SPEED_PU_PER_KRPM factor is used to convert between krpm and the scaled unit of velocity.  This value represents what 1.0 pu/s (scaled speed unit) represents in krpm.  It is used to convert our scaled units into real world units for display purposes.

  • Hi Adam,

    So in lab13c.c  line 717 : STPOSPLAN_addCfgTran( , , , , _IQ(0.1 * ST*SPEED_PU_PER_KRPM, , );

    The figure 0.1 is the desired speed i krpm ?

    If I change 0.1 to 1.0 I will get 1.0 krpm real speed. The speed changes I know but I did not measure it.

    Best Regards,

    Ingemar

  • Ingemar,

    You are exactly correct.  If you change the 0.1 to 1.0, the speed limit will be 1000 rpm.

  • Hi Adam,

    An other question about lab13c:

    729 STPOSPLAN_addCfgState(stObj->posPlanHandle, 0,             0,                 200L); // StateIdx0: A

    The StateTimer ticks relation to System timing.

    I have not found the decrement tick time.

    200L is equal to ? us ?

    Is it  the same as fcontrol  or fspeed or something else.

    Best Regards,

    Ingemar

  • Ingemar,

    The state timer is in the units of Speed Loop Samples.  So 200L refers to 200 Speed Loop Samples.

  • Hi Adam,

    Now we got the lab 13b working with our motors. The design uses 2 motors so now I have some more questions.

    We need to Flash the program in the DRV8301/28069M.

    The SW 1 is used to set “gMotorVars.RunPositionProfile" to TRUE, and this works.

    The "gMotorVars.PosStepInt_MRev" and "gMotorVars.PosStepFrac_MRev" are also assigmed with the relevant values.

    Bu what is the best way to handle e.g. to set the following:

    "gMotorVars.Flag_enableSys"

    "gMotorVars.Flag_Run_Identify"

    In the end these will be handled by a CAN bus communication, but now we will hava a simple demo.

    I can of course map the SW2 to for example "gMotorVars.Flag_enableSys" and

    take an other GPIO-pin  to set "gMotorVars.Flag_Run_Identify".

    But is it OK the set these to "1" before entering the "for-loop"

    The status of these variables can be mapped to the LED's (LED10 and LED11) on th DRV8302 board.

    If I choose Flash build in CCS, how do I control what code will still be executed in RAM ?

    Best Regards,

    Ingemar

  • Ingemar,

    Ingemar Dahlqvist said:
    But is it OK the set these to "1" before entering the "for-loop"

    It should be fine to do this.  I have some demos where I have hard coded gMotorVars.Flag_Run_Identify and gMotorVars.Flag_enableSys to 1.

    Ingemar Dahlqvist said:
    If I choose Flash build in CCS, how do I control what code will still be executed in RAM ?

    I can't speak specifically about how to do this, you should look into the C2000 Compiler User Guide for how to control which functions get copied into RAM at startup.

  • Hi Adam,

    Some more thoughts about running from Flash.

    In hal.c the paged and random Flash access wate states are set to 3

    I this mandatory or can I reduce the pages wait state to 1 and the random to 2 ?

    Best Regards,

    Ingemar

  • Ingemar,

    I wouldn't change those values unless you change the clock frequency on the chip.  Those values are based on the speed of the flash memory in the F28069M.  You should look into the device datasheet for more information.

  • Hi Adam,

    A new question about the IQ format.
    If a set gMotorVars.MaxJrk_krpmps2 = _IQ(127) thes results in the debugger a display of 2047 (IQ20)

    Best Regards,
    Ingemar
  • Ingemar,

    You are setting a number in a different Q-type than what is expected by the gMotorVars.MaxJrk_krpmps2 variable, so in the watch window it won't show up as the exact same number since you are using two different Q-types to the same variable.
  • Hi Adam,

    IQ values are now fixed.

    But now I have another problem.

    I hard coded the

    gMotorVars.Flag_enableSys

    and

    gMotorVars.Flag_Run_Identify

    before the for(;;) loop "// waiting forenable system to be set".

    Build the Flash in CCS, run the debugger and those vrables are set and everything works as it should,

    However if I power down he 8301 board, the controller board, close CCS and then power up controller board and then the 8301 board,

    I expected the software to run , but don't.

    What else do I have to do running without the CCS debuggerr ?

    Control card needs power from the USB so is still connected.

    Best Regards,

    Ingemar

  • Look at the documentation surrounding the switches on the front of the controlcard, they control the boot mode of the mcu.