標(biāo)題:
基于STM32的平衡小車核心算法
[打印本頁]
作者:
kuangleilei
時間:
2020-11-1 17:45
標(biāo)題:
基于STM32的平衡小車核心算法
#include "math.h"
#include "stdio.h"
#include "control.h"
#include "debug.H"
#include "MPU6050.H"
#include "communicate.h"
#include "bsp.h"
#include "ultrasonic.h"
#include "infrare.h"
unsigned char g_u8MainEventCount;
unsigned char g_u8SpeedControlCount;
unsigned char g_u8SpeedControlPeriod;
unsigned char g_u8DirectionControlPeriod;
unsigned char g_u8DirectionControlCount;
unsigned char g_cMotorDisable = 0;//值等于0時電機(jī)正常轉(zhuǎn)動,否則停止轉(zhuǎn)動
int g_iGravity_Offset = 0;
/******電機(jī)控制參數(shù)******/
float g_fSpeedControlOut;
float g_fSpeedControlOutOld;
float g_fSpeedControlOutNew;
float g_fAngleControlOut;
float g_fLeftMotorOut;
float g_fRightMotorOut;
/******速度控制參數(shù)******/
short g_s16LeftMotorPulse;
short g_s16RightMotorPulse;
int g_s32LeftMotorPulseOld;
int g_s32RightMotorPulseOld;
int g_s32LeftMotorPulseSigma;
int g_s32RightMotorPulseSigma;
float g_fCarSpeed;
float g_iCarSpeedSet;
float g_fCarSpeedOld;
float g_fCarPosition;
/*-----角度環(huán)和速度環(huán)PID控制參數(shù)-----*/
PID_t g_tCarAnglePID={17.0, 0, 23.0}; //*5 /10
PID_t g_tCarSpeedPID={15.25, 1.08, 0}; //i/10
/******藍(lán)牙控制參數(shù)******/
float g_fBluetoothSpeed;
float g_fBluetoothDirection;
float g_fBluetoothDirectionOld;
float g_fBluetoothDirectionNew;
float g_fBluetoothDirectionOut;
float g_fCarAngle; //
float g_fGyroAngleSpeed; //
float g_fGravityAngle; //
int g_iLeftTurnRoundCnt = 0;
int g_iRightTurnRoundCnt = 0;
static int AbnormalSpinFlag = 0;
/***************************************************************
** 函數(shù)名稱: CarUpstandInit
** 功能描述: 全局變量初始化函數(shù)
***************************************************************/
void CarUpstandInit(void)
{
//g_iAccelInputVoltage_X_Axis = g_iGyroInputVoltage_Y_Axis = 0;
g_s16LeftMotorPulse = g_s16RightMotorPulse = 0;
g_s32LeftMotorPulseOld = g_s32RightMotorPulseOld = 0;
g_s32LeftMotorPulseSigma = g_s32RightMotorPulseSigma = 0;
g_fCarSpeed = g_fCarSpeedOld = 0;
g_fCarPosition = 0;
g_fCarAngle = 0;
g_fGyroAngleSpeed = 0;
g_fGravityAngle = 0;
g_fAngleControlOut = g_fSpeedControlOut = g_fBluetoothDirectionOut = 0;
g_fLeftMotorOut = g_fRightMotorOut = 0;
g_fBluetoothSpeed = g_fBluetoothDirection = 0;
g_fBluetoothDirectionNew = g_fBluetoothDirectionOld = 0;
g_u8MainEventCount=0;
g_u8SpeedControlCount=0;
g_u8SpeedControlPeriod=0;
}
/***************************************************************
** 函數(shù)名稱: AbnormalSpinDetect
** 功能描述: 電機(jī)轉(zhuǎn)速異常檢測
***************************************************************/
void AbnormalSpinDetect(short leftSpeed,short rightSpeed)
{
static unsigned short count = 0;
//速度設(shè)置為0時檢測,否則不檢測
if(g_iCarSpeedSet==0)
{
if(((leftSpeed>30)&&(rightSpeed>30)&&(g_fCarAngle > -30) && (g_fCarAngle < 30))
||((leftSpeed<-30)&&(rightSpeed<-30))&&(g_fCarAngle > -30) && (g_fCarAngle < 30))
{// 左右電機(jī)轉(zhuǎn)速大于30、方向相同、持續(xù)時間超過250ms,且車身角度不超過30度,則判斷為懸空空轉(zhuǎn)
count++;
if(count>50){
count = 0;
AbnormalSpinFlag = 1;
}
}
else{
count = 0;
}
}
else{
count = 0;
}
}
/***************************************************************
** 函數(shù)名稱: LandingDetect
** 功能描述: 小車著地檢測
***************************************************************/
void LandingDetect(void)
{
static float lastCarAngle = 0;
static unsigned short count = 0,count1 = 0;
if(AbnormalSpinFlag == 0)return;
// 小車角度5°~-5°啟動檢測
if((g_fCarAngle > -5) && (g_fCarAngle < 5))
{
count1++;
if(count1 >= 50)
{//每隔250ms判斷一次小車角度變化量,變化量小于0.8°或大于-0.8°判斷為小車靜止
count1 = 0;
if(((g_fCarAngle - lastCarAngle) < 0.8) && ((g_fCarAngle - lastCarAngle) > -0.8))
{
count++;
if(count >= 4){
count = 0;
count1 = 0;
g_fCarPosition = 0;
AbnormalSpinFlag = 0;
}
}
else{
count = 0;
}
lastCarAngle = g_fCarAngle;
}
}
else
{
count1 = 0;
count = 0;
}
}
/***************************************************************
** 函數(shù)名稱: MotorManage
** 功能描述: 電機(jī)使能/失能控制
***************************************************************/
void MotorManage(void)
{
AbnormalSpinDetect(g_s16LeftMotorPulse, g_s16RightMotorPulse);
LandingDetect();
if(AbnormalSpinFlag)
{
g_cMotorDisable |= (0x01<<1);
}
else
{
g_cMotorDisable &= ~(0x01<<1);
}
if(g_fCarAngle > 30 || g_fCarAngle < (-30))
{
g_cMotorDisable |= (0x01<<2);
}
else
{
g_cMotorDisable &= ~(0x01<<2);
}
}
/***************************************************************
** 函數(shù)名稱: SetMotorVoltageAndDirection
** 功能描述: 電機(jī)轉(zhuǎn)速及方向控制函數(shù)
***************************************************************/
void SetMotorVoltageAndDirection(int i16LeftVoltage,int i16RightVoltage)
{
if(i16LeftVoltage<0)
{
GPIO_SetBits(GPIOA, GPIO_Pin_3 );
GPIO_ResetBits(GPIOA, GPIO_Pin_4 );
i16LeftVoltage = (-i16LeftVoltage);
}
else
{
GPIO_SetBits(GPIOA, GPIO_Pin_4 );
GPIO_ResetBits(GPIOA, GPIO_Pin_3 );
}
if(i16RightVoltage<0)
{
GPIO_SetBits(GPIOB, GPIO_Pin_0 );
GPIO_ResetBits(GPIOB, GPIO_Pin_1 );
i16RightVoltage = (-i16RightVoltage);
}
else
{
GPIO_SetBits(GPIOB, GPIO_Pin_1 );
GPIO_ResetBits(GPIOB, GPIO_Pin_0 );
}
if(i16RightVoltage > MOTOR_OUT_MAX)
{
i16RightVoltage = MOTOR_OUT_MAX;
}
if(i16LeftVoltage > MOTOR_OUT_MAX)
{
i16LeftVoltage = MOTOR_OUT_MAX;
}
if(g_cMotorDisable)
{
TIM_SetCompare1(TIM3,0);
TIM_SetCompare2(TIM3,0);
}
else
{
TIM_SetCompare1(TIM3,i16RightVoltage);
TIM_SetCompare2(TIM3,i16LeftVoltage);
}
}
/***************************************************************
** 函數(shù)名稱: MotorOutput
** 功能描述: 電機(jī)輸出函數(shù)
將直立控制、速度控制、方向控制的輸出量進(jìn)行疊加,并加
入死區(qū)常量,對輸出飽和作出處理。
***************************************************************/
void MotorOutput(void)
{
g_fLeftMotorOut = g_fAngleControlOut - g_fSpeedControlOut - g_fBluetoothDirection ;
g_fRightMotorOut = g_fAngleControlOut - g_fSpeedControlOut + g_fBluetoothDirection ;
/*增加死區(qū)常數(shù)*/
if((int)g_fLeftMotorOut>0) g_fLeftMotorOut += MOTOR_OUT_DEAD_VAL;
else if((int)g_fLeftMotorOut<0) g_fLeftMotorOut -= MOTOR_OUT_DEAD_VAL;
if((int)g_fRightMotorOut>0) g_fRightMotorOut += MOTOR_OUT_DEAD_VAL;
else if((int)g_fRightMotorOut<0) g_fRightMotorOut -= MOTOR_OUT_DEAD_VAL;
/*輸出飽和處理,防止超出PWM范圍*/
if((int)g_fLeftMotorOut > MOTOR_OUT_MAX) g_fLeftMotorOut = MOTOR_OUT_MAX;
if((int)g_fLeftMotorOut < MOTOR_OUT_MIN) g_fLeftMotorOut = MOTOR_OUT_MIN;
if((int)g_fRightMotorOut > MOTOR_OUT_MAX) g_fRightMotorOut = MOTOR_OUT_MAX;
if((int)g_fRightMotorOut < MOTOR_OUT_MIN) g_fRightMotorOut = MOTOR_OUT_MIN;
SetMotorVoltageAndDirection((int)g_fLeftMotorOut,(int)g_fRightMotorOut);
}
void GetMotorPulse(void) //采集電機(jī)速度脈沖
{
g_s16LeftMotorPulse = TIM_GetCounter(TIM2);
g_s16RightMotorPulse= -TIM_GetCounter(TIM4);
TIM2->CNT = 0;
TIM4->CNT = 0; //清零
g_s32LeftMotorPulseSigma += g_s16LeftMotorPulse;
g_s32RightMotorPulseSigma += g_s16RightMotorPulse;
g_iLeftTurnRoundCnt -= g_s16LeftMotorPulse;
g_iRightTurnRoundCnt -= g_s16RightMotorPulse;
}
void AngleCalculate(void)
{
//-------加速度--------------------------
//量程為±2g時,靈敏度:16384 LSB/g
g_fGravityAngle = atan2(g_fAccel_y/16384.0,g_fAccel_z/16384.0) * 180.0 / 3.14;
g_fGravityAngle = g_fGravityAngle - g_iGravity_Offset;
//-------角速度-------------------------
//范圍為2000deg/s時,換算關(guān)系:16.4 LSB/(deg/s)
g_fGyro_x = g_fGyro_x / 16.4; //計(jì)算角速度值
g_fGyroAngleSpeed = g_fGyro_x;
//-------互補(bǔ)濾波---------------
g_fCarAngle = 0.98 * (g_fCarAngle + g_fGyroAngleSpeed * 0.005) + 0.02 * g_fGravityAngle;
}
/***************************************************************
** 函數(shù)名稱: AngleControl
** 功能描述: 角度環(huán)控制函數(shù)
***************************************************************/
void AngleControl(void)
{
g_fAngleControlOut = (CAR_ANGLE_SET-g_fCarAngle) * g_tCarAnglePID.P *5 + \
(CAR_ANGLE_SPEED_SET-g_fGyroAngleSpeed) * (g_tCarAnglePID.D /10);
}
/***************************************************************
** 函數(shù)名稱: SpeedControl
** 功能描述: 速度環(huán)控制函數(shù)
***************************************************************/
void SpeedControl(void)
{
float fP,fI;
float fDelta;
g_fCarSpeed = (g_s32LeftMotorPulseSigma + g_s32RightMotorPulseSigma ) * 0.5 ;
g_s32LeftMotorPulseSigma = g_s32RightMotorPulseSigma = 0; //全局變量 注意及時清零
g_fCarSpeed = 0.7 * g_fCarSpeedOld + 0.3 * g_fCarSpeed ;//低通濾波,使速度更平滑
g_fCarSpeedOld = g_fCarSpeed;
fDelta = CAR_SPEED_SET;
fDelta -= g_fCarSpeed;
fP = fDelta * (g_tCarSpeedPID.P);
fI = fDelta * (g_tCarSpeedPID.I/10.0);
g_fCarPosition += fI;
g_fCarPosition += g_fBluetoothSpeed;
//積分上限設(shè)限
if((s16)g_fCarPosition > CAR_POSITION_MAX) g_fCarPosition = CAR_POSITION_MAX;
if((s16)g_fCarPosition < CAR_POSITION_MIN) g_fCarPosition = CAR_POSITION_MIN;
g_fSpeedControlOutOld = g_fSpeedControlOutNew;
g_fSpeedControlOutNew = fP + g_fCarPosition;
}
/***************************************************************
** 函數(shù)名稱: SpeedControlOutput
** 功能描述: 速度環(huán)控制輸出函數(shù)-分多步逐次逼近最終輸出,盡可能將對直立環(huán)的干擾降低。
***************************************************************/
void SpeedControlOutput(void)
{
float fValue;
fValue = g_fSpeedControlOutNew - g_fSpeedControlOutOld ;
g_fSpeedControlOut = fValue * (g_u8SpeedControlPeriod + 1) / SPEED_CONTROL_PERIOD + g_fSpeedControlOutOld;
}
/***************************************************************
** 函數(shù)名稱: Scale
** 功能描述: 量程歸一化處理
***************************************************************/
float Scale(float input, float inputMin, float inputMax, float outputMin, float outputMax) {
float output;
if (inputMin < inputMax)
output = (input - inputMin) / ((inputMax - inputMin) / (outputMax - outputMin));
else
output = (inputMin - input) / ((inputMin - inputMax) / (outputMax - outputMin));
if (output > outputMax)
output = outputMax;
else if (output < outputMin)
output = outputMin;
return output;
}
/***************************************************************
** 函數(shù)名稱: Steer
** 功能描述: 遙控速度及方向處理函數(shù)
***************************************************************/
void Steer(float direct, float speed)
{
if(direct > 0)
g_fBluetoothDirection = Scale(direct, 0, 10, 0, 400);
else
g_fBluetoothDirection = -Scale(direct, 0, -10, 0, 400);
if(speed > 0)
g_iCarSpeedSet = Scale(speed, 0, 10, 0, 70);
else
g_iCarSpeedSet = -Scale(speed, 0, -10, 0, 70);
}
void UltraControl(int mode)
{
if(mode == 0)
{
if((Distance >= 0) && (Distance<= 12))
{//距離小于12cm則后退
Steer(0, -4);
}
else if((Distance> 18) && (Distance<= 30))
{//距離大于18cm且小于30則前進(jìn)
Steer(0, 4);
}
else
Steer(0, 0);
}
else if(mode == 1)
{
if((Distance >= 0) && (Distance<= 20))
{//右轉(zhuǎn)750個脈沖計(jì)數(shù),轉(zhuǎn)彎角度約為90度
Steer(5, 0);
g_iLeftTurnRoundCnt = 750;
g_iRightTurnRoundCnt = -750;
}
if((g_iLeftTurnRoundCnt < 0)&&(g_iRightTurnRoundCnt > 0))
{
Steer(0, 4);
}
}
}
/***************************************************************
** 函數(shù)名稱: TailingControl
** 功能描述: 紅外尋跡
***************************************************************/
void TailingControl(void)
{
#if INFRARE_DEBUG_EN > 0
char buff[32];
#endif
char result;
float direct = 0;
float speed = 0;
result = InfraredDetect();
if(result & infrared_channel_Lc)
direct = -10;
else if(result & infrared_channel_Lb)
direct = -6;
else if(result & infrared_channel_La)
direct = -4;
else if(result & infrared_channel_Rc)
direct = 10;
else if(result & infrared_channel_Rb)
direct = 6;
else if(result & infrared_channel_Ra)
direct = 4;
else
direct = 0.0;
speed = 3;
Steer(direct, speed);
#if INFRARE_DEBUG_EN > 0
sprintf(buff, "Steer:%d, Speed:%d\r\n",(int)direct, (int)speed);
DebugOutStr(buff);
#endif
}
復(fù)制代碼
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1