574 lines
16 KiB
C
574 lines
16 KiB
C
/****************************************************************************
|
|
* apps/examples/foc/foc_parseargs.c
|
|
*
|
|
* 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.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <getopt.h>
|
|
#include <inttypes.h>
|
|
|
|
#include "foc_debug.h"
|
|
#include "foc_thr.h"
|
|
#include "foc_parseargs.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define OPT_FKI (SCHAR_MAX + 1)
|
|
#define OPT_FKP (SCHAR_MAX + 2)
|
|
|
|
#define OPT_IRKI (SCHAR_MAX + 3)
|
|
#define OPT_IRC (SCHAR_MAX + 4)
|
|
#define OPT_IRS (SCHAR_MAX + 5)
|
|
#define OPT_IIV (SCHAR_MAX + 6)
|
|
#define OPT_IIS (SCHAR_MAX + 7)
|
|
|
|
#define OPT_VOPLLKP (SCHAR_MAX + 8)
|
|
#define OPT_VOPLLKI (SCHAR_MAX + 9)
|
|
#define OPT_VODIVS (SCHAR_MAX + 10)
|
|
#define OPT_VODIVF (SCHAR_MAX + 11)
|
|
|
|
#define OPT_VCPIKP (SCHAR_MAX + 12)
|
|
#define OPT_VCPIKI (SCHAR_MAX + 13)
|
|
|
|
#define OPT_ANFOS (SCHAR_MAX + 14)
|
|
#define OPT_ANFOG (SCHAR_MAX + 15)
|
|
|
|
#define OPT_OLFORCE (SCHAR_MAX + 16)
|
|
#define OPT_OLTHR (SCHAR_MAX + 17)
|
|
#define OPT_OLHYS (SCHAR_MAX + 18)
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
static struct option g_long_options[] =
|
|
{
|
|
{ "time", required_argument, 0, 't' },
|
|
{ "help", no_argument, 0, 'h' },
|
|
{ "fmode", required_argument, 0, 'f' },
|
|
{ "mmode", required_argument, 0, 'm' },
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_TORQ
|
|
{ "torq", required_argument, 0, 'r' },
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
|
{ "vel", required_argument, 0, 'v' },
|
|
{ "acc", required_argument, 0, 'a' },
|
|
{ "dec", required_argument, 0, 'd' },
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_POS
|
|
{ "pos", required_argument, 0, 'x' },
|
|
#endif
|
|
{ "state", required_argument, 0, 's' },
|
|
{ "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 },
|
|
{ "fki", required_argument, 0, OPT_FKI },
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_IDENT
|
|
{ "irki", required_argument, 0, OPT_IRKI },
|
|
{ "irc", required_argument, 0, OPT_IRC },
|
|
{ "irs", required_argument, 0, OPT_IRS },
|
|
{ "iiv", required_argument, 0, OPT_IIV },
|
|
{ "iis", required_argument, 0, OPT_IIS },
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_PLL
|
|
{ "vopllkp", required_argument, 0, OPT_VOPLLKP },
|
|
{ "vopllki", required_argument, 0, OPT_VOPLLKI },
|
|
#endif
|
|
#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
|
|
#ifdef CONFIG_INDUSTRY_FOC_ANGLE_ONFO
|
|
{ "anfos", required_argument, 0, OPT_ANFOS },
|
|
{ "anfog", required_argument, 0, OPT_ANFOG },
|
|
#endif
|
|
{ 0, 0, 0, 0 }
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: foc_help
|
|
****************************************************************************/
|
|
|
|
static void foc_help(FAR struct args_s *args)
|
|
{
|
|
PRINTF("Usage: foc [OPTIONS]\n");
|
|
PRINTF(" [-t] run time (default: %d)\n",
|
|
CONFIG_EXAMPLES_FOC_TIME_DEFAULT);
|
|
PRINTF(" [-h] shows this message and exits\n");
|
|
PRINTF(" [-f] FOC run mode (default: %d)\n",
|
|
CONFIG_EXAMPLES_FOC_FMODE);
|
|
PRINTF(" 1 - IDLE mode\n");
|
|
PRINTF(" 2 - voltage mode\n");
|
|
PRINTF(" 3 - current mode\n");
|
|
PRINTF(" [-m] controller mode (default: %d)\n",
|
|
CONFIG_EXAMPLES_FOC_MMODE);
|
|
PRINTF(" 1 - torqe control\n");
|
|
PRINTF(" 2 - velocity control\n");
|
|
PRINTF(" 3 - position control\n");
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_ALIGN
|
|
PRINTF(" 4 - align only\n");
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_IDENT
|
|
PRINTF(" 5 - ident only\n");
|
|
#endif
|
|
PRINTF(" 6 - IDLE state\n");
|
|
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_TORQ
|
|
PRINTF(" [-r] torque [x1000]\n");
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
|
PRINTF(" [-v] velocity [x1000]\n");
|
|
PRINTF(" [-a] acceleration [x1000] (default: %" PRId32 ")\n",
|
|
args->cfg.acc);
|
|
PRINTF(" [-d] deceleration [x1000] (default: %" PRId32 ")\n",
|
|
args->cfg.dec);
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_POS
|
|
PRINTF(" [-x] position [x1000]\n");
|
|
#endif
|
|
PRINTF(" [-s] motor state init (default: %d)\n",
|
|
args->state);
|
|
PRINTF(" 1 - motor free\n");
|
|
PRINTF(" 2 - motor stop\n");
|
|
PRINTF(" 3 - motor CW\n");
|
|
PRINTF(" 4 - motor CCW\n");
|
|
PRINTF(" [-j] enable specific instances\n");
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
|
PRINTF(" [-o] openloop Vq/Iq setting [x1000] (default: %" PRId32 ")\n",
|
|
args->cfg.qparam);
|
|
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(" [--fkp] PI Kp coefficient [x1000] (default: %" PRId32 ")\n",
|
|
args->cfg.foc_pi_kp);
|
|
PRINTF(" [--fki] PI Ki coefficient [x1000] (default: %" PRId32 ")\n",
|
|
args->cfg.foc_pi_ki);
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_IDENT
|
|
PRINTF(" [--irki] res Ki coefficient [x1000] (default: %" PRId32 ")\n",
|
|
args->cfg.ident_res_ki);
|
|
PRINTF(" [--irc] res current [x1000] (default: %" PRId32 ")\n",
|
|
args->cfg.ident_res_curr);
|
|
PRINTF(" [--irs] res sec (default: %" PRId32 ")\n",
|
|
args->cfg.ident_res_sec);
|
|
PRINTF(" [--iiv] ind voltage [x1000] (default: %" PRId32 ")\n",
|
|
args->cfg.ident_ind_volt);
|
|
PRINTF(" [--iis] ind sec (default: %" PRId32 ")\n",
|
|
args->cfg.ident_ind_sec);
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_PLL
|
|
PRINTF(" [--vopllkp] velobs PLL Kp [x1] (default: %" PRId32 ")\n",
|
|
args->cfg.vel_pll_kp);
|
|
PRINTF(" [--vopllki] velobs PLL Ki [x1] (default: %" PRId32 ")\n",
|
|
args->cfg.vel_pll_ki);
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
|
PRINTF(" [--vodivs] velobs DIV samples (default: %" PRId32 ")\n",
|
|
args->cfg.vel_div_samples);
|
|
PRINTF(" [--vodivf] velobs DIV filter (default: %" PRId32 ")\n",
|
|
args->cfg.vel_div_filter);
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_VELCTRL_PI
|
|
PRINTF(" [--vcpikp] velctrl PI Kp [x1000000] (default: %" PRId32 ")\n",
|
|
args->cfg.vel_pi_kp);
|
|
PRINTF(" [--vcpiki] velctrl PI Ki [x1000000] (default: %" PRId32 ")\n",
|
|
args->cfg.vel_pi_ki);
|
|
#endif
|
|
#ifdef CONFIG_INDUSTRY_FOC_ANGLE_ONFO
|
|
PRINTF(" [--anfos] angobs NFO Slow [x1] (default: %" PRId32 ")\n",
|
|
args->cfg.ang_nfo_slow);
|
|
PRINTF(" [--anfog] angobs NFO Gain [x1] (default: %" PRId32 ")\n",
|
|
args->cfg.ang_nfo_gain);
|
|
#endif
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: parse_args
|
|
****************************************************************************/
|
|
|
|
void parse_args(FAR struct args_s *args, int argc, FAR char **argv)
|
|
{
|
|
int option_index = 0;
|
|
int c = 0;
|
|
|
|
while (1)
|
|
{
|
|
c = getopt_long(argc, argv, "ht:f:m:o:r:v:a:d:x:s:j:", g_long_options,
|
|
&option_index);
|
|
|
|
if (c == -1)
|
|
{
|
|
break;
|
|
}
|
|
|
|
switch (c)
|
|
{
|
|
#ifdef CONFIG_EXAMPLES_FOC_CONTROL_PI
|
|
case OPT_FKP:
|
|
{
|
|
args->cfg.foc_pi_kp = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case OPT_FKI:
|
|
{
|
|
args->cfg.foc_pi_ki = atoi(optarg);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_IDENT
|
|
case OPT_IRKI:
|
|
{
|
|
args->cfg.ident_res_ki = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case OPT_IRC:
|
|
{
|
|
args->cfg.ident_res_curr = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case OPT_IRS:
|
|
{
|
|
args->cfg.ident_res_sec = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case OPT_IIV:
|
|
{
|
|
args->cfg.ident_ind_volt = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case OPT_IIS:
|
|
{
|
|
args->cfg.ident_ind_sec = atoi(optarg);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_PLL
|
|
case OPT_VOPLLKP:
|
|
{
|
|
args->cfg.vel_pll_kp = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case OPT_VOPLLKI:
|
|
{
|
|
args->cfg.vel_pll_ki = atoi(optarg);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_EXAMPLES_FOC_VELOBS_DIV
|
|
case OPT_VODIVS:
|
|
{
|
|
args->cfg.vel_div_samples = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case OPT_VODIVF:
|
|
{
|
|
args->cfg.vel_div_filter = atoi(optarg);
|
|
break;
|
|
}
|
|
#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
|
|
|
|
#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);
|
|
break;
|
|
}
|
|
|
|
case 'h':
|
|
{
|
|
foc_help(args);
|
|
exit(0);
|
|
}
|
|
|
|
case 'f':
|
|
{
|
|
args->cfg.fmode = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case 'm':
|
|
{
|
|
args->cfg.mmode = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_TORQ
|
|
case 'r':
|
|
{
|
|
args->cfg.torqmax = atoi(optarg);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
|
case 'v':
|
|
{
|
|
args->cfg.velmax = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case 'a':
|
|
{
|
|
args->cfg.acc = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case 'd':
|
|
{
|
|
args->cfg.dec = atoi(optarg);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_POS
|
|
case 'x':
|
|
{
|
|
args->cfg.posmax = atoi(optarg);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
case 's':
|
|
{
|
|
args->state = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case 'j':
|
|
{
|
|
args->en = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_OPENLOOP
|
|
case 'o':
|
|
{
|
|
args->cfg.qparam = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case OPT_OLFORCE:
|
|
{
|
|
args->cfg.ol_force = true;
|
|
break;
|
|
}
|
|
|
|
# ifdef CONFIG_EXAMPLES_FOC_ANGOBS
|
|
case OPT_OLTHR:
|
|
{
|
|
args->cfg.ol_thr = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case OPT_OLHYS:
|
|
{
|
|
args->cfg.ol_hys = atoi(optarg);
|
|
break;
|
|
}
|
|
# endif
|
|
#endif
|
|
|
|
case '?':
|
|
default:
|
|
{
|
|
if (argv[optind - 1] == NULL)
|
|
{
|
|
PRINTF("ERROR: invalid option argument for %s\n",
|
|
argv[optind - 2]);
|
|
}
|
|
else
|
|
{
|
|
PRINTF("ERROR: invalid option %s\n", argv[optind - 1]);
|
|
}
|
|
|
|
foc_help(args);
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: validate_args
|
|
****************************************************************************/
|
|
|
|
int validate_args(FAR struct args_s *args)
|
|
{
|
|
int ret = -EINVAL;
|
|
|
|
#ifdef CONFIG_EXAMPLES_FOC_CONTROL_PI
|
|
/* Current PI controller */
|
|
|
|
if (args->cfg.foc_pi_kp == 0 && args->cfg.foc_pi_ki == 0)
|
|
{
|
|
PRINTF("ERROR: missing FOC Kp/Ki configuration\n");
|
|
goto errout;
|
|
}
|
|
#endif
|
|
|
|
/* FOC operation mode */
|
|
|
|
if (args->cfg.fmode != FOC_FMODE_IDLE &&
|
|
args->cfg.fmode != FOC_FMODE_VOLTAGE &&
|
|
args->cfg.fmode != FOC_FMODE_CURRENT)
|
|
{
|
|
PRINTF("Invalid op mode value %d s\n", args->cfg.fmode);
|
|
goto errout;
|
|
}
|
|
|
|
/* Example control mode */
|
|
|
|
if (args->cfg.mmode != FOC_MMODE_IDLE &&
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_TORQ
|
|
args->cfg.mmode != FOC_MMODE_TORQ &&
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_VEL
|
|
args->cfg.mmode != FOC_MMODE_VEL &&
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_POS
|
|
args->cfg.mmode != FOC_MMODE_POS &&
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_ALIGN
|
|
args->cfg.mmode != FOC_MMODE_ALIGN_ONLY &&
|
|
#endif
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_IDENT
|
|
args->cfg.mmode != FOC_MMODE_IDENT_ONLY &&
|
|
#endif
|
|
1)
|
|
{
|
|
PRINTF("Invalid ctrl mode value %d s\n", args->cfg.mmode);
|
|
goto errout;
|
|
}
|
|
|
|
/* Example state */
|
|
|
|
if (args->state != FOC_EXAMPLE_STATE_FREE &&
|
|
args->state != FOC_EXAMPLE_STATE_STOP &&
|
|
args->state != FOC_EXAMPLE_STATE_CW &&
|
|
args->state != FOC_EXAMPLE_STATE_CCW)
|
|
{
|
|
PRINTF("Invalid state value %d s\n", args->state);
|
|
goto errout;
|
|
}
|
|
|
|
/* Time parameter */
|
|
|
|
if (args->time <= 0 && args->time != -1)
|
|
{
|
|
PRINTF("Invalid time value %d s\n", args->time);
|
|
goto errout;
|
|
}
|
|
|
|
#ifdef CONFIG_EXAMPLES_FOC_HAVE_IDENT
|
|
/* Motor identification parameters */
|
|
|
|
if (args->cfg.ident_res_ki == 0 || args->cfg.ident_res_curr == 0 ||
|
|
args->cfg.ident_res_sec == 0)
|
|
{
|
|
PRINTF("ERROR: missing motor res ident configuration\n");
|
|
goto errout;
|
|
}
|
|
|
|
if (args->cfg.ident_ind_volt == 0 || args->cfg.ident_ind_sec == 0)
|
|
{
|
|
PRINTF("ERROR: missing motor ind ident configuration\n");
|
|
goto errout;
|
|
}
|
|
#endif
|
|
|
|
/* Otherwise OK */
|
|
|
|
ret = OK;
|
|
|
|
errout:
|
|
return ret;
|
|
}
|