【Day19】:PWM输出-模拟类比讯号

PWM-脉冲宽度调变

我相信很多人在使用Arduion的时候还是不清楚PWM到底在干嘛?
PWM是一种可以将类比讯号以数位编码来表示的技术,而表示的方法就是利用高频率的方波,并时时的改变工作周期(duty cycle),达到模拟类比讯号的效果。
https://ithelp.ithome.com.tw/upload/images/20210908/20141525b2RQKT3lFD.png
为什麽这样的波形就可以模拟类比讯号的输出呢?
我们可以用LED来想像,如果波的频率很慢,例如1秒高电位1秒低电位,那我们肉眼就会看到灯泡闪烁,那如果频率超级高呢?例如频率是1MHz,也就是1秒钟高低电位变化一百万次,这已经远远的超出肉眼可以辨识的频率了,此时你就会看到LED的亮度变一半。我们可以调整一个周期内高电位的比率(这也就是duty cycle),如果在一个周期内有90%的时间都是高电位的话,那自然灯泡的亮度就会比较亮。

如何描述一个方波

有两个参数,第一个就是频率,另一个就是工作周期(duty cycle)。假设一个PWM的频率是1kHz、工作周期为30%,那也就是一个波的周期是1ms,而在这一毫秒当中,有0.3ms是高电位。

Arduino的analogWrite输出的就是方波,而他预设的频率为490Hz不太能更动,而我们函式放的参数是0~255,这竟是调整工作周期,255时,工作周期为100%

PWM输出-设定

我们首先打开TIM2、CH1的PWM Output,选哪一个channel都没关系,只是不同channel会对应到不同的脚位(TIM2 CH1的脚位是PA0),一样可以在底下configuration的GPIO setting里面找到。
https://ithelp.ithome.com.tw/upload/images/20210908/20141525kMPLvdranu.jpg
方波的输出是利用timer,我们需要调整三个参数,PSC、ARR、与Pulse,这些参数与timer的使用相同,只有pulse是新的,在预设情形下CNT < Pulse的情况会是输出高电位,反之则输出低电位。
我们首先产生一个频率为1kHz,dutycycle为50%的方波。三个参数的配置如下:
PSC = 15
ARR = 1000
Pulse = 500
=>duty cycle = 500 / 1000 * 100% = 50%

https://ithelp.ithome.com.tw/upload/images/20210908/201415252EfzYtBKYL.jpg

程序

只需要一个函式就可以了!

HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)

把它放在while回圈之前启动一次即可,第二个参数放你要启用哪一个频道,可以为TIM_CHANNEL_1~4,如果要一次启用多个也可以放TIM_CHANNEL_ALL。

HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
while (1)
{
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */

但是问题来了,你要如何知道你有正确输出呢?
有两种方式,一种是你直接拿电表测量,但这种方式你只会测量到平均出来的电压,一般GPIO的输出是3.3V,而我们设定的duty cycle = 50% 因此用电表量出来的电压应为3.3 * 0.5 = 1.65V。但是这种方式并不是很值观的看到我们的输出,也有可能它本身的输出就是1.65V啊。因此这时候我们就需要使用示波器,这真的可以说是一个很好用的工具,重要性不亚於三用电表。他也是我们debug的好工具。
在这里我们就不教学示波器的操作了,它的用法其实与三用电表很相似,只是它测量的频率非常高,并在萤幕上显示波形。底下是用示波器看到PA0这个脚位输出的波形,可以看到频率为1.005kHz,工作周期为49.93%与我们设定的值相当接近。
https://ithelp.ithome.com.tw/upload/images/20210908/20141525GXFX3tV74T.jpg

接下来还有一个问题,我们都知道伺服马达是透过不同的工作周期来调整角度,那我们要控制角度也就是要调整工作周期,因此我们要有办法更改pulse的值。

__HAL_TIM_SET_AUTORELOAD(__HANDLE__, __AUTORELOAD__) 
__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)

第一个函式可以改ARR的值,第二个函式可以修改Pulse的值。这里要注意的是,同一个timer,的ARR值是相同的,也就是说同一个timer,不同频道所产生的方波,频率皆相同。而Pulse则是每个频道独立的,因此我们可以再同一个timer中不同频道产生出不同工作周期的方波。
例如我们要修改TIM2的ARR值为50可以写成:

__HAL_TIM_SET_AUTORELOAD(&htim2, 50);

而我们要修改TIM2的Channel 1的Pulse为50可以写成:

__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,50);

小结

学会这个功能之後,相当於解锁了新的领域,我们可以用来控制伺服马达、步进马达...,PWM的输出难度不大,只要稍微计算一下工作周期ARR、PSC、Pulse,来符合我们要的频率与工作周期即可。明天我们就来实际控制Servo!


<<:  【Day16】:Counter的硬体实现

>>:  【Day22】:旋转编码器—Encoder

Day 16. slate × Interfaces × CustomType

slate 将 typescript 的型别扩充相关的内容都集合在 interfaces/cust...

Endpoint

我们用到的 API endpoint 只有一个,就是用来取得港铁机场快綫、东涌綫、屯马綫及将军澳綫最...

CompTIA Security+ SY0-601 Certification to Enhance Your Career Path

Pass CompTIA Security+ SY0-601 Exam Having CompTIA...

【Day27】Figma篇 : 设计到切版

对於设计师来说使用UI设计软件,除了可以善用之前提到的那些设计工具来增加效率和提升设计方法以外,还有...

【前端效能优化】Lighthouse 检测後将图片转为 webp 格式

原先的网站表现分数只有 74分 更换图片格式後网站表现分数 97分 可以看见最大内容绘制 LCP(L...