2023-04-19 23:54:02 +08:00
|
|
|
|
#include "moto.h"
|
|
|
|
|
#include "Arduino.h"
|
2023-05-07 02:56:19 +08:00
|
|
|
|
#include "config.h"
|
|
|
|
|
|
2023-04-19 23:54:02 +08:00
|
|
|
|
uint8_t CaninBuffer[8]; // 接收指令缓冲区
|
|
|
|
|
moto_measure_t moto_chassis;
|
|
|
|
|
PID_TypeDef moto_pid;
|
|
|
|
|
|
|
|
|
|
moto::moto()
|
|
|
|
|
{
|
2023-05-09 22:41:01 +08:00
|
|
|
|
_closed = true;
|
2023-04-19 23:54:02 +08:00
|
|
|
|
}
|
|
|
|
|
bool moto::init()
|
|
|
|
|
{
|
|
|
|
|
Serial.println("init moto");
|
2023-04-22 16:59:32 +08:00
|
|
|
|
pid_init();
|
2023-05-07 02:56:19 +08:00
|
|
|
|
CAN.setPins(MOTO_CAN_RX, MOTO_CAN_TX);
|
2023-04-19 23:54:02 +08:00
|
|
|
|
// start the CAN bus at 500 kbps
|
|
|
|
|
if (!CAN.begin(1000E3))
|
|
|
|
|
{
|
|
|
|
|
Serial.println("Starting CAN failed!");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
CAN.onReceive(onReceive);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
moto::~moto()
|
|
|
|
|
{
|
|
|
|
|
}
|
2023-04-22 16:59:32 +08:00
|
|
|
|
|
2023-04-19 23:54:02 +08:00
|
|
|
|
void moto::update()
|
|
|
|
|
{
|
2023-05-09 22:41:01 +08:00
|
|
|
|
if (!_closed)
|
2023-04-22 16:59:32 +08:00
|
|
|
|
{
|
2023-05-09 22:41:01 +08:00
|
|
|
|
unsigned long dt = millis() - moto_chassis.starttime; // 时间差
|
|
|
|
|
float x = 0.0f;
|
|
|
|
|
float mspeed = 0.0f;
|
|
|
|
|
float _msoftspeed = moto_pid.target;
|
|
|
|
|
if (dt < _acctime)
|
2023-05-07 02:56:19 +08:00
|
|
|
|
{
|
2023-05-09 22:41:01 +08:00
|
|
|
|
x = float(dt) / _acctime; // 归一化时间
|
|
|
|
|
// 公式参考 https://mp.weixin.qq.com/s/bhdvA3Ex6lAWVmBril-Sag
|
|
|
|
|
mspeed = (-2 * x * x * x + 3 * x * x); // S曲线速度公式--计算归一化速度
|
|
|
|
|
_msoftspeed = _start_speed + mspeed * _ds;
|
2023-05-07 02:56:19 +08:00
|
|
|
|
}
|
|
|
|
|
pid_cal(&moto_pid, moto_chassis.speed_rpm, _msoftspeed);
|
2023-04-22 16:59:32 +08:00
|
|
|
|
set_moto_current(moto_pid.output);
|
2023-05-09 22:41:01 +08:00
|
|
|
|
// printf("tar:%.2f,dt:%d,ds:%.2f,x:%.2f,mspeed:%.2f,motspeed:%.2f,out:%.2f\n",
|
|
|
|
|
// moto_pid.target,dt,_ds,x,mspeed,_msoftspeed,moto_pid.output);
|
2023-04-22 16:59:32 +08:00
|
|
|
|
}
|
2023-04-19 23:54:02 +08:00
|
|
|
|
}
|
2023-05-09 15:25:31 +08:00
|
|
|
|
void moto::settime_acc(float acctime)
|
|
|
|
|
{
|
2023-05-09 22:41:01 +08:00
|
|
|
|
if (acctime == -1)
|
|
|
|
|
_acctime = abs((_ds * SACCEL_TIME) / ((float)OUTPUT_MAX * MOTO_REDUCTION)); // 加减速时间
|
|
|
|
|
else
|
|
|
|
|
_acctime = acctime;
|
2023-05-12 00:13:59 +08:00
|
|
|
|
|
|
|
|
|
printf("settime_acc:%.2f\n", _acctime);
|
2023-05-09 15:25:31 +08:00
|
|
|
|
}
|
2023-04-19 23:54:02 +08:00
|
|
|
|
|
2023-05-09 22:41:01 +08:00
|
|
|
|
void moto::setspeedtarget(float new_target)
|
2023-04-19 23:54:02 +08:00
|
|
|
|
{
|
2023-04-22 16:59:32 +08:00
|
|
|
|
moto_pid.target = new_target * MOTO_REDUCTION;
|
2023-05-09 22:41:01 +08:00
|
|
|
|
moto_chassis.starttime = millis(); // 换算为绝对时间
|
|
|
|
|
_start_speed = moto_chassis.speed_rpm;
|
|
|
|
|
_ds = moto_pid.target - _start_speed; // 速度差
|
|
|
|
|
_closed = false;
|
2023-05-10 01:54:38 +08:00
|
|
|
|
printf("speedtarget:tm:%d,target:%.2f\n", moto_chassis.starttime, new_target);
|
2023-04-19 23:54:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void moto::set_moto_current(int16_t iq1)
|
|
|
|
|
{
|
2023-04-22 16:59:32 +08:00
|
|
|
|
iq1 = MOTO_REVERSED * iq1;
|
2023-04-19 23:54:02 +08:00
|
|
|
|
CAN.beginPacket(0x200, 8);
|
|
|
|
|
CAN.write((uint8_t)((iq1 >> 8) & 0xFF));
|
|
|
|
|
CAN.write((uint8_t)(iq1 & 0xFF));
|
|
|
|
|
CAN.write(0x00);
|
|
|
|
|
CAN.write(0x00);
|
|
|
|
|
CAN.write(0x00);
|
|
|
|
|
CAN.write(0x00);
|
|
|
|
|
CAN.write(0x00);
|
|
|
|
|
CAN.write(0x00);
|
|
|
|
|
CAN.endPacket();
|
|
|
|
|
}
|
|
|
|
|
void moto::get_moto_measure(moto_measure_t *ptr, uint8_t *message_ptr)
|
|
|
|
|
{
|
|
|
|
|
// 处理数据
|
|
|
|
|
ptr->last_angle = ptr->angle;
|
2023-04-22 16:59:32 +08:00
|
|
|
|
ptr->angle = (uint16_t)MOTO_REVERSED * (message_ptr[0] << 8 | message_ptr[1]); // 角度
|
|
|
|
|
ptr->speed_rpm = (int16_t)MOTO_REVERSED * (message_ptr[2] << 8 | message_ptr[3]); // 速度
|
|
|
|
|
ptr->real_current = (int16_t)MOTO_REVERSED * (message_ptr[4] << 8 | message_ptr[5]); // 实际转矩电流
|
|
|
|
|
ptr->temperature = message_ptr[6]; // 电机温度,2006没有,为0
|
2023-04-19 23:54:02 +08:00
|
|
|
|
|
|
|
|
|
if (ptr->angle - ptr->last_angle > MOTO_MAXANG_HALF)
|
|
|
|
|
ptr->round_cnt--;
|
|
|
|
|
else if (ptr->angle - ptr->last_angle < -MOTO_MAXANG_HALF)
|
|
|
|
|
ptr->round_cnt++;
|
|
|
|
|
ptr->total_angle = ptr->round_cnt * MOTO_MAXANG + ptr->angle - ptr->offset_angle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
moto_measure_t moto::getmotoinfo()
|
|
|
|
|
{
|
2023-04-22 16:59:32 +08:00
|
|
|
|
// 在中断里面计算时间太长会导致重启,在取信息时计算浮点
|
2023-04-19 23:54:02 +08:00
|
|
|
|
moto_chassis.output_speed_rpm = (float)moto_chassis.speed_rpm / MOTO_REDUCTION;
|
|
|
|
|
moto_chassis.output_round_cnt = (moto_chassis.round_cnt + (float)(moto_chassis.angle - moto_chassis.offset_angle) / MOTO_MAXANG) / MOTO_REDUCTION;
|
|
|
|
|
return moto_chassis;
|
|
|
|
|
}
|
2023-05-09 22:41:01 +08:00
|
|
|
|
// 关闭电机输出,防止堵转
|
2023-04-22 16:59:32 +08:00
|
|
|
|
void moto::close()
|
|
|
|
|
{
|
2023-05-09 22:41:01 +08:00
|
|
|
|
pid_init();
|
|
|
|
|
set_moto_current(0);
|
|
|
|
|
_closed = true;
|
2023-04-22 16:59:32 +08:00
|
|
|
|
}
|
2023-04-19 23:54:02 +08:00
|
|
|
|
void moto::onReceive(int packetSize)
|
|
|
|
|
{
|
|
|
|
|
if (!CAN.packetRtr())
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < packetSize; i++)
|
|
|
|
|
{
|
|
|
|
|
CaninBuffer[i] = CAN.read();
|
|
|
|
|
}
|
|
|
|
|
get_moto_measure(&moto_chassis, CaninBuffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/////////////PID控制
|
2023-04-22 16:59:32 +08:00
|
|
|
|
void pid_init()
|
|
|
|
|
{
|
|
|
|
|
pid_param_init(&moto_pid, 10000, 10000, 10, 8000, 0, 10.0f, 1.0f, 0.5f); //
|
|
|
|
|
// pid_param_init(&moto_pid, 10000, 10000, 10, 8000, 0, 14.0f, 0.01f, 0.0f); ////
|
|
|
|
|
}
|
2023-04-19 23:54:02 +08:00
|
|
|
|
void pid_param_init(PID_TypeDef *pid,
|
|
|
|
|
uint16_t maxout,
|
|
|
|
|
uint16_t intergral_limit,
|
|
|
|
|
float deadband,
|
|
|
|
|
int16_t max_err,
|
|
|
|
|
int16_t target,
|
|
|
|
|
float kp,
|
|
|
|
|
float ki,
|
|
|
|
|
float kd)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
memset(pid, 0, sizeof(PID_TypeDef));
|
|
|
|
|
|
|
|
|
|
pid->DeadBand = deadband;
|
|
|
|
|
pid->IntegralLimit = intergral_limit;
|
|
|
|
|
pid->MaxOutput = maxout;
|
|
|
|
|
pid->Max_Err = max_err;
|
|
|
|
|
pid->target = target;
|
|
|
|
|
|
|
|
|
|
pid->kp = kp;
|
|
|
|
|
pid->ki = ki;
|
|
|
|
|
pid->kd = kd;
|
|
|
|
|
|
|
|
|
|
pid->output = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void pid_reset(PID_TypeDef *pid, float kp, float ki, float kd)
|
|
|
|
|
{
|
|
|
|
|
pid->kp = kp;
|
|
|
|
|
pid->ki = ki;
|
|
|
|
|
pid->kd = kd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void pid_target(PID_TypeDef *pid, float new_target)
|
|
|
|
|
{
|
|
|
|
|
pid->target = new_target;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-22 16:59:32 +08:00
|
|
|
|
float pid_cal(PID_TypeDef *pid, int16_t measure, float pidtarget)
|
2023-04-19 23:54:02 +08:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
pid->lasttime = pid->thistime;
|
|
|
|
|
pid->thistime = xTaskGetTickCount() * portTICK_RATE_MS; // 换算为绝对时间
|
|
|
|
|
pid->dtime = pid->thistime - pid->lasttime; // 更新两次计算的时间
|
|
|
|
|
|
|
|
|
|
pid->last_err = pid->err;
|
2023-04-22 16:59:32 +08:00
|
|
|
|
pid->err = pidtarget - measure;
|
|
|
|
|
// pid->err = pid->target - measure;
|
2023-04-19 23:54:02 +08:00
|
|
|
|
|
|
|
|
|
if (abs(pid->err) > pid->DeadBand)
|
|
|
|
|
{
|
|
|
|
|
pid->pout = pid->kp * pid->err;
|
|
|
|
|
pid->iout += (pid->ki * pid->err);
|
|
|
|
|
pid->dout = pid->kd * (pid->err - pid->last_err); // 除以dtime??
|
|
|
|
|
|
|
|
|
|
// 积分限幅
|
|
|
|
|
if (pid->iout > pid->IntegralLimit)
|
|
|
|
|
pid->iout = pid->IntegralLimit;
|
|
|
|
|
if (pid->iout < -pid->IntegralLimit)
|
|
|
|
|
pid->iout = -pid->IntegralLimit;
|
|
|
|
|
|
|
|
|
|
pid->output = pid->pout + pid->iout + pid->dout;
|
|
|
|
|
|
|
|
|
|
if (pid->output > pid->MaxOutput)
|
|
|
|
|
{
|
|
|
|
|
pid->output = pid->MaxOutput;
|
|
|
|
|
}
|
|
|
|
|
if (pid->output < -(pid->MaxOutput))
|
|
|
|
|
{
|
|
|
|
|
pid->output = -(pid->MaxOutput);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pid->output; // 进入死区维持原值
|
|
|
|
|
}
|