This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new de6a38466 examples/foc: add velocity PI controller
de6a38466 is described below

commit de6a3846686bfd0fd52e6e1146996100ade7922e
Author: raiden00pl <raide...@railab.me>
AuthorDate: Tue May 16 14:10:18 2023 +0200

    examples/foc: add velocity PI controller
---
 examples/foc/Kconfig           | 37 +++++++++++++++++++++++
 examples/foc/foc_cfg.h         |  9 ++++++
 examples/foc/foc_fixed16_thr.c | 10 +++----
 examples/foc/foc_float_thr.c   | 10 +++----
 examples/foc/foc_main.c        |  4 +++
 examples/foc/foc_motor_b16.c   | 66 +++++++++++++++++++++++++++++++++++++-----
 examples/foc/foc_motor_b16.h   |  4 +++
 examples/foc/foc_motor_f32.c   | 66 +++++++++++++++++++++++++++++++++++++-----
 examples/foc/foc_motor_f32.h   |  4 +++
 examples/foc/foc_parseargs.c   | 27 +++++++++++++++++
 10 files changed, 211 insertions(+), 26 deletions(-)

diff --git a/examples/foc/Kconfig b/examples/foc/Kconfig
index 0e4de7207..c3d03f9f8 100644
--- a/examples/foc/Kconfig
+++ b/examples/foc/Kconfig
@@ -196,10 +196,47 @@ config EXAMPLES_FOC_VELOBS
 
 if EXAMPLES_FOC_HAVE_VEL
 
+config EXAMPLES_FOC_VELCTRL_FREQ
+       int "FOC example velocity controller frequency"
+       default 1000
+
 config EXAMPLES_FOC_VELNOW_FILTER
        int "FOC example velocity controller (x1000)"
        default 990
 
+choice
+       prompt "FOC velocity controller selection"
+       default EXAMPLES_FOC_VELCTRL_PI
+
+config EXAMPLES_FOC_VELCTRL_PI
+       bool "FOC velocity PI controller"
+
+endchoice # FOC velocity controller
+
+if EXAMPLES_FOC_VELCTRL_PI
+
+config EXAMPLES_FOC_VELCTRL_PI_KP
+       int "FOC velocity PI Kp (1000000x)"
+       default 0
+       ---help---
+               The Kp coefficient used in controller is:
+               Kp = EXAMPLES_FOC_VELCTRL_PI_KP/1000000
+
+config EXAMPLES_FOC_VELCTRL_PI_KI
+       int "FOC velocity PI Ki (1000000x)"
+       default 0
+       ---help---
+               The Ki coefficient used in controller is:
+               Ki = EXAMPLES_FOC_VELCTRL_PI_KI/1000000
+
+config EXAMPLES_FOC_VELCTRL_PI_SAT
+       int "FOC velocity PI saturation (1000x)"
+       default 0
+       ---help---
+               The unit is micro-ampere (1/1000000 ampere)
+
+endif # EXAMPLES_FOC_VELCTRL_PI
+
 endif # EXAMPLES_FOC_HAVE_VEL
 
 if EXAMPLES_FOC_VELOBS
diff --git a/examples/foc/foc_cfg.h b/examples/foc/foc_cfg.h
index 7a59c7c9d..9475cdbf7 100644
--- a/examples/foc/foc_cfg.h
+++ b/examples/foc/foc_cfg.h
@@ -199,6 +199,11 @@
 #  endif
 #endif
 
+/* Velocity controller prescaler */
+
+#define VEL_CONTROL_PRESCALER (CONFIG_EXAMPLES_FOC_NOTIFIER_FREQ /  \
+                               CONFIG_EXAMPLES_FOC_VELCTRL_FREQ)
+
 /****************************************************************************
  * Public Type Definition
  ****************************************************************************/
@@ -246,6 +251,10 @@ struct foc_thr_cfg_s
   uint32_t vel_div_samples;     /* Vel DIV observer samples */
   uint32_t vel_div_filter;      /* Vel DIV observer filter (x1000) */
 #endif
+#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
+  uint32_t vel_pi_kp;           /* Vel controller PI Kp (x1000000) */
+  uint32_t vel_pi_ki;           /* Vel controller PI Ki (x1000000) */
+#endif
 };
 
 #endif /* __APPS_EXAMPLES_FOC_FOC_CFG_H */
