从零开始写STM32平衡小车代码,从0到1

教你从零开始写STM32平衡小车代码

前言:

本人也是学生,只是分享一下自己的设计思路与代码教学。

这次STM32平衡小车是基于STM32CubeMX软件生成HAL库代码编写。

第一部分:前期准备

这部分主要是关于组装基本平衡小车需要的零件

1.小车车架以及电机固定架轮子和联轴器(我是通过淘宝上购买的)

2.带有编码器的直流电机

3.直流电机驱动电路(也可以通过网上购买推荐大鱼电子的电机驱动价格:30+)

4.一个STM32最小系统板(本人芯片型号为STM32F103ZET6)

5.一个陀螺仪随意型号可以买贵一点的这样数据不会很多毛刺,如果要节约成本就需要自己进行滤波优化了。(本人使用的是维特智能jy61p)

6.3S航模电池,想要小车跑起来电池是必不可少的

第二部分:新建STM32CubeMX工程

主页面

进入页面后先选择一款MUC:点击 ACCESS TO MCU

在此搜索你们使用的芯片型号即可

进去后先点击SYS修改Debug模式,我这里选择SWD

在RCC下选择外部晶振如图

点击上方的时钟树,正确配置后只要在最后

这个位置,输入最大的速率,软件就会自动配置好时钟树

最后在上方的项目管理界面选择你要的IDE

勾选需要的配置,这样工程就基本建立完成。

第三部分:配置需要的外设

在第二部分的基础上配置

1.定时器

首先是定时器,想要驱动电机,我们需要配置定时器生成PWM波

这里使用TIM1的CH1和CH2生成PWM控制两路电机

自动重装载值设置为7200-1

这样生成的是10khz的方波足够我们使用了

这里顺便说一下电机的驱动原理:电机的转速是和PWM的占空比成正比的。

2.编码器

编码器是读取电机真实速度,作为后序PID控制的反馈值。

TIM2和TIM3都如图配置编码器模式

3.主要控制定时器

配置一个10ms的定时器,作为我们的控制周期

网上很多平衡小车都是通过陀螺仪的引脚外部中进行控制周期

其实不是很需要这样,这样写代码也不好理解

只需要确保陀螺仪的回传速率能够大于等于控制周期即可

4.串口

作为陀螺仪数据的接收和处理

波特率为115200

如果和我是同款陀螺仪的话初始波特率是9600回传速率是10hz需要使用官方的上位机进行设置。

其实也可以使用指令进行配置,但是我一直没有成功,最后还是使用TTL连接上位机配置。

这样所有需要的配置都配置完啦,接下来只要点击右上角的生成代码就可以啦。

会生成这样一个文件夹

打开里面的MDK-ARM就是熟悉的Keil了因为我选择的是MDK IDE

第四部分:代码编写

1.基础HAL库运行编写

因为上面的步骤软件已经帮我们把基础的外设驱动代码编写完了

接下来我们要做一些必要的代码

在HAL库中定时器中断需要我们手动开启

找到main.c

开启定时器中断开启编码器和PWM以及串口接收中断

以及编码器启动,和PWM生成都需要手动先开启

2.编码器代码

因为编码器是基于定时器的,所以我们找到tim.c底下进行代码编写

找到user code begin1

因为HAL库代码是软件生成的我们需要按照提示进行编写代码,否则下次生成代码,会消失

intRead_Encoder(uint8_tTIMX){

intEncoder_TIM;

switch(TIMX)

{

case2:Encoder_TIM=(short)TIM2->CNT;TIM2->CNT=0;break;

case3:Encoder_TIM=(short)TIM3->CNT;TIM3->CNT=0;break;

case4:Encoder_TIM=(short)TIM4->CNT;TIM4->CNT=0;break;

default:Encoder_TIM=0;

}

returnEncoder_TIM;}

编码器代码如上,控制周期为10ms

3.电机控制代码

先前讲过电机主要是通过PWM的占空比进行速度控制

所以我们需要编写一个控制占空比的函数

voidsetspeed(intleft_1,intright_1){

if(right_1>0)

{

HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_RESET);//电机方向控制HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET);

}

else

{

HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,GPIO_PIN_SET);//电机方向控制HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_RESET);

}

if(left_1>0)

{

HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_RESET);

HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_SET);

}

else

{

HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_SET);

HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_RESET);

}

if(left_16900)//满速是7200限制速度避免坏电机left_1=-6900;

if(left_1>6900)

left_1=6900;

if(right_16900)

right_1=-6900;

if(right_1>6900)

right_1=6900;

left_1=abs(left_1);//输出占空比一定不能是负值right_1=abs(right_1);

__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,left_1);

__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,right_1);}

稍微讲解一下代码,首先需要对输入的占空比进行判断,是负的还是正的

对电机进行方向控制

后序进行一个限制速率的操作,避免电机太快损坏

由于输出给驱动的占空比一定不是能负数,所以我们还需要一个abs函数取绝对值

__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2,left_1);

