mirror of
				https://github.com/IcedRooibos/py32f0-template.git
				synced 2025-11-03 10:22:05 -08:00 
			
		
		
		
	
		
			
				
	
	
		
			792 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			792 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/******************************************************************************
 | 
						|
 * @file     controller_functions.h
 | 
						|
 * @brief    Public header file for CMSIS DSP Library
 | 
						|
 * @version  V1.10.0
 | 
						|
 * @date     08 July 2021
 | 
						|
 * Target Processor: Cortex-M and Cortex-A cores
 | 
						|
 ******************************************************************************/
 | 
						|
/*
 | 
						|
 * Copyright (c) 2010-2020 Arm Limited or its affiliates. All rights reserved.
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier: Apache-2.0
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the License); you may
 | 
						|
 * not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 * www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, software
 | 
						|
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 | 
						|
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 * See the License for the specific language governing permissions and
 | 
						|
 * limitations under the License.
 | 
						|
 */
 | 
						|
 | 
						|
 
 | 
						|
#ifndef _CONTROLLER_FUNCTIONS_H_
 | 
						|
#define _CONTROLLER_FUNCTIONS_H_
 | 
						|
 | 
						|
#include "arm_math_types.h"
 | 
						|
#include "arm_math_memory.h"
 | 
						|
 | 
						|
#include "dsp/none.h"
 | 
						|
#include "dsp/utils.h"
 | 
						|
 | 
						|
#ifdef   __cplusplus
 | 
						|
