mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
pid_ctrl: abstract into example common component
This commit is contained in:
parent
b6c5a6ee8b
commit
f0fab687ad
4
examples/common_components/pid_ctrl/CMakeLists.txt
Normal file
4
examples/common_components/pid_ctrl/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
set(srcs "src/pid_ctrl.c")
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "include")
|
2
examples/common_components/pid_ctrl/component.mk
Normal file
2
examples/common_components/pid_ctrl/component.mk
Normal file
@ -0,0 +1,2 @@
|
||||
COMPONENT_ADD_INCLUDEDIRS := include
|
||||
COMPONENT_SRCDIRS := src
|
100
examples/common_components/pid_ctrl/include/pid_ctrl.h
Normal file
100
examples/common_components/pid_ctrl/include/pid_ctrl.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PID calculation type
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
PID_CAL_TYPE_INCREMENTAL, /*!< Incremental PID control */
|
||||
PID_CAL_TYPE_POSITIONAL, /*!< Positional PID control */
|
||||
} pid_calculate_type_t;
|
||||
|
||||
/**
|
||||
* @brief Type of PID control block handle
|
||||
*
|
||||
*/
|
||||
typedef struct pid_ctrl_block_t *pid_ctrl_block_handle_t;
|
||||
|
||||
/**
|
||||
* @brief PID control parameters
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
float kp; // PID Kp parameter
|
||||
float ki; // PID Ki parameter
|
||||
float kd; // PID Kd parameter
|
||||
float max_output; // PID maximum output limitation
|
||||
float min_output; // PID minimum output limitation
|
||||
float max_integral; // PID maximum integral value limitation
|
||||
float min_integral; // PID minimum integral value limitation
|
||||
pid_calculate_type_t cal_type; // PID calculation type
|
||||
} pid_ctrl_parameter_t;
|
||||
|
||||
/**
|
||||
* @brief PID control configuration
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
pid_ctrl_parameter_t init_param; // Initial parameters
|
||||
} pid_ctrl_config_t;
|
||||
|
||||
/**
|
||||
* @brief Create a new PID control session, returns the handle of control block
|
||||
*
|
||||
* @param[in] config PID control configuration
|
||||
* @param[out] ret_pid Returned PID control block handle
|
||||
* @return
|
||||
* - ESP_OK: Created PID control block successfully
|
||||
* - ESP_ERR_INVALID_ARG: Created PID control block failed because of invalid argument
|
||||
* - ESP_ERR_NO_MEM: Created PID control block failed because out of memory
|
||||
*/
|
||||
esp_err_t pid_new_control_block(const pid_ctrl_config_t *config, pid_ctrl_block_handle_t *ret_pid);
|
||||
|
||||
/**
|
||||
* @brief Delete the PID control block
|
||||
*
|
||||
* @param[in] pid PID control block handle, created by `pid_new_control_block()`
|
||||
* @return
|
||||
* - ESP_OK: Delete PID control block successfully
|
||||
* - ESP_ERR_INVALID_ARG: Delete PID control block failed because of invalid argument
|
||||
*/
|
||||
esp_err_t pid_del_control_block(pid_ctrl_block_handle_t pid);
|
||||
|
||||
/**
|
||||
* @brief Update PID parameters
|
||||
*
|
||||
* @param[in] pid PID control block handle, created by `pid_new_control_block()`
|
||||
* @param[in] params PID parameters
|
||||
* @return
|
||||
* - ESP_OK: Update PID parameters successfully
|
||||
* - ESP_ERR_INVALID_ARG: Update PID parameters failed because of invalid argument
|
||||
*/
|
||||
esp_err_t pid_update_parameters(pid_ctrl_block_handle_t pid, const pid_ctrl_parameter_t *params);
|
||||
|
||||
/**
|
||||
* @brief Input error and get PID control result
|
||||
*
|
||||
* @param[in] pid PID control block handle, created by `pid_new_control_block()`
|
||||
* @param[in] input_error error data that feed to the PID controller
|
||||
* @param[out] ret_result result after PID calculation
|
||||
* @return
|
||||
* - ESP_OK: Run a PID compute successfully
|
||||
* - ESP_ERR_INVALID_ARG: Run a PID compute failed because of invalid argument
|
||||
*/
|
||||
esp_err_t pid_compute(pid_ctrl_block_handle_t pid, float input_error, float *ret_result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
140
examples/common_components/pid_ctrl/src/pid_ctrl.c
Normal file
140
examples/common_components/pid_ctrl/src/pid_ctrl.c
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
#include "pid_ctrl.h"
|
||||
|
||||
static const char *TAG = "pid_ctrl";
|
||||
|
||||
typedef struct pid_ctrl_block_t pid_ctrl_block_t;
|
||||
typedef float (*pid_cal_func_t)(pid_ctrl_block_t *pid, float error);
|
||||
|
||||
struct pid_ctrl_block_t {
|
||||
float Kp; // PID Kp value
|
||||
float Ki; // PID Ki value
|
||||
float Kd; // PID Kd value
|
||||
float previous_err1; // e(k-1)
|
||||
float previous_err2; // e(k-2)
|
||||
float integral_err; // Sum of error
|
||||
float last_output; // PID output in last control period
|
||||
float max_output; // PID maximum output limitation
|
||||
float min_output; // PID minimum output limitation
|
||||
float max_integral; // PID maximum integral value limitation
|
||||
float min_integral; // PID minimum integral value limitation
|
||||
pid_cal_func_t calculate_func; // calculation function, depends on actual PID type set by user
|
||||
};
|
||||
|
||||
static float pid_calc_positional(pid_ctrl_block_t *pid, float error)
|
||||
{
|
||||
float output = 0;
|
||||
/* Add current error to the integral error */
|
||||
pid->integral_err += error;
|
||||
/* If the integral error is out of the range, it will be limited */
|
||||
pid->integral_err = MIN(pid->integral_err, pid->max_integral);
|
||||
pid->integral_err = MAX(pid->integral_err, pid->min_integral);
|
||||
|
||||
/* Calculate the pid control value by location formula */
|
||||
/* u(k) = e(k)*Kp + (e(k)-e(k-1))*Kd + integral*Ki */
|
||||
output = error * pid->Kp +
|
||||
(error - pid->previous_err1) * pid->Kd +
|
||||
pid->integral_err * pid->Ki;
|
||||
|
||||
/* If the output is out of the range, it will be limited */
|
||||
output = MIN(output, pid->max_output);
|
||||
output = MAX(output, pid->min_output);
|
||||
|
||||
/* Update previous error */
|
||||
pid->previous_err1 = error;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static float pid_calc_incremental(pid_ctrl_block_t *pid, float error)
|
||||
{
|
||||
float output = 0;
|
||||
|
||||
/* Calculate the pid control value by increment formula */
|
||||
/* du(k) = (e(k)-e(k-1))*Kp + (e(k)-2*e(k-1)+e(k-2))*Kd + e(k)*Ki */
|
||||
/* u(k) = du(k) + u(k-1) */
|
||||
output = (error - pid->previous_err1) * pid->Kp +
|
||||
(error - 2 * pid->previous_err1 + pid->previous_err2) * pid->Kd +
|
||||
error * pid->Ki +
|
||||
pid->last_output;
|
||||
|
||||
/* If the output is beyond the range, it will be limited */
|
||||
output = MIN(output, pid->max_output);
|
||||
output = MAX(output, pid->min_output);
|
||||
|
||||
/* Update previous error */
|
||||
pid->previous_err2 = pid->previous_err1;
|
||||
pid->previous_err1 = error;
|
||||
|
||||
/* Update last output */
|
||||
pid->last_output = output;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
esp_err_t pid_new_control_block(const pid_ctrl_config_t *config, pid_ctrl_block_handle_t *ret_pid)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
pid_ctrl_block_t *pid = NULL;
|
||||
/* Check the input pointer */
|
||||
ESP_GOTO_ON_FALSE(config && ret_pid, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
|
||||
pid = calloc(1, sizeof(pid_ctrl_block_t));
|
||||
ESP_GOTO_ON_FALSE(pid, ESP_ERR_NO_MEM, err, TAG, "no mem for PID control block");
|
||||
ESP_GOTO_ON_ERROR(pid_update_parameters(pid, &config->init_param), err, TAG, "init PID parameters failed");
|
||||
*ret_pid = pid;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if (pid) {
|
||||
free(pid);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t pid_del_control_block(pid_ctrl_block_handle_t pid)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(pid, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
free(pid);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pid_compute(pid_ctrl_block_handle_t pid, float input_error, float *ret_result)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(pid && ret_result, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
*ret_result = pid->calculate_func(pid, input_error);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pid_update_parameters(pid_ctrl_block_handle_t pid, const pid_ctrl_parameter_t *params)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(pid && params, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
pid->Kp = params->kp;
|
||||
pid->Ki = params->ki;
|
||||
pid->Kd = params->kd;
|
||||
pid->max_output = params->max_output;
|
||||
pid->min_output = params->min_output;
|
||||
pid->max_integral = params->max_integral;
|
||||
pid->min_integral = params->min_integral;
|
||||
/* Set the calculate function according to the PID type */
|
||||
switch (params->cal_type) {
|
||||
case PID_CAL_TYPE_INCREMENTAL:
|
||||
pid->calculate_func = pid_calc_incremental;
|
||||
break;
|
||||
case PID_CAL_TYPE_POSITIONAL:
|
||||
pid->calculate_func = pid_calc_positional;
|
||||
break;
|
||||
default:
|
||||
ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_ARG, TAG, "invalid PID calculation type:%d", params->cal_type);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
set(COMPONENT_SRCS "pid_ctrl.c")
|
||||
|
||||
idf_component_register(SRCS "${COMPONENT_SRCS}"
|
||||
INCLUDE_DIRS .
|
||||
PRIV_REQUIRES "driver")
|
@ -1 +0,0 @@
|
||||
COMPONENT_ADD_INCLUDEDIRS := .
|
@ -1,123 +0,0 @@
|
||||
/* General Purpose PID example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "esp_check.h"
|
||||
#include "pid_ctrl.h"
|
||||
|
||||
static const char *TAG = "pid_ctrl";
|
||||
|
||||
static float pid_calc_location(pid_ctrl_t *pid, float error)
|
||||
{
|
||||
float output = 0;
|
||||
/* Add current error to the integral error */
|
||||
pid->integral_err += error;
|
||||
/* If the integral error is out of the range, it will be limited */
|
||||
pid->integral_err = pid->integral_err > pid->max_integral_limit ? pid->max_integral_limit : pid->integral_err;
|
||||
pid->integral_err = pid->integral_err < pid->min_integral_limit ? pid->min_integral_limit : pid->integral_err;
|
||||
|
||||
/* Calculate the pid control value by location formula */
|
||||
/* u(k) = e(k)*Kp + (e(k)-e(k-1))*Kd + integral*Ki */
|
||||
output = error * pid->Kp +
|
||||
(error - pid->previous_err1) * pid->Kd +
|
||||
pid->integral_err * pid->Ki;
|
||||
|
||||
/* If the output is out of the range, it will be limited */
|
||||
output = output > pid->max_output_limit ? pid->max_output_limit : output;
|
||||
output = output < pid->min_output_limit ? pid->min_output_limit : output;
|
||||
|
||||
/* Update previous error */
|
||||
pid->previous_err1 = error;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static float pid_calc_increment(pid_ctrl_t *pid, float error)
|
||||
{
|
||||
float output = 0;
|
||||
|
||||
/* Calculate the pid control value by increment formula */
|
||||
/* du(k) = (e(k)-e(k-1))*Kp + (e(k)-2*e(k-1)+e(k-2))*Kd + e(k)*Ki */
|
||||
/* u(k) = du(k) + u(k-1) */
|
||||
output = (error-pid->previous_err1)*pid->Kp +
|
||||
(error-2*pid->previous_err1+pid->previous_err2)*pid->Kd +
|
||||
error*pid->Ki +
|
||||
pid->last_output;
|
||||
|
||||
/* If the output is beyond the range, it will be limited */
|
||||
output = output > pid->max_output_limit ? pid->max_output_limit : output;
|
||||
output = output < pid->min_output_limit ? pid->min_output_limit : output;
|
||||
|
||||
/* Update previous error */
|
||||
pid->previous_err2 = pid->previous_err1;
|
||||
pid->previous_err1 = error;
|
||||
|
||||
/* Update last output */
|
||||
pid->last_output = output;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
esp_err_t pid_integral_clear(pid_ctrl_t *pid)
|
||||
{
|
||||
esp_err_t ret;
|
||||
/* Check the input pointer */
|
||||
ESP_GOTO_ON_FALSE(pid, ESP_ERR_INVALID_ARG, err, TAG, "Input a NULL pointer\n");
|
||||
|
||||
/* Clear the integral error in pid structure */
|
||||
pid->integral_err = 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t pid_init(float Kp, float Ki, float Kd, pid_calculate_type_e type, pid_ctrl_t **pid)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
/* Check the input pointer */
|
||||
ESP_GOTO_ON_FALSE(pid, ESP_ERR_INVALID_ARG, err, TAG, "Input a NULL pointer\n");
|
||||
|
||||
*pid = calloc(1, sizeof(pid_ctrl_t));
|
||||
ESP_GOTO_ON_FALSE((*pid), ESP_ERR_NO_MEM, err, TAG, "There is no memory for PID structure\n");
|
||||
|
||||
/* Set the PID parameters */
|
||||
(*pid)->Kp = Kp;
|
||||
(*pid)->Ki = Ki;
|
||||
(*pid)->Kd = Kd;
|
||||
|
||||
/* Select the PID work mode */
|
||||
(*pid)->type = type;
|
||||
|
||||
/* Initialize the pid history variables */
|
||||
(*pid)->previous_err1 = 0;
|
||||
(*pid)->previous_err2 = 0;
|
||||
(*pid)->integral_err = 0;
|
||||
(*pid)->last_output = 0;
|
||||
|
||||
/* Set pid default limitation */
|
||||
(*pid)->max_output_limit = 100;
|
||||
(*pid)->min_output_limit = -100;
|
||||
(*pid)->max_integral_limit = 1000;
|
||||
(*pid)->max_integral_limit = -1000;
|
||||
|
||||
/* Set the calculate function according to the PID type */
|
||||
(*pid)->calculate_func =
|
||||
(*pid)->type == PID_INCREMENT ? pid_calc_increment : pid_calc_location;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pid_deinit(pid_ctrl_t **pid)
|
||||
{
|
||||
if((*pid) != NULL)
|
||||
{
|
||||
free(*pid);
|
||||
*pid = NULL;
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
/* General Purpose PID example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#define LOCATION_PID_DEFAULT_CONFIG(p, i, d, max_o, min_o, max_i, min_i) \
|
||||
{ \
|
||||
.Kp = p, \
|
||||
.Ki = i, \
|
||||
.Kd = d, \
|
||||
.max_output_limit = max_o, \
|
||||
.min_output_limit = min_o, \
|
||||
.max_integral_limit = max_i, \
|
||||
.min_integral_limit = min_i, \
|
||||
.type = PID_LOCATION \
|
||||
}
|
||||
|
||||
#define INCREMENT_PID_DEFAULT_CONFIG(p, i, d, max_o, min_o, max_i, min_i, init_out) \
|
||||
{ \
|
||||
.Kp = p, \
|
||||
.Ki = i, \
|
||||
.Kd = d, \
|
||||
.max_output_limit = max_o, \
|
||||
.min_output_limit = min_o, \
|
||||
.max_integral_limit = max_i, \
|
||||
.min_integral_limit = min_i, \
|
||||
.last_output = init_out, \
|
||||
.type = PID_INCREMENT \
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
PID_INCREMENT = 0,
|
||||
PID_LOCATION
|
||||
} pid_calculate_type_e;
|
||||
|
||||
typedef struct pid_ctrl pid_ctrl_t;
|
||||
|
||||
struct pid_ctrl{
|
||||
/* pid parameters (Set by user) */
|
||||
float Kp; // PID Kp value
|
||||
float Ki; // PID Ki value
|
||||
float Kd; // PID Kd value
|
||||
|
||||
/* history variables */
|
||||
float previous_err1; // e(k-1)
|
||||
float previous_err2; // e(k-2)
|
||||
float integral_err; // Sum of error
|
||||
float last_output; // PID output in last control period
|
||||
|
||||
/* limitation */
|
||||
float max_output_limit; // PID maximum output limitation
|
||||
float min_output_limit; // PID minimum output limitation
|
||||
float max_integral_limit; // PID maximum integral value limitation
|
||||
float min_integral_limit; // PID minimum integral value limitation
|
||||
|
||||
/* PID calculation function type (Set by user) */
|
||||
pid_calculate_type_e type; // PID calculation type
|
||||
|
||||
/* PID calculation function */
|
||||
float (*calculate_func)(pid_ctrl_t *pid, float error); // PID calculation function pointer
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief PID initialization
|
||||
*
|
||||
* @param Kp PID kp value
|
||||
* @param Ki PID ki value
|
||||
* @param Kd PID kd value
|
||||
* @param type PID calculation type
|
||||
* @param pid Secondary poiter of pid control struct
|
||||
* @return
|
||||
* - ESP_OK: PID initialized successfully
|
||||
* - ESP_ERR_INVALID_ARG: The secondary pointer is NULL
|
||||
* - ESP_ERR_NO_MEM: There is no memory for PID structure
|
||||
*/
|
||||
esp_err_t pid_init(float Kp, float Ki, float Kd, pid_calculate_type_e type, pid_ctrl_t **pid);
|
||||
|
||||
/**
|
||||
* @brief PID deinitialization
|
||||
*
|
||||
* @param pid Secondary poiter of pid control struct
|
||||
*/
|
||||
void pid_deinit(pid_ctrl_t **pid);
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param pid The pointer of pid control struct
|
||||
* @return
|
||||
* - ESP_OK: PID integral value cleared successfully
|
||||
* - ESP_ERR_INVALID_ARG: The pointer is NULL
|
||||
*/
|
||||
esp_err_t pid_integral_clear(pid_ctrl_t *pid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -63,8 +63,8 @@ static void print_current_status(void)
|
||||
printf(" Configuration\n Period = %d ms\tPID = %s\n\n",
|
||||
mc->cfg.ctrl_period, mc->cfg.pid_enable ? "enabled" : "disabled");
|
||||
printf(" PID - %s\n Kp = %.3f\tKi = %.3f\tKd = %.3f\n\n",
|
||||
(mc->pid->type == PID_LOCATION) ? "Location" : "Increment",
|
||||
mc->pid->Kp, mc->pid->Ki, mc->pid->Kd);
|
||||
(mc->pid_param.cal_type == PID_CAL_TYPE_POSITIONAL) ? "Location" : "Increment",
|
||||
mc->pid_param.kp, mc->pid_param.ki, mc->pid_param.kd);
|
||||
printf(" Expectation - %s\n init = %.3f\tmax = %.3f\tmin = %.3f\tpace = %.3f\n\n",
|
||||
mc->cfg.expt_mode ? (mc->cfg.expt_mode == MOTOR_CTRL_MODE_TRIANGLE ? "Triangle" : "Rectangle") : "Fixed",
|
||||
mc->cfg.expt_init, mc->cfg.expt_max, mc->cfg.expt_min, mc->cfg.expt_pace);
|
||||
@ -143,35 +143,37 @@ static int do_motor_ctrl_expt_cmd(int argc, char **argv)
|
||||
|
||||
static int do_motor_ctrl_pid_cmd(int argc, char **argv)
|
||||
{
|
||||
int ret = 0;
|
||||
MOTOR_CTRL_CMD_CHECK(motor_ctrl_pid_args);
|
||||
xSemaphoreTake(g_motor_mux, portMAX_DELAY);
|
||||
if (motor_ctrl_pid_args.kp->count) {
|
||||
mc->pid->Kp = motor_ctrl_pid_args.kp->dval[0];
|
||||
printf("pid: kp = %.3f\n", mc->pid->Kp);
|
||||
mc->pid_param.kp = motor_ctrl_pid_args.kp->dval[0];
|
||||
printf("pid: kp = %.3f\n", mc->pid_param.kp);
|
||||
}
|
||||
if (motor_ctrl_pid_args.ki->count) {
|
||||
mc->pid->Ki = motor_ctrl_pid_args.ki->dval[0];
|
||||
printf("pid: ki = %.3f\n", mc->pid->Ki);
|
||||
mc->pid_param.ki = motor_ctrl_pid_args.ki->dval[0];
|
||||
printf("pid: ki = %.3f\n", mc->pid_param.ki);
|
||||
}
|
||||
if (motor_ctrl_pid_args.kd->count) {
|
||||
mc->pid->Kd = motor_ctrl_pid_args.kd->dval[0];
|
||||
printf("pid: kd = %.3f\n", mc->pid->Kd);
|
||||
mc->pid_param.kd = motor_ctrl_pid_args.kd->dval[0];
|
||||
printf("pid: kd = %.3f\n", mc->pid_param.kd);
|
||||
}
|
||||
|
||||
if (motor_ctrl_pid_args.type->count) {
|
||||
if (!strcmp(*motor_ctrl_pid_args.type->sval, "loc")) {
|
||||
mc->pid->type = PID_LOCATION;
|
||||
printf("pid: type = location\n");
|
||||
} else if (!strcmp(*motor_ctrl_pid_args.type->sval, "inc")) {
|
||||
mc->pid->type = PID_INCREMENT;
|
||||
printf("pid: type = increment\n");
|
||||
if (!strcmp(motor_ctrl_pid_args.type->sval[0], "loc")) {
|
||||
mc->pid_param.cal_type = PID_CAL_TYPE_POSITIONAL;
|
||||
printf("pid: type = positional\n");
|
||||
} else if (!strcmp(motor_ctrl_pid_args.type->sval[0], "inc")) {
|
||||
mc->pid_param.cal_type = PID_CAL_TYPE_INCREMENTAL;
|
||||
printf("pid: type = incremental\n");
|
||||
} else {
|
||||
mc->pid->type = PID_INCREMENT;
|
||||
printf("pid: type = increment\n");
|
||||
printf("Invalid pid type:%s\n", motor_ctrl_pid_args.type->sval[0]);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
pid_update_parameters(mc->pid, &mc->pid_param);
|
||||
xSemaphoreGive(g_motor_mux);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_motor_ctrl_motor_cmd(int argc, char **argv)
|
||||
@ -183,7 +185,7 @@ static int do_motor_ctrl_motor_cmd(int argc, char **argv)
|
||||
// Start the motor
|
||||
brushed_motor_start(mc);
|
||||
mc->cfg.running_sec ?
|
||||
printf("motor: motor starts to run in %d seconds\n", mc->cfg.running_sec):
|
||||
printf("motor: motor starts to run in %d seconds\n", mc->cfg.running_sec) :
|
||||
printf("motor: motor starts to run, input 'motor -d' to stop it\n");
|
||||
}
|
||||
|
||||
|
@ -118,10 +118,14 @@ static int pcnt_get_pulse_callback(void *args)
|
||||
static void motor_ctrl_default_init(void)
|
||||
{
|
||||
motor_ctrl.cfg.pid_enable = true;
|
||||
motor_ctrl.cfg.pid_init_kp = 0.8;
|
||||
motor_ctrl.cfg.pid_init_ki = 0.0;
|
||||
motor_ctrl.cfg.pid_init_kd = 0.1;
|
||||
motor_ctrl.cfg.pid_init_type = PID_INCREMENT;
|
||||
motor_ctrl.pid_param.kp = 0.8;
|
||||
motor_ctrl.pid_param.ki = 0.0;
|
||||
motor_ctrl.pid_param.kd = 0.1;
|
||||
motor_ctrl.pid_param.cal_type = PID_CAL_TYPE_INCREMENTAL;
|
||||
motor_ctrl.pid_param.max_output = 100;
|
||||
motor_ctrl.pid_param.min_output = -100;
|
||||
motor_ctrl.pid_param.max_integral = 1000;
|
||||
motor_ctrl.pid_param.min_integral = -1000;
|
||||
motor_ctrl.cfg.expt_init = 30;
|
||||
motor_ctrl.cfg.expt_mode = MOTOR_CTRL_MODE_TRIANGLE;
|
||||
motor_ctrl.cfg.expt_max = 50;
|
||||
@ -195,11 +199,10 @@ static void motor_ctrl_init_all(void)
|
||||
/* 3.MCPWM initialization */
|
||||
motor_ctrl_mcpwm_init();
|
||||
/* 4.pid_ctrl initialization */
|
||||
pid_init(motor_ctrl.cfg.pid_init_kp,
|
||||
motor_ctrl.cfg.pid_init_ki,
|
||||
motor_ctrl.cfg.pid_init_kd,
|
||||
motor_ctrl.cfg.pid_init_type,
|
||||
&motor_ctrl.pid);
|
||||
pid_ctrl_config_t pid_config = {
|
||||
.init_param = motor_ctrl.pid_param,
|
||||
};
|
||||
pid_new_control_block(&pid_config, &motor_ctrl.pid);
|
||||
/* 5.Timer initialization */
|
||||
motor_ctrl_timer_init();
|
||||
}
|
||||
@ -220,7 +223,7 @@ static void mcpwm_brushed_motor_ctrl_thread(void *arg)
|
||||
if (motor_ctrl.cfg.pid_enable) {
|
||||
/* Calculate the output by PID algorithm according to the pulse. Pid_output here is the duty of MCPWM */
|
||||
motor_ctrl.error = motor_ctrl.expt - motor_ctrl.pulse_in_one_period;
|
||||
motor_ctrl.pid_output = motor_ctrl.pid->calculate_func(motor_ctrl.pid, motor_ctrl.error);
|
||||
pid_compute(motor_ctrl.pid, motor_ctrl.error, &motor_ctrl.pid_output);
|
||||
} else {
|
||||
motor_ctrl.pid_output = motor_ctrl.expt;
|
||||
}
|
||||
|
@ -32,7 +32,8 @@ typedef struct {
|
||||
/* Handles */
|
||||
rotary_encoder_t *encoder; // PCNT rotary encoder handler
|
||||
motor_ctrl_timer_info_t *timer_info; // Timer infomation handler
|
||||
pid_ctrl_t *pid; // PID algoritm handler
|
||||
pid_ctrl_block_handle_t pid; // PID algoritm handler
|
||||
pid_ctrl_parameter_t pid_param; // PID parameters
|
||||
QueueHandle_t timer_evt_que; // Timer event queue handler
|
||||
|
||||
/* Control visualization */
|
||||
@ -49,10 +50,6 @@ typedef struct {
|
||||
struct {
|
||||
/* PID configuration */
|
||||
bool pid_enable; // PID enable flag
|
||||
float pid_init_kp; // PID initial kp value
|
||||
float pid_init_ki; // PID initial ki value
|
||||
float pid_init_kd; // PID initial kd value
|
||||
pid_calculate_type_e pid_init_type; // PID initial calcalation type (PID_INCREMENT/PID_LOCATION)
|
||||
|
||||
/* Expectation configuration */
|
||||
float expt_init; // Initial expectation
|
||||
|
Loading…
x
Reference in New Issue
Block a user