就是HAL库设置TIM1通道2的占空比函数

4.陀螺仪

陀螺仪是整个小车的灵魂,但是代码太长不好展示,大家可以去卖家找对应的例程

这里说一下思路就是通过串口不断读取数据

/***************串口中断回调函数数据处理***************/voidHAL_UART_RxCpltCallback(UART_HandleTypeDef*huart){

if(huart->Instance==USART2)

{

USART2_IT_OK=USART2_IT_OK+1;

CopeSerial2Data(jydata);

//陀螺仪数据处理

//加速度a[0]=(float)stcAcc.a[0]/32768*16;

a[1]=(float)stcAcc.a[1]/32768*16;

a[2]=(float)stcAcc.a[2]/32768*16;

//角速度w[0]=(float)stcGyro.w[0]/32768*2000;

w[1]=(float)stcGyro.w[1]/32768*2000;

w[2]=(float)stcGyro.w[2]/32768*2000;

//角度Angle[0]=(float)stcAngle.Angle[0]/32768*180;

Angle[1]=(float)stcAngle.Angle[1]/32768*180;

Angle[2]=(float)stcAngle.Angle[2]/32768*180;

//四元素q[0]=(float)stcQ.q[0]/32768;

q[1]=(float)stcQ.q[1]/32768;

q[2]=(float)stcQ.q[2]/32768;

q[3]=(float)stcQ.q[3]/32768;

HAL_UART_Receive_IT(&huart2,&jydata,1);

}}

5.PID算法代码

PID算法在小车中有很多种

这里使用的是经过推导后的直立环和速度环

要让小车直立这两个环是必不可少的

转向环可以暂时不需要

直立环是让小车具有一个直立的趋势

速度环是让小车在直立的情况下还能在原地不动

转向环是让小车具有走直线的能力

这里的代码借鉴了平衡小车之家的代码

直立环代码

floatBias,kp=100,kd=12;intbalance(floatAngle,floatGyro){

intbalance;

Bias=Angle-3;//===求出平衡的角度中值和机械相关balance=kp*Bias+Gyro*kd;//===计算平衡控制的电机PWM PD控制   kp是P系数 kd是D系数returnbalance;}

单单有直立环是很难直立起来的还需要加入速度环

速度环代码

floatVelocity_Kp=60,Velocity_Ki=0.3;//PID参数intvelocity(intencoder_left,intencoder_right){

staticfloatVelocity,Encoder_Least,Encoder,Movement;

staticfloatEncoder_Integral;

//=============速度PI控制器=======================//Encoder_Least=(encoder_left+encoder_right)-0;//===获取最新速度偏差==测量速度(左右编码器之和)-目标速度(此处为零)Encoder*=0.8;//===一阶低通滤波器Encoder+=Encoder_Least*0.2;//===一阶低通滤波器Encoder_Integral+=Encoder;//===积分出位移积分时间:10msEncoder_Integral=Encoder_Integral-Movement;//===接收遥控器数据,控制前进后退if(Encoder_Integral>10000)Encoder_Integral=10000;//===积分限幅if(Encoder_Integral10000)Encoder_Integral=-10000;//===积分限幅Velocity=Encoder*Velocity_Kp+Encoder_Integral*Velocity_Ki;//===速度控制returnVelocity;}

至于PID的调参,那就是另一门学问了,这里就先不讲解

PID代码里面的一些低通滤波也不做讲解,想要做出来只要会用就行了

至此基本的代码都已经写完,是不是感觉其实平衡小车并不难造

接下来就是控制部分的代码了,要将上面的代码有序的组合起来

合成小车的灵魂

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */

  if (htim->Instance == TIM8) {

    HAL_IncTick();

  }

  /* USER CODE BEGIN Callback 1 */

if (htim->Instance == TIM1) //10khz

{

TIM1_IT_OK = 1;

}

if (htim->Instance == TIM2) //encoder

{

TIM2_IT_OK = 1;

}

if (htim->Instance == TIM3) //encoder

{

TIM3_IT_OK = 1;

}

if (htim->Instance == TIM4) //5ms

{

TIM4_IT_OK = 1;

}

if (htim->Instance == TIM6) //10ms

{

TIM6_IT_OK = 1;

Left_Speed = -Read_Encoder(3);

Right_Speed = -Read_Encoder(2);

Balance_Pwm = balance(-Angle[0],-w[0]);

Velocity_Pwm = velocity(Left_Speed,Right_Speed);

setspeed(Balance_Pwm+Velocity_Pwm,Balance_Pwm+Velocity_Pwm);

}

  /* USER CODE END Callback 1 */

}

这里是HAL库的定时器中断回调函数

因为我设置的是TIM6就在TIM6的中断回调函数中进行编写

注意控制周期是10ms对应陀螺仪的速率一定不能低于100hz不然小车就会一直摇摆。

先读取编码器的数据,自己在操作的时候要调好正负,因为每个人安装都不太一样

平衡小车pid调参后

ok教程到此结

