硬件配置

在做这个小项目前, 考察过STM32F103C8T6, STM32F401CCU6STC89C52这三个MCU, 并实际跑了一些用例

  • STC89C52在代码上要简单得多, 它的问题是没有ADC功能, 所以无法用于遥控器部分, 只能用于小车部分, 而且PWM输出是软输出, 通过主循环实现的. 带ADC功能的STC单片机型号有STC12C5A系列和STC15F, STC15W系列, 但是现在市场价格都很贵, 单单芯片就需要22RMB.
  • STM32F103C8T6的功能应对这个项目没问题, 在网上这个型号的代码特别丰富, 问题在于现在价格太贵了, 一个原装芯片的最小系统板价格为38RMB, CH版也要25RMB, 相对于高一代且系统板价格仅为15RMB的STM32F401CCU6没有优势.
  • STM32F401CCU6最小系统板价格15RMB, 功能应对这个项目没有问题, 它的劣势是可参考的资料少. STM32F4系列在国内使用的较少, 代码例子在网上少并且很多是针对F407这些高级型号的, 如果用在F401上需要额外的调整.

最终选择的是STM32F401CCU6, 代码上的问题都不是问题, 对吗?

遥控器部分

  • 电源: 3.7V 18650锂电
  • 3.3V稳压: 一个1N4148二极管
  • MCU: STM32F401CCU6最小系统板
  • 输入: 双轴摇杆模块
  • 无线: nRF24L01模块

硬件部分的说明

  • 1N4148能产生0.6V的压降, 对于3.7V的锂电来说是足够的, 实际测试18650两端电压约4.0V, 通过1N4148后输出的电压是3.2V. STM32F401CCU6, nRF24L01和双轴摇杆耗电量都非常小, 1N4148应付这个没问题.
  • 因为单节18650电池盒输出线是裸的多芯软线, 不方便直接连到模块上, 并且因为这部分两个模块nRF24L01和双轴摇杆都需要用到3.3V电压, 所以另外用万能板做了一个中转, PCB接线端子用来连接电源线, 3V3通过一个1N4148后接到3V3的排针上, 另一个排针是地线.
  • 这个接线端子是从炸掉的L9110s模块上拆的

小车部分

  • 电源: 7.4V (18650锂电x2)
  • 6V稳压: 串联两个IN4007
  • 3.3V稳压: AMS1117 3.3V模块
  • MCU: STM32F401CCU6
  • 无线: nRF24L01模块
  • 电机驱动: L9110双路x2
  • 小车底盘
  • 48:1减速电机x4

硬件部分的说明

  • 电机用的是普通的48:1减速电机, 工作电压为6V, 另外L9110s虽然标称能到12V, 市面上的L9110s大部分到不了这么高, 安全电压在7V左右, 所以这里需要将电压降到6V附近, 通过两个1N4007能产生1.2V的压降
  • 运行时每个电机的电流为0.15A, 合计0.6A, STM32F401,nRF24L01的耗电可以忽略不计, 1N4007的工作电流为1A, 应该是够的
  • STM32需要的3.3V和电源电压相差较远, 直接用AMS1117模块做降压了
  • 因为有4个电机, 所以需要两个双通道L9110s模块
  • 电池盒引出的是裸的多芯软线, 不方便直接连到模块上, 因此另外用万能板做了个中间板, 加了接线端子连接电池盒, 正极串联两个1N4007输出到正极排针, 另外还有地线排针, 以及四组排针用于L9110s的输入(各侧的两个通道共用一组PWM)

接线

遥控器部分

MCU需要的接口如下

  • UART: 方便调试

    • PA9 => USB2TTL的RX
    • PA10 => USB2TTL的TX
  • SPI: 连接nRF24L01
    • PA5,PA6,PA7, PB13,PB14,PB15
  • ADC: 两个pin, 连接双轴摇杆
    • PA0 => 摇杆AXIS X
    • PA1 => 摇杆AXIS Y
  • VCC
  • GND

与nRF24L01的接线

STM32 nRF24L01
PA4 SPI1_NSS N/A
PA5 SPI1_SCK SCK
PA6 SPI1_MISO MISO
PA7 SPI1_MOSI MOSI
PB13 IRQ
PB14 CE
PB15 CSN

