PullupDev/src/moto.cpp

224 lines
5.8 KiB
C++
Raw Normal View History

#include "moto.h"
#include "Arduino.h"
uint8_t CaninBuffer[8]; // 接收指令缓冲区
moto_measure_t moto_chassis;
PID_TypeDef moto_pid;
moto::moto()
{
_runing = false;
brake = true;
_closed=false;
}
bool moto::init()
{
Serial.println("init moto");
pid_init();
CAN.setPins(26, 27);
// 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()
{
}
// int16_t delta;
// int16_t max_speed_change = 100; // 500 ok 100电源不报高压错误但有点震荡
// int16_t set_speed_temp;
void moto::update()
{
// //可以柔和改变速度柔和程度max_speed_change越小越柔和,但太小需要调PID
// for (uint8_t i = 0; i < 2; i++)
// {
// // 加减速
// delta = (int16_t)moto_pid.target - moto_chassis.speed_rpm;
// if (delta > max_speed_change)
// set_speed_temp = (float)(moto_chassis.speed_rpm + max_speed_change);
// else if (delta < -max_speed_change)
// set_speed_temp = (float)(moto_chassis.speed_rpm - max_speed_change);
// else
// set_speed_temp = moto_pid.target;
// pid_cal(&moto_pid, moto_chassis.speed_rpm,set_speed_temp);
// }
if ((_runing || brake)&&!_closed)
{
pid_cal(&moto_pid, moto_chassis.speed_rpm, moto_pid.target);
set_moto_current(moto_pid.output);
}
}
// void moto::update()
// {
// pid_cal(&moto_pid, moto_chassis.speed_rpm);
// set_moto_current(moto_pid.output);
// }
void moto::settarget(float new_target)
{
// 为了马上停止跳过PID控制器
if (new_target == 0.0f)
{
// 没刹车直接断开电流控制
_runing = false;
if (!brake)
{
pid_init();
set_moto_current(0);
}
}
else
{ _runing = true;
_closed=false;
}
moto_pid.target = new_target * MOTO_REDUCTION;
}
void moto::set_moto_current(int16_t iq1)
{
iq1 = MOTO_REVERSED * iq1;
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;
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
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;
// ptr->output_speed_rpm= (float)ptr->speed_rpm / MOTO_REDUCTION;
// ptr->output_round_cnt= ptr->round_cnt + (float)(ptr->angle - ptr->offset_angle)/MOTO_MAXANG/ MOTO_REDUCTION;
}
moto_measure_t moto::getmotoinfo()
{
// 在中断里面计算时间太长会导致重启,在取信息时计算浮点
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;
}
//关闭电机输出,防止堵转
void moto::close()
{
set_moto_current(0);
_closed=true;
}
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控制
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); ////
}
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;
}
float pid_cal(PID_TypeDef *pid, int16_t measure, float pidtarget)
{
pid->lasttime = pid->thistime;
pid->thistime = xTaskGetTickCount() * portTICK_RATE_MS; // 换算为绝对时间
pid->dtime = pid->thistime - pid->lasttime; // 更新两次计算的时间
pid->last_err = pid->err;
pid->err = pidtarget - measure;
// pid->err = pid->target - measure;
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; // 进入死区维持原值
}