摘要
这个项目是在20年11月初开始的,当时的我很迷茫,本应该去实习的我在线上培训,觉得无聊,便有了自己一人做项目的想法。也没想到这个项目做了将近整整一个月,才差不多做了出来。也是准备做两个项目的,这是第一个而已。
项目所需物料清单
主控板用到了c8t6、小车底盘(这个硬件是这项目于最贵的物料了),可以用大鱼电子、或者平衡小车之家的。由于经费的原因,我买了两个带电机的车轮、加上了亚克力板,勉强搭成了小车底盘。我的电机用的是JGA25-370电机。电机线正负是表示动力线1、2。电机线接反可以实现车轮反转的效果。为了布线方便,我用到了面包板。由于对焊接并不是很熟练,没用到洞洞板,这算是这个项目不大光彩的地方。用到的模块有mpu6050、oled(四针)、稳压模块(12V转5V)、JGA25-370电机、电机驱动模块(tb6612fng)、12v锂电池,目前想到的就这些模块。
项目过程中遇到的问题
这个项目历时一个月,过程的艰辛可想而知,也是本人太菜的原因,基础也很差。当时遇到的第一个问题就是稳压模块不知道怎么用,由于没有加上稳压模块,导致电机不转,这个问题困扰了很久,也问了很多人,最终知道了稳压模块是来将12v的电压降为5v的电压来给单片机供电的,虽然没用稳压模块,电机驱动模块并没有烧坏。用了稳压模块,由于不会焊接,就用了面包板代替了洞洞板。这让我也了解了面板板的强大之处。对于我这个小白来说。焊接的技术太差了,会焊接的同学可以忽略,本人计算机专业的,对电烙铁、焊锡并不是很了解。在校也没进实验室。电子、通信、自动化的同学应该带焊接并不陌生的。第一个问题花了很长一段时间的。
由于用到了洞洞板,接线就方便了许多。接着遇到的问题就是PID调节了。这个PID是真的难调。我们知道,虽说平衡小车是三闭环控制系统。但是仅仅直立环也是可以平衡的,只是不够精确罢了。直立环加速度环是完全可以平衡的,可以不用转向环的。
机械中值的确定
每个物体都有属于自己的机械中值,机械中值是调节PID的第一步,要想小车平衡性能非常好,首先必须得调节机械中值。之前也有人说过,要想小车能平衡,首先要让小车有一个短暂的平衡,不能一落地小车就倒。接着我们来谈谈如何来确定小车的机械中值。将小车的mpu6050测试代码烧录到主控,将小车放置地上顺时针转动,直至倒下,记下小车的角度。接着将小车逆时针转动,直至倒下,记下小车的角度。将两次角度的值相加,除以2,此时这个值就是小车的机械中值。确定好机械中值,就可以来调节速度环、直立环了。
PD(直立环)调节
我目前做的平衡小车v1.0版本,功能还有PID调节并不是很完善,目前小车只用到了直立环,根据我的调节,光直立环是可以平衡的。在调节直立环的时候,速度环PI中的kp、ki是必须置零的。首先判断直立环kp的极性,令kp=+1,kd=0;烧录程序,若小车向前倾,车轮向前加速,则说明极性正确,反之,则说明极性错误,令kp=-1。若小车两轮转动方向不一致,则说明硬件电机正负极接反了,需对调一下。kp极性判断完毕,接下来调节Kp的大小,令kd=0,不断增加kp,直至小车出现高频幅度震荡,调节kp不断消除震荡,持续增加,直至小车出现高频震荡,此时直立环调节完毕,由于kp、kd系数取的都是最大值,需要将系数乘以0.6,则是最平稳的。这是PD(直立环)调节。
PI(速度环)调节
在调节速度环PI的过程中,直立环的kp、kd是不需要置零的,首先也是判断极性,令kp=+1,烧录代码,用手向前转动一侧车轮,若两侧车轮同时向前加速,则kp极性正确,反之,则极性不正确,kp=-1。若kp极性判断正确,则可以通过调节Kp、Ki来让小车达到平衡。
程序讲解
mpu6050模块只用了五个引脚,分别是VCC、GND、SCL、SDA、INT,用到了IIC,引脚INT有相应的电平输出,依次可以触发外部中断作为控制周期,周期性反馈数据,保持mpu6050 数据的实时性。
/**************************************************************************
函数功能:外部中断初始化
入口参数:无
返回 值:无
作 用:是用来配置MPU6050引脚INT的,每当MPU6050有数据输出时,引脚INT有相应的电平输出。
依次来触发外部中断作为控制周期。保持MPU6050数据的实时性。
**************************************************************************/
void MPU6050_EXTI_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5);
EXTI_InitStructure.EXTI_Line=EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
}
编码器通过定时器输入捕获脉冲数,来测速的。定时器中断和外部中断一直不是很理解,今天经过别人指导,豁然开朗。定时器中断是通过定时器的重转载值,分频系数以及计数模式等设置,然后定义它的中断触发方式而产生的中断,一般溢出中断比较多。编码器encode采用的就是定时器中断。外部中断则是通过定义管脚的电平状态,通过外部的电平来触发它产生的中断。mpu6050 INT引脚触发就是外部中断。
**************************************************************************
函数功能:单位时间读取编码器计数
入口参数:定时器
返回 值:速度值
**************************************************************************/
int Read_Encoder(u8 TIMX)
{
int Encoder_TIM;
switch(TIMX)
{
case 2: Encoder_TIM= (short)TIM2 -》 CNT; TIM2 -》 CNT=0;break;
case 3: Encoder_TIM= (short)TIM3 -》 CNT; TIM3 -》 CNT=0;break;
case 4: Encoder_TIM= (short)TIM4 -》 CNT; TIM4 -》 CNT=0;break;
default: Encoder_TIM=0;
}
return Encoder_TIM;
}
控制代码如下:直立环PD控制、速度环PI控制
KP、KD、KP、KI系数、机械中值
int Balance_Pwm,Velocity_Pwm,Turn_Pwm;
float Mechanical_angle=0; // 无超声波、电池平躺着的小车机械中值
float balance_UP_KP=1000; // 小车直立环KP(第一次kp调1000 、参数乘以0.6 1000 //600
float balance_UP_KD=-1.2; //-1.2 -1.2 //-1.08
float velocity_KP=0; // 1.0
float velocity_KI=0; //0.005
PD控制
/**************************************************************************
函数功能:直立PD控制
入口参数:角度、机械平衡角度(机械中值)、角速度
返回 值:直立控制PWM
**************************************************************************/
int balance_UP(float Angle,float Mechanical_balance,float Gyro)
{
float Bias;
int balance;
Bias=Angle-Mechanical_balance; //===求出平衡的角度中值和机械相关
balance=balance_UP_KP*Bias+balance_UP_KD*Gyro; //===计算平衡控制的电机PWM PD控制 kp是P系数 kd是D系数
return balance;
}
摘要
这个项目是在20年11月初开始的,当时的我很迷茫,本应该去实习的我在线上培训,觉得无聊,便有了自己一人做项目的想法。也没想到这个项目做了将近整整一个月,才差不多做了出来。也是准备做两个项目的,这是第一个而已。
项目所需物料清单
主控板用到了c8t6、小车底盘(这个硬件是这项目于最贵的物料了),可以用大鱼电子、或者平衡小车之家的。由于经费的原因,我买了两个带电机的车轮、加上了亚克力板,勉强搭成了小车底盘。我的电机用的是JGA25-370电机。电机线正负是表示动力线1、2。电机线接反可以实现车轮反转的效果。为了布线方便,我用到了面包板。由于对焊接并不是很熟练,没用到洞洞板,这算是这个项目不大光彩的地方。用到的模块有mpu6050、oled(四针)、稳压模块(12V转5V)、JGA25-370电机、电机驱动模块(tb6612fng)、12v锂电池,目前想到的就这些模块。
项目过程中遇到的问题
这个项目历时一个月,过程的艰辛可想而知,也是本人太菜的原因,基础也很差。当时遇到的第一个问题就是稳压模块不知道怎么用,由于没有加上稳压模块,导致电机不转,这个问题困扰了很久,也问了很多人,最终知道了稳压模块是来将12v的电压降为5v的电压来给单片机供电的,虽然没用稳压模块,电机驱动模块并没有烧坏。用了稳压模块,由于不会焊接,就用了面包板代替了洞洞板。这让我也了解了面板板的强大之处。对于我这个小白来说。焊接的技术太差了,会焊接的同学可以忽略,本人计算机专业的,对电烙铁、焊锡并不是很了解。在校也没进实验室。电子、通信、自动化的同学应该带焊接并不陌生的。第一个问题花了很长一段时间的。
由于用到了洞洞板,接线就方便了许多。接着遇到的问题就是PID调节了。这个PID是真的难调。我们知道,虽说平衡小车是三闭环控制系统。但是仅仅直立环也是可以平衡的,只是不够精确罢了。直立环加速度环是完全可以平衡的,可以不用转向环的。
机械中值的确定
每个物体都有属于自己的机械中值,机械中值是调节PID的第一步,要想小车平衡性能非常好,首先必须得调节机械中值。之前也有人说过,要想小车能平衡,首先要让小车有一个短暂的平衡,不能一落地小车就倒。接着我们来谈谈如何来确定小车的机械中值。将小车的mpu6050测试代码烧录到主控,将小车放置地上顺时针转动,直至倒下,记下小车的角度。接着将小车逆时针转动,直至倒下,记下小车的角度。将两次角度的值相加,除以2,此时这个值就是小车的机械中值。确定好机械中值,就可以来调节速度环、直立环了。
PD(直立环)调节
我目前做的平衡小车v1.0版本,功能还有PID调节并不是很完善,目前小车只用到了直立环,根据我的调节,光直立环是可以平衡的。在调节直立环的时候,速度环PI中的kp、ki是必须置零的。首先判断直立环kp的极性,令kp=+1,kd=0;烧录程序,若小车向前倾,车轮向前加速,则说明极性正确,反之,则说明极性错误,令kp=-1。若小车两轮转动方向不一致,则说明硬件电机正负极接反了,需对调一下。kp极性判断完毕,接下来调节Kp的大小,令kd=0,不断增加kp,直至小车出现高频幅度震荡,调节kp不断消除震荡,持续增加,直至小车出现高频震荡,此时直立环调节完毕,由于kp、kd系数取的都是最大值,需要将系数乘以0.6,则是最平稳的。这是PD(直立环)调节。
PI(速度环)调节
在调节速度环PI的过程中,直立环的kp、kd是不需要置零的,首先也是判断极性,令kp=+1,烧录代码,用手向前转动一侧车轮,若两侧车轮同时向前加速,则kp极性正确,反之,则极性不正确,kp=-1。若kp极性判断正确,则可以通过调节Kp、Ki来让小车达到平衡。
程序讲解
mpu6050模块只用了五个引脚,分别是VCC、GND、SCL、SDA、INT,用到了IIC,引脚INT有相应的电平输出,依次可以触发外部中断作为控制周期,周期性反馈数据,保持mpu6050 数据的实时性。
/**************************************************************************
函数功能:外部中断初始化
入口参数:无
返回 值:无
作 用:是用来配置MPU6050引脚INT的,每当MPU6050有数据输出时,引脚INT有相应的电平输出。
依次来触发外部中断作为控制周期。保持MPU6050数据的实时性。
**************************************************************************/
void MPU6050_EXTI_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5);
EXTI_InitStructure.EXTI_Line=EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
}
编码器通过定时器输入捕获脉冲数,来测速的。定时器中断和外部中断一直不是很理解,今天经过别人指导,豁然开朗。定时器中断是通过定时器的重转载值,分频系数以及计数模式等设置,然后定义它的中断触发方式而产生的中断,一般溢出中断比较多。编码器encode采用的就是定时器中断。外部中断则是通过定义管脚的电平状态,通过外部的电平来触发它产生的中断。mpu6050 INT引脚触发就是外部中断。
**************************************************************************
函数功能:单位时间读取编码器计数
入口参数:定时器
返回 值:速度值
**************************************************************************/
int Read_Encoder(u8 TIMX)
{
int Encoder_TIM;
switch(TIMX)
{
case 2: Encoder_TIM= (short)TIM2 -》 CNT; TIM2 -》 CNT=0;break;
case 3: Encoder_TIM= (short)TIM3 -》 CNT; TIM3 -》 CNT=0;break;
case 4: Encoder_TIM= (short)TIM4 -》 CNT; TIM4 -》 CNT=0;break;
default: Encoder_TIM=0;
}
return Encoder_TIM;
}
控制代码如下:直立环PD控制、速度环PI控制
KP、KD、KP、KI系数、机械中值
int Balance_Pwm,Velocity_Pwm,Turn_Pwm;
float Mechanical_angle=0; // 无超声波、电池平躺着的小车机械中值
float balance_UP_KP=1000; // 小车直立环KP(第一次kp调1000 、参数乘以0.6 1000 //600
float balance_UP_KD=-1.2; //-1.2 -1.2 //-1.08
float velocity_KP=0; // 1.0
float velocity_KI=0; //0.005
PD控制
/**************************************************************************
函数功能:直立PD控制
入口参数:角度、机械平衡角度(机械中值)、角速度
返回 值:直立控制PWM
**************************************************************************/
int balance_UP(float Angle,float Mechanical_balance,float Gyro)
{
float Bias;
int balance;
Bias=Angle-Mechanical_balance; //===求出平衡的角度中值和机械相关
balance=balance_UP_KP*Bias+balance_UP_KD*Gyro; //===计算平衡控制的电机PWM PD控制 kp是P系数 kd是D系数
return balance;
}
举报