小车部分

MCU需要的接口如下

  • UART: 方便调试

    • PA9,PA10, 同上
  • SPI: 连接nRF24L01
    • PA5,PA6,PA7, PB13,PB14,PB15
  • PWM: 4个pin, 输出4组PWM, 分别对应左右侧的两组 L9110
    • PA0,PA2: 左侧电机
    • PA1,PA3: 右侧电机

nRF24L01接线同上.

功能实现

遥控器部分

这一块主要是通过两个ADC通道采集摇杆电压, ADC采集使用的DMA的模式, 在主循环中定时(几十到几百毫秒)去读取电压, 并转换到[0, FF]区间, 通过nRF24L01发射出去. ADC采集电压时, 每个通道使用4个u16做缓存, 输出的数值是对这个4个数值做平均, 抑制抖动.

涉及的技术名词: UART, ADC, DMA, TIMER, SPI

小车部分

小车部分的功能有几部分:

  1. nRF24L01的中断接收. 需要将nRF24L01的接收配置为中断模式, 这样只有在遥控端发出指令时, 小车才做相应的动作, 相比在循环中检测接收信息并调整输出的实现方式更及时高效.
  2. PWM输出控制小车的速度和方向.
  3. 将接收得到的X轴Y轴向量, 映射到两路电机的方向和强度.

涉及的技术名词: UART, TIMER, EXTI, SPI, PWM

以下具体说明

nRF24L01的中断接收

这部分需要在STM32上新增一个EXTI中断源, 映射到nRF24L01的IRQ PIN脚. 这个中断是低电平触发, 注意在处理完中断后, 需要清空接收缓冲, 不然下一次还会读到旧值.

中断处理的方法内根据接收到的数值调整PWM输出, 实现遥控功能.

这里还有一个定时器TIM3, 当前设置的定时时间为0.5秒, 每次中断处理时会将定时器初始化, 在定时器经过0.5秒后触发时, 会将PWM输出归零, 归零后电机都会停止. 通过这个机制, 在遥控器发出指令后小车会在当前指令下输出PWM 0.5秒, 如果持续收到指令则持续输出, 如果未收到指令, 则在0.5秒后停止输出, 体现在小车运动上, 就是每次指令下小车会移动0.5秒.

PWM输出控制速度和方向

PWM的频率选择: 48:1减速电机是淘宝上最便宜常见的减速电机, 最佳PWM频率是25Hz-50Hz. 这个频率的来源在这里, 里面有很详细的说明和实验测试结果. 我把我关心的部分内容翻译了一下, 可以看这里. 我在实际使用中观察到的结果是符合这篇文章的结论的.

这里多说几句. 关于电机的PWM频率选择, 在网上查了很久, 得到的结果大部分是错误的, 很多人文章里写的频率是6-20KHz. 这里需要注意区分一下, 如果你用的是直流有刷电机, 那么用这么高的PWM频率是会出问题的, 建议在几十到几百Hz的范围去测试.

PWM控制速度比较好理解, 但是控制方向的具体实现需要通过两个PWM配合. 尝试过通过1路PWM+1路GPIO进行方向切换, 但是无法正常工作, 最后还是要通过两路PWM. 根据方向, 设置其中一路PWM输出为0. 这里为了避免出现双高电平(网上有很多人提到双高导致L9110s烧毁), 在程序中先设置输出为0的一路PWM, 再输出另一路不为0的PWM.

X轴Y轴向量映射到左右两路电机

这一块花了我一些时间. 在网络上找到的资料看, 实现方式更多是通过Y轴计算出左右电机整体的前进后退占空比, 然后通过X轴计算左右电机占空比差值, 再将这两个结果叠加, 得到最后的左右电机占空比. 这个计算方式的问题是当工作点在Y轴区间两端的时候, 此时叠加的差值会使Y轴的值超出区间, 但是实际上这个数值是不可能的, 所以要么将两个通道的数值都往回拉, 要么就忽略Y轴超出区间的部分, 都不是很合理.