diff --git a/examples/foc/foc_fixed16_thr.c b/examples/foc/foc_fixed16_thr.c
index d3d7bbc5c..1b0c89700 100644
--- a/examples/foc/foc_fixed16_thr.c
+++ b/examples/foc/foc_fixed16_thr.c
@@ -295,10 +295,8 @@ int foc_fixed16_thr(FAR struct foc_ctrl_env_s *envp)
   struct foc_mq_s         handle;
   struct foc_motor_b16_s  motor;
   struct foc_device_s     dev;
-  int                     time = 0;
   int                     ret  = OK;
 
-  UNUSED(time);
   DEBUGASSERT(envp);
 
   PRINTFV("foc_fixed_thr, id=%d\n", envp->id);
@@ -341,7 +339,7 @@ int foc_fixed16_thr(FAR struct foc_ctrl_env_s *envp)
 
   while (motor.mq.quit == false)
     {
-      PRINTFV("foc_fixed16_thr %d %d\n", envp->id, time);
+      PRINTFV("foc_fixed16_thr %d %d\n", envp->id, motor.time);
 
       /* Handle mqueue */
 
@@ -441,7 +439,7 @@ int foc_fixed16_thr(FAR struct foc_ctrl_env_s *envp)
 #ifdef FOC_STATE_PRINT_PRE
           /* Print state if configured */
 
-          if (time % FOC_STATE_PRINT_PRE == 0)
+          if (motor.time % FOC_STATE_PRINT_PRE == 0)
             {
               foc_state_print(&motor);
             }
@@ -467,7 +465,7 @@ int foc_fixed16_thr(FAR struct foc_ctrl_env_s *envp)
 #ifdef CONFIG_EXAMPLES_FOC_NXSCOPE
           /* Capture nxscope samples */
 
-          if (time % CONFIG_EXAMPLES_FOC_NXSCOPE_PRESCALER == 0)
+          if (motor.time % CONFIG_EXAMPLES_FOC_NXSCOPE_PRESCALER == 0)
             {
               foc_fixed16_nxscope(envp->nxs, &motor, &dev);
             }
@@ -488,7 +486,7 @@ int foc_fixed16_thr(FAR struct foc_ctrl_env_s *envp)
 
       /* Increase counter */
 
-      time += 1;
+      motor.time += 1;
     }
 
 errout:
diff --git a/examples/foc/foc_float_thr.c b/examples/foc/foc_float_thr.c
index 94d8596be..0e2d89d62 100644
--- a/examples/foc/foc_float_thr.c
+++ b/examples/foc/foc_float_thr.c
@@ -300,10 +300,8 @@ int foc_float_thr(FAR struct foc_ctrl_env_s *envp)
   struct foc_mq_s         handle;
   struct foc_motor_f32_s  motor;
   struct foc_device_s     dev;
-  int                     time = 0;
   int                     ret  = OK;
 
-  UNUSED(time);
   DEBUGASSERT(envp);
 
   PRINTFV("foc_float_thr, id=%d\n", envp->id);
@@ -346,7 +344,7 @@ int foc_float_thr(FAR struct foc_ctrl_env_s *envp)
 
   while (motor.mq.quit == false)
     {
-      PRINTFV("foc_float_thr %d %d\n", envp->id, time);
+      PRINTFV("foc_float_thr %d %d\n", envp->id, motor.time);
 
       /* Handle mqueue */
 
@@ -446,7 +444,7 @@ int foc_float_thr(FAR struct foc_ctrl_env_s *envp)
 #ifdef FOC_STATE_PRINT_PRE
           /* Print state if configured */
 
-          if (time % FOC_STATE_PRINT_PRE == 0)
+          if (motor.time % FOC_STATE_PRINT_PRE == 0)
             {
               foc_state_print(&motor);
             }
@@ -455,7 +453,7 @@ int foc_float_thr(FAR struct foc_ctrl_env_s *envp)
 #ifdef CONFIG_EXAMPLES_FOC_NXSCOPE
           /* Capture nxscope samples */
 
-          if (time % CONFIG_EXAMPLES_FOC_NXSCOPE_PRESCALER == 0)
+          if (motor.time % CONFIG_EXAMPLES_FOC_NXSCOPE_PRESCALER == 0)
             {
               foc_float_nxscope(envp->nxs, &motor, &dev);
             }
@@ -493,7 +491,7 @@ int foc_float_thr(FAR struct foc_ctrl_env_s *envp)
 
       /* Increase counter */
 
-      time += 1;
+      motor.time += 1;
     }
 
 errout:
