[MSP-EXP432E401Y] [代码分享]MSP432E401 LauchPad驱动MG90S舵机

[复制链接]

2

主题

12

帖子

148

积分

二氧化硅

Rank: 2

积分
148
查看: 617回复: 4 发表于 2021-4-12 16:13:27   只看该作者
本帖最后由 pikka 于 2021-4-12 16:15 编辑

首先感谢TI和培训网在上个月的活动中为广大学子赠送了板卡,为正在准备国赛的同学提供了很大的帮助。
一、背景介绍
MSP432E4系列MCU是是一款主流的高性能 MCU,主频可达120MHz ,拥有USB2.0和百兆以太网等丰富的外设。目前,网络上关于E4系列的分享还很少,因此撰写本文,为竞赛培训网的发展做一些微薄的贡献。根据代码分享活动面向入门者的要求,本文讨论时会尽量贴近初学者的知识范围,增加一些背景知识介绍。
舵机是一种伺服电机,主要用于需要输出某一控制角度的场合,例如机器人的肢体转动、控制航模和船模的舵。舵机可以根据控制信号转动到指定的角度,常见的转动范围有0-90°、0-180°、0-360°,使用时可按需购买。下图展示了两种常用的低成本舵机的图片。关于舵机的更多内容,可以参考这篇文章
从图中可以看到,舵机共有三根引线,其中两根分别是电源和地,第三根则是信号线。舵机一般使用50Hz的不同脉宽的PWM波控制旋转角度,具体到今天我们控制的MG90S舵机,数据手册上标注占空比在5%至10%,对应-90°到90°的旋转角度。
image-20210412141310531.png
现在我们已经知道,只要使单片机输出PWM波即可控制舵机旋转。MSP432E4系列单片机可以通过两种方法产生PWM波,分别是使用PWM外设和通用定时器外设的PWM模式。在这里,我想先花一些篇幅为初学的同学介绍定时器产生PWM波的原理。
定时器外设和PWM外设的内部都有计数器,启动定时器后,在输入时钟源的每一个周期中计数器的值都会增加或减少1(暂时不考虑中央对齐的情况),这两种情况分别称作向上计数和向下计数。以向上计数为例,计数器会从零开始不断增加,直至抵达一个预先设定好的数,然后重新从零开始计数,这称为计数器溢出,设定的值称为装载值(Load Value)。可以发现,可以通过预先设定的数,使得计数器溢出定时发生。例如假设时钟频率是10MHz,装载值是10000,那么计数器溢出的频率就是1KHz。而在PWM输出模式下,我们又另外指定一个值,并规定计数器小于这个值的时候是高电平,大于这个值的时候是低电平(当然反过来也是可以的),通过调整这个值的大小,我们就能控制高低电平的比例,这个值称作匹配值(Match Value)。这两个功能同时作用,就能够得到频率一定的、脉宽可调的PWM波了。

二、项目实战
开发环境:CCSv10, SimpleLink MSP432E4 SDK 4.20.00.12, CCS Compiler, No RTOS
1 引子
承接上文的例子,假如时钟频率是10MHz,要求产生占空比是50%的1KHz的PWM波,可以设定装载值为10000,匹配值为5000,使用Driverlib的函数表达出来就是下面的样子。
  1. TimerLoadSet(TIMER_BASE, TIMER, 10000);
  2. TimerMatchSet(TIMER_BASE, TIMER, 5000);
复制代码

只需要在前后分别添加定时器时钟配置、引脚配置和定时器启动的代码,就能够生成PWM波了,非常简单。
2 预分频值与装载值
但驱动舵机却要复杂一点。舵机使用50Hz的PWM波控制,那么首先要产生50Hz的PWM波。假设MCU工作在120MHz的最高频率,并以系统时钟作为外设时钟源,那么需要的分频系数将是2 400 000,也就是0x249F00,根据上文的结论,我们可以把0x249F00设定为装载值。但是,MSP432E4系列单片机的PWM外设只有16bit的计数器,无法放入这个24bit的数,因此只能使用通用定时器的PWM模式。通用定时器的PWM模式下计数器同样只有16bit,因此还需要使用8bit的预分频(Prescaler)共同构成一个24bit的计数器。
了解过其他单片机的朋友可能对Prescaler并不陌生,在一些单片机,如STM32里面,它的作用是将时钟源的输入频率降低到原来的1/2^n,是一个真正的“分频”器,但在MSP432E4里则完全不是这个样子,预分频器的值代表了一个周期内16bit的计数器满溢(即到达最大值0xFFFF)的次数。举个例子,假设预分频器设置为1,装载值设定为0x2000,那么实际的计数数将会是1*0x10000+0x2000=0x12000。因此,需要的24bit装载值的前8bit放入预分频中,后16bit放入装载值中,即可达到目的。为了提高代码的可重用性,实际的值使用Systemclock变量计算得到,在更改主频时无需另作修改。
  1. uint32_t systemClock;
  2. /* Configure the system clock for 120 MHz */
  3. systemClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |
  4.                                     SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480),
  5.                                     120000000);

  6. /* Period to generate 50Hz PWM */
  7. uint32_t total_period = systemClock/50;

  8. TimerPrescaleSet(TIMER3_BASE, TIMER_B, total_period>>16);
  9. TimerLoadSet(TIMER3_BASE, TIMER_B, total_period&=0xFFFF);
