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

263 lines
7.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
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);
}
}
// 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));
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);
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();
// 上电回零
by_motion_set_speed_m1(-30);
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);
// 等待复位
}
by_motion_set_speed_m1(0);
by_motion_set_distance2(130, 30);
delay_ms(2600);
by_motion_set_distance2(0, 30);
}
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);
}
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;
}
}