examples/foc: add phase angle observer support (sensorless mode)
This app can work now as sensorless ESC. Also introduce a cmd line option that force open-loop control which is useful when tuning angle/velocity observers
This commit is contained in:
parent
a4ceb82d67
commit
1c922f2d2d
@ -91,6 +91,7 @@ choice
|
||||
|
||||
config EXAMPLES_FOC_SENSORLESS
|
||||
bool "FOC example sensorless configuration"
|
||||
select EXAMPLES_FOC_ANGOBS
|
||||
|
||||
config EXAMPLES_FOC_SENSORED
|
||||
bool "FOC example sensored configuration"
|
||||
@ -239,6 +240,90 @@ endif # EXAMPLES_FOC_VELCTRL_PI
|
||||
|
||||
endif # EXAMPLES_FOC_HAVE_VEL
|
||||
|
||||
config EXAMPLES_FOC_ANGOBS
|
||||
bool "FOC example phase angle observer support"
|
||||
default n
|
||||
|
||||
choice
|
||||
prompt "FOC angle observer selection"
|
||||
default EXAMPLES_FOC_ANGOBS_NFO
|
||||
depends on EXAMPLES_FOC_ANGOBS
|
||||
|
||||
config EXAMPLES_FOC_ANGOBS_SMO
|
||||
bool "FOC angle SMO observer"
|
||||
select INDUSTRY_FOC_ANGLE_OSMO
|
||||
|
||||
config EXAMPLES_FOC_ANGOBS_NFO
|
||||
bool "FOC angle NFO observer"
|
||||
select INDUSTRY_FOC_ANGLE_ONFO
|
||||
|
||||
endchoice # FOC angle observer
|
||||
|
||||
if EXAMPLES_FOC_ANGOBS
|
||||
|
||||
config EXAMPLES_FOC_ANGOBS_HYS
|
||||
int "FOC angle observer hysteresis [x1]"
|
||||
default 0
|
||||
---help---
|
||||
Hysteresis added to the observer to open-loop transition.
|
||||
|
||||
config EXAMPLES_FOC_ANGOBS_THR
|
||||
int "FOC angle observer velocity threshold [x1]"
|
||||
default 0
|
||||
---help---
|
||||
Once the motor reaches this speed, we switch from the open-loop angle
|
||||
to the observer angle.
|
||||
|
||||
config EXAMPLES_FOC_ANGOBS_MERGE_RATIO
|
||||
int "FOC angle observer merge ratio"
|
||||
default 50
|
||||
range 0 50
|
||||
---help---
|
||||
This parameter determines how quickly we make the transition from the
|
||||
open-loop angle to the observer angle after reaching the observer threshold
|
||||
velocity. The smaler the value, the smoother the transition.
|
||||
If set to 0 - smooth transition is disabled.
|
||||
|
||||
endif # EXAMPLES_FOC_ANGOBS
|
||||
|
||||
if EXAMPLES_FOC_ANGOBS_SMO
|
||||
|
||||
config EXAMPLES_FOC_ANGOBS_SMO_KSLIDE
|
||||
int "FOC angle SMO observer Kslide (x1000)"
|
||||
default 0
|
||||
---help---
|
||||
The Kslide coefficient used in observer is:
|
||||
Kslide = EXAMPLES_FOC_ANGOBS_SMO_KSLIDE/1000
|
||||
|
||||
config EXAMPLES_FOC_ANGOBS_SMO_ERRMAX
|
||||
int "FOC angle SMO observer err_max (x1000)"
|
||||
default 0
|
||||
---help---
|
||||
The err_max coefficient used in observer is:
|
||||
err_max = EXAMPLES_FOC_ANGOBS_SMO_ERRMAX/1000
|
||||
|
||||
endif # EXAMPLES_FOC_ANGOBS_SMO
|
||||
|
||||
if EXAMPLES_FOC_ANGOBS_NFO
|
||||
|
||||
config EXAMPLES_FOC_ANGOBS_NFO_GAIN
|
||||
int "FOC angle NFO observer gain (x1)"
|
||||
default 0
|
||||
---help---
|
||||
The gain coefficient used in observer at maximum duty cycle.
|
||||
|
||||
config EXAMPLES_FOC_ANGOBS_NFO_GAINSLOW
|
||||
int "FOC angle NFO observer gain slow (x1)"
|
||||
default 0
|
||||
---help---
|
||||
The gain coefficient used in observer at minimum duty cycle.
|
||||
|
||||
endif # EXAMPLES_FOC_ANGOBS_NFO
|
||||
|
||||
config EXAMPLES_FOC_VELOBS
|
||||
bool "FOC example velocity observer support"
|
||||
default n
|
||||
|
||||
if EXAMPLES_FOC_VELOBS
|
||||
|
||||
choice
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
@ -204,6 +206,12 @@
|
||||
#define VEL_CONTROL_PRESCALER (CONFIG_EXAMPLES_FOC_NOTIFIER_FREQ / \
|
||||
CONFIG_EXAMPLES_FOC_VELCTRL_FREQ)
|
||||
|
||||
/* Open-loop to observer angle merge factor */
|
||||
|
||||
#if CONFIG_EXAMPLES_FOC_ANGOBS_MERGE_RATIO > 0
|
||||
# define ANGLE_MERGE_FACTOR (CONFIG_EXAMPLES_FOC_ANGOBS_MERGE_RATIO / 100.0f)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Type Definition
|
||||
****************************************************************************/
|
||||
@ -213,7 +221,12 @@ struct foc_thr_cfg_s
|
||||
int fmode; /* FOC control mode */
|
||||
int mmode; /* Motor control mode */
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
int qparam; /* Open-loop Q setting (x1000) */
|
||||
uint32_t qparam; /* Open-loop Q setting (x1000) */
|
||||
bool ol_force; /* Force open-loop */
|
||||
# ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
uint32_t ol_thr; /* Observer vel threshold [x1] */
|
||||
uint32_t ol_hys; /* Observer vel hysteresys [x1] */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_CONTROL_PI
|
||||
@ -255,6 +268,11 @@ struct foc_thr_cfg_s
|
||||
uint32_t vel_pi_kp; /* Vel controller PI Kp (x1000000) */
|
||||
uint32_t vel_pi_ki; /* Vel controller PI Ki (x1000000) */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INDUSTRY_FOC_ANGLE_ONFO
|
||||
uint32_t ang_nfo_slow; /* Ang NFO slow gain (x1) */
|
||||
uint32_t ang_nfo_gain; /* Ang NFO gain (x1) */
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* __APPS_EXAMPLES_FOC_FOC_CFG_H */
|
||||
|
@ -284,6 +284,10 @@ static void foc_float_nxscope(FAR struct foc_nxscope_s *nxs,
|
||||
ptr = (FAR float *)&motor->vel_obs;
|
||||
nxscope_put_vfloat(&nxs->nxs, i++, ptr, 1);
|
||||
#endif
|
||||
#if (CONFIG_EXAMPLES_FOC_NXSCOPE_CFG & FOC_NXSCOPE_AOBS)
|
||||
ptr = (FAR float *)&motor->angle_obs;
|
||||
nxscope_put_vfloat(&nxs->nxs, i++, ptr, 1);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_FOC_NXSCOPE_CONTROL
|
||||
nxscope_unlock(&nxs->nxs);
|
||||
|
@ -75,7 +75,12 @@ struct args_s g_args =
|
||||
.fmode = CONFIG_EXAMPLES_FOC_FMODE,
|
||||
.mmode = CONFIG_EXAMPLES_FOC_MMODE,
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
.qparam = CONFIG_EXAMPLES_FOC_OPENLOOP_Q,
|
||||
.qparam = CONFIG_EXAMPLES_FOC_OPENLOOP_Q,
|
||||
.ol_force = false,
|
||||
# ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
.ol_hys = CONFIG_EXAMPLES_FOC_ANGOBS_HYS,
|
||||
.ol_thr = CONFIG_EXAMPLES_FOC_ANGOBS_THR,
|
||||
# endif
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_CONTROL_PI
|
||||
.foc_pi_kp = CONFIG_EXAMPLES_FOC_IDQ_KP,
|
||||
@ -123,6 +128,10 @@ struct args_s g_args =
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
|
||||
.vel_pi_kp = CONFIG_EXAMPLES_FOC_VELCTRL_PI_KP,
|
||||
.vel_pi_ki = CONFIG_EXAMPLES_FOC_VELCTRL_PI_KI,
|
||||
#endif
|
||||
#ifdef CONFIG_INDUSTRY_FOC_ANGLE_ONFO
|
||||
.ang_nfo_slow = CONFIG_EXAMPLES_FOC_ANGOBS_NFO_GAINSLOW,
|
||||
.ang_nfo_gain = CONFIG_EXAMPLES_FOC_ANGOBS_NFO_GAIN,
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
@ -269,7 +269,7 @@ static int foc_runmode_init(FAR struct foc_motor_b16_s *motor)
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_SENSORLESS
|
||||
# ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
motor->openloop_now = true;
|
||||
motor->openloop_now = FOC_OPENLOOP_ENABLED;
|
||||
# else
|
||||
# error
|
||||
# endif
|
||||
@ -771,6 +771,89 @@ static int foc_motor_run_init(FAR struct foc_motor_b16_s *motor)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
/****************************************************************************
|
||||
* Name: foc_motor_openloop_trans
|
||||
****************************************************************************/
|
||||
|
||||
static void foc_motor_openloop_trans(FAR struct foc_motor_b16_s *motor)
|
||||
{
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
|
||||
/* Set the intergral part of the velocity PI controller equal to the
|
||||
* open-loop Q current value.
|
||||
*
|
||||
* REVISIT: this may casue a velocity overshoot when going from open-loop
|
||||
* to closed-loop. We can either use part of the open-loop Q
|
||||
* current here or gradually reduce the Q current during
|
||||
* transition.
|
||||
*/
|
||||
|
||||
motor->vel_pi.part[1] = b16mulb16(motor->dir, motor->openloop_q);
|
||||
motor->vel_pi.part[0] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: foc_motor_openloop_angobs
|
||||
****************************************************************************/
|
||||
|
||||
static void foc_motor_openloop_angobs(FAR struct foc_motor_b16_s *motor)
|
||||
{
|
||||
b16_t vel_abs = 0;
|
||||
|
||||
vel_abs = b16abs(motor->vel_el);
|
||||
|
||||
/* Disable open-loop if velocity above threshold */
|
||||
|
||||
if (motor->openloop_now == FOC_OPENLOOP_ENABLED)
|
||||
{
|
||||
if (vel_abs >= motor->ol_thr)
|
||||
{
|
||||
/* Store angle error between the forced open-loop angle and
|
||||
* observer output. The error will be gradually eliminated over
|
||||
* the next controller cycles.
|
||||
*/
|
||||
|
||||
#ifdef ANGLE_MERGE_FACTOR
|
||||
motor->angle_step = b16mulb16(motor->angle_err,
|
||||
ftob16(ANGLE_MERGE_FACTOR));
|
||||
motor->angle_err = motor->angle_ol - motor->angle_obs;
|
||||
#endif
|
||||
|
||||
motor->openloop_now = FOC_OPENLOOP_TRANSITION;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle transition end */
|
||||
|
||||
else if (motor->openloop_now == FOC_OPENLOOP_TRANSITION)
|
||||
{
|
||||
if (motor->angle_err == 0)
|
||||
{
|
||||
/* Call open-open loop transition handler */
|
||||
|
||||
foc_motor_openloop_trans(motor);
|
||||
|
||||
motor->openloop_now = FOC_OPENLOOP_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable open-loop if velocity below threshold with hysteresis */
|
||||
|
||||
else if (motor->openloop_now == FOC_OPENLOOP_DISABLED)
|
||||
{
|
||||
/* For better stability we add hysteresis from transition
|
||||
* from closed-loop to open-loop.
|
||||
*/
|
||||
|
||||
if (vel_abs < (motor->ol_thr - motor->ol_hys))
|
||||
{
|
||||
motor->openloop_now = FOC_OPENLOOP_ENABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: foc_motor_run
|
||||
****************************************************************************/
|
||||
@ -786,6 +869,15 @@ static int foc_motor_run(FAR struct foc_motor_b16_s *motor)
|
||||
|
||||
DEBUGASSERT(motor);
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
if (motor->envp->cfg->ol_force == false)
|
||||
{
|
||||
/* Handle open-loop to observer transition */
|
||||
|
||||
foc_motor_openloop_angobs(motor);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
/* Open-loop works only in velocity control mode */
|
||||
|
||||
@ -883,13 +975,14 @@ static int foc_motor_run(FAR struct foc_motor_b16_s *motor)
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
/* Force open-loop current */
|
||||
|
||||
if (motor->openloop_now == true)
|
||||
if (motor->openloop_now == FOC_OPENLOOP_ENABLED ||
|
||||
motor->openloop_now == FOC_OPENLOOP_TRANSITION)
|
||||
{
|
||||
/* Get open-loop currents
|
||||
* NOTE: Id always set to 0
|
||||
/* Get open-loop currents. Positive for CW direction, negative for
|
||||
* CCW direction. Id always set to 0.
|
||||
*/
|
||||
|
||||
q_ref = b16idiv(motor->envp->cfg->qparam, 1000);
|
||||
q_ref = b16mulb16(motor->dir, motor->openloop_q);
|
||||
d_ref = 0;
|
||||
}
|
||||
#endif
|
||||
@ -916,6 +1009,240 @@ errout:
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: foc_motor_ang_get
|
||||
****************************************************************************/
|
||||
|
||||
static int foc_motor_ang_get(FAR struct foc_motor_b16_s *motor)
|
||||
{
|
||||
struct foc_angle_in_b16_s ain;
|
||||
struct foc_angle_out_b16_s aout;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(motor);
|
||||
|
||||
/* Update open-loop angle handler */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
||||
ain.vel = motor->vel.set;
|
||||
#endif
|
||||
ain.angle = motor->angle_now;
|
||||
ain.dir = motor->dir;
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
if (motor->openloop_now != FOC_OPENLOOP_DISABLED)
|
||||
{
|
||||
foc_angle_run_b16(&motor->openloop, &ain, &aout);
|
||||
|
||||
/* Store open-loop angle */
|
||||
|
||||
motor->angle_ol = aout.angle;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_QENCO
|
||||
ret = foc_angle_run_b16(&motor->qenco, &ain, &aout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_HALL
|
||||
ret = foc_angle_run_b16(&motor->hall, &ain, &aout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_SMO
|
||||
ret = foc_angle_run_b16(&motor->ang_smo, &ain, &aout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
motor->angle_obs = aout.angle;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_NFO
|
||||
ret = foc_angle_run_b16(&motor->ang_nfo, &ain, &aout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
motor->angle_obs = aout.angle;
|
||||
#endif
|
||||
|
||||
/* Store electrical angle from sensor or observer */
|
||||
|
||||
if (aout.type == FOC_ANGLE_TYPE_ELE)
|
||||
{
|
||||
/* Store electrical angle */
|
||||
|
||||
motor->angle_el = aout.angle;
|
||||
}
|
||||
|
||||
else if (aout.type == FOC_ANGLE_TYPE_MECH)
|
||||
{
|
||||
/* Store mechanical angle */
|
||||
|
||||
motor->angle_m = aout.angle;
|
||||
|
||||
/* Convert mechanical angle to electrical angle */
|
||||
|
||||
motor->angle_el = (b16muli(motor->angle_m,
|
||||
motor->phy.p) %
|
||||
MOTOR_ANGLE_E_MAX_B16);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
/* Get open-loop phase angle */
|
||||
|
||||
if (motor->openloop_now == FOC_OPENLOOP_ENABLED)
|
||||
{
|
||||
motor->angle_now = motor->angle_ol;
|
||||
motor->angle_el = motor->angle_ol;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_SENSORLESS
|
||||
/* Handle smooth open-loop to closed-loop transition */
|
||||
|
||||
if (motor->openloop_now == FOC_OPENLOOP_TRANSITION)
|
||||
{
|
||||
#ifdef ANGLE_MERGE_FACTOR
|
||||
if (b16abs(motor->angle_err) > b16abs(motor->angle_step))
|
||||
{
|
||||
motor->angle_now = motor->angle_obs + motor->angle_err;
|
||||
|
||||
/* Update error */
|
||||
|
||||
motor->angle_err -= motor->angle_step;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
motor->angle_now = motor->angle_obs;
|
||||
motor->angle_err = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get angle from observer if closed-loop now */
|
||||
|
||||
else
|
||||
{
|
||||
motor->angle_now = motor->angle_obs;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_SENSORED
|
||||
/* Get phase angle from sensor */
|
||||
|
||||
motor->angle_now = motor->angle_el;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_EXAMPLES_FOC_SENSORED) || defined(CONFIG_EXAMPLES_FOC_ANGOBS)
|
||||
errout:
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
||||
/****************************************************************************
|
||||
* Name: foc_motor_vel_get
|
||||
****************************************************************************/
|
||||
|
||||
static int foc_motor_vel_get(FAR struct foc_motor_b16_s *motor)
|
||||
{
|
||||
struct foc_velocity_in_b16_s vin;
|
||||
struct foc_velocity_out_b16_s vout;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(motor);
|
||||
|
||||
/* Update velocity handler input data */
|
||||
|
||||
vin.state = &motor->foc_state;
|
||||
vin.angle = motor->angle_now;
|
||||
vin.vel = motor->vel.now;
|
||||
vin.dir = motor->dir;
|
||||
|
||||
/* Get velocity from observer */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
||||
ret = foc_velocity_run_b16(&motor->vel_div, &vin, &vout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_velocity_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_PLL
|
||||
ret = foc_velocity_run_b16(&motor->vel_pll, &vin, &vout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_velocity_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get motor electrical velocity now */
|
||||
|
||||
#if defined(CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP) && \
|
||||
!defined(CONFIG_EXAMPLES_FOC_VELOBS)
|
||||
/* No velocity feedback - assume that electical velocity is velocity set
|
||||
* in a open-loop contorller.
|
||||
*/
|
||||
|
||||
UNUSED(vin);
|
||||
UNUSED(vout);
|
||||
|
||||
motor->vel_el = motor->vel.set;
|
||||
#elif defined(CONFIG_EXAMPLES_FOC_VELOBS)
|
||||
if (motor->openloop_now == FOC_OPENLOOP_DISABLED)
|
||||
{
|
||||
/* Get electrical velocity from observer if we are in closed-loop */
|
||||
|
||||
motor->vel_el = motor->vel_obs;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise use open-loop velocity */
|
||||
|
||||
motor->vel_el = motor->vel.set;
|
||||
}
|
||||
#else
|
||||
/* Need electrical velocity source here - raise assertion */
|
||||
|
||||
ASSERT(0);
|
||||
#endif
|
||||
|
||||
LP_FILTER_B16(motor->vel.now, motor->vel_el, motor->vel_filter);
|
||||
|
||||
/* Get mechanical velocity (rad/s) */
|
||||
|
||||
motor->vel_mech = b16mulb16(motor->vel_el, motor->phy.one_by_p);
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS
|
||||
errout:
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_EXAMPLES_FOC_HAVE_VEL */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -936,6 +1263,12 @@ int foc_motor_init(FAR struct foc_motor_b16_s *motor,
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_HALL
|
||||
struct foc_hall_cfg_b16_s hl_cfg;
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_SMO
|
||||
struct foc_angle_osmo_cfg_b16_s smo_cfg;
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_NFO
|
||||
struct foc_angle_onfo_cfg_b16_s nfo_cfg;
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
||||
struct foc_vel_div_b16_cfg_s odiv_cfg;
|
||||
#endif
|
||||
@ -965,6 +1298,10 @@ int foc_motor_init(FAR struct foc_motor_b16_s *motor,
|
||||
|
||||
motor->per = b16divi(b16ONE, CONFIG_EXAMPLES_FOC_NOTIFIER_FREQ);
|
||||
motor->iphase_adc = ftob16((CONFIG_EXAMPLES_FOC_IPHASE_ADC) / 100000.0f);
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
motor->ol_thr = ftob16(motor->envp->cfg->ol_thr / 1.0f);
|
||||
motor->ol_hys = ftob16(motor->envp->cfg->ol_hys / 1.0f);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_RUN
|
||||
/* Initialize controller run mode */
|
||||
@ -991,6 +1328,10 @@ int foc_motor_init(FAR struct foc_motor_b16_s *motor,
|
||||
|
||||
ol_cfg.per = motor->per;
|
||||
foc_angle_cfg_b16(&motor->openloop, &ol_cfg);
|
||||
|
||||
/* Store open-loop Q-param */
|
||||
|
||||
motor->openloop_q = ftob16(motor->envp->cfg->qparam / 1000.0f);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_QENCO
|
||||
@ -1055,6 +1396,58 @@ int foc_motor_init(FAR struct foc_motor_b16_s *motor,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_SMO
|
||||
/* Initialzie SMO angle observer handler */
|
||||
|
||||
ret = foc_angle_init_b16(&motor->ang_smo,
|
||||
&g_foc_angle_osmo_b16);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_init_b16 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Configure SMO angle handler */
|
||||
|
||||
smo_cfg.per = motor->per;
|
||||
smo_cfg.k_slide = ftob16(CONFIG_EXAMPLES_FOC_ANGOBS_SMO_KSLIDE / 1000.0f);
|
||||
smo_cfg.err_max = ftob16(CONFIG_EXAMPLES_FOC_ANGOBS_SMO_ERRMAX / 1000.0f);
|
||||
memcpy(&smo_cfg.phy, &motor->phy, sizeof(struct motor_phy_params_b16_s));
|
||||
|
||||
ret = foc_angle_cfg_b16(&motor->ang_smo, &smo_cfg);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_cfg_b16 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_NFO
|
||||
/* Initialzie NFO angle observer handler */
|
||||
|
||||
ret = foc_angle_init_b16(&motor->ang_nfo,
|
||||
&g_foc_angle_onfo_b16);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_init_b16 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Configure NFO angle handler */
|
||||
|
||||
nfo_cfg.per = motor->per;
|
||||
nfo_cfg.gain = ftob16(motor->envp->cfg->ang_nfo_gain / 1.0f);
|
||||
nfo_cfg.gain_slow = ftob16(motor->envp->cfg->ang_nfo_slow / 1.0f);
|
||||
memcpy(&nfo_cfg.phy, &motor->phy, sizeof(struct motor_phy_params_b16_s));
|
||||
|
||||
ret = foc_angle_cfg_b16(&motor->ang_nfo, &nfo_cfg);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_cfg_b16 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
||||
/* Initialize velocity observer */
|
||||
|
||||
@ -1142,6 +1535,9 @@ int foc_motor_init(FAR struct foc_motor_b16_s *motor,
|
||||
|
||||
/* Connect align callbacks private data */
|
||||
|
||||
# ifdef CONFIG_EXAMPLES_FOC_SENSORLESS
|
||||
align_cfg.cb.priv = &motor->openloop;
|
||||
# endif
|
||||
# ifdef CONFIG_EXAMPLES_FOC_HAVE_QENCO
|
||||
align_cfg.cb.priv = &motor->qenco;
|
||||
# endif
|
||||
@ -1268,6 +1664,28 @@ int foc_motor_deinit(FAR struct foc_motor_b16_s *motor)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_SMO
|
||||
/* Deinitialize SMO observer handler */
|
||||
|
||||
ret = foc_angle_deinit_b16(&motor->ang_smo);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_deinit_b16 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_NFO
|
||||
/* Deinitialize NFO observer handler */
|
||||
|
||||
ret = foc_angle_deinit_b16(&motor->ang_nfo);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_deinit_b16 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
||||
/* Deinitialize DIV observer handler */
|
||||
|
||||
@ -1346,164 +1764,29 @@ errout:
|
||||
|
||||
int foc_motor_get(FAR struct foc_motor_b16_s *motor)
|
||||
{
|
||||
struct foc_angle_in_b16_s ain;
|
||||
struct foc_angle_out_b16_s aout;
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
||||
struct foc_velocity_in_b16_s vin;
|
||||
struct foc_velocity_out_b16_s vout;
|
||||
#endif
|
||||
int ret = OK;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(motor);
|
||||
|
||||
/* Update open-loop angle handler */
|
||||
/* Get motor angle */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
||||
ain.vel = motor->vel.set;
|
||||
#endif
|
||||
ain.angle = motor->angle_now;
|
||||
ain.dir = motor->dir;
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
foc_angle_run_b16(&motor->openloop, &ain, &aout);
|
||||
|
||||
/* Store open-loop angle */
|
||||
|
||||
motor->angle_ol = aout.angle;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_QENCO
|
||||
ret = foc_angle_run_b16(&motor->qenco, &ain, &aout);
|
||||
ret = foc_motor_ang_get(motor);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_HALL
|
||||
ret = foc_angle_run_b16(&motor->hall, &ain, &aout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_SENSORED
|
||||
/* Handle angle from sensor */
|
||||
|
||||
if (aout.type == FOC_ANGLE_TYPE_ELE)
|
||||
{
|
||||
/* Store electrical angle */
|
||||
|
||||
motor->angle_el = aout.angle;
|
||||
}
|
||||
|
||||
else if (aout.type == FOC_ANGLE_TYPE_MECH)
|
||||
{
|
||||
/* Store mechanical angle */
|
||||
|
||||
motor->angle_m = aout.angle;
|
||||
|
||||
/* Convert mechanical angle to electrical angle */
|
||||
|
||||
motor->angle_el = (b16muli(motor->angle_m,
|
||||
motor->phy.p) %
|
||||
MOTOR_ANGLE_E_MAX_B16);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
#endif /* CONFIG_EXAMPLES_FOC_SENSORED */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
/* Get phase angle now */
|
||||
|
||||
if (motor->openloop_now == true)
|
||||
{
|
||||
motor->angle_now = motor->angle_ol;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Get phase angle from observer or sensor */
|
||||
|
||||
motor->angle_now = motor->angle_el;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
||||
/* Update velocity handler input data */
|
||||
/* Get motor velocity */
|
||||
|
||||
vin.state = &motor->foc_state;
|
||||
vin.angle = motor->angle_now;
|
||||
vin.vel = motor->vel.now;
|
||||
vin.dir = motor->dir;
|
||||
|
||||
/* Get velocity */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
||||
ret = foc_velocity_run_b16(&motor->vel_div, &vin, &vout);
|
||||
ret = foc_motor_vel_get(motor);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_velocity_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_PLL
|
||||
ret = foc_velocity_run_b16(&motor->vel_pll, &vin, &vout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_velocity_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get motor electrical velocity now */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
if (motor->openloop_now == true)
|
||||
{
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS
|
||||
/* Electrical velocity from observer */
|
||||
|
||||
motor->vel_el = motor->vel_obs;
|
||||
#else
|
||||
UNUSED(vin);
|
||||
UNUSED(vout);
|
||||
|
||||
/* No velocity feedback - assume that electical velocity is
|
||||
* velocity set
|
||||
*/
|
||||
|
||||
motor->vel_el = motor->vel.set;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS
|
||||
/* Store electrical velocity */
|
||||
|
||||
motor->vel_el = motor->vel_obs;
|
||||
#else
|
||||
ASSERT(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
LP_FILTER_B16(motor->vel.now, motor->vel_el, motor->vel_filter);
|
||||
|
||||
/* Get mechanical velocity */
|
||||
|
||||
motor->vel_mech = b16mulb16(motor->vel_el, motor->phy.one_by_p);
|
||||
#endif /* CONFIG_EXAMPLES_FOC_HAVE_VEL */
|
||||
|
||||
#if defined(CONFIG_EXAMPLES_FOC_SENSORED) || defined(CONFIG_EXAMPLES_FOC_VELOBS)
|
||||
errout:
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,11 @@ struct foc_motor_b16_s
|
||||
b16_t per; /* Controller period in seconds */
|
||||
b16_t iphase_adc; /* Iphase ADC scaling factor */
|
||||
b16_t pwm_duty_max; /* PWM duty max */
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
b16_t ol_thr; /* Angle observer threshold velocity */
|
||||
b16_t ol_hys; /* Angle observer hysteresis */
|
||||
b16_t angle_step; /* Open-loop transition step */
|
||||
#endif
|
||||
|
||||
/* Velocity controller data ***********************************************/
|
||||
|
||||
@ -100,11 +105,18 @@ struct foc_motor_b16_s
|
||||
pid_controller_b16_t vel_pi; /* Velocity controller */
|
||||
#endif
|
||||
|
||||
/* Motor state ************************************************************/
|
||||
/* Angle state ************************************************************/
|
||||
|
||||
b16_t angle_now; /* Phase angle now */
|
||||
b16_t angle_m; /* Motor mechanical angle */
|
||||
b16_t angle_el; /* Motor electrical angle */
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
b16_t angle_ol; /* Phase angle open-loop */
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
b16_t angle_obs; /* Angle observer output */
|
||||
b16_t angle_err; /* Open-loop to observer error */
|
||||
#endif
|
||||
|
||||
/* Velocity state *********************************************************/
|
||||
|
||||
@ -154,8 +166,8 @@ struct foc_motor_b16_s
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
foc_angle_b16_t openloop; /* Open-loop angle handler */
|
||||
bool openloop_now; /* Open-loop now */
|
||||
b16_t angle_ol; /* Phase angle open-loop */
|
||||
uint8_t openloop_now; /* Open-loop now */
|
||||
b16_t openloop_q; /* Open-loop Q parameter */
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_HALL
|
||||
foc_angle_b16_t hall; /* Hall angle handler */
|
||||
@ -171,6 +183,12 @@ struct foc_motor_b16_s
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_PLL
|
||||
foc_velocity_b16_t vel_pll; /* PLL velocity observer */
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_SMO
|
||||
foc_angle_b16_t ang_smo; /* SMO angle observer */
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_NFO
|
||||
foc_angle_b16_t ang_nfo; /* NFO angle observer */
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -269,7 +269,7 @@ static int foc_runmode_init(FAR struct foc_motor_f32_s *motor)
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_SENSORLESS
|
||||
# ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
motor->openloop_now = true;
|
||||
motor->openloop_now = FOC_OPENLOOP_ENABLED;
|
||||
# else
|
||||
# error
|
||||
# endif
|
||||
@ -755,6 +755,88 @@ static int foc_motor_run_init(FAR struct foc_motor_f32_s *motor)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
/****************************************************************************
|
||||
* Name: foc_motor_openloop_trans
|
||||
****************************************************************************/
|
||||
|
||||
static void foc_motor_openloop_trans(FAR struct foc_motor_f32_s *motor)
|
||||
{
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
|
||||
/* Set the intergral part of the velocity PI controller equal to the
|
||||
* open-loop Q current value.
|
||||
*
|
||||
* REVISIT: this may casue a velocity overshoot when going from open-loop
|
||||
* to closed-loop. We can either use part of the open-loop Q
|
||||
* current here or gradually reduce the Q current during
|
||||
* transition.
|
||||
*/
|
||||
|
||||
motor->vel_pi.part[1] = motor->dir * motor->openloop_q;
|
||||
motor->vel_pi.part[0] = 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: foc_motor_openloop_angobs
|
||||
****************************************************************************/
|
||||
|
||||
static void foc_motor_openloop_angobs(FAR struct foc_motor_f32_s *motor)
|
||||
{
|
||||
float vel_abs = 0.0f;
|
||||
|
||||
vel_abs = fabsf(motor->vel_el);
|
||||
|
||||
/* Disable open-loop if velocity above threshold */
|
||||
|
||||
if (motor->openloop_now == FOC_OPENLOOP_ENABLED)
|
||||
{
|
||||
if (vel_abs >= motor->ol_thr)
|
||||
{
|
||||
/* Store angle error between the forced open-loop angle and
|
||||
* observer output. The error will be gradually eliminated over
|
||||
* the next controller cycles.
|
||||
*/
|
||||
|
||||
#ifdef ANGLE_MERGE_FACTOR
|
||||
motor->angle_err = motor->angle_ol - motor->angle_obs;
|
||||
motor->angle_step = (motor->angle_err * ANGLE_MERGE_FACTOR);
|
||||
#endif
|
||||
|
||||
motor->openloop_now = FOC_OPENLOOP_TRANSITION;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle transition end */
|
||||
|
||||
else if (motor->openloop_now == FOC_OPENLOOP_TRANSITION)
|
||||
{
|
||||
if (motor->angle_err == 0.0f)
|
||||
{
|
||||
/* Call open-open loop transition handler */
|
||||
|
||||
foc_motor_openloop_trans(motor);
|
||||
|
||||
motor->openloop_now = FOC_OPENLOOP_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable open-loop if velocity below threshold with hysteresis */
|
||||
|
||||
else if (motor->openloop_now == FOC_OPENLOOP_DISABLED)
|
||||
{
|
||||
/* For better stability we add hysteresis from transition
|
||||
* from closed-loop to open-loop.
|
||||
*/
|
||||
|
||||
if (vel_abs < (motor->ol_thr - motor->ol_hys))
|
||||
{
|
||||
motor->openloop_now = FOC_OPENLOOP_ENABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: foc_motor_run
|
||||
****************************************************************************/
|
||||
@ -770,10 +852,19 @@ static int foc_motor_run(FAR struct foc_motor_f32_s *motor)
|
||||
|
||||
DEBUGASSERT(motor);
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
if (motor->envp->cfg->ol_force == false)
|
||||
{
|
||||
/* Handle open-loop to observer transition */
|
||||
|
||||
foc_motor_openloop_angobs(motor);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
/* Open-loop works only in velocity control mode */
|
||||
|
||||
if (motor->openloop_now == true)
|
||||
if (motor->openloop_now == FOC_OPENLOOP_ENABLED)
|
||||
{
|
||||
# ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
||||
if (motor->envp->cfg->mmode != FOC_MMODE_VEL)
|
||||
@ -835,7 +926,7 @@ static int foc_motor_run(FAR struct foc_motor_f32_s *motor)
|
||||
/* Run velocity controller if no in open-loop */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
if (motor->openloop_now == false)
|
||||
if (motor->openloop_now == FOC_OPENLOOP_DISABLED)
|
||||
#endif
|
||||
{
|
||||
/* Get velocity error */
|
||||
@ -867,13 +958,14 @@ static int foc_motor_run(FAR struct foc_motor_f32_s *motor)
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
/* Force open-loop current */
|
||||
|
||||
if (motor->openloop_now == true)
|
||||
if (motor->openloop_now == FOC_OPENLOOP_ENABLED ||
|
||||
motor->openloop_now == FOC_OPENLOOP_TRANSITION)
|
||||
{
|
||||
/* Get open-loop currents
|
||||
* NOTE: Id always set to 0
|
||||
/* Get open-loop currents. Positive for CW direction, negative for
|
||||
* CCW direction. Id always set to 0.
|
||||
*/
|
||||
|
||||
q_ref = (motor->envp->cfg->qparam / 1000.0f);
|
||||
q_ref = motor->dir * motor->openloop_q;
|
||||
d_ref = 0.0f;
|
||||
}
|
||||
#endif
|
||||
@ -900,6 +992,246 @@ errout:
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: foc_motor_ang_get
|
||||
****************************************************************************/
|
||||
|
||||
static int foc_motor_ang_get(FAR struct foc_motor_f32_s *motor)
|
||||
{
|
||||
struct foc_angle_in_f32_s ain;
|
||||
struct foc_angle_out_f32_s aout;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(motor);
|
||||
|
||||
/* Update open-loop angle handler */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
||||
ain.vel = motor->vel.set;
|
||||
#endif
|
||||
ain.state = &motor->foc_state;
|
||||
ain.angle = motor->angle_now;
|
||||
ain.dir = motor->dir;
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
if (motor->openloop_now != FOC_OPENLOOP_DISABLED)
|
||||
{
|
||||
foc_angle_run_f32(&motor->openloop, &ain, &aout);
|
||||
|
||||
/* Store open-loop angle */
|
||||
|
||||
motor->angle_ol = aout.angle;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_QENCO
|
||||
ret = foc_angle_run_f32(&motor->qenco, &ain, &aout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_HALL
|
||||
ret = foc_angle_run_f32(&motor->hall, &ain, &aout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_SMO
|
||||
ret = foc_angle_run_f32(&motor->ang_smo, &ain, &aout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
motor->angle_obs = aout.angle;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_NFO
|
||||
ret = foc_angle_run_f32(&motor->ang_nfo, &ain, &aout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
motor->angle_obs = aout.angle;
|
||||
#endif
|
||||
|
||||
/* Store electrical angle from sensor or observer */
|
||||
|
||||
if (aout.type == FOC_ANGLE_TYPE_ELE)
|
||||
{
|
||||
/* Store as electrical angle */
|
||||
|
||||
motor->angle_el = aout.angle;
|
||||
}
|
||||
|
||||
else if (aout.type == FOC_ANGLE_TYPE_MECH)
|
||||
{
|
||||
/* Store as mechanical angle */
|
||||
|
||||
motor->angle_m = aout.angle;
|
||||
|
||||
/* Convert mechanical angle to electrical angle */
|
||||
|
||||
motor->angle_el = fmodf(motor->angle_m * motor->phy.p,
|
||||
MOTOR_ANGLE_E_MAX);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
/* Get open-loop phase angle */
|
||||
|
||||
if (motor->openloop_now == FOC_OPENLOOP_ENABLED)
|
||||
{
|
||||
motor->angle_now = motor->angle_ol;
|
||||
motor->angle_el = motor->angle_ol;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_SENSORLESS
|
||||
/* Handle smooth open-loop to closed-loop transition */
|
||||
|
||||
if (motor->openloop_now == FOC_OPENLOOP_TRANSITION)
|
||||
{
|
||||
#ifdef ANGLE_MERGE_FACTOR
|
||||
if (fabsf(motor->angle_err) > fabsf(motor->angle_step))
|
||||
{
|
||||
motor->angle_now = motor->angle_obs + motor->angle_err;
|
||||
|
||||
/* Update error */
|
||||
|
||||
motor->angle_err -= motor->angle_step;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
motor->angle_now = motor->angle_obs;
|
||||
motor->angle_err = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get angle from observer if closed-loop now */
|
||||
|
||||
else
|
||||
{
|
||||
motor->angle_now = motor->angle_obs;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_SENSORED
|
||||
/* Get phase angle from sensor */
|
||||
|
||||
motor->angle_now = motor->angle_el;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_EXAMPLES_FOC_SENSORED) || defined(CONFIG_EXAMPLES_FOC_ANGOBS)
|
||||
errout:
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
||||
/****************************************************************************
|
||||
* Name: foc_motor_vel_get
|
||||
****************************************************************************/
|
||||
|
||||
static int foc_motor_vel_get(FAR struct foc_motor_f32_s *motor)
|
||||
{
|
||||
struct foc_velocity_in_f32_s vin;
|
||||
struct foc_velocity_out_f32_s vout;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(motor);
|
||||
|
||||
/* Update velocity handler input data */
|
||||
|
||||
vin.state = &motor->foc_state;
|
||||
vin.angle = motor->angle_now;
|
||||
vin.vel = motor->vel.now;
|
||||
vin.dir = motor->dir;
|
||||
|
||||
/* Get velocity */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
||||
ret = foc_velocity_run_f32(&motor->vel_div, &vin, &vout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_velocity_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
motor->vel_obs = vout.velocity;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_PLL
|
||||
ret = foc_velocity_run_f32(&motor->vel_pll, &vin, &vout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_velocity_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
motor->vel_obs = vout.velocity;
|
||||
#endif
|
||||
|
||||
/* Get motor electrical velocity now */
|
||||
|
||||
#if defined(CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP) && \
|
||||
!defined(CONFIG_EXAMPLES_FOC_VELOBS)
|
||||
/* No velocity feedback - assume that electical velocity is
|
||||
* velocity set
|
||||
*/
|
||||
|
||||
UNUSED(vin);
|
||||
UNUSED(vout);
|
||||
|
||||
motor->vel_el = motor->vel.set;
|
||||
#elif defined(CONFIG_EXAMPLES_FOC_VELOBS)
|
||||
if (motor->openloop_now == FOC_OPENLOOP_DISABLED)
|
||||
{
|
||||
/* Get electrical velocity from observer if we are in closed-loop */
|
||||
|
||||
motor->vel_el = motor->vel_obs;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise use open-loop velocity */
|
||||
|
||||
motor->vel_el = motor->vel.set;
|
||||
}
|
||||
#else
|
||||
/* Need electrical velocity source here - raise assertion */
|
||||
|
||||
ASSERT(0);
|
||||
#endif
|
||||
|
||||
/* Store filtered velocity */
|
||||
|
||||
LP_FILTER(motor->vel.now, motor->vel_el, motor->vel_filter);
|
||||
|
||||
/* Get mechanical velocity (rad/s) */
|
||||
|
||||
motor->vel_mech = motor->vel_el * motor->phy.one_by_p;
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS
|
||||
errout:
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_EXAMPLES_FOC_HAVE_VEL */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -920,6 +1252,12 @@ int foc_motor_init(FAR struct foc_motor_f32_s *motor,
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_HALL
|
||||
struct foc_hall_cfg_f32_s hl_cfg;
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_SMO
|
||||
struct foc_angle_osmo_cfg_f32_s smo_cfg;
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_NFO
|
||||
struct foc_angle_onfo_cfg_f32_s nfo_cfg;
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
||||
struct foc_vel_div_f32_cfg_s odiv_cfg;
|
||||
#endif
|
||||
@ -949,6 +1287,10 @@ int foc_motor_init(FAR struct foc_motor_f32_s *motor,
|
||||
|
||||
motor->per = (float)(1.0f / CONFIG_EXAMPLES_FOC_NOTIFIER_FREQ);
|
||||
motor->iphase_adc = ((CONFIG_EXAMPLES_FOC_IPHASE_ADC) / 100000.0f);
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
motor->ol_thr = (motor->envp->cfg->ol_thr / 1.0f);
|
||||
motor->ol_hys = (motor->envp->cfg->ol_hys / 1.0f);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_RUN
|
||||
/* Initialize controller run mode */
|
||||
@ -975,6 +1317,10 @@ int foc_motor_init(FAR struct foc_motor_f32_s *motor,
|
||||
|
||||
ol_cfg.per = motor->per;
|
||||
foc_angle_cfg_f32(&motor->openloop, &ol_cfg);
|
||||
|
||||
/* Store open-loop Q-param */
|
||||
|
||||
motor->openloop_q = motor->envp->cfg->qparam / 1000.0f;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_QENCO
|
||||
@ -1039,6 +1385,58 @@ int foc_motor_init(FAR struct foc_motor_f32_s *motor,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_SMO
|
||||
/* Initialzie SMO angle observer handler */
|
||||
|
||||
ret = foc_angle_init_f32(&motor->ang_smo,
|
||||
&g_foc_angle_osmo_f32);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_init_f32 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Configure SMO angle handler */
|
||||
|
||||
smo_cfg.per = motor->per;
|
||||
smo_cfg.k_slide = (CONFIG_EXAMPLES_FOC_ANGOBS_SMO_KSLIDE / 1000.0f);
|
||||
smo_cfg.err_max = (CONFIG_EXAMPLES_FOC_ANGOBS_SMO_ERRMAX / 1000.0f);
|
||||
memcpy(&smo_cfg.phy, &motor->phy, sizeof(struct motor_phy_params_f32_s));
|
||||
|
||||
ret = foc_angle_cfg_f32(&motor->ang_smo, &smo_cfg);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_cfg_f32 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_NFO
|
||||
/* Initialzie NFO angle observer handler */
|
||||
|
||||
ret = foc_angle_init_f32(&motor->ang_nfo,
|
||||
&g_foc_angle_onfo_f32);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_init_f32 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Configure NFO angle handler */
|
||||
|
||||
nfo_cfg.per = motor->per;
|
||||
nfo_cfg.gain = (motor->envp->cfg->ang_nfo_gain / 1.0f);
|
||||
nfo_cfg.gain_slow = (motor->envp->cfg->ang_nfo_slow / 1.0f);
|
||||
memcpy(&nfo_cfg.phy, &motor->phy, sizeof(struct motor_phy_params_f32_s));
|
||||
|
||||
ret = foc_angle_cfg_f32(&motor->ang_nfo, &nfo_cfg);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_cfg_f32 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
||||
/* Initialize velocity observer */
|
||||
|
||||
@ -1126,6 +1524,9 @@ int foc_motor_init(FAR struct foc_motor_f32_s *motor,
|
||||
|
||||
/* Connect align callbacks private data */
|
||||
|
||||
# ifdef CONFIG_EXAMPLES_FOC_SENSORLESS
|
||||
align_cfg.cb.priv = &motor->openloop;
|
||||
# endif
|
||||
# ifdef CONFIG_EXAMPLES_FOC_HAVE_QENCO
|
||||
align_cfg.cb.priv = &motor->qenco;
|
||||
# endif
|
||||
@ -1254,6 +1655,28 @@ int foc_motor_deinit(FAR struct foc_motor_f32_s *motor)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_SMO
|
||||
/* Deinitialize SMO observer handler */
|
||||
|
||||
ret = foc_angle_deinit_f32(&motor->ang_smo);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_deinit_f32 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_NFO
|
||||
/* Deinitialize NFO observer handler */
|
||||
|
||||
ret = foc_angle_deinit_f32(&motor->ang_nfo);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTFV("ERROR: foc_angle_deinit_f32 failed %d!\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
||||
/* Deinitialize DIV observer handler */
|
||||
|
||||
@ -1332,169 +1755,29 @@ errout:
|
||||
|
||||
int foc_motor_get(FAR struct foc_motor_f32_s *motor)
|
||||
{
|
||||
struct foc_angle_in_f32_s ain;
|
||||
struct foc_angle_out_f32_s aout;
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
||||
struct foc_velocity_in_f32_s vin;
|
||||
struct foc_velocity_out_f32_s vout;
|
||||
#endif
|
||||
int ret = OK;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(motor);
|
||||
|
||||
/* Update open-loop angle handler */
|
||||
/* Get motor angle */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
||||
ain.vel = motor->vel.set;
|
||||
#endif
|
||||
ain.angle = motor->angle_now;
|
||||
ain.dir = motor->dir;
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
foc_angle_run_f32(&motor->openloop, &ain, &aout);
|
||||
|
||||
/* Store open-loop angle */
|
||||
|
||||
motor->angle_ol = aout.angle;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_QENCO
|
||||
ret = foc_angle_run_f32(&motor->qenco, &ain, &aout);
|
||||
ret = foc_motor_ang_get(motor);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_HALL
|
||||
ret = foc_angle_run_f32(&motor->hall, &ain, &aout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_angle_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_SENSORED
|
||||
/* Handle angle from sensor */
|
||||
|
||||
if (aout.type == FOC_ANGLE_TYPE_ELE)
|
||||
{
|
||||
/* Store electrical angle */
|
||||
|
||||
motor->angle_el = aout.angle;
|
||||
}
|
||||
|
||||
else if (aout.type == FOC_ANGLE_TYPE_MECH)
|
||||
{
|
||||
/* Store mechanical angle */
|
||||
|
||||
motor->angle_m = aout.angle;
|
||||
|
||||
/* Convert mechanical angle to electrical angle */
|
||||
|
||||
motor->angle_el = fmodf(motor->angle_m * motor->phy.p,
|
||||
MOTOR_ANGLE_E_MAX);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
#endif /* CONFIG_EXAMPLES_FOC_SENSORED */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
/* Get phase angle now */
|
||||
|
||||
if (motor->openloop_now == true)
|
||||
{
|
||||
motor->angle_now = motor->angle_ol;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Get phase angle from observer or sensor */
|
||||
|
||||
motor->angle_now = motor->angle_el;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
||||
/* Update velocity handler input data */
|
||||
/* Get motor velocity */
|
||||
|
||||
vin.state = &motor->foc_state;
|
||||
vin.angle = motor->angle_now;
|
||||
vin.vel = motor->vel.now;
|
||||
vin.dir = motor->dir;
|
||||
|
||||
/* Get velocity */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
||||
ret = foc_velocity_run_f32(&motor->vel_div, &vin, &vout);
|
||||
ret = foc_motor_vel_get(motor);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_velocity_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
motor->vel_obs = vout.velocity;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_PLL
|
||||
ret = foc_velocity_run_f32(&motor->vel_pll, &vin, &vout);
|
||||
if (ret < 0)
|
||||
{
|
||||
PRINTF("ERROR: foc_velocity_run failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
motor->vel_obs = vout.velocity;
|
||||
#endif
|
||||
|
||||
/* Get motor electrical velocity now */
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
if (motor->openloop_now == true)
|
||||
{
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS
|
||||
/* Electrical velocity from observer */
|
||||
|
||||
motor->vel_el = motor->vel_obs;
|
||||
#else
|
||||
UNUSED(vin);
|
||||
UNUSED(vout);
|
||||
|
||||
/* No velocity feedback - assume that electical velocity is
|
||||
* velocity set
|
||||
*/
|
||||
|
||||
motor->vel_el = motor->vel.set;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS
|
||||
/* Store electrical velocity */
|
||||
|
||||
motor->vel_el = motor->vel_obs;
|
||||
#else
|
||||
ASSERT(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Store filtered velocity */
|
||||
|
||||
LP_FILTER(motor->vel.now, motor->vel_el, motor->vel_filter);
|
||||
|
||||
/* Get mechanical velocity */
|
||||
|
||||
motor->vel_mech = motor->vel_el * motor->phy.one_by_p;
|
||||
#endif /* CONFIG_EXAMPLES_FOC_HAVE_VEL */
|
||||
|
||||
#if defined(CONFIG_EXAMPLES_FOC_SENSORED) || defined(CONFIG_EXAMPLES_FOC_VELOBS)
|
||||
errout:
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,10 @@ struct foc_motor_f32_s
|
||||
float per; /* Controller period in seconds */
|
||||
float iphase_adc; /* Iphase ADC scaling factor */
|
||||
float pwm_duty_max; /* PWM duty max */
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
float ol_thr; /* Angle observer threshold velocity */
|
||||
float ol_hys; /* Angle observer hysteresis */
|
||||
#endif
|
||||
|
||||
/* Velocity controller data ***********************************************/
|
||||
|
||||
@ -100,11 +104,19 @@ struct foc_motor_f32_s
|
||||
pid_controller_f32_t vel_pi; /* Velocity controller */
|
||||
#endif
|
||||
|
||||
/* Motor state ************************************************************/
|
||||
/* Angle state ************************************************************/
|
||||
|
||||
float angle_now; /* Phase angle now */
|
||||
float angle_m; /* Motor mechanical angle */
|
||||
float angle_el; /* Motor electrical angle */
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
float angle_ol; /* Phase angle open-loop */
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
float angle_obs; /* Angle observer output */
|
||||
float angle_err; /* Open-loop to observer error */
|
||||
float angle_step; /* Open-loop transition step */
|
||||
#endif
|
||||
|
||||
/* Velocity state *********************************************************/
|
||||
|
||||
@ -154,8 +166,8 @@ struct foc_motor_f32_s
|
||||
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
foc_angle_f32_t openloop; /* Open-loop angle handler */
|
||||
bool openloop_now; /* Open-loop now */
|
||||
float angle_ol; /* Phase angle open-loop */
|
||||
uint8_t openloop_now; /* Open-loop now */
|
||||
float openloop_q; /* Open-loop Q parameter */
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_HALL
|
||||
foc_angle_f32_t hall; /* Hall angle handler */
|
||||
@ -171,6 +183,12 @@ struct foc_motor_f32_s
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_PLL
|
||||
foc_velocity_f32_t vel_pll; /* PLL velocity observer */
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_SMO
|
||||
foc_angle_f32_t ang_smo; /* SMO angle observer */
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_ANGOBS_NFO
|
||||
foc_angle_f32_t ang_nfo; /* NFO angle observer */
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -242,6 +242,9 @@ int foc_nxscope_init(FAR struct foc_nxscope_s *nxs)
|
||||
#if (CONFIG_EXAMPLES_FOC_NXSCOPE_CFG & FOC_NXSCOPE_VOBS)
|
||||
nxscope_chan_init(&nxs->nxs, i++, "vobs", u.u8, 1, 0);
|
||||
#endif
|
||||
#if (CONFIG_EXAMPLES_FOC_NXSCOPE_CFG & FOC_NXSCOPE_AOBS)
|
||||
nxscope_chan_init(&nxs->nxs, i++, "aobs", u.u8, 1, 0);
|
||||
#endif
|
||||
|
||||
if (i > CONFIG_EXAMPLES_FOC_NXSCOPE_CHANNELS)
|
||||
{
|
||||
|
@ -53,6 +53,7 @@
|
||||
#define FOC_NXSCOPE_VDQCOMP (1 << 15) /* VDQ compensation */
|
||||
#define FOC_NXSCOPE_SVM3 (1 << 16) /* Space-vector modulation sector */
|
||||
#define FOC_NXSCOPE_VOBS (1 << 17) /* Output from velocity observer */
|
||||
#define FOC_NXSCOPE_AOBS (1 << 18) /* Output from angle observer */
|
||||
/* Max 32-bit */
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -53,6 +53,13 @@
|
||||
#define OPT_VCPIKP (SCHAR_MAX + 11)
|
||||
#define OPT_VCPIKI (SCHAR_MAX + 12)
|
||||
|
||||
#define OPT_ANFOS (SCHAR_MAX + 13)
|
||||
#define OPT_ANFOG (SCHAR_MAX + 14)
|
||||
|
||||
#define OPT_OLFORCE (SCHAR_MAX + 16)
|
||||
#define OPT_OLTHR (SCHAR_MAX + 17)
|
||||
#define OPT_OLHYS (SCHAR_MAX + 18)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
@ -76,6 +83,11 @@ static struct option g_long_options[] =
|
||||
{ "en", required_argument, 0, 'j' },
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
{ "oqset", required_argument, 0, 'o' },
|
||||
{ "olforce", no_argument, 0, OPT_OLFORCE },
|
||||
# ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
{ "olthr", required_argument, 0, OPT_OLTHR },
|
||||
{ "olhys", required_argument, 0, OPT_OLHYS },
|
||||
# endif
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_CONTROL_PI
|
||||
{ "fkp", required_argument, 0, OPT_FKP },
|
||||
@ -99,6 +111,10 @@ static struct option g_long_options[] =
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
|
||||
{ "vcpikp", required_argument, 0, OPT_VCPIKP },
|
||||
{ "vcpiki", required_argument, 0, OPT_VCPIKI },
|
||||
#endif
|
||||
#ifdef CONFIG_INDUSTRY_FOC_ANGLE_ONFO
|
||||
{ "anfos", required_argument, 0, OPT_ANFOS },
|
||||
{ "anfog", required_argument, 0, OPT_ANFOG },
|
||||
#endif
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
@ -154,6 +170,13 @@ static void foc_help(void)
|
||||
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
||||
PRINTF(" [-o] openloop Vq/Iq setting [x1000] (default: %d)\n",
|
||||
CONFIG_EXAMPLES_FOC_OPENLOOP_Q);
|
||||
PRINTF(" [--olforce] force openloop\n");
|
||||
# ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
||||
PRINTF(" [--olthr] observer vel threshold [x1] (default: %d)\n",
|
||||
CONFIG_EXAMPLES_FOC_ANGOBS_THR);
|
||||
PRINTF(" [--olhys] observer vel hysteresys [x1] (default: %d)\n",
|
||||
CONFIG_EXAMPLES_FOC_ANGOBS_THR);
|
||||
# endif
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_CONTROL_PI
|
||||
PRINTF(" [--fki] PI Kp coefficient [x1000] (default: %d)\n",
|
||||
@ -186,11 +209,17 @@ static void foc_help(void)
|
||||
CONFIG_EXAMPLES_FOC_VELOBS_DIV_FILTER);
|
||||
#endif
|
||||
#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
|
||||
PRINTF(" [--vpikp] velctrl PI Kp (default: %d)\n",
|
||||
PRINTF(" [--vcpikp] velctrl PI Kp (default: %d)\n",
|
||||
CONFIG_EXAMPLES_FOC_VELCTRL_PI_KP);
|
||||
PRINTF(" [--vpiki] velctrl PI Ki (default: %d)\n",
|
||||
PRINTF(" [--vcpiki] velctrl PI Ki (default: %d)\n",
|
||||
CONFIG_EXAMPLES_FOC_VELCTRL_PI_KI);
|
||||
#endif
|
||||
#ifdef CONFIG_INDUSTRY_FOC_ANGLE_ONFO
|
||||
PRINTF(" [--anfos] angobs NFO Slow (default: %d)\n",
|
||||
CONFIG_EXAMPLES_FOC_ANGOBS_NFO_GAINSLOW);
|
||||
PRINTF(" [--anfog] angobs NFO Gain (default: %d)\n",
|
||||
CONFIG_EXAMPLES_FOC_ANGOBS_NFO_GAIN);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -306,6 +335,20 @@ void parse_args(FAR struct args_s *args, int argc, FAR char **argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INDUSTRY_FOC_ANGLE_ONFO
|
||||
case OPT_ANFOS:
|
||||
{
|
||||
args->cfg.ang_nfo_slow = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case OPT_ANFOG:
|
||||
{
|
||||
args->cfg.ang_nfo_gain = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case 't':
|
||||
{
|
||||
args->time = atoi(optarg);
|
||||
@ -372,6 +415,24 @@ void parse_args(FAR struct args_s *args, int argc, FAR char **argv)
|
||||
args->cfg.qparam = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case OPT_OLFORCE:
|
||||
{
|
||||
args->cfg.ol_force = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case OPT_OLTHR:
|
||||
{
|
||||
args->cfg.ol_thr = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case OPT_OLHYS:
|
||||
{
|
||||
args->cfg.ol_hys = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case '?':
|
||||
|
@ -80,6 +80,15 @@ enum foc_angle_type_e
|
||||
FOC_ANGLE_TYPE_MECH = 2, /* Mechanical angle */
|
||||
};
|
||||
|
||||
/* Open-loop stage */
|
||||
|
||||
enum foc_openloop_stage_e
|
||||
{
|
||||
FOC_OPENLOOP_ENABLED = 1, /* Open-loop enabled */
|
||||
FOC_OPENLOOP_TRANSITION = 2, /* Open-loop to closed-loop transition */
|
||||
FOC_OPENLOOP_DISABLED = 3, /* Open-loop disabled */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
Loading…
x
Reference in New Issue
Block a user