nuttx/include/dsp.h

609 lines
20 KiB
C
Raw Normal View History

/****************************************************************************
* include/dsp.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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
*
* http://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 __INCLUDE_DSP_H
#define __INCLUDE_DSP_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/compiler.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Disable DEBUGASSERT macro if LIBDSP debug is not enabled */
#ifdef CONFIG_LIBDSP_DEBUG
# ifndef CONFIG_DEBUG_ASSERTIONS
# warning "Need CONFIG_DEBUG_ASSERTIONS to work properly"
# endif
# define LIBDSP_DEBUGASSERT(x) DEBUGASSERT(x)
#else
# undef LIBDSP_DEBUGASSERT
# define LIBDSP_DEBUGASSERT(x)
#endif
#ifndef CONFIG_LIBDSP_PRECISION
# define CONFIG_LIBDSP_PRECISION 0
#endif
/* Phase rotation direction */
2021-03-01 20:05:45 +01:00
#define DIR_NONE (0.0f)
#define DIR_CW (1.0f)
#define DIR_CCW (-1.0f)
2020-04-03 21:18:18 +02:00
/* Some math constants ******************************************************/
#define SQRT3_BY_TWO_F (0.866025f)
#define SQRT3_BY_THREE_F (0.57735f)
#define ONE_BY_SQRT3_F (0.57735f)
#define TWO_BY_SQRT3_F (1.15470f)
2020-04-03 21:18:18 +02:00
/* Some lib constants *******************************************************/
/* These are defined only in the NuttX math library */
#ifndef M_PI_F
#define M_PI_F ((float)M_PI)
#endif
#ifndef M_PI_2_F
#define M_PI_2_F ((float)M_PI_2)
#endif
/* Motor electrical angle is in range 0.0 to 2*PI */
#define MOTOR_ANGLE_E_MAX (2.0f*M_PI_F)
#define MOTOR_ANGLE_E_MIN (0.0f)
#define MOTOR_ANGLE_E_RANGE (MOTOR_ANGLE_E_MAX - MOTOR_ANGLE_E_MIN)
/* Motor mechanical angle is in range 0.0 to 2*PI */
#define MOTOR_ANGLE_M_MAX (2.0f*M_PI_F)
#define MOTOR_ANGLE_M_MIN (0.0f)
#define MOTOR_ANGLE_M_RANGE (MOTOR_ANGLE_M_MAX - MOTOR_ANGLE_M_MIN)
2020-04-03 21:18:18 +02:00
/* Some useful macros *******************************************************/
/****************************************************************************
* Name: LP_FILTER
*
* Description:
* Simple single-pole digital low pass filter:
* Y(n) = (1-beta)*Y(n-1) + beta*X(n) = (beta * (Y(n-1) - X(n)))
*
* filter - (0.0 - 1.0) where 1.0 gives unfiltered values
* filter = T * (2*PI) * f_c
*
* phase shift = -arctan(f_in/f_c)
*
* T - period at which the digital filter is being calculated
* f_in - input frequency of the filter
* f_c - cutoff frequency of the filter
*
* REFERENCE: https://www.embeddedrelated.com/showarticle/779.php
*
****************************************************************************/
#define LP_FILTER(val, sample, filter) val -= (filter * (val - sample))
/****************************************************************************
* Name: SVM3_BASE_VOLTAGE_GET
*
* Description:
* Get maximum voltage for SVM3 without overmodulation
*
* Notes:
2021-03-30 18:03:59 +02:00
* max possible phase voltage for 3-phase power inverter:
* Vd = (2/3)*Vdc
* max phase reference voltage according to SVM modulation diagram:
* Vrefmax = Vd * cos(30*) = SQRT3_BY_2 * Vd
* which give us:
* Vrefmax = SQRT3_BY_3 * Vdc
*
* Vdc - bus voltage
*
****************************************************************************/
#define SVM3_BASE_VOLTAGE_GET(vbus) (vbus * SQRT3_BY_THREE_F)
/****************************************************************************
* Public Types
****************************************************************************/
/* This structure represents phase angle.
* Besides angle value it also stores sine and cosine values for given angle.
*/
struct phase_angle_f32_s
{
float angle; /* Phase angle in radians <0, 2PI> */
float sin; /* Phase angle sine */
float cos; /* Phase angle cosine */
};
typedef struct phase_angle_f32_s phase_angle_f32_t;
/* This structure stores motor angles and corresponding sin and cos values
*
* th_el = th_m * pole_pairs
* th_m = th_el/pole_pairs
*
* where:
* th_el - motor electrical angle
* th_m - motor mechanical angle
* pole_pairs - motor pole pairs
*
* NOTE: pole_pairs = poles_total/2
*/
struct motor_angle_f32_s
{
phase_angle_f32_t angle_el; /* Electrical angle */
float anglem; /* Mechanical angle in radians <0, 2PI> */
float one_by_p; /* Aux variable */
uint8_t p; /* Number of the motor pole pairs */
int8_t i; /* Pole counter */
};
/* Float number saturaton */
struct float_sat_f32_s
{
float min; /* Lower limit */
float max; /* Upper limit */
};
typedef struct float_sat_f32_s float_sat_f32_t;
/* PI/PID controller state structure */
struct pid_controller_f32_s
{
bool aw_en; /* Integral part decay if saturated */
bool ireset_en; /* Intergral part reset if saturated */
bool pisat_en; /* PI saturation enabled */
bool pidsat_en; /* PID saturation enabled */
bool _res; /* Reserved */
float out; /* Controller output */
float_sat_f32_t sat; /* Output saturation */
float err; /* Current error value */
float err_prev; /* Previous error value */
float KP; /* Proportional coefficient */
float KI; /* Integral coefficient */
float KD; /* Derivative coefficient */
float part[3]; /* 0 - proporitonal part
* 1 - integral part
* 2 - derivative part
*/
float KC; /* Integral anti-windup decay coefficient */
float aw; /* Integral anti-windup decay part */
};
typedef struct pid_controller_f32_s pid_controller_f32_t;
/* This structure represents the ABC frame (3 phase vector) */
struct abc_frame_f32_s
{
float a; /* A component */
float b; /* B component */
float c; /* C component */
};
typedef struct abc_frame_f32_s abc_frame_f32_t;
/* This structure represents the alpha-beta frame (2 phase vector) */
struct ab_frame_f32_s
{
float a; /* Alpha component */
float b; /* Beta component */
};
typedef struct ab_frame_f32_s ab_frame_f32_t;
/* This structure represent the direct-quadrature frame */
struct dq_frame_f32_s
{
float d; /* Driect component */
float q; /* Quadrature component */
};
typedef struct dq_frame_f32_s dq_frame_f32_t;
/* Space Vector Modulation data for 3-phase system */
struct svm3_state_f32_s
{
uint8_t sector; /* Current space vector sector */
float d_u; /* Duty cycle for phase U */
float d_v; /* Duty cycle for phase V */
float d_w; /* Duty cycle for phase W */
};
/* Motor open-loop control data */
struct openloop_data_f32_s
{
float angle; /* Open-loop current angle normalized to <0.0, 2PI> */
float per; /* Open-loop control execution period */
};
/* Common motor speed observer structure */
struct motor_sobserver_f32_s
{
float speed; /* Estimated observer speed */
float per; /* Observer execution period */
/* There are different types of motor observers which different
* sets of private data.
*/
void *so; /* Speed estimation observer data */
};
/* Common motor angle observer structure */
struct motor_aobserver_f32_s
{
float angle; /* Estimated observer angle */
float per; /* Observer execution period */
/* There are different types of motor observers which different
* sets of private data.
*/
void *ao; /* Angle estimation observer data */
};
/* Speed observer division method data */
struct motor_sobserver_div_f32_s
{
float angle_diff; /* Angle difference */
float angle_acc; /* Accumulated angle */
float angle_prev; /* Previous angle */
float one_by_dt; /* Frequency of observer execution */
float cntr; /* Sample counter */
float samples; /* Number of samples for observer */
float filter; /* Low-pass filter for final omega */
};
/* Speed observer PLL method data */
struct motor_sobserver_pll_f32_s
{
float pll_phase;
float pll_kp;
float pll_ki;
};
/* Motor Sliding Mode Observer private data */
struct motor_aobserver_smo_f32_s
{
float k_slide; /* Bang-bang controller gain */
float err_max; /* Linear mode threshold */
float one_by_err_max; /* One by err_max */
2020-04-03 21:18:18 +02:00
float F; /* Current observer F gain (1-Ts*R/L) */
float G; /* Current observer G gain (Ts/L) */
float emf_lp_filter1; /* Adaptive first low pass EMF filter */
float emf_lp_filter2; /* Adaptive second low pass EMF filter */
ab_frame_f32_t emf; /* Estimated back-EMF */
ab_frame_f32_t emf_f; /* Fitlered estimated back-EMF */
ab_frame_f32_t z; /* Correction factor */
ab_frame_f32_t i_est; /* Estimated idq current */
ab_frame_f32_t v_err; /* v_err = v_ab - emf */
ab_frame_f32_t i_err; /* i_err = i_est - i_dq */
ab_frame_f32_t sign; /* Bang-bang controller sign */
};
/* Motor Nonlinear FluxLink Observer private data */
struct motor_aobserver_nfo_f32_s
{
float x1;
float x2;
};
/* FOC initialize data */
struct foc_initdata_f32_s
{
float id_kp; /* KP for d current */
float id_ki; /* KI for d current */
float iq_kp; /* KP for q current */
float iq_ki; /* KI for q current */
};
/* Field Oriented Control (FOC) data */
struct foc_data_f32_s
{
abc_frame_f32_t v_abc; /* Voltage in ABC frame */
ab_frame_f32_t v_ab; /* Voltage in alpha-beta frame */
dq_frame_f32_t v_dq; /* Requested voltage in dq frame */
ab_frame_f32_t v_ab_mod; /* Modulation voltage normalized to
* magnitude (0.0, 1.0)
*/
abc_frame_f32_t i_abc; /* Current in ABC frame */
ab_frame_f32_t i_ab; /* Current in alpha-beta frame */
dq_frame_f32_t i_dq; /* Current in dq frame */
dq_frame_f32_t i_dq_err; /* DQ current error */
dq_frame_f32_t i_dq_ref; /* Requested current for the FOC
2021-07-16 23:37:45 +02:00
* current controller
*/
pid_controller_f32_t id_pid; /* Current d-axis component PI controller */
pid_controller_f32_t iq_pid; /* Current q-axis component PI controller */
float vdq_mag_max; /* Maximum dq voltage magnitude */
float vab_mod_scale; /* Voltage alpha-beta modulation scale */
phase_angle_f32_t angle; /* Phase angle */
};
/* Motor physical parameters.
* This data structure was designed to work with BLDC/PMSM motors,
* but probably can be used to describe different types of motors.
*/
struct motor_phy_params_f32_s
{
uint8_t p; /* Number of the motor pole pairs */
float flux_link; /* Flux linkage */
2021-03-01 20:39:42 +01:00
float res; /* Phase-to-neutral resistance */
float ind; /* Average phase-to-neutral inductance */
float one_by_ind; /* Inverse phase-to-neutral inductance */
};
/* PMSM motor physcial parameters */
struct pmsm_phy_params_f32_s
{
struct motor_phy_params_f32_s motor; /* Motor common PHY */
float iner; /* Rotor inertia */
float flux_link; /* Flux linkage */
float ind_d; /* d-inductance */
float ind_q; /* q-inductance */
float one_by_iner; /* One by intertia */
float one_by_indd; /* One by Ld */
float one_by_indq; /* One by Lq */
};
/* PMSM motor model state */
struct pmsm_model_state_f32_s
{
/* Motor model phase current */
abc_frame_f32_t i_abc;
ab_frame_f32_t i_ab;
dq_frame_f32_t i_dq;
/* Motor model phase voltage */
abc_frame_f32_t v_abc;
ab_frame_f32_t v_ab;
dq_frame_f32_t v_dq;
/* Motor model angle */
struct motor_angle_f32_s angle;
/* Angular speed */
float omega_e;
float omega_m;
};
/* PMSM motor model external conditions */
struct pmsm_model_ext_f32_s
{
float load; /* Motor model load torque */
};
/* PMSM motor model */
struct pmsm_model_f32_s
{
struct pmsm_phy_params_f32_s phy; /* Motor model physical parameters */
struct pmsm_model_state_f32_s state; /* Motor model state */
struct pmsm_model_ext_f32_s ext; /* Motor model external conditions */
float per; /* Control period */
float id_int; /* Id integral part */
float iq_int; /* Iq integral part */
};
/****************************************************************************
2020-04-03 21:18:18 +02:00
* Public Functions Prototypes
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/* Math functions */
float fast_sin(float angle);
float fast_sin2(float angle);
float fast_cos(float angle);
float fast_cos2(float angle);
float fast_atan2(float y, float x);
void f_saturate(FAR float *val, float min, float max);
float vector2d_mag(float x, float y);
void vector2d_saturate(FAR float *x, FAR float *y, float max);
void dq_saturate(FAR dq_frame_f32_t *dq, float max);
float dq_mag(FAR dq_frame_f32_t *dq);
/* PID controller functions */
void pid_controller_init(FAR pid_controller_f32_t *pid,
float KP, float KI, float KD);
void pi_controller_init(FAR pid_controller_f32_t *pid,
float KP, float KI);
void pid_saturation_set(FAR pid_controller_f32_t *pid, float min, float max);
void pi_saturation_set(FAR pid_controller_f32_t *pid, float min, float max);
void pid_integral_reset(FAR pid_controller_f32_t *pid);
void pi_integral_reset(FAR pid_controller_f32_t *pid);
float pi_controller(FAR pid_controller_f32_t *pid, float err);
float pid_controller(FAR pid_controller_f32_t *pid, float err);
void pi_antiwindup_enable(FAR pid_controller_f32_t *pid, float KC,
bool enable);
void pi_ireset_enable(FAR pid_controller_f32_t *pid, bool enable);
/* Transformation functions */
void clarke_transform(FAR abc_frame_f32_t *abc, FAR ab_frame_f32_t *ab);
void inv_clarke_transform(FAR ab_frame_f32_t *ab, FAR abc_frame_f32_t *abc);
void park_transform(FAR phase_angle_f32_t *angle, FAR ab_frame_f32_t *ab,
FAR dq_frame_f32_t *dq);
void inv_park_transform(FAR phase_angle_f32_t *angle, FAR dq_frame_f32_t *dq,
FAR ab_frame_f32_t *ab);
/* Phase angle related functions */
void angle_norm(FAR float *angle, float per, float bottom, float top);
void angle_norm_2pi(FAR float *angle, float bottom, float top);
void phase_angle_update(FAR struct phase_angle_f32_s *angle, float val);
2020-04-03 21:18:18 +02:00
/* 3-phase system space vector modulation */
void svm3_init(FAR struct svm3_state_f32_s *s);
void svm3(FAR struct svm3_state_f32_s *s, FAR ab_frame_f32_t *ab);
void svm3_current_correct(FAR struct svm3_state_f32_s *s,
float *c0, float *c1, float *c2);
/* Field Oriented Control */
void foc_init(FAR struct foc_data_f32_s *foc,
FAR struct foc_initdata_f32_s *init);
void foc_vbase_update(FAR struct foc_data_f32_s *foc, float vbase);
void foc_angle_update(FAR struct foc_data_f32_s *foc,
FAR phase_angle_f32_t *angle);
void foc_iabc_update(FAR struct foc_data_f32_s *foc,
FAR abc_frame_f32_t *i_abc);
void foc_voltage_control(FAR struct foc_data_f32_s *foc,
FAR dq_frame_f32_t *vdq_ref);
void foc_current_control(FAR struct foc_data_f32_s *foc,
FAR dq_frame_f32_t *idq_ref,
FAR dq_frame_f32_t *vdq_comp,
FAR dq_frame_f32_t *v_dq_ref);
void foc_vabmod_get(FAR struct foc_data_f32_s *foc,
FAR ab_frame_f32_t *v_ab_mod);
void foc_vdq_mag_max_get(FAR struct foc_data_f32_s *foc, FAR float *max);
/* BLDC/PMSM motor observers */
void motor_sobserver_init(FAR struct motor_sobserver_f32_s *observer,
FAR void *so, float per);
void motor_aobserver_init(FAR struct motor_aobserver_f32_s *observer,
FAR void *ao, float per);
float motor_sobserver_speed_get(FAR struct motor_sobserver_f32_s *o);
float motor_aobserver_angle_get(FAR struct motor_aobserver_f32_s *o);
void motor_aobserver_smo_init(FAR struct motor_aobserver_smo_f32_s *smo,
float kslide, float err_max);
void motor_aobserver_smo(FAR struct motor_aobserver_f32_s *o,
FAR ab_frame_f32_t *i_ab, FAR ab_frame_f32_t *v_ab,
FAR struct motor_phy_params_f32_s *phy, float dir,
float speed);
void motor_sobserver_div_init(FAR struct motor_sobserver_div_f32_s *so,
uint8_t samples, float filer, float per);
void motor_sobserver_div(FAR struct motor_sobserver_f32_s *o, float angle);
void motor_aobserver_nfo_init(FAR struct motor_aobserver_nfo_f32_s *nfo);
void motor_aobserver_nfo(FAR struct motor_aobserver_f32_s *o,
FAR ab_frame_f32_t *i_ab, FAR ab_frame_f32_t *v_ab,
FAR struct motor_phy_params_f32_s *phy, float gain);
void motor_sobserver_pll_init(FAR struct motor_sobserver_pll_f32_s *so,
float pll_kp, float pll_ki);
void motor_sobserver_pll(FAR struct motor_sobserver_f32_s *o, float angle);
/* Motor openloop control */
void motor_openloop_init(FAR struct openloop_data_f32_s *op, float per);
void motor_openloop(FAR struct openloop_data_f32_s *op, float speed,
float dir);
float motor_openloop_angle_get(FAR struct openloop_data_f32_s *op);
/* Motor angle */
void motor_angle_init(FAR struct motor_angle_f32_s *angle, uint8_t p);
void motor_angle_e_update(FAR struct motor_angle_f32_s *angle,
2020-04-03 21:18:18 +02:00
float angle_new, float dir);
void motor_angle_m_update(FAR struct motor_angle_f32_s *angle,
2020-04-03 21:18:18 +02:00
float angle_new, float dir);
float motor_angle_m_get(FAR struct motor_angle_f32_s *angle);
float motor_angle_e_get(FAR struct motor_angle_f32_s *angle);
/* Motor physical parameters */
void motor_phy_params_init(FAR struct motor_phy_params_f32_s *phy,
uint8_t poles, float res, float ind);
/* PMSM physical parameters functions */
void pmsm_phy_params_init(FAR struct pmsm_phy_params_f32_s *phy,
uint8_t poles, float res, float ind,
float iner, float flux,
float ind_d, float ind_q);
/* PMSM motor model */
int pmsm_model_initialize(FAR struct pmsm_model_f32_s *model,
FAR struct pmsm_phy_params_f32_s *phy,
float per);
int pmsm_model_elec(FAR struct pmsm_model_f32_s *model,
FAR ab_frame_f32_t *vab);
int pmsm_model_mech(FAR struct pmsm_model_f32_s *model, float load);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __INCLUDE_DSP_H */