我使用的计算方式, 是先规定摇杆圆周4个方向上对应LR通道的值:

  • 0° => L:FF, R:-FF
  • 90° => L:FF, R:FF
  • 180° => L:-FF, R:FF
  • 270° => L-FF, R:-FF

将摇杆得到的XY轴的值做成向量, 将这个向量投影为圆周上某一点, 再根据圆周上这个点两端的值计算当前点的LR值.

因为摇杆得到的XY轴空间, 实际上是一个正方形, 将其映射到圆上时, 有一个有趣的现象, 当角度位于0°到45°时, 向量的长度等于X轴的值, 而在45°到90°时, 向量长度等于Y轴的值, 这个使得计算简便了许多.

遇到的问题

L9110s发热烧毁

电源为两节18650, 电压为3.7x2=7.4V, 两路pwm输出, 当从0,0 -> 0,全速时, 电机无动作, L9110s发烫然后冒烟烧毁. 这个直接导致两个模块各烧了一片L9110s. 于是上网查相关的资料

相关的讨论

因为模块已经带了输出电容和上拉电阻, 所以

可能的原因是

  1. 电机启动电流过大导致模块烧毁. 电机静态电阻为6.5Ω, 电压7.4V时电流超过1A,

    应对方案: 串联一个5Ω的限流电阻, 可以将电流降到7.4/(6.5+5)=0.64A, 避免超出L9110s的最大电流, 运转中的电机阻抗为40Ω - 45Ω, 此时电阻上的分压不到1V, 影响不大.
  2. L9110s耐压超限. 有人说最高到6.5V.

    应对方案: 在L9110s输入电压前串联2个1N4007, 将电压降到7.4-1.4=6V, 串联2个时,启动电流1A,正向电阻0.7Ω, 空转时0.15A,正向电阻5Ω
  3. PWM频率过高. 过高的PWM频率会导致电机在低占空比时无法启动,
  4. PWM同时输出高电平

最终解决方案

  1. 串联两个1N4007将电压降到6.2V
  2. PWM频率降到100Hz

有些占空比下电机不动

在逐渐增大占空比的过程中, 有些值下电机不转, 能听到吱吱声, 如果手摸着L9110s芯片, 能感觉到此时有一阵发烫, 所以此时电流到位了, 但是没能驱动电机.

这个原因和前一个问题是一样的, 因为PWM频率过高(17.5KHz), 无法驱动电机, 在将频率降到100Hz后这个问题就没再出现.

小车在运行一段时间后中断灯常亮, 失去响应

经过检查, 是因为在处理nRF24L01接收中断时, 加入了一个延时1ms的处理, 会卡在这个延时函数上, 将这个延时处理删除后就未再出现这个情况

参考

