Kinetis Motor Suite Knowledge Base

cancel
Showing results for 
Search instead for 
Did you mean: 

Kinetis Motor Suite Knowledge Base

Labels

Discussions

There was a bug in the KMS 1.2.0 SNLESSHALL reference projects when using torque mode.   The drv.c file provided in the attachment is for the SNLESSHALL reference project.     In the SNLESSHALL project, the goal is to start the motor using the Hall sensors but then transition into FOC.  It isn't intended to use the Halls for the complete speed range. In this version, it now does the startup similar to sensorless velocity.  In that it will track the speed reference until it reaches the crossover speed ("Speed Threshold" in GUI), once the speed reference reaches the crossover speed it will transition into FOC and will run in torque mode as you expect.  If you want to speed up faster before getting into FOC, you can increase the acceleration and jerk of the speed profile before the transition into FOC.
View full article
Introduction: KMS  has a built in Motion Sequence Builder tool that gives you a very quick way of commanding various motor control scenarios.  If your motor control device requires external control of the speed, position or torque you will need to adapt the provided KMS reference design to your needs.    I recommend you start by using the Motion Sequence Builder to create a plan and variables that resemble your application. Examples provided include a blender, a ceiling fan and a washing machine for speed control and a security camera panning example for position control.   After completing the KMS GUI motor commissioning and experimenting with your motion plan, you will want to drive your motor within your application without the GUI and outside the bounds of the motion plan.  Now to create your own control system, to commanded speed, torque or position driven from another source.    This document covers the basics of performing those commands. In these example you will be interacting with the User block.  The User block aggregates the main motor operating states capable of being called by the user. This is intended to provide an easy, consistent code interface for the user to be able to command a specific operating state and perform certain common configurations of the desired state.   Knowing the State of the Motor: Before you tell the motor to go-to-speed, or go-to-position, or command a torque, you need to know that the motor is ready to accept your command.  I strongly suggest you read Chapter 2 of the KMS API reference manual.  Some of the text below is copied from there.   States that can be accessed via the User block include: Idle Fault Self-commissioning (SCM) Inertia Estimation (Inertia) PWM Duty Control Voltage Control Current Control (Current) Speed Control (Speed) Position Control (Position) [Sensored Position] Motion Sequence (Plan) Braking (Brake) Encoder Alignment (Align) [Sensored Velocity or Sensored Position]   Once in a state you can update the speed or position or torque directly.  Prior to entering the user state that commands speed, position or torque you need to take the input and covert it to the proper units.   Where to put your Control Code:   In the main loop, the code snippet below checks the state of the DC bus and the Fault indicator.   /* DC BUS Charging Indicator */   if(DRV_getDcbBusVoltage()<DRV_getDcbBusUnderVoltageThreshold()||DRV_getIsFaultActive())         {             BUS_VOLTAGE_LEDOFF;         }         else         {             BUS_VOLTAGE_LEDON;         }         /* FAULT Indicator */         if (DRV_getIsFaultActive()) // Pulled Up Switch is Active Low         {             FAULT_LEDON;         }         else         {             FAULT_LEDOFF;         }                       You can put your control code in this loop or better yet you can put your control code in the interrupt service routine that executes at the slow tick rate.   /**  * @fn      SWI_IRQHandler(void)  * @brief   Run slow isr task  *  * @return  None  * @ingroup SLOW_ISR  */ void SWI_IRQHandler(void) {     static timestamp_t SlowIsrStartLast = 0;     /*!< Previous Start of ISR timestamp for measuring period  */       timestamp_t startCycleCount = GetProfilerCycles();     CpuUtilization.SlowIsrPeriod = startCycleCount -SlowIsrStartLast;     SlowIsrStartLast = startCycleCount;       /* Clear source of ISR */     NVIC_ClearPendingIRQ(SWI_IRQn);       /* Update drive module */     DRV_updateSlowTick();       /* Diagnostic counter */     slowTicks++;; ‍‍‍‍‍‍     /* insert control code here  for example test for state*/     /*LED1 to indicate motor in Plan mode */     if(user.state == USER_RUN_PLAN)     {         LED4_ON;     }     else     {         LED4_OFF;     }     Conversion: The conveyor example below has two inputs derived from the ADC result register. In the next code listing, the inputs values are scaled and converted to LQ format. These controls are demonstrated in the conveyor belt demonstration shown in the video  Kinetis Motor Control Made Easy . The two potentiometers shown in the picture are fed into an ADC channel.         /*poll external outputs*/     /*GPIO have HW enabled anti-glitch and Pullup*/     /*1 = on 0 = off */     userPlanVariables.On_Off=!((bool)GPIO_DRV_ReadPinInput(kGpioOnOff));     /*high = 1, low = 0 */     userPlanVariables.Low_High=(bool)GPIO_DRV_ReadPinInput(kGpioHighLow);         /*in High speed operation need slightly higher bandwidth */     if(userPlanVariables.Low_High == 0)     {         userPlanVariables.Bandwidth_High = _LQ20(70.0);         userPlanVariables.Bandwidth_Low = _LQ20(10.0);             }     else     {         userPlanVariables.Bandwidth_High = _LQ20(100.0);         userPlanVariables.Bandwidth_Low = _LQ20(15.0);     }     /*Value Scaled to 0-1 in LQ Format Q12->GlobalLQ*/  userPlanVariables . Bandwidth_Scale = _LQXtoLQY ( adc0Results [ 0 ], 12 , GLOBAL_LQ );  position . config . lq20Bw_radps = _LQ20mpyLQX ( userPlanVariables . Bandwidth_High - userPlanVariables . Bandwidth_Low , 20U , userPlanVariables . Bandwidth_Scale , GLOBAL_LQ ) \   + userPlanVariables . Bandwidth_Low ; /*Value Scaled to 0-1 in LQ Format with light exponential weighting .5821*(e^x-1)*/  userPlanVariables . Jerk_Scale = _LQmpy ( _LQXtoLQY ( _LQ20exp ( _LQXtoLQY ( adc1Results [ 0 ], 12 , 20U )), 20 , GLOBAL_LQ ) - _LQ ( 1.0 ), \   _LQ ( 0.581992 )); ‍‍‍‍‍‍‍   You cannot just set the target speed like this using and integer value for RPM.   user.command.targetSpeed = 100; The KMS code uses QMath in the calculations. Conversion of a float or integer to a LQ type is easy to do using the API calls. Check out Chapter 24 Math for the details on the QMath library.   In KMS all values are normalized fixed-point.  So setting user.command.targetSpeed to 100 sets the target speed to a very small value (<< 1RPM).   You need to convert from RPM into the normalized fixed point used by KMS.  user.command.targetSpeed = _LQ(100.0 / FULL_SCALE_SPEED_RPM);   In the above line, FULL_SCALE_SPEED_RPM represents the maximum possible speed in the system.  Dividing the input speed of 100.0 by this value will convert your input into a normalized value.  Since KMS is also fixed point, we need to convert this normalized floating-point number to fixed point.  The macro _LQ will convert from floating point into fixed point at the default Qness.  The variable user.command.targetSpeed is defined as an _lq variable.  This means it is a 32-bit container with a Qness of 24 (24 bits after the decimal point).  By default all _lq variables default to Q24 unless otherwise noted in the variable name.     Commanding Speed: In the KMS_API RM, the user block is defined. The user.state definitions are in the user.h file. If you want to idle the motor you would write: user. state =  USER_IDLE ; To set the user state to run speed you would write: user. state =  USER_RUN_SPEED ;   Here is a list of all the USER_States for speed control. /**  * @enum USER_state_e  * @brief USER state-machine states  */ typedef enum {  USER_IDLE = 0 , /**< 0: USER IDLE state */  USER_FAULT = 1 , /**< 1: USER FAULT state */  USER_SCM = 2 , /**< 2: USER self-commissioning state */  USER_INERTIA = 3 , /**< 3: USER inertia estimation state */  USER_RUN_DUTY = 4 , /**< 4: DSM run PWM duty control state */  USER_RUN_VOLTAGE = 5 , /**< 5: DSM run voltage control state */  USER_RUN_CURRENT = 6 , /**< 6: USER run current control state */  USER_RUN_SPEED = 7 , /**< 7: USER run speed control state */  USER_RUN_PLAN = 8 , /**< 8: USER run a motion plan state */  USER_BRAKE = 9 , /**< 9: USER braking state */ } USER_state_e ; ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍   If you use the feedback_3ph.c as an example piece of code, the raw ADC reading is converted to a _sq with the use of the function (_sq): tempSQ = ( _sq )(adcResults-> phaseBCurrent  - v-> calib . offsetIb ); Likewise, the conversion of the RAW ADC result to LQ is accomplished using the (_lq) function. In the following code example an ADC input is used to control the speed. The code below, takes the ADC results and converts it to an _lq type by means of the following statement: adc0Results[0] = (_lq) adc0RawResults[0];   /* code start */ // declare these as global variables in main.c _lq adcSpeed = 0 ; _lq adcSpeedAccum = 0 ; _lq adcSpeedAvg = 0 ; uint16_t speedUpdateCounter = 0 ;   // this code takes the ADC reading, downshifts it by 4 to remove noise and uses that as a percentage of the maximum applicaton speed (in this case 20krpm) adcSpeed = _LQmpyLQX (( adc0Results [ 0 ] >> 4 ), 8 , _LQ ( 20000.0 / FULL_SCALE_SPEED_RPM ), 24 ); adcSpeed = _LQsat ( adcSpeed , _LQ ( 1.0 ), _LQ ( 0.0 ));   // this code averages the adc reading over 125 samples before setting it to user.command.targetSpeed // it will also handle setting the control mode if the commanded speed is larger than 0 if ( adcSpeed > _LQ ( 0.0 )) {                 user . state = USER_RUN_SPEED ;                 if ( speedUpdateCounter >= 125 )                 {                      speedUpdateCounter = 0 ;                      adcSpeedAvg = ( adcSpeedAccum / 125 ) & 0x00FF0000 ;                      user . command . targetSpeed = adcSpeedAvg ;                      adcSpeedAccum = 0 ;                 }                 else                 {                      adcSpeedAccum = adcSpeed + adcSpeedAccum ;                      speedUpdateCounter ++ ;                  } } else {         user . state = USER_IDLE ;         adcSpeedAccum = 0 ;         adcSpeedAvg = 0 ;         speedUpdateCounter = 0 ; } ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Setting command Values: Before you change a user.state there are parameters like acceleration and jerk you can modify. Prior to change the state you can update any number of other command values list in the function below. The list gives a quick look at the parameters you can update prior to changing the motor state. Each of the command values listed can be updated prior to this call. As you can see, setting the speed value in the line containing command.targetSpeed is just one of five values sent to the drive command.   After setting these parameters, you command a state change to USER_RUN_SPEED user. state =  USER_RUN_SPEED ;   The user state “USER_RUN_SPEED” executes this function which start the motor on the new trajectory. /**  * @fn USER_runSpeedState(USER_t *pUSER, SPEED_t *speed, DRV_control_e controlType, \  * TRF_rVector16_t startupStatorRefCurrent, _sq fwIdRef)  * @brief Runs the Speed Control USER state  * @param pUSER - pointer to the USER block  * @return none  */ static void USER_runSpeedState ( USER_t * pUSER ) {   /* For trajectory, just send command values to DRV*/  pUSER -> output . drvCommand . targetSpeed = pUSER -> command . targetSpeed ;  pUSER -> output . drvCommand . limitAcc = pUSER -> command . limitAcc ;  pUSER -> output . drvCommand . lq20LimitJerk = pUSER -> command . lq20LimitJerk ;  pUSER -> output . drvCommand . IqRefMax = pUSER -> command . IqRefMax ;  pUSER -> output . drvCommand . IqRefMin = pUSER -> command . IqRefMin ; /* Run trajectory generator in this state */  pUSER -> output . drvCommand . runTrajectory = true ; return ; } /* end of USER_runSpeedState() */ ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍     Commanding Torque: If you wanted to command torque (current), then you would initialize the command values identified in the code below. In addition to command .statorRefCurrent, you can specify a command.targetSpeed.  /**  * @fn USER_runCurrentState(USER_t *pUSER)  * @brief Runs the Current control USER state  * @param pUSER - pointer to the USER block  * @return none  */ static void USER_runCurrentState ( USER_t * pUSER ) {  pUSER -> output . drvCommand . targetSpeed = pUSER -> command . targetSpeed ;  pUSER -> output . drvCommand . limitAcc = pUSER -> command . limitAcc ;  pUSER -> output . drvCommand . lq20LimitJerk = pUSER -> command . lq20LimitJerk ;  pUSER -> output . drvCommand . statorRefCurrent = pUSER -> command . statorRefCurrent ;  pUSER -> output . drvCommand . enableDCInjection = pUSER -> command . enableDCInjection ; return ; } /* end of USER_runCurrentState() */ ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Commanding Position: When using KMS to control a position, the call to the following function is made.  The motor position control follows a trajectory that you choose prior to the call by setting the command values to the motor drive state machine. In the position control reference project include file "user.h" there are two more USER state-machine states added to the list of USER_STATES -> USER_RUN_POSITION and USER_ALIGN. /**  * @enum    USER_state_e  * @brief   USER state-machine states  */ typedef enum {     USER_IDLE         = 0 , /**< 0: USER IDLE state */     USER_FAULT        = 1 , /**< 1: USER FAULT state */     USER_SCM          = 2 , /**< 2: USER self-commissioning state */     USER_INERTIA      = 3 , /**< 3: USER inertia estimation state */     USER_RUN_DUTY     = 4 , /**< 4: DSM run PWM duty control state */     USER_RUN_VOLTAGE  = 5 , /**< 5: DSM run voltage control state */     USER_RUN_CURRENT  = 6 , /**< 6: USER run current control state */     USER_RUN_SPEED    = 7 , /**< 7: USER run position-controlled speed state */     USER_RUN_PLAN     = 8 , /**< 8: USER run a motion plan state */     USER_BRAKE        = 9 , /**< 9: USER braking state */     USER_RUN_POSITION = 10 , /**< 10: USER run position control state */     USER_ALIGN        = 11   /**< 11: USER force motor into alignment */ } USER_state_e ; ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ To command a position, set the command values and then set the state to USER_RUN_POSITION user. state =  USER_RUN_POSITION ; This will result in a trajectory to be executed.  /**  * @fn USER runSpeedState(USER_t *pUSER,SPEED_t *speed,DRV_control_e controlType,  * TRF_rVector16_t startupStatorRefCurrent, _sq fwIdRef)  * @brief Runs the Speed Control USER state  * @param pUSER - pointer to the USER block  * @return none  */ static void USER_runPositionState ( USER_t * pUSER ) {   /* For trajectory, just send command values to DRV*/  pUSER -> output . drvCommand . runTrajectory = pUSER -> command . runTrajectory ;  pUSER -> output . drvCommand . posStepInt_mrev = pUSER -> command . posStepInt_mrev ;  pUSER -> output . drvCommand . posStepFrac_mrev = pUSER -> command . posStepFrac_mrev ;  pUSER -> output . drvCommand . limitVel = pUSER -> command . limitVel ;  pUSER -> output . drvCommand . limitAcc = pUSER -> command . limitAcc ;  pUSER -> output . drvCommand . limitDec = pUSER -> command . limitDec ;  pUSER -> output . drvCommand . lq20LimitJerk = pUSER -> command . lq20LimitJerk ;  pUSER -> output . drvCommand . IqRefMax = pUSER -> command . IqRefMax ;  pUSER -> output . drvCommand . IqRefMin = pUSER -> command . IqRefMin ; /* Run trajectory generator in position mode */  pUSER -> output . drvCommand . velocityMode = false ; return ; } /* end of USER_runSpeedState() */ ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Below is a bare metal code example used to drive the X or Y axis of a position controller.  The UART receives the command and a sync pulse on a GPIO starts the trajectory profile. This is not very robust code with very little command format checking.  I encourage you to consider the limit conditions and correctness of the input command values before using them to command the motor position.  This code tends to occasionally miss-fire and send the 3D printer base flying to the end stop. user . state = USER_RUN_POSITION ; while ( true ) { // LED2 GREEN is DC BUS Charging Indicator, disable if fault if ( DRV_getDcbBusVoltage () < DRV_getDcbBusUnderVoltageThreshold () || DRV_getIsFaultActive ()) LED2_OFF ; else LED2_ON ; // Expected format: xAAAAAAAABBBBBBBBX // Wait for initial 'x' or 'y', remember to set this in axis variable GPIOC_PSOR = ( 1 << 3 ); //set buffer ready do { cin = UART1_CharIn ();} while ( cin != axis ); // Read AAAAAAAA (dx as a float) mem = ( byte * ) & f1 ; for ( i = 0 ; i < 4 ; i ++ ) { * mem = UART1_ByteIn (); mem ++ ;} // Read BBBBBBBB (dy as a float) mem = ( byte * ) & f2 ; for ( i = 0 ; i < 4 ; i ++ ) { * mem = UART1_ByteIn (); mem ++ ;} // Wait for final 'X' or 'Y': if not an 'X' or 'Y', ignore message cin = UART1_CharIn (); if ( cin == axis -32 )   {  GPIOC_PCOR = ( 1 << 3 );   UART_CharOut ( axis );   // Valid Message, go ahead and execute   // ROTATION: extract integer part of rotation  value = ( int ) f1 ;  user . command . posStepInt_mrev = value ;   //UART_TextOut("IntRotation=");   UART_DbleOut ( value , 4 , 1 );   // ROTATION: extract fractional part of rotation  user . command . posStepFrac_mrev = _LQ ( f1 - value );   //UART_TextOut("FracRotation=");   UART_DbleOut ( f1 - value , 4 , 4 );   // SPEED: extract integer part of rotation  f2 = f2 / 4000.0 ;  user . command . limitVel = _LQ ( f2 );   //UART_TextOut("SpeedRPM=");   UART_DbleOut ( f2 , 4 , 4 );  GPIOC_PSOR = ( 1 << 6 );   // Wait for Sync   while ((( GPIOE_PDIR & ( 1 << 6 )) == 0 ));  GPIOC_PCOR = ( 1 << 6 );  flag = 0 ; done = 1 ; user . command . runTrajectory = 1 ;   while ( done == 1 ) { UART_CharOut ( '1' );}  GPIOC_PSOR = ( 1 << 6 );   } } //while (true)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍   Conclusion: Four steps are needed: Check the existing state of the motor, managing faults and trajectories. Convert the commanded inputs to the fixed-point values needed by KMS. Set the configuration parameters, like acceleration, jerk and speed. Change the user state to the desired state, Speed, Torque, Position.     Philip Drake Systems Applications Engineer
View full article
A recent post brought up a good point that I replied to just now.kms, #kinetismotorsuite‌. I wanted for create a document to address the issues he faced, the idea of a ROM and to give a little information about KMS at NXP. A ROM would be ideal for this application. However, NXP had developed the MCUs prior to the availablity of the KMS library and the MCUs did not include a ROM The IP we used: NXP has implemented IP in the MCU (MCU features) that enable customer to use secured code, marked as execute only.   The feature on the MCUs that enable this option is call flash access protection (FAC).  Any code placed in the flash can be protected from being read through any means by setting the Flash access control bits.  The NXP system architects chose to offer the KV series that had FAC with the option of using KMS.  Mass Erase Protection: Please see the MKV RM for more information on these features! With the introduction of KMS we saw the need to protect the MCU flash from mass erase and made some IP improvements to enable this.  The KV series MCUs shipped after ww14 of 2016 have an added feature to prevent mass erase of the flash even when the MCU is not-secured. This means that the FSEC bits in the FPROT registers of the flash don't come into play when the MCU is enabling or disabling mass erase.  The MEEN bits in the FSEC register can be set to 'b10, thus preventing the mass erase of the MCU's flash.  CAUTION: As always when you secure the MCU and disable Mass Erase, the MCU flash is locked down and cannot be accessed.  The only way you can get back into the flash is to enabled another flash option called the Back Door Access. . KMS Reference Project Protection Option: This setting is available in the flash config of the KMS reference projects.  You can change a #define to engage this protection. It is not engaged as a default because the tools did not properly respond to the setting of the MEEN bits Tools: The tool vendors included Segger, IAR, P&E as well as the OpenSDA MBED firmware that was previously supplied  did not handle the mass erase protection IP very well at first.  In fact, it is only with the latest release of P&E firmware updates and eclipse plug-ins, that the mass erase is prevented.   Philip Drake Senior Systems Applications Engineer NXP Semiconductor
View full article
Attached is a guidelines presentation that is appropriate for 2 layer boards. It relies on transmission line techniques to prevent noise problems – emissions and susceptibility. The transmission line techniques are meant for emissions, but the concepts aid susceptibility as well since noise voltages and currents are generally kept under control.   The length of traces versus the wavelength of the signal transitions is not an easy subject to grasp. A ¼ wavelength antenna is an efficient antenna for propagation and reception. Traces of any length greater than about 1/10 of a wavelength that do not have controlled impedances will present discontinuities that can cause system supply noise and crosstalk. One basic element for high speed design is to not split ground planes, or more properly, to not cross a split in a return plane. Two layer boards do not have effective ground planes, and the return paths are difficult to find. It’s the return paths that cause most of the problems in EMC. The guidelines document shows how we have built 2 layer designs that excelled in harsh noise environments. One of the basic points was to keep each signal adjacent to a return path all along its length. This meant stitching top and bottom grounds to direct the energy where we wanted it to go.   Your 2 layer board may work fine in normal operation. My concern is the transient cases, whether ESD, line transients, or self-generated noise. Also see:   Daniel Beeker has a great training “Effective Printed Circuit Board Design”   here .
View full article
If you have a KV31, or KV11 evaluation board and you want to evaluate Kinetis Motor Suite (KMS) then read on. KMS came out in the 2nd quarter of 2016.  With that announcement we began supporting KMS on the FRDM-KV31F, the TWR-KV31F120M and the HVP-KV31120M. With the announcement June 2017 we added support for HVP-KV11Z75M, TWR-KV11Z75M, and FRDM-KV11Z evaluation boards. Before that announcement NXP had sold all but the FRDM-KV11Z evaluation boards to customers and to distributors world wide. The FRDM-KV11Z are all KMS enabled since they are brand new.  Those sold prior to these announcements did not include the KMS library on the eval board's MCU. As a general rule: evaluation boards in the thin square white NXP box are KMS enabled boards.  I'm holding up one of these boxes in the picture below.  The older Freescale brown boxes may not be KMS enabled. For sure if the Quick start guide says it is KMS enabled then the KMS library is pre-programmed into the MCU. If you have the older board and want to swap it out for one that is KMS enabled, contact me on this community and I will help you out.  I will accept your older board, place the factory image on the board's MCU and send it back. Happy Motoring, Philip Drake Senior Applications and System Engineer NXP Semiconductor
View full article
KMS-enabled devices come with pre-loaded firmware that is essential to the platform. We have taken precautions to make sure this pre-loaded firmware cannot be erased, but older tool versions have the potential to erase it under certain conditions. For this reason we recommend that you make sure to update your tools as follows:   P&E's plugin v2.3.8 (at least) and later for debugging using the board debugger or an external P&E dongle. Current version as of writing of this post is 2.7.0.   If using KDS (Kinetis Design Studio) make sure to be using version 3.2 or later.   To update to the latest P&E plugin please follow these steps: In KDS go to Help -> Install New Software Select PEMicro - http://www.pemicro.com/eclipse/updates from the Work with drop down menu Select to install the latest P&E plugin and click Next. Once the installation is complete, please restart IDE and confirm that the latest plugin is installed by going to Help -> Installation Details and seeing that GBDU ARM Pemicro plugin installed is v2.7.0 (or later).
View full article
#Introduction: This document steps the changing of the TWR-MC-LV3PH board to work at 48V 16 A and how to effect these changes in the KMS tool. As you begin to customize your hardware this document can be used to supplement the information you need to get your custom board up and running with KMS. Please Add these steps to change the max voltage and/or current values in the KMS tool.    Version 3: Corrected VBUS maximum voltage showing relationship the KMS GUI invokes on the Nominal Motor Bus voltage.  Version 4: Added paragraph on the sizing of the shunt resistors in response to Pavel's notes. Regards, Philip
View full article
OH NO! It has come to my attention that a batch of FRDM-KV31F MCU boards, were shipped to people, programmed with MBED OpenSDA firmware.   The Kinetis Motor Suite GUI scripts load the reference project image into the KV31F MCU flash using the MSD programming built into the P&E Micro firmware. It specifically looks for the FRDM-KV31F MSD drive.  NXP moved away from the MBED firmware to eliminate the mass erase possibilities that could occur.   The FRDM-KV31F does not appear on these MBED boards. In fact, unless you have run the mbedWinSerial.exe installer found here, or get the latest driver here  the mbed serial port will not enumerate. Plug in your FRDM-KV31F board and run the installer.  But let's not stop there. We want to make sure you don't mass erase your MCU and blow away the  KMS execute only library stored in the MCU's flash.   Let me give you a work around for now. Any MBED enabled FRDM board will still work with KMS, but you should use the Segger JLINK debug interface. It will not mass erase your KMS firmware like the MBED debug interface can.   WORKAROUND: The workaround uses the Segger Jlink OPENSDA 2.1 firmware.   The MBED OPENSDA driver can be replaced with the SEGGER jlink version of the debug tool. https://www.segger.com/opensda.html. It does not have a drag and drop feature which is used by KMS, but that is not a bad thing.  The segger debug has a good serial interface and is supported by KDS and IAR.    Steps for the workaround Put the MBED debug into bootloader mode Drag and drop the .bin of the Segger debug tool Power cycle board. Open KMS – create a new project When the image does not match and KMS wants to communicate or download a new image, decline.  We will do this manually with the IDE. If IAR – open the new project – compile the release versions of startup and platform. Open options for the FRDM target application and change debugger from PEMICRO to JLINK if KDS - do the same basic switch that we did with IAR – select the JLINK as the download and debug interface. Compile and download to the MCU. Run the program and exit from debug. If you are using KDS you will have to now have to hit the reset button on the FRDM-KV31F board. Go back to the KMS window and connect with the  icon  and then verify this icon shows you  connected Execute KMS normally. If you use the Motion Sequence Build, note that hitting the TARGET will compile but the download script will fail. You will want to compile and download the project back in the IDE. I hope this is a help. I’ll be working on a way to get the PEMICRO OPENSDA binary onto the board for MSD drag and drop functionality.   Happy Motoring Philip Drake Systems Engineer NXP
View full article