复制代码

3 匹配值
下面来探讨匹配值的设置。通用定时器的PWM模式只允许向下计数,且在默认情况下,PWM输出引脚在计数值小于匹配值时为高电平,大于匹配值时为低电平,结合前文数据手册所述的5%~10%占空比,以角度制表示的匹配值的计算函数如下所示:
  1. /* angle参数取值范围为-90~90 */
  2. uint32_t pwmhigh_period_cal(int angle, uint32_t total_period){
  3.     return (0.025*total_period*angle/90 + 0.925*total_period);
  4. }
复制代码

计算的结果同样是一个24bit的数,分别写入预分频匹配值和匹配值,使用Driverlib的函数代码如下所示。当需要修改匹配值时,只需要重新计算一次匹配值,并同样调用函数更新预分频匹配值和匹配值即可。
  1. /* Initialize the servo to 0° */
  2. uint32_t high_period = pwmhigh_period_cal(0, total_period);
  3. TimerPrescaleMatchSet(TIMER_BASE, TIMER, high_period>>16);
  4. TimerMatchSet(TIMER_BASE, TIMER, high_period&0xFFFF);

  5. TimerEnable(TIMER3_BASE, TIMER_B);
复制代码


4 硬件连接
MG90S 舵机应使用5V供电,因此电源线(红线)连接LaunchPad的5V引脚,地线(棕线)连接GND引脚,本例程使用PA7输出,信号线(橙线)连接PA7引脚,具体连线可参考下面图片。
本程序会首先驱动MG90S舵机转动至0°并保持约3.1秒,随后会在90°和-90°两个角度来回摆动。舵机处于0°、90°和-90°时的状态分别如下图所示。
IMG_20210412_153931.jpg
IMG_20210412_153911.jpg
IMG_20210412_154019.jpg

三、总结
到这里你应该了解了MSP432E4系列MCU控制MG90S舵机的方法了,工程文件和MG90S数据手册见附件。此处再对整个程序流程进行梳理,方便读者理解。
  • 设置系统时钟为 120MHz
  • 使能 GPIOA 外设时钟,将 PA7 配置为 Timer3 的输出引脚
  • 使能 TIMER3 外设时钟,配置 TIMER3 的 TIMER_B 为 PWM 模式
  • 计算与设置预分频值和装载值
  • 计算与设置角度0°时的预分频匹配值和匹配值
  • 启动定时器
  • 计算与设置角度90°时的预分频匹配值和匹配值
  • 计算与设置角度-90°时的预分频匹配值和匹配值

MG90S_MSP432E401Y_Driverlib.zip (275.53 KB, 下载次数: 13)

68

主题

409

帖子

880

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
880
发表于 2021-4-12 17:42:53   只看该作者
很好的分享,谢谢~

2

主题

12

帖子

148

积分

二氧化硅

Rank: 2

积分
148
发表于 2021-4-12 21:46:48   只看该作者
补充两个小点~1. 尽管MG90S数据手册上标注的占空比是5%至10%,某些舵机(例如我的)需要更大的脉宽才能旋转到极限位置。解决的方法是根据自己的舵机情况修改计算匹配值的函数,如下所示
  1. uint32_t pwmhigh_period_cal(int angle, uint32_t total_period){
  2.     return (0.025*total_period*angle/90 + 0.925*total_period);
  3. }
复制代码
数据0.025是根据5%至10%的占空比给出的,假设我希望将占空比调成4%至11%,只需将0.025改为0.035即可。
2. 在附件的工程中,定时器修改匹配值之前会先停止定时器,修改完再启动定时器。这其实是为了方便观察波形,在实际应用中修改匹配值并不需要关闭定时器。

0

主题

6

帖子

1

积分

一粒轻沙

Rank: 1

积分
1
发表于 7 天前   只看该作者
感谢分享

0

主题

2

帖子

23

积分

一粒轻沙

Rank: 1

积分
23
发表于 6 天前   只看该作者
谢谢分享
快速回复 返回顶部 返回列表