Files
BC5D-POS-firmware/app/by_motion.c

263 lines
7.0 KiB
C
Raw Normal View History

2024-06-10 18:04:45 +08:00
#include "by_motion.h"
#include "pid.h"
#include "by_utils.h"
#include "by_debug.h"
#define DRV_ENABLE() gpio_bits_set(GPIOA, GPIO_PINS_12)
#define DRV_DISABLE() gpio_bits_reset(GPIOA, GPIO_PINS_12)
#define MU (2.854f) // speed = \mu * speed_in_pulse
by_motor_param param_m1;
by_motor_param param_m2;
PID_TypeDef pid_m1;
PID_TypeDef pid_m2;
uint8_t motion_enable_flag;
uint8_t motion_busy_flag;
uint8_t motion_reset_flag;
int16_t time_via;
float position_abs;
void by_motion_set_pwm_m1(int32_t pwm_duty)
{
pwm_duty = clip_s32(pwm_duty, -900, 900); // 不可以拉满哦
if (pwm_duty < 0) {
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_4, -pwm_duty);
2024-06-10 18:04:45 +08:00
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_3, 0);
} else {
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_4, 0);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_3, pwm_duty);
2024-06-10 18:04:45 +08:00
}
}
// void by_motion_set_pwm_m2(int32_t pwm_duty)
// {
// pwm_duty = clip_s32(pwm_duty, -900, 900); // 不可以拉满哦
// if (pwm_duty < 0) {
// tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_3, -pwm_duty);
// tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_4, 0);
// } else {
// tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_3, 0);
// tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_4, pwm_duty);
// }
// }
int16_t by_motion_get_speed_m1(void)
{
#define alpha (0.1f)
static float last_speed = 0.0f;
param_m1.real_speed = alpha * last_speed + (1.0f - alpha) * (float)(-1 * (int16_t)tmr_counter_value_get(TMR3));
2024-06-10 18:04:45 +08:00
last_speed = param_m1.real_speed;
tmr_counter_value_set(TMR3, 0);
return (int16_t)param_m1.real_speed;
#undef alpha
}
// int16_t by_motion_get_speed_m2(void)
// {
// #define alpha (0.1f)
// static float last_speed = 0.0f;
// param_m2.real_speed = alpha * last_speed + (1.0f - alpha) * (float)(-1 * (int16_t)tmr_counter_value_get(TMR3));
// last_speed = param_m2.real_speed;
// tmr_counter_value_set(TMR3, 0);
// return (int16_t)param_m2.real_speed;
// #undef alpha
// }
void by_motion_set_speed_m1(int16_t speed)
{
param_m1.target_speed = speed;
}
// void by_motion_set_speed_m2(int16_t speed)
// {
// param_m2.target_speed = speed;
// }
void by_motion_set_distance(float distance, int16_t speed)
{
// TODO 验证距离是否超限
if (motion_busy_flag) {
return;
}
if (speed < 0) {
speed = -speed;
}
position_abs += distance;
if (distance < 0.0f) {
by_motion_set_speed_m1(-1 * speed);
distance = -distance;
} else {
by_motion_set_speed_m1(speed);
}
motion_busy_flag = 1;
time_via = (int16_t)(distance * 50.0f / ((float)speed * MU)); // 控制频率为 50Hz控制值单位为 s
// lwprintf("time_via = %d\r\n", time_via);
LOGD("position_abs = %f\r\n", position_abs);
}
void by_motion_set_distance2(float distance, int16_t speed)
{
// TODO 验证距离是否超限
if (motion_busy_flag) {
return;
}
if (speed < 0) {
speed = -speed;
}
if (distance < 0.0f) {
distance = -distance;
}
distance = distance - position_abs;
position_abs += distance;
if (5.0 >= position_abs) {
position_abs = 0;
by_motion_set_speed_m1(-20);
2024-06-10 18:04:45 +08:00
motion_busy_flag = 1;
motion_reset_flag = 1;
LOGD("RESET position_abs = %f\r\n", position_abs);
return;
}
if (distance < 0.0f) {
distance = -distance;
by_motion_set_speed_m1(-1 * speed);
} else {
by_motion_set_speed_m1(speed);
}
motion_busy_flag = 1;
time_via = (int16_t)(distance * 50.0f / ((float)speed * MU)); // 控制频率为 50Hz控制值单位为 s
LOGD("position_abs = %f\r\n", position_abs);
// lwprintf("time_via = %d\r\n", time_via);
}
void by_motion_init(void)
{
motion_enable_flag = 0;
motion_busy_flag = 0;
time_via = 0;
position_abs = 0.0f; // TODO 待添加复位操作
by_motion_set_pwm_m1(0);
// by_motion_set_pwm_m2(0);
/* set default parameters */
param_m1.Kp = BY_MOTION_DEFAULT_KP_M1;
param_m1.Ki = BY_MOTION_DEFAULT_KI_M1;
param_m1.Kd = BY_MOTION_DEFAULT_KD_M1;
// param_m2.Kp = BY_MOTION_DEFAULT_KP_M2;
// param_m2.Ki = BY_MOTION_DEFAULT_KI_M2;
// param_m2.Kd = BY_MOTION_DEFAULT_KD_M2;
/* load parameters form ee */
// TODO
PID(&pid_m1, &param_m1.real_speed, &param_m1.out_pwm, &param_m1.target_speed, param_m1.Kp, param_m1.Ki, param_m1.Kd, _PID_P_ON_E, _PID_CD_DIRECT);
PID_SetMode(&pid_m1, _PID_MODE_AUTOMATIC);
PID_SetSampleTime(&pid_m1, 20);
PID_SetOutputLimits(&pid_m1, -900, 900);
// PID(&pid_m2, &param_m2.real_speed, &param_m2.out_pwm, &param_m2.target_speed, param_m2.Kp, param_m2.Ki, param_m2.Kd, _PID_P_ON_E, _PID_CD_DIRECT);
// PID_SetMode(&pid_m2, _PID_MODE_AUTOMATIC);
// PID_SetSampleTime(&pid_m2, 10);
// PID_SetOutputLimits(&pid_m2, -400, 400);
motion_enable_flag = 1;
DRV_ENABLE();
// 上电回零
2024-07-17 18:21:23 +08:00
by_motion_set_speed_m1(-30);
2024-06-10 18:04:45 +08:00
while (SET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_4)) {
// lwprintf("%f, %f, %f\r\n", param_m1.real_speed, param_m1.target_speed, param_m1.out_pwm);
2024-06-10 18:04:45 +08:00
// 等待复位
}
by_motion_set_speed_m1(0);
by_motion_set_distance2(130, 30);
2024-07-17 18:21:23 +08:00
delay_ms(2600);
by_motion_set_distance2(0, 30);
2024-06-10 18:04:45 +08:00
}
void by_motion_run(void)
{
if (motion_enable_flag) {
by_motion_get_speed_m1();
// by_motion_get_speed_m2();
PID_Compute(&pid_m1);
// PID_Compute(&pid_m2);
by_motion_set_pwm_m1((int32_t)param_m1.out_pwm);
// by_motion_set_pwm_m2((int32_t)param_m2.out_pwm);
}
}
void by_motion_can_handle(uint16_t stdd_id, const uint8_t *data, uint8_t len)
{
if (0x08 == stdd_id) {
uint8_t mode = data[0];
int16_t speed = (int16_t)data[1];
// float distance = (float)(data[2] | (data[3] << 8) | (data[4] << 16) | (data[5] << 24));
float distance;
memcpy(&distance, &data[2], 4);
if (0 == mode) {
by_motion_set_distance2(distance, speed);
} else if (1 == mode) {
by_motion_set_distance(distance, speed);
}
}
// #define BC2D_MODEL1
// if (0x01 == stdd_id) {
// #if defined(BC2D_MODEL1)
// int16_t speed_m1_temp = (int16_t)(data[0] | (data[1] << 8));
// int16_t speed_m2_temp = (int16_t)(data[2] | (data[3] << 8));
// by_motion_set_speed_m1(speed_m1_temp);
// by_motion_set_speed_m2(speed_m2_temp);
// #elif defined(BC2D_MODEL2)
// int16_t speed_m1_temp = (int16_t)(data[4] | (data[5] << 8));
// int16_t speed_m2_temp = (int16_t)(data[6] | (data[7] << 8));
// by_motion_set_speed_m1(speed_m1_temp);
// by_motion_set_speed_m2(speed_m2_temp);
// #endif
// }
// LOGD("m1:%f,%f,%f", param_m1.real_speed, param_m1.target_speed, param_m1.out_pwm);
// LOGD("m2:%f,%f,%f", param_m2.real_speed, param_m2.target_speed, param_m2.out_pwm);
2024-06-10 18:04:45 +08:00
}
void by_motion_tmr_handle(void)
{
if (!motion_busy_flag) {
return;
}
if (motion_reset_flag) {
if (!gpio_input_data_bit_read(GPIOB, GPIO_PINS_4)) {
motion_reset_flag = 0;
motion_busy_flag = 0;
by_motion_set_speed_m1(0);
}
return;
}
if (time_via > 0) {
time_via--;
} else {
by_motion_set_speed_m1(0);
motion_busy_flag = 0;
}
}