extern "C"
 | 
						|
{
 | 
						|
#endif
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief Macros required for SINE and COSINE Controller functions
 | 
						|
   */
 | 
						|
 | 
						|
#define CONTROLLER_Q31_SHIFT  (32 - 9)
 | 
						|
  /* 1.31(q31) Fixed value of 2/360 */
 | 
						|
  /* -1 to +1 is divided into 360 values so total spacing is (2/360) */
 | 
						|
#define INPUT_SPACING         0xB60B61
 | 
						|
  
 | 
						|
/**
 | 
						|
 * @defgroup groupController Controller Functions
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
 /**
 | 
						|
   * @ingroup groupController
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @addtogroup SinCos
 | 
						|
   * @{
 | 
						|
   */
 | 
						|
 | 
						|
/**
 | 
						|
   * @brief  Floating-point sin_cos function.
 | 
						|
   * @param[in]  theta   input value in degrees
 | 
						|
   * @param[out] pSinVal  points to the processed sine output.
 | 
						|
   * @param[out] pCosVal  points to the processed cos output.
 | 
						|
   */
 | 
						|
  void arm_sin_cos_f32(
 | 
						|
        float32_t theta,
 | 
						|
        float32_t * pSinVal,
 | 
						|
        float32_t * pCosVal);
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief  Q31 sin_cos function.
 | 
						|
   * @param[in]  theta    scaled input value in degrees
 | 
						|
   * @param[out] pSinVal  points to the processed sine output.
 | 
						|
   * @param[out] pCosVal  points to the processed cosine output.
 | 
						|
   */
 | 
						|
  void arm_sin_cos_q31(
 | 
						|
        q31_t theta,
 | 
						|
        q31_t * pSinVal,
 | 
						|
        q31_t * pCosVal);
 | 
						|
 | 
						|
  /**
 | 
						|
   * @} end of SinCos group
 | 
						|
   */
 | 
						|
 | 
						|
 /**
 | 
						|
   * @ingroup groupController
 | 
						|
   */
 | 
						|
 | 
						|
/**
 | 
						|
   * @defgroup PID PID Motor Control
 | 
						|
   *
 | 
						|
   * A Proportional Integral Derivative (PID) controller is a generic feedback control
 | 
						|
   * loop mechanism widely used in industrial control systems.
 | 
						|
   * A PID controller is the most commonly used type of feedback controller.
 | 
						|
   *
 | 
						|
   * This set of functions implements (PID) controllers
 | 
						|
   * for Q15, Q31, and floating-point data types.  The functions operate on a single sample
 | 
						|
   * of data and each call to the function returns a single processed value.
 | 
						|
   * <code>S</code> points to an instance of the PID control data structure.  <code>in</code>
 | 
						|
   * is the input sample value. The functions return the output value.
 | 
						|
   *
 | 
						|
   * \par Algorithm:
 | 
						|
   * <pre>
 | 
						|
   *    y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]
 | 
						|
   *    A0 = Kp + Ki + Kd
 | 
						|
   *    A1 = (-Kp ) - (2 * Kd )
 | 
						|
   *    A2 = Kd
 | 
						|
   * </pre>
 | 
						|
   *
 | 
						|
   * \par
 | 
						|
   * where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant
 | 
						|
   *
 | 
						|
   * \par
 | 
						|
   * \image html PID.gif "Proportional Integral Derivative Controller"
 | 
						|
   *
 | 
						|
   * \par
 | 
						|
   * The PID controller calculates an "error" value as the difference between
 | 
						|
   * the measured output and the reference input.
 | 
						|
   * The controller attempts to minimize the error by adjusting the process control inputs.
 | 
						|
   * The proportional value determines the reaction to the current error,
 | 
						|
   * the integral value determines the reaction based on the sum of recent errors,
 | 
						|
   * and the derivative value determines the reaction based on the rate at which the error has been changing.
 | 
						|
   *
 | 
						|
   * \par Instance Structure
 | 
						|
   * The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure.
 | 
						|
   * A separate instance structure must be defined for each PID Controller.
 | 
						|
   * There are separate instance structure declarations for each of the 3 supported data types.
 | 
						|
   *
 | 
						|
   * \par Reset Functions
 | 
						|
   * There is also an associated reset function for each data type which clears the state array.
 | 
						|
   *
 | 
						|
   * \par Initialization Functions
 | 
						|
   * There is also an associated initialization function for each data type.
 | 
						|
   * The initialization function performs the following operations:
 | 
						|
   * - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains.
 | 
						|
   * - Zeros out the values in the state buffer.
 | 
						|
   *
 | 
						|
   * \par
 | 
						|
   * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function.
 | 
						|
   *
 | 
						|
   * \par Fixed-Point Behavior
 | 
						|
   * Care must be taken when using the fixed-point versions of the PID Controller functions.
 | 
						|
   * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered.
 | 
						|
   * Refer to the function specific documentation below for usage guidelines.
 | 
						|
   */
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief Instance structure for the Q15 PID Control.
 | 
						|
   */
 | 
						|
  typedef struct
 | 
						|
  {
 | 
						|
          q15_t A0;           /**< The derived gain, A0 = Kp + Ki + Kd . */
 | 
						|
#if !defined (ARM_MATH_DSP)
 | 
						|
          q15_t A1;           /**< The derived gain A1 = -Kp - 2Kd */
 | 
						|
          q15_t A2;           /**< The derived gain A1 = Kd. */
 | 
						|
#else
 | 
						|
          q31_t A1;           /**< The derived gain A1 = -Kp - 2Kd | Kd.*/
 | 
						|
#endif
 | 
						|
          q15_t state[3];     /**< The state array of length 3. */
 | 
						|
          q15_t Kp;           /**< The proportional gain. */
 | 
						|
          q15_t Ki;           /**< The integral gain. */
 | 
						|
          q15_t Kd;           /**< The derivative gain. */
 | 
						|
  } arm_pid_instance_q15;
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief Instance structure for the Q31 PID Control.
 | 
						|
   */
 | 
						|
  typedef struct
 | 
						|
  {
 | 
						|
          q31_t A0;            /**< The derived gain, A0 = Kp + Ki + Kd . */
 | 
						|
          q31_t A1;            /**< The derived gain, A1 = -Kp - 2Kd. */
 | 
						|
          q31_t A2;            /**< The derived gain, A2 = Kd . */
 | 
						|
          q31_t state[3];      /**< The state array of length 3. */
 | 
						|
          q31_t Kp;            /**< The proportional gain. */
 | 
						|
          q31_t Ki;            /**< The integral gain. */
 | 
						|
          q31_t Kd;            /**< The derivative gain. */
 | 
						|
  } arm_pid_instance_q31;
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief Instance structure for the floating-point PID Control.
 | 
						|
   */
 | 
						|
  typedef struct
 | 
						|
  {
 | 
						|
          float32_t A0;          /**< The derived gain, A0 = Kp + Ki + Kd . */
 | 
						|
          float32_t A1;          /**< The derived gain, A1 = -Kp - 2Kd. */
 | 
						|
          float32_t A2;          /**< The derived gain, A2 = Kd . */
 | 
						|
          float32_t state[3];    /**< The state array of length 3. */
 | 
						|
          float32_t Kp;          /**< The proportional gain. */
 | 
						|
          float32_t Ki;          /**< The integral gain. */
 | 
						|
          float32_t Kd;          /**< The derivative gain. */
 | 
						|
  } arm_pid_instance_f32;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief  Initialization function for the floating-point PID Control.
 | 
						|
   * @param[in,out] S               points to an instance of the PID structure.
 | 
						|
   * @param[in]     resetStateFlag  flag to reset the state. 0 = no change in state 1 = reset the state.
 | 
						|
   */
 | 
						|
  void arm_pid_init_f32(
 | 
						|
        arm_pid_instance_f32 * S,
 | 
						|
        int32_t resetStateFlag);
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief  Reset function for the floating-point PID Control.
 | 
						|
   * @param[in,out] S  is an instance of the floating-point PID Control structure
 | 
						|
   */
 | 
						|
  void arm_pid_reset_f32(
 | 
						|
        arm_pid_instance_f32 * S);
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief  Initialization function for the Q31 PID Control.
 | 
						|
   * @param[in,out] S               points to an instance of the Q15 PID structure.
 | 
						|
   * @param[in]     resetStateFlag  flag to reset the state. 0 = no change in state 1 = reset the state.
 | 
						|
   */
 | 
						|
  void arm_pid_init_q31(
 | 
						|
        arm_pid_instance_q31 * S,
 | 
						|
        int32_t resetStateFlag);
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief  Reset function for the Q31 PID Control.
 | 
						|
   * @param[in,out] S   points to an instance of the Q31 PID Control structure
 | 
						|
   */
 | 
						|
 | 
						|
  void arm_pid_reset_q31(
 | 
						|
        arm_pid_instance_q31 * S);
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief  Initialization function for the Q15 PID Control.
 | 
						|
   * @param[in,out] S               points to an instance of the Q15 PID structure.
 | 
						|
   * @param[in]     resetStateFlag  flag to reset the state. 0 = no change in state 1 = reset the state.
 | 
						|
   */
 | 
						|
  void arm_pid_init_q15(
 | 
						|
        arm_pid_instance_q15 * S,
 | 
						|
        int32_t resetStateFlag);
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief  Reset function for the Q15 PID Control.
 | 
						|
   * @param[in,out] S  points to an instance of the q15 PID Control structure
 | 
						|
   */
 | 
						|
  void arm_pid_reset_q15(
 | 
						|
        arm_pid_instance_q15 * S);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @addtogroup PID
 | 
						|
   * @{
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief         Process function for the floating-point PID Control.
 | 
						|
   * @param[in,out] S   is an instance of the floating-point PID Control structure
 | 
						|
   * @param[in]     in  input sample to process
 | 
						|
   * @return        processed output sample.
 | 
						|
   */
 | 
						|
  __STATIC_FORCEINLINE float32_t arm_pid_f32(
 | 
						|
  arm_pid_instance_f32 * S,
 | 
						|
  float32_t in)
 | 
						|
  {
 | 
						|
    float32_t out;
 | 
						|
 | 
						|
    /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]  */
 | 
						|
    out = (S->A0 * in) +
 | 
						|
      (S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]);
 | 
						|
 | 
						|
    /* Update state */
 | 
						|
    S->state[1] = S->state[0];
 | 
						|
    S->state[0] = in;
 | 
						|
    S->state[2] = out;
 | 
						|
 | 
						|
    /* return to application */
 | 
						|
    return (out);
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
/**
 | 
						|
  @brief         Process function for the Q31 PID Control.
 | 
						|
  @param[in,out] S  points to an instance of the Q31 PID Control structure
 | 
						|
  @param[in]     in  input sample to process
 | 
						|
  @return        processed output sample.
 | 
						|
 | 
						|
  \par Scaling and Overflow Behavior
 | 
						|
         The function is implemented using an internal 64-bit accumulator.
 | 
						|
         The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit.
 | 
						|
         Thus, if the accumulator result overflows it wraps around rather than clip.
 | 
						|
         In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions.
 | 
						|
         After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format.
 | 
						|
 */
 | 
						|
__STATIC_FORCEINLINE q31_t arm_pid_q31(
 | 
						|
  arm_pid_instance_q31 * S,
 | 
						|
  q31_t in)
 | 
						|
  {
 | 
						|
    q63_t acc;
 | 
						|
    q31_t out;
 | 
						|
 | 
						|
    /* acc = A0 * x[n]  */
 | 
						|
    acc = (q63_t) S->A0 * in;
 | 
						|
 | 
						|
    /* acc += A1 * x[n-1] */
 | 
						|
    acc += (q63_t) S->A1 * S->state[0];
 | 
						|
 | 
						|
    /* acc += A2 * x[n-2]  */
 | 
						|
    acc += (q63_t) S->A2 * S->state[1];
 | 
						|
 | 
						|
    /* convert output to 1.31 format to add y[n-1] */
 | 
						|
    out = (q31_t) (acc >> 31U);
 | 
						|
 | 
						|
    /* out += y[n-1] */
 | 
						|
    out += S->state[2];
 | 
						|
 | 
						|
    /* Update state */
 | 
						|
    S->state[1] = S->state[0];
 | 
						|
    S->state[0] = in;
 | 
						|
    S->state[2] = out;
 | 
						|
 | 
						|
    /* return to application */
 | 
						|
    return (out);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  @brief         Process function for the Q15 PID Control.
 | 
						|
  @param[in,out] S   points to an instance of the Q15 PID Control structure
 | 
						|
  @param[in]     in  input sample to process
 | 
						|
  @return        processed output sample.
 | 
						|
 | 
						|
  \par Scaling and Overflow Behavior
 | 
						|
         The function is implemented using a 64-bit internal accumulator.
 | 
						|
         Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result.
 | 
						|
         The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format.
 | 
						|
         There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved.
 | 
						|
         After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits.
 | 
						|
         Lastly, the accumulator is saturated to yield a result in 1.15 format.
 | 
						|
 */
 | 
						|
__STATIC_FORCEINLINE q15_t arm_pid_q15(
 | 
						|
  arm_pid_instance_q15 * S,
 | 
						|
  q15_t in)
 | 
						|
  {
 | 
						|
    q63_t acc;
 | 
						|
    q15_t out;
 | 
						|
 | 
						|
#if defined (ARM_MATH_DSP)
 | 
						|
    /* Implementation of PID controller */
 | 
						|
 | 
						|
    /* acc = A0 * x[n]  */
 | 
						|
    acc = (q31_t) __SMUAD((uint32_t)S->A0, (uint32_t)in);
 | 
						|
 | 
						|
    /* acc += A1 * x[n-1] + A2 * x[n-2]  */
 | 
						|
    acc = (q63_t)__SMLALD((uint32_t)S->A1, (uint32_t)read_q15x2 (S->state), (uint64_t)acc);
 | 
						|
#else
 | 
						|
    /* acc = A0 * x[n]  */
 | 
						|
    acc = ((q31_t) S->A0) * in;
 | 
						|
 | 
						|
    /* acc += A1 * x[n-1] + A2 * x[n-2]  */
 | 
						|
    acc += (q31_t) S->A1 * S->state[0];
 | 
						|
    acc += (q31_t) S->A2 * S->state[1];
 | 
						|
#endif
 | 
						|
 | 
						|
    /* acc += y[n-1] */
 | 
						|
    acc += (q31_t) S->state[2] << 15;
 | 
						|
 | 
						|
    /* saturate the output */
 | 
						|
    out = (q15_t) (__SSAT((q31_t)(acc >> 15), 16));
 | 
						|
 | 
						|
    /* Update state */
 | 
						|
    S->state[1] = S->state[0];
 | 
						|
    S->state[0] = in;
 | 
						|
    S->state[2] = out;
 | 
						|
 | 
						|
    /* return to application */
 | 
						|
    return (out);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * @} end of PID group
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @ingroup groupController
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @defgroup park Vector Park Transform
 | 
						|
   *
 | 
						|
   * Forward Park transform converts the input two-coordinate vector to flux and torque components.
 | 
						|
   * The Park transform can be used to realize the transformation of the <code>Ialpha</code> and the <code>Ibeta</code> currents
 | 
						|
   * from the stationary to the moving reference frame and control the spatial relationship between
 | 
						|
   * the stator vector current and rotor flux vector.
 | 
						|
   * If we consider the d axis aligned with the rotor flux, the diagram below shows the
 | 
						|
   * current vector and the relationship from the two reference frames:
 | 
						|
   * \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame"
 | 
						|
   *
 | 
						|
   * The function operates on a single sample of data and each call to the function returns the processed output.
 | 
						|
   * The library provides separate functions for Q31 and floating-point data types.
 | 
						|
   * \par Algorithm
 | 
						|
   * \image html parkFormula.gif
 | 
						|
   * where <code>Ialpha</code> and <code>Ibeta</code> are the stator vector components,
 | 
						|
   * <code>pId</code> and <code>pIq</code> are rotor vector components and <code>cosVal</code> and <code>sinVal</code> are the
 | 
						|
   * cosine and sine values of theta (rotor flux position).
 | 
						|
   * \par Fixed-Point Behavior
 | 
						|
   * Care must be taken when using the Q31 version of the Park transform.
 | 
						|
   * In particular, the overflow and saturation behavior of the accumulator used must be considered.
 | 
						|
   * Refer to the function specific documentation below for usage guidelines.
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @addtogroup park
 | 
						|
   * @{
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @brief Floating-point Park transform
 | 
						|
   * @param[in]  Ialpha  input two-phase vector coordinate alpha
 | 
						|
   * @param[in]  Ibeta   input two-phase vector coordinate beta
 | 
						|
   * @param[out] pId     points to output   rotor reference frame d
 | 
						|
   * @param[out] pIq     points to output   rotor reference frame q
 | 
						|
   * @param[in]  sinVal  sine value of rotation angle theta
 | 
						|
   * @param[in]  cosVal  cosine value of rotation angle theta
 | 
						|
   * @return     none
 | 
						|
   *
 | 
						|
   * The function implements the forward Park transform.
 | 
						|
   *
 | 
						|
   */
 | 
						|
  __STATIC_FORCEINLINE void arm_park_f32(
 | 
						|
  float32_t Ialpha,
 | 
						|
  float32_t Ibeta,
 | 
						|
  float32_t * pId,
 | 
						|
  float32_t * pIq,
 | 
						|
  float32_t sinVal,
 | 
						|
  float32_t cosVal)
 | 
						|
  {
 | 
						|
    /* Calculate pId using the equation, pId = Ialpha * cosVal + Ibeta * sinVal */
 | 
						|
    *pId = Ialpha * cosVal + Ibeta * sinVal;
 | 
						|
 | 
						|
    /* Calculate pIq using the equation, pIq = - Ialpha * sinVal + Ibeta * cosVal */
 | 
						|
    *pIq = -Ialpha * sinVal + Ibeta * cosVal;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  @brief  Park transform for Q31 version
 | 
						|
  @param[in]  Ialpha  input two-phase vector coordinate alpha
 | 
						|
  @param[in]  Ibeta   input two-phase vector coordinate beta
 | 
						|
  @param[out] pId     points to output rotor reference frame d
 | 
						|
  @param[out] pIq     points to output rotor reference frame q
 | 
						|
  @param[in]  sinVal  sine value of rotation angle theta
 | 
						|
  @param[in]  cosVal  cosine value of rotation angle theta
 | 
						|
  @return     none
 | 
						|
 | 
						|
  \par Scaling and Overflow Behavior
 | 
						|
         The function is implemented using an internal 32-bit accumulator.
 | 
						|
         The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
 | 
						|
         There is saturation on the addition and subtraction, hence there is no risk of overflow.
 | 
						|
 */
 | 
						|
__STATIC_FORCEINLINE void arm_park_q31(
 | 
						|
  q31_t Ialpha,
 | 
						|
  q31_t Ibeta,
 | 
						|
  q31_t * pId,
 | 
						|
  q31_t * pIq,
 | 
						|
  q31_t sinVal,
 | 
						|
  q31_t cosVal)
 | 
						|
  {
 | 
						|
    q31_t product1, product2;                    /* Temporary variables used to store intermediate results */
 | 
						|
    q31_t product3, product4;                    /* Temporary variables used to store intermediate results */
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (Ialpha * cosVal) */
 | 
						|
    product1 = (q31_t) (((q63_t) (Ialpha) * (cosVal)) >> 31);
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (Ibeta * sinVal) */
 | 
						|
    product2 = (q31_t) (((q63_t) (Ibeta) * (sinVal)) >> 31);
 | 
						|
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (Ialpha * sinVal) */
 | 
						|
    product3 = (q31_t) (((q63_t) (Ialpha) * (sinVal)) >> 31);
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (Ibeta * cosVal) */
 | 
						|
    product4 = (q31_t) (((q63_t) (Ibeta) * (cosVal)) >> 31);
 | 
						|
 | 
						|
    /* Calculate pId by adding the two intermediate products 1 and 2 */
 | 
						|
    *pId = __QADD(product1, product2);
 | 
						|
 | 
						|
    /* Calculate pIq by subtracting the two intermediate products 3 from 4 */
 | 
						|
    *pIq = __QSUB(product4, product3);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * @} end of park group
 | 
						|
   */
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @ingroup groupController
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @defgroup inv_park Vector Inverse Park transform
 | 
						|
   * Inverse Park transform converts the input flux and torque components to two-coordinate vector.
 | 
						|
   *
 | 
						|
   * The function operates on a single sample of data and each call to the function returns the processed output.
 | 
						|
   * The library provides separate functions for Q31 and floating-point data types.
 | 
						|
   * \par Algorithm
 | 
						|
   * \image html parkInvFormula.gif
 | 
						|
   * where <code>pIalpha</code> and <code>pIbeta</code> are the stator vector components,
 | 
						|
   * <code>Id</code> and <code>Iq</code> are rotor vector components and <code>cosVal</code> and <code>sinVal</code> are the
 | 
						|
   * cosine and sine values of theta (rotor flux position).
 | 
						|
   * \par Fixed-Point Behavior
 | 
						|
   * Care must be taken when using the Q31 version of the Park transform.
 | 
						|
   * In particular, the overflow and saturation behavior of the accumulator used must be considered.
 | 
						|
   * Refer to the function specific documentation below for usage guidelines.
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @addtogroup inv_park
 | 
						|
   * @{
 | 
						|
   */
 | 
						|
 | 
						|
   /**
 | 
						|
   * @brief  Floating-point Inverse Park transform
 | 
						|
   * @param[in]  Id       input coordinate of rotor reference frame d
 | 
						|
   * @param[in]  Iq       input coordinate of rotor reference frame q
 | 
						|
   * @param[out] pIalpha  points to output two-phase orthogonal vector axis alpha
 | 
						|
   * @param[out] pIbeta   points to output two-phase orthogonal vector axis beta
 | 
						|
   * @param[in]  sinVal   sine value of rotation angle theta
 | 
						|
   * @param[in]  cosVal   cosine value of rotation angle theta
 | 
						|
   * @return     none
 | 
						|
   */
 | 
						|
  __STATIC_FORCEINLINE void arm_inv_park_f32(
 | 
						|
  float32_t Id,
 | 
						|
  float32_t Iq,
 | 
						|
  float32_t * pIalpha,
 | 
						|
  float32_t * pIbeta,
 | 
						|
  float32_t sinVal,
 | 
						|
  float32_t cosVal)
 | 
						|
  {
 | 
						|
    /* Calculate pIalpha using the equation, pIalpha = Id * cosVal - Iq * sinVal */
 | 
						|
    *pIalpha = Id * cosVal - Iq * sinVal;
 | 
						|
 | 
						|
    /* Calculate pIbeta using the equation, pIbeta = Id * sinVal + Iq * cosVal */
 | 
						|
    *pIbeta = Id * sinVal + Iq * cosVal;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  @brief  Inverse Park transform for   Q31 version
 | 
						|
  @param[in]  Id       input coordinate of rotor reference frame d
 | 
						|
  @param[in]  Iq       input coordinate of rotor reference frame q
 | 
						|
  @param[out] pIalpha  points to output two-phase orthogonal vector axis alpha
 | 
						|
  @param[out] pIbeta   points to output two-phase orthogonal vector axis beta
 | 
						|
  @param[in]  sinVal   sine value of rotation angle theta
 | 
						|
  @param[in]  cosVal   cosine value of rotation angle theta
 | 
						|
  @return     none
 | 
						|
 | 
						|
  @par Scaling and Overflow Behavior
 | 
						|
         The function is implemented using an internal 32-bit accumulator.
 | 
						|
         The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
 | 
						|
         There is saturation on the addition, hence there is no risk of overflow.
 | 
						|
 */
 | 
						|
__STATIC_FORCEINLINE void arm_inv_park_q31(
 | 
						|
  q31_t Id,
 | 
						|
  q31_t Iq,
 | 
						|
  q31_t * pIalpha,
 | 
						|
  q31_t * pIbeta,
 | 
						|
  q31_t sinVal,
 | 
						|
  q31_t cosVal)
 | 
						|
  {
 | 
						|
    q31_t product1, product2;                    /* Temporary variables used to store intermediate results */
 | 
						|
    q31_t product3, product4;                    /* Temporary variables used to store intermediate results */
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (Id * cosVal) */
 | 
						|
    product1 = (q31_t) (((q63_t) (Id) * (cosVal)) >> 31);
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (Iq * sinVal) */
 | 
						|
    product2 = (q31_t) (((q63_t) (Iq) * (sinVal)) >> 31);
 | 
						|
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (Id * sinVal) */
 | 
						|
    product3 = (q31_t) (((q63_t) (Id) * (sinVal)) >> 31);
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (Iq * cosVal) */
 | 
						|
    product4 = (q31_t) (((q63_t) (Iq) * (cosVal)) >> 31);
 | 
						|
 | 
						|
    /* Calculate pIalpha by using the two intermediate products 1 and 2 */
 | 
						|
    *pIalpha = __QSUB(product1, product2);
 | 
						|
 | 
						|
    /* Calculate pIbeta by using the two intermediate products 3 and 4 */
 | 
						|
    *pIbeta = __QADD(product4, product3);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * @} end of Inverse park group
 | 
						|
   */
 | 
						|
 | 
						|
/**
 | 
						|
   * @ingroup groupController
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @defgroup clarke Vector Clarke Transform
 | 
						|
   * Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector.
 | 
						|
   * Generally the Clarke transform uses three-phase currents <code>Ia, Ib and Ic</code> to calculate currents
 | 
						|
   * in the two-phase orthogonal stator axis <code>Ialpha</code> and <code>Ibeta</code>.
 | 
						|
   * When <code>Ialpha</code> is superposed with <code>Ia</code> as shown in the figure below
 | 
						|
   * \image html clarke.gif Stator current space vector and its components in (a,b).
 | 
						|
   * and <code>Ia + Ib + Ic = 0</code>, in this condition <code>Ialpha</code> and <code>Ibeta</code>
 | 
						|
   * can be calculated using only <code>Ia</code> and <code>Ib</code>.
 | 
						|
   *
 | 
						|
   * The function operates on a single sample of data and each call to the function returns the processed output.
 | 
						|
   * The library provides separate functions for Q31 and floating-point data types.
 | 
						|
   * \par Algorithm
 | 
						|
   * \image html clarkeFormula.gif
 | 
						|
   * where <code>Ia</code> and <code>Ib</code> are the instantaneous stator phases and
 | 
						|
   * <code>pIalpha</code> and <code>pIbeta</code> are the two coordinates of time invariant vector.
 | 
						|
   * \par Fixed-Point Behavior
 | 
						|
   * Care must be taken when using the Q31 version of the Clarke transform.
 | 
						|
   * In particular, the overflow and saturation behavior of the accumulator used must be considered.
 | 
						|
   * Refer to the function specific documentation below for usage guidelines.
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @addtogroup clarke
 | 
						|
   * @{
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   *
 | 
						|
   * @brief  Floating-point Clarke transform
 | 
						|
   * @param[in]  Ia       input three-phase coordinate <code>a</code>
 | 
						|
   * @param[in]  Ib       input three-phase coordinate <code>b</code>
 | 
						|
   * @param[out] pIalpha  points to output two-phase orthogonal vector axis alpha
 | 
						|
   * @param[out] pIbeta   points to output two-phase orthogonal vector axis beta
 | 
						|
   * @return        none
 | 
						|
   */
 | 
						|
  __STATIC_FORCEINLINE void arm_clarke_f32(
 | 
						|
  float32_t Ia,
 | 
						|
  float32_t Ib,
 | 
						|
  float32_t * pIalpha,
 | 
						|
  float32_t * pIbeta)
 | 
						|
  {
 | 
						|
    /* Calculate pIalpha using the equation, pIalpha = Ia */
 | 
						|
    *pIalpha = Ia;
 | 
						|
 | 
						|
    /* Calculate pIbeta using the equation, pIbeta = (1/sqrt(3)) * Ia + (2/sqrt(3)) * Ib */
 | 
						|
    *pIbeta = (0.57735026919f * Ia + 1.15470053838f * Ib);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  @brief  Clarke transform for Q31 version
 | 
						|
  @param[in]  Ia       input three-phase coordinate <code>a</code>
 | 
						|
  @param[in]  Ib       input three-phase coordinate <code>b</code>
 | 
						|
  @param[out] pIalpha  points to output two-phase orthogonal vector axis alpha
 | 
						|
  @param[out] pIbeta   points to output two-phase orthogonal vector axis beta
 | 
						|
  @return     none
 | 
						|
 | 
						|
  \par Scaling and Overflow Behavior
 | 
						|
         The function is implemented using an internal 32-bit accumulator.
 | 
						|
         The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
 | 
						|
         There is saturation on the addition, hence there is no risk of overflow.
 | 
						|
 */
 | 
						|
__STATIC_FORCEINLINE void arm_clarke_q31(
 | 
						|
  q31_t Ia,
 | 
						|
  q31_t Ib,
 | 
						|
  q31_t * pIalpha,
 | 
						|
  q31_t * pIbeta)
 | 
						|
  {
 | 
						|
    q31_t product1, product2;                    /* Temporary variables used to store intermediate results */
 | 
						|
 | 
						|
    /* Calculating pIalpha from Ia by equation pIalpha = Ia */
 | 
						|
    *pIalpha = Ia;
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (1/(sqrt(3)) * Ia) */
 | 
						|
    product1 = (q31_t) (((q63_t) Ia * 0x24F34E8B) >> 30);
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (2/sqrt(3) * Ib) */
 | 
						|
    product2 = (q31_t) (((q63_t) Ib * 0x49E69D16) >> 30);
 | 
						|
 | 
						|
    /* pIbeta is calculated by adding the intermediate products */
 | 
						|
    *pIbeta = __QADD(product1, product2);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * @} end of clarke group
 | 
						|
   */
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * @ingroup groupController
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @defgroup inv_clarke Vector Inverse Clarke Transform
 | 
						|
   * Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases.
 | 
						|
   *
 | 
						|
   * The function operates on a single sample of data and each call to the function returns the processed output.
 | 
						|
   * The library provides separate functions for Q31 and floating-point data types.
 | 
						|
   * \par Algorithm
 | 
						|
   * \image html clarkeInvFormula.gif
 | 
						|
   * where <code>pIa</code> and <code>pIb</code> are the instantaneous stator phases and
 | 
						|
   * <code>Ialpha</code> and <code>Ibeta</code> are the two coordinates of time invariant vector.
 | 
						|
   * \par Fixed-Point Behavior
 | 
						|
   * Care must be taken when using the Q31 version of the Clarke transform.
 | 
						|
   * In particular, the overflow and saturation behavior of the accumulator used must be considered.
 | 
						|
   * Refer to the function specific documentation below for usage guidelines.
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * @addtogroup inv_clarke
 | 
						|
   * @{
 | 
						|
   */
 | 
						|
 | 
						|
   /**
 | 
						|
   * @brief  Floating-point Inverse Clarke transform
 | 
						|
   * @param[in]  Ialpha  input two-phase orthogonal vector axis alpha
 | 
						|
   * @param[in]  Ibeta   input two-phase orthogonal vector axis beta
 | 
						|
   * @param[out] pIa     points to output three-phase coordinate <code>a</code>
 | 
						|
   * @param[out] pIb     points to output three-phase coordinate <code>b</code>
 | 
						|
   * @return     none
 | 
						|
   */
 | 
						|
  __STATIC_FORCEINLINE void arm_inv_clarke_f32(
 | 
						|
  float32_t Ialpha,
 | 
						|
  float32_t Ibeta,
 | 
						|
  float32_t * pIa,
 | 
						|
  float32_t * pIb)
 | 
						|
  {
 | 
						|
    /* Calculating pIa from Ialpha by equation pIa = Ialpha */
 | 
						|
    *pIa = Ialpha;
 | 
						|
 | 
						|
    /* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */
 | 
						|
    *pIb = -0.5f * Ialpha + 0.8660254039f * Ibeta;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  @brief  Inverse Clarke transform for Q31 version
 | 
						|
  @param[in]  Ialpha  input two-phase orthogonal vector axis alpha
 | 
						|
  @param[in]  Ibeta   input two-phase orthogonal vector axis beta
 | 
						|
  @param[out] pIa     points to output three-phase coordinate <code>a</code>
 | 
						|
  @param[out] pIb     points to output three-phase coordinate <code>b</code>
 | 
						|
  @return     none
 | 
						|
 | 
						|
  \par Scaling and Overflow Behavior
 | 
						|
         The function is implemented using an internal 32-bit accumulator.
 | 
						|
         The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
 | 
						|
         There is saturation on the subtraction, hence there is no risk of overflow.
 | 
						|
 */
 | 
						|
__STATIC_FORCEINLINE void arm_inv_clarke_q31(
 | 
						|
  q31_t Ialpha,
 | 
						|
  q31_t Ibeta,
 | 
						|
  q31_t * pIa,
 | 
						|
  q31_t * pIb)
 | 
						|
  {
 | 
						|
    q31_t product1, product2;                    /* Temporary variables used to store intermediate results */
 | 
						|
 | 
						|
    /* Calculating pIa from Ialpha by equation pIa = Ialpha */
 | 
						|
    *pIa = Ialpha;
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (1/(2*sqrt(3)) * Ia) */
 | 
						|
    product1 = (q31_t) (((q63_t) (Ialpha) * (0x40000000)) >> 31);
 | 
						|
 | 
						|
    /* Intermediate product is calculated by (1/sqrt(3) * pIb) */
 | 
						|
    product2 = (q31_t) (((q63_t) (Ibeta) * (0x6ED9EBA1)) >> 31);
 | 
						|
 | 
						|
    /* pIb is calculated by subtracting the products */
 | 
						|
    *pIb = __QSUB(product2, product1);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * @} end of inv_clarke group
 | 
						|
   */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  
 | 
						|
#ifdef   __cplusplus
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#endif /* ifndef _CONTROLLER_FUNCTIONS_H_ */
 |