diff --git a/examples/foc/foc_main.c b/examples/foc/foc_main.c
index 9258a46f6..79107073f 100644
--- a/examples/foc/foc_main.c
+++ b/examples/foc/foc_main.c
@@ -119,6 +119,10 @@ struct args_s g_args =
 #ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
     .vel_div_samples = CONFIG_EXAMPLES_FOC_VELOBS_DIV_SAMPLES,
     .vel_div_filter = CONFIG_EXAMPLES_FOC_VELOBS_DIV_FILTER,
+#endif
+#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
   }
 };
diff --git a/examples/foc/foc_motor_b16.c b/examples/foc/foc_motor_b16.c
index f039c2f5e..68ab8741b 100644
--- a/examples/foc/foc_motor_b16.c
+++ b/examples/foc/foc_motor_b16.c
@@ -777,6 +777,9 @@ static int foc_motor_run_init(FAR struct foc_motor_b16_s 
*motor)
 
 static int foc_motor_run(FAR struct foc_motor_b16_s *motor)
 {
+#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
+  b16_t vel_err = 0.0f;
+#endif
   b16_t q_ref = 0;
   b16_t d_ref = 0;
   int   ret   = OK;
@@ -804,6 +807,14 @@ static int foc_motor_run(FAR struct foc_motor_b16_s *motor)
   q_ref = motor->dq_ref.q;
   d_ref = motor->dq_ref.d;
 
+  /* Ignore controller if motor is free or stopped */
+
+  if (motor->mq.app_state == FOC_EXAMPLE_STATE_FREE ||
+      motor->mq.app_state == FOC_EXAMPLE_STATE_STOP)
+    {
+      goto no_controller;
+    }
+
   /* Controller */
 
   switch (motor->envp->cfg->mmode)
@@ -823,14 +834,39 @@ static int foc_motor_run(FAR struct foc_motor_b16_s 
*motor)
 #ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
       case FOC_MMODE_VEL:
         {
-          /* Run velocity ramp controller */
-
-          ret = foc_ramp_run_b16(&motor->ramp, motor->vel.des,
-                                 motor->vel.now, &motor->vel.set);
-          if (ret < 0)
+          if (motor->time % VEL_CONTROL_PRESCALER == 0)
             {
-              PRINTF("ERROR: foc_ramp_run failed %d\n", ret);
-              goto errout;
+              /* Run velocity ramp controller */
+
+              ret = foc_ramp_run_b16(&motor->ramp,
+                                     motor->dir * motor->vel.des,
+                                     motor->vel.now,
+                                     &motor->vel.set);
+              if (ret < 0)
+                {
+                  PRINTF("ERROR: foc_ramp_run failed %d\n", ret);
+                  goto errout;
+                }
+
+              /* Run velocity controller if no in open-loop */
+
+#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
+              if (motor->openloop_now == false)
+#endif
+                {
+                  /* Get velocity error */
+
+                  vel_err = motor->vel.set - motor->vel.now;
+
+#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
+                  /* PI velocit controller */
+
+                  q_ref = pi_controller_b16(&motor->vel_pi, vel_err);
+                  d_ref = 0;
+#else
+#  error Missing velocity controller
+#endif
+                }
             }
 
           break;
@@ -858,6 +894,8 @@ static int foc_motor_run(FAR struct foc_motor_b16_s *motor)
     }
 #endif
 
+no_controller:
+
   /* Set DQ reference frame */
 
   motor->dq_ref.q = q_ref;
@@ -1067,6 +1105,20 @@ int foc_motor_init(FAR struct foc_motor_b16_s *motor,
     }
 #endif
 
+#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
+  /* Initialize velocity controller */
+
+  pi_controller_init_b16(&motor->vel_pi,
+                   ftob16(motor->envp->cfg->vel_pi_kp / 1000000.0f),
+                   ftob16(motor->envp->cfg->vel_pi_ki / 1000000.0f));
+
+  pi_saturation_set_b16(&motor->vel_pi,
+                   ftob16(-CONFIG_EXAMPLES_FOC_VELCTRL_PI_SAT / 1000.0f),
+                   ftob16(CONFIG_EXAMPLES_FOC_VELCTRL_PI_SAT / 1000.0f));
+
+  pi_antiwindup_enable_b16(&motor->vel_pi, ftob16(0.99f), true);
+#endif
+
 #ifdef CONFIG_EXAMPLES_FOC_HAVE_ALIGN
   /* Initialize motor alignment routine */
 
diff --git a/examples/foc/foc_motor_b16.h b/examples/foc/foc_motor_b16.h
index 843302da8..a10bf2d93 100644
--- a/examples/foc/foc_motor_b16.h
+++ b/examples/foc/foc_motor_b16.h
@@ -87,6 +87,7 @@ struct foc_motor_b16_s
   dq_frame_b16_t                dq_ref;       /* DQ reference */
   dq_frame_b16_t                vdq_comp;     /* DQ voltage compensation */
   int                           foc_mode;     /* FOC mode */
+  int                           time;         /* Helper counter */
   b16_t                         vbus;         /* Power bus voltage */
   b16_t                         per;          /* Controller period in seconds 
*/
   b16_t                         iphase_adc;   /* Iphase ADC scaling factor */
@@ -95,6 +96,9 @@ struct foc_motor_b16_s
   /* Velocity controller data ***********************************************/
 
   struct foc_ramp_b16_s         ramp;         /* Velocity ramp data */
+#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
+  pid_controller_b16_t          vel_pi;       /* Velocity controller */
+#endif
 
   /* Motor state ************************************************************/
 
diff --git a/examples/foc/foc_motor_f32.c b/examples/foc/foc_motor_f32.c
index 35ef15da5..f55f8f79b 100644
--- a/examples/foc/foc_motor_f32.c
+++ b/examples/foc/foc_motor_f32.c
@@ -761,6 +761,9 @@ static int foc_motor_run_init(FAR struct foc_motor_f32_s 
*motor)
 
 static int foc_motor_run(FAR struct foc_motor_f32_s *motor)
 {
+#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
+  float vel_err = 0.0f;
+#endif
   float q_ref = 0.0f;
   float d_ref = 0.0f;
   int   ret   = OK;
@@ -788,6 +791,14 @@ static int foc_motor_run(FAR struct foc_motor_f32_s *motor)
   q_ref = motor->dq_ref.q;
   d_ref = motor->dq_ref.d;
 
+  /* Ignore controller if motor is free or stopped */
+
+  if (motor->mq.app_state == FOC_EXAMPLE_STATE_FREE ||
+      motor->mq.app_state == FOC_EXAMPLE_STATE_STOP)
+    {
+      goto no_controller;
+    }
+
   /* Controller */
 
   switch (motor->envp->cfg->mmode)
@@ -807,14 +818,39 @@ static int foc_motor_run(FAR struct foc_motor_f32_s 
*motor)
 #ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
       case FOC_MMODE_VEL:
         {
-          /* Run velocity ramp controller */
-
-          ret = foc_ramp_run_f32(&motor->ramp, motor->vel.des,
-                                 motor->vel.now, &motor->vel.set);
-          if (ret < 0)
+          if (motor->time % VEL_CONTROL_PRESCALER == 0)
             {
-              PRINTF("ERROR: foc_ramp_run failed %d\n", ret);
-              goto errout;
+              /* Run velocity ramp controller */
+
+              ret = foc_ramp_run_f32(&motor->ramp,
+                                     motor->dir * motor->vel.des,
+                                     motor->vel.now,
+                                     &motor->vel.set);
+              if (ret < 0)
+                {
+                  PRINTF("ERROR: foc_ramp_run failed %d\n", ret);
+                  goto errout;
+                }
+
+              /* Run velocity controller if no in open-loop */
+
+#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
+              if (motor->openloop_now == false)
+#endif
+                {
+                  /* Get velocity error */
+
+                  vel_err = motor->vel.set - motor->vel.now;
+
+#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
+                  /* PI velocit controller */
+
+                  q_ref = pi_controller(&motor->vel_pi, vel_err);
+                  d_ref = 0;
+#else
+#  error Missing velocity controller
+#endif
+                }
             }
 
           break;
@@ -842,6 +878,8 @@ static int foc_motor_run(FAR struct foc_motor_f32_s *motor)
     }
 #endif
 
+no_controller:
+
   /* Set DQ reference frame */
 
   motor->dq_ref.q = q_ref;
@@ -1051,6 +1089,20 @@ int foc_motor_init(FAR struct foc_motor_f32_s *motor,
     }
 #endif
 
+#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
+  /* Initialize velocity controller */
+
+  pi_controller_init(&motor->vel_pi,
+                     (motor->envp->cfg->vel_pi_kp / 1000000.0f),
+                     (motor->envp->cfg->vel_pi_ki / 1000000.0f));
+
+  pi_saturation_set(&motor->vel_pi,
+                    -(CONFIG_EXAMPLES_FOC_VELCTRL_PI_SAT / 1000.0f),
+                    (CONFIG_EXAMPLES_FOC_VELCTRL_PI_SAT / 1000.0f));
+
+  pi_antiwindup_enable(&motor->vel_pi, 0.99f, true);
+#endif
+
 #ifdef CONFIG_EXAMPLES_FOC_HAVE_ALIGN
   /* Initialize motor alignment routine */
 
diff --git a/examples/foc/foc_motor_f32.h b/examples/foc/foc_motor_f32.h
index 84d8a3c7b..ddcec9fc9 100644
--- a/examples/foc/foc_motor_f32.h
+++ b/examples/foc/foc_motor_f32.h
@@ -87,6 +87,7 @@ struct foc_motor_f32_s
   dq_frame_f32_t                dq_ref;       /* DQ reference */
   dq_frame_f32_t                vdq_comp;     /* DQ voltage compensation */
   int                           foc_mode;     /* FOC mode */
+  int                           time;         /* Helper counter */
   float                         vbus;         /* Power bus voltage */
   float                         per;          /* Controller period in seconds 
*/
   float                         iphase_adc;   /* Iphase ADC scaling factor */
@@ -95,6 +96,9 @@ struct foc_motor_f32_s
   /* Velocity controller data ***********************************************/
 
   struct foc_ramp_f32_s         ramp;         /* Velocity ramp data */
+#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
+  pid_controller_f32_t          vel_pi;       /* Velocity controller */
+#endif
 
   /* Motor state ************************************************************/
 
diff --git a/examples/foc/foc_parseargs.c b/examples/foc/foc_parseargs.c
index 609500eac..b43812164 100644
--- a/examples/foc/foc_parseargs.c
+++ b/examples/foc/foc_parseargs.c
@@ -50,6 +50,9 @@
 #define OPT_VODIVS  (SCHAR_MAX + 9)
 #define OPT_VODIVF  (SCHAR_MAX + 10)
 
+#define OPT_VCPIKP  (SCHAR_MAX + 11)
+#define OPT_VCPIKI  (SCHAR_MAX + 12)
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -92,6 +95,10 @@ static struct option g_long_options[] =
 #ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
     { "vodivs", required_argument, 0, OPT_VODIVS },
     { "vodivf", required_argument, 0, OPT_VODIVF },
+#endif
+#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
+    { "vcpikp", required_argument, 0, OPT_VCPIKP },
+    { "vcpiki", required_argument, 0, OPT_VCPIKI },
 #endif
     { 0, 0, 0, 0 }
   };
@@ -178,6 +185,12 @@ static void foc_help(void)
   PRINTF("  [--vodivf] velobs DIV filter (default: %d)\n",
          CONFIG_EXAMPLES_FOC_VELOBS_DIV_FILTER);
 #endif
+#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
+  PRINTF("  [--vpikp] velctrl PI Kp (default: %d)\n",
+         CONFIG_EXAMPLES_FOC_VELCTRL_PI_KP);
+  PRINTF("  [--vpiki] velctrl PI Ki (default: %d)\n",
+         CONFIG_EXAMPLES_FOC_VELCTRL_PI_KI);
+#endif
 }
 
 /****************************************************************************
@@ -279,6 +292,20 @@ void parse_args(FAR struct args_s *args, int argc, FAR 
char **argv)
             }
 #endif
 
+#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
+          case OPT_VCPIKP:
+            {
+              args->cfg.vel_pi_kp = atoi(optarg);
+              break;
+            }
+
+          case OPT_VCPIKI:
+            {
+              args->cfg.vel_pi_ki = atoi(optarg);
+              break;
+            }
+#endif
+
           case 't':
             {
               args->time = atoi(optarg);

Reply via email to