从零开始写STM32平衡小车代码,从0到1相关推荐

  1. Qt系列——炫酷的Qt APP+STM32平衡小车

    一. Qt设计 采用了C++--Qt设计了炫酷的主页面,里面包含了各类仪表widget,其中有个类似钢铁侠的按钮可以触发和控制平衡小车的蜂鸣器.设计的摇杆按钮可以控制前进.后退.左转.右转.蓝牙连接等 ...

  2. 关于STM32平衡小车的几个关键疑问

    引用文章 一.关于姿态融合 首先需要提一点关键的,**如果是采用卡尔曼滤波或者互补滤波,尽可能把采样时间调小,这样可以增加滤波的效果.建议采样时间不要高于10ms,起初我在测试的时候采样时间设置为20 ...

  3. STM32平衡小车学习总结

    目录 STM32f103c8t6引脚功能图: 1. stm32--GPIO工作模式 输入浮空: 输入上拉: 输入下拉: 模拟输入: 开漏输出: 开漏复用功能: 推挽式输出: 推挽式复用功能: 2. 编 ...

  4. PID算法优化(以平衡小车代码为例)

    PID控制 这篇文章是PID控制的进阶说明,如果没有看过PID控制(上)的读者,请先看看PID控制(上),以便更容易看懂这篇文章.关注微信公众号"电子搬砖师"即可阅读PID控制(上 ...

  5. stm32平衡小车(2)-----编码器电机驱动

    前言:之前做arduino小车的时候使用的是L298N电机,没有用过编码器,这次第一次用编码器,还是比较懵圈,记录一下学的整个过程. 1.编码器的简介 霍尔编码器是一种通过磁电转换将输出轴上的机械几何 ...

  6. STM32平衡小车 TB6612电机驱动学习

    TB6612FNG简介 单片机引脚的电流一般只有几十个毫安,无法驱动电机,因此一般是通过单片机控制电机驱动芯片进而控制电机.TB6612是比较常用的电机驱动芯片之一. TB6612FNG可以同时控制两 ...

  7. stm32平衡小车硬件部分

    硬件部分 硬件购买及连接 小车底板 大鱼的,加邮费8块 108 电机驱动 tb6612fng 7.3 (这里要看清VM最大电压多少,可能不同店铺的不一样吧,要最大12V的) 主控 stm32f103c ...

  8. 【STM32平衡小车】电磁巡线技术的发展及电磁巡线介绍(一)

    一.常见的路径识别 路径识别方法主要有两大类,一类是依靠红外光电传感器,一类是依靠摄像头. 红外光电传感器以其体积小.价格低廉.安装灵活方便且不受环 境可见光干扰等特点得到了广泛的应用. 对于该类传感 ...

  9. stm32两轮平衡小车项目详解

    摘要 这个项目是在20年11月初开始的,当时的我很迷茫,本应该去实习的我在线上培训,觉得无聊,便有了自己一人做项目的想法.也没想到这个项目做了将近整整一个月,才差不多做了出来.也是准备做两个项目的,这 ...

最新文章

  1. MusicXML 3.0 (7) - 连线、延音线
  2. 设计模式心得笔记--简单工厂
  3. Kubernetes Deployment与Replica Set
  4. 年过30 ,这10条人生建议句句肺腑
  5. ajax 调用后台的方法
  6. ARP-Address Resolution Protocol-地址解析协议
  7. 发布支持多线程的PowerShell模块 —— MultiThreadTaskRunner
  8. Python函数积累
  9. Java BigInteger类| isProbablePrime()方法与示例
  10. 详解YUV系列(二)--YUV422
  11. word批量替换向下箭头为回车符号、批量删除空行、批量空格与空行
  12. jzoj5424【NOIP2017提高A组集训10.25】凤凰院凶真
  13. 大数据杀熟?苹果回应:定价权在开发者那
  14. Anaconda与ROS共存
  15. 2022保研夏令营经验贴(中科大、华科、武大、国防科大、浙大软件、中科院)
  16. 89c51单片机汇编语言,AT89C2051时钟程序——MCS51单片机汇编程序
  17. 分解质因数C语言实现
  18. vissim跟驰模型_VISSIM,PARAMICS,TSIS仿真软件对比分析 -
  19. 【产品经理】B端产品规划和Roadmap怎么做?
  20. 批量下载“爱书音”有声小说mp3

热门文章

  1. Nexus 7二代 新Nexus 7 中文版ROOT教程
  2. 【MySQL学习】4、MySQL存储过程和函数
  3. 如何在word文档中间插入起始页码!!!
  4. 买卖股票的最佳时机系列
  5. linux怎么运行amd64,Ubuntu 10.04 amd64安装和配置
  6. Airtest 安装及模拟器连接
  7. 手把手Selenium安装使用及实战爬取前程无忧招聘网站(一)
  8. JAVA数据库课程设计—简易网上银行管理系统-java图形用户界面
  9. 封装原声ajax,原生AJAX封装的简单实现
  10. java求圆的周长、面积