找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4860|回复: 7
打印 上一主题 下一主题
收起左侧

STM32F103C8T6单片机跷跷板平衡车程序,MPU6050,PID

  [复制链接]
跳转到指定楼层
楼主
ID:587435 发表于 2019-7-21 15:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32F103C8T6,跷跷板平衡车,MPU6050,PID

元件清单:
OLED显示屏
STM32F103C8T6最小系统
MPU6050陀螺仪
TB6612FNG驱动模块
LM2596稳压
12V锂电池
直流减速电机带编码器*2
红外循迹探头*5
37mm直流减速电机固定座 铁质*2
65mm轮胎*2
铁质 连轴器*2
杜邦线若干
万向轮
铜柱
洞洞板

单片机源程序如下:
  1. #include "stm32f10x.h"
  2. #include "sys.h"

  3. char x[10];//角度显示缓冲数组
  4. u8 Tim[7]=  "Time : ";//时间显示数组
  5. extern float Roll; //读取到的6050角度值
  6. float Roll_1,Roll_2,Roll_3;//分别是最新时刻角度值,上一时刻角度值,以及积分角度值
  7. float power;//小车最终输出动力
  8. float KP=8.0,KD=0.5,KI=0.02,PrevError_C =0;//PID参数
  9. u8 pid_flag=0;//分时刻读取角度值的标志位
  10. extern u16 tim_flag;//计时标志位
  11. extern int tim;//秒计时,一秒加一
  12. double zz=0;//平衡计时
  13. int main()//主函数
  14. {
  15.         delay_init();//延时函数初始化
  16.         IIC_Init();//IIC初始化
  17.         MPU6050_initialize();//6050初始化
  18.         DMP_Init();//MPU6050内置DMP的初始化
  19.         OLED_Init();//OLED初始化
  20.         OLED_Clear();//OLED清屏
  21.         GPIO_INIT();//控制减速电机IO口初始化
  22.         HW_INIT();//红外探头使用IO口初始化
  23.         TIM3_INIT();//定时器初始化,用于放PWM波,控制车的速度
  24.         Qianjin();//使车向前跑(相对的)
  25.         TIM3->CCR1=80;//左轮动力80
  26.         TIM3->CCR2=80;//右轮动力80
  27.         OLED_ShowString(0,4, Tim);//OLED显示不改变数组         
  28.         Read_DMP();//读取一次角度值
  29.         while(1)//无限循环
  30.         {
  31.                 sprintf(x,"Angle: %0.2f",Roll);//此函数用于将数组加入可变参数
  32.                 OLED_ShowString(0,0,(u8*)x);//显示上列数组
  33.                 if(tim>=99)tim=99;//计时上限99秒
  34.                 OLED_ShowNum(48,4,tim,3,12);//显示时间,单位/秒
  35.                 OLED_ShowNum(0,6,zz,4,12);//显示平衡时间
  36.                 OLED_ShowNum(32,6,power,4,12);//显示当前动力值

  37. /***************************平衡PID算法********************************/
  38.                 pid_flag++;//运行时间标志
  39.                 if(pid_flag==1)//记录1时刻角度值
  40.                 {
  41.                         Roll_1=Roll;
  42.                 }
  43.                 if(pid_flag==2)//记录2时刻角度值
  44.                 {
  45.                         pid_flag=0;
  46.                         Roll_2=Roll;
  47.                         PrevError_C=Roll_2-Roll_1;//两次角度的差值
  48.                 }
  49.                 Read_DMP();//读取当前角度值
  50.                 Roll_3+=Roll;//积分值累加
  51.                 power=KP*abs(Roll)+KI*abs(Roll_3)+KD*PrevError_C;//PID计算当前合适的动力值
  52.                 if(power>90)        power=90;//动力值限幅
  53.                 if(Roll>1.7)//判断角度值
  54.                 {               
  55.                         if(PrevError_C<-0.03)//预判是否需要后退
  56.                                 Qianjin();
  57.                         else                                                                 //不需要就继续走
  58.                                 Houtui();
  59.                         TIM3->CCR1=power+30;
  60.                         TIM3->CCR2=power;
  61.                 }
  62.                 if(Roll<-1.7) //判断角度值         
  63.                 {
  64.                         if(PrevError_C>0.03)//预判是否需要后退
  65.                                 Houtui();
  66.                         else                                                                 //不需要就继续走
  67.                                 Qianjin();
  68.                         TIM3->CCR1=power+20;
  69.                         TIM3->CCR2=power;
  70.                 }
  71.                 if((Roll<=1.7)&&(Roll>=-1.7)&&(PrevError_C<0.03&&PrevError_C>-0.03))//平衡条件限定
  72.                 {
  73.                         Tingzhi();//停止
  74.                         TIM3->CCR1=0;//动力值为0
  75.                         TIM3->CCR2=0;
  76.                         Roll_3=0;        //积分清零
  77.                         zz++;//平衡计时
  78.                         if(zz>888)//达到平衡时间观察
  79.                         {
  80.                                 while(1)
  81.                                 {
  82.                                         Qianjin();TIM3->CCR1=95;TIM3->CCR2=80;//匀速向前
  83.                                         if(HW5==0)//右后探头检测到黑线
  84.                                         {
  85.                                                         Tingzhi();//停止
  86.                                                         while(1)
  87.                                                         {
  88.                                                                 Tingzhi();
  89.                                                                 TIM3->CCR1=0;//动力为0
  90.                                                                 TIM3->CCR2=0;
  91.                                                         }
  92.                                         }
  93.                                 }
  94.                         }
  95.                 }
  96.         }
  97. }
复制代码

所有资料51hei提供下载:
project+注释.7z (68.97 KB, 下载次数: 183)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏10 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:511461 发表于 2019-7-23 10:09 | 只看该作者
学习一下
回复

使用道具 举报

板凳
ID:425297 发表于 2019-7-24 12:48 | 只看该作者
亲请问  有接线图么
回复

使用道具 举报

地板
ID:90358 发表于 2019-7-24 15:12 | 只看该作者
学习下,谢谢
回复

使用道具 举报

5#
ID:259648 发表于 2021-4-17 13:40 来自手机 | 只看该作者
你好 ,可以发一下实物图么?  看到可以与我联系,非常感谢。
回复

使用道具 举报

6#
ID:462629 发表于 2021-12-28 10:06 | 只看该作者
有电路原理图,源码吗
回复

使用道具 举报

7#
ID:1004880 发表于 2022-2-12 10:52 | 只看该作者
woyaodwn 发表于 2021-12-28 10:06
有电路原理图,源码吗

找到源代码了吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表