STM32
直播中

小芳

13年用户 954经验值
私信 关注
[问答]

怎样去设计一种基于stm32的两轮平衡小车

两轮平衡小车是由哪些模块组成的?
怎样去设计一种基于STM32的两轮平衡小车?

回帖(1)

江孟琢

2021-9-28 15:40:30
  摘要
  这个项目是在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
完善资料,
赚取积分