用STM32F401和nRF24L01制作无线调速小车的更多相关文章

  1. 玩转X-CTR100 l STM32F4 l TB6612直流电机调速控制

    我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 本文介绍X-CTR100控制器的直流调速电机控制,X ...

  2. 直流调速系统Modelica基本模型

    为了便于在OpenModelica进行仿真,形成一个完整的仿真模型,没有使用第三方的库,参照了DrModelica的例程,按照Modelica库的开源模型定义了所用的基本元件模型. 首先给出一些基本类 ...

  3. 过渡与动画 - steps调速函数&CSS值与单位之ch

    写在前面 上一篇中我们熟悉五种内置的缓动曲线和(三次)贝塞尔曲线,并且基于此完成了缓动效果. 但是如果我们想要实现逐帧动画,基于贝塞尔曲线的调速函数就显得有些无能为力了,因为我们并不需要帧与帧之间的过 ...

  4. PLECS_晶闸管调速系统_9w

    3. 直流电机开环调压调速系统模型搭建 (1)电路图 (2)仿真 当 α = pi / 2.7 的时候,直流电机的稳定转速大约保持很低的速度. 随着α的减少,直流电机的速度逐渐增大.当α = pi / ...

  5. 过渡与动画 - 逐帧动画&steps调速函数

    写在前面 上一篇中我们熟悉五种内置的缓动曲线和(三次)贝塞尔曲线,并且基于此完成了缓动效果. 但是如果我们想要实现逐帧动画,基于贝塞尔曲线的调速函数就显得有些无能为力了,因为我们并不需要帧与帧之间的过 ...

  6. 过渡与动画 - 缓动效果&基于贝塞尔曲线的调速函数

    难题 给过渡和动画加上缓动效果是一种常见的手法(比如具有回弹效果的过渡过程)是一种流行的表现手法,可以让界面显得更加生动和真实:在现实世界中,物体A点到B点往往也是不完全匀速的 以纯技术的角度来看,回 ...

  7. [问题解决]不使用PWM调速系统,彻底解决一个L298N带动两个电机却转速不同的问题

    问题描述:由单片机的VCC引脚供电,使用L298N控制两个电机,发现左右两个轮子的转速老是不一样,更多的情况是左轮转速高(左轮电机接OUT1和OUT2),右轮转速低(右轮电机接OUT3和OUT4)甚至 ...

  8. 直流电机PWM调速系统中控制电压非线性研究_控制元件_工业自动化控制_文章

    直流电机PWM调速系统中控制电压非线性研究_控制元件_工业自动化控制_文章_e-works数字化企业网 http://articles.e-works.net.cn/Component/Article ...

  9. 51单片机—使用PWM对直流电机调速

    文章目录 - 什么是PWM - PWM是怎么对直流电机进行调速的 - 通过定时器中断实现PWM调速 - 上代码 - 什么是PWM PWM(脉宽调制),是靠改变脉冲宽度来控制输出电压,通过改变周期来控制 ...

  10. Renix中如何实现流调速——网络测试仪实操

    在Renix操作中有时我们需要进行流调速,那么如何实现呢?接下来为您详细介绍. 第一步:预约测试资源 首先打开Renix软件,连接机箱, 预约端口 第二步:流调速 例如:端口下有3条流,分别设置为10 ...

随机推荐

  1. python3使用json、pickle和sqlite3持久化存储字典对象

    技术背景 在各种python的项目中,我们时常要持久化的在系统中存储各式各样的python的数据结构,常用的比如字典等.尤其是在云服务类型中的python项目中,要持久化或者临时的在缓存中储存一些用户 ...

  2. Laravel - blade 基础语法和include的使用

    <!-- 1. 模板中输出PHP变量 --> @section('footer')    <div style="color:#fff">     @par ...

  3. 常见的IE布局兼容问题

    (1)  div 中内容在IE和火狐中居中问题: (2)高度的问题,div出现重叠 (3)浮动引发的问题如外围DIV无法框住内部元素: (4)IE浮动margin产生双倍距离-display:inli ...

  4. MyBatis04——使用注解开发

    使用注解开发 MyBatis3提供了新的基于注解的配置,但是MyBatis映射并不能用注解来构建. sql类型主要分成: @select @update @insert @delete 注意:利用注解 ...

  5. Nginx双层域名时 iframe嵌入/跳转页面的处理过程

    Nginx双层域名时 iframe嵌入/跳转页面的处理过程 背景 两年前在上一家公司内遇到一个Nginx的问题 当时的场景是 双层nginx代理时(一层域名侧, 一层拆分微服务的网关层) 程序里面会打 ...

  6. [转帖]Docker限制容器的资源

      docker在默认运行容器的情况下,是不会对运行的容器进行资源限制的,在自己的实验环境的话是随便你怎么弄的,不过在生产中是一定会对docker运行的容器进行资源限制的,如果不限制的话在生产中会带来 ...

  7. redis 6源码解析之 sds

    redis使用sds(simple dynamic string)实现了字符串的存储.sds实际上就是TLV格式的数据结构.其数据结构主要分为如下5种,主要分为首部和数据部分,首部给出了type和le ...

  8. vue混入mixin

    <div id="app"> --{{nick11}} </div> <script> // 全局混入 不需要注册 var m1 = Vue.m ...

  9. c#通过表达式树优雅的实现分组取TopN笔记

    需要引入nuget包来实现ef.functions调用row_number Thinktecture.EntityFrameworkCore.SqlServer 调用方式: //顺排 context. ...

  10. VictoriaMetrics源码阅读:极端吝啬,vm序列化数据到磁盘的细节

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu 公众号:一本正经的瞎扯 源码请看:https://github.com/ahfuzhang/vi ...