【.NET 与树莓派】PWM 调节LED小灯的亮度
在开始本文内容之前,老周先纠正一个错误。在上一篇中,提到过 Arduino 开发板的 Vin 引脚,文中老周说这个供电口的输入电压不能高于 5.5V。这里有错,被卖家给的使用说明忽悠了,上 Arduino 官网看了一下说明和原理图,Vin 引脚的有效电压是 7 - 12V,和DC输入口一样;输入电压不能高于 5.5V 的是 5V 引脚。5V 引脚既可以为元器件供电(输出),也可以向这个引脚输入 5V 电压为开发板供电。
=========================================================================================================
本篇文章最后会完成一个很简单的实验,这个实验基本是电子实验中最经典的,被许多教程重复了几亿次。尽管是个老掉牙的实验,但该实验简单,而且有代表性。啥实验?就是标题上写着的,调节LED小灯的亮度。
当然了,不是你家里装的LED大灯泡,以开发板输出的功率,是不能点亮那种大灯泡的。咱们实验用的一般是发光二级管,如下面高清无码大图所示。
这个玩意儿很便宜,一两块钱能买到一堆,非常适合我们这种待脱贫人群的日常把玩。当你拿到这个玩意儿的时候,你可能会有一个疑问:这货有两个脚 ,没有标注正负极,我怎么区分呢?不知道你有没有仔细看,这货其实是国家三级残疾的,一条腿长,一条腿短,医学上叫啥来着,忘了。人家生产商是故意让它残疾,然后领养它的人就知道怎么照顾它了——长的那条腿是正极(阳极),短的是负极(阴极)。现在明白乎?
还有一种是四条腿的,分为“三长一短”和“三短一长”,咋理解?先看图。
这种叫 RGB 发光二极管,实际上和两个脚的是一样的,只是它分了蓝、绿、红三种颜色的光,然后三种光以不同亮度混合,可以组成各种颜色。“三长一短”就是 R G B 三个脚是正极,短的那个是负极,也就是说它们共一个负极,叫共阴;“三短一长”就是 R G B 三个脚是负极,长的那个是正极,即它们共用一个正极,叫共阳。
发灯二极管不同的颜色所需电压有差异,一般是 2.0 - 2.2 V,电压上下有波动没关系,烧不了,但是过高了就会烧。经老周实测,二极管如果不接电阻直接供 5V 就很危险,发热严重,3.3 V 情况相对好一点。但是,电阻肯定要加的,保险一点嘛,当然也不用加 1k 那么恐怖,200 Ω 左右就可以了。
你可以选可调电阻,这样比较灵活,就像这种,也很便宜。
这种电阻顶部有个螺丝,用“一”字螺丝刀旋转可以调节电阻。这种便宜,所以没有可视屏幕,可以用万用表来测电阻。你会发现电阻上面有三个脚,老周画了一个模拟图。
中间的 C 点类似个滑块,通过顶部的旋转螺丝,AC,CB两段的电阻会改变。假设这个电阻的最大阻值为 200 Ω,那么:
1、A、B 两端相接,其阻值就是固定的 200 Ω;
2、A、C 两端相接,可旋转螺丝来调节电阻大小,假如调节为 50 Ω;
3、B、C 两端相接,也可以通过旋转螺丝来调节阻值;
4、A-C 与 B-C 两段的电阻之和等于最大阻值,所以:若 A-C为160Ω,那么 B-C 段阻值为 200-160 = 40Ω。
以上计算为理论数据,使用万用表检测,会存在几欧姆的误差。
接下来咱们要了解一个概念—— PWM,全称为 Pulse Width Modulation,可译为“可调制脉冲”。在前面的烂文中,老周提过,GPIO 通信时输出两个状态信号,还记得不?哦,猜对了,就是高电平和低电平。好,现在你想一下,如果一个 GPIO 接口以一定的频率不断地输出电平信号,会发生什么?是不是会产生如下图所示的波形?
其中,突起来的就是高电平,与横轴重合的是低电平,由于通信接口只使用两个电平信号,于是发生的波形就成了方波。
方波的周期,也就是一秒钟内有多少个周期,就是我们常说的频率,单位是 Hz。例如,某脉冲方波的频率为 50 Hz,即一秒钟内循环50次,那么,每个周期的时长为 1 / 50 = 0.02 秒,合 20 毫秒。
既然脉冲中一个周期内可以输出高电平或低电平,那么,高电平与低电平两者所占用的时间,就形成另一个名词——占空比。用一句话解释,就是:高电平持续的时间占整个周期的百分比。
沿用上文的举例,若周期是 20 毫秒,如果高电平持续的时间为10毫秒,那么占空比 = 10/20 = 50%;如果高电平持续的时间为 15 毫秒,那么占空比 = 15/20 = 75%,低电平占用的时间比就是 25%。但占空比的定义是关注高电平的持续时间。
咱们这一次调节发光二极管亮度的实验就是用到 PWM。当然,调节电压或电阻也能改变亮度,不过开发板自身可不能改变电压和电阻,可以用一些稳压模块来调节。
为什么脉冲可以改变灯的亮度呢?回想一下,前面咱们聊过,对开发板而言,高电平的电压是 3.3V,低电平是 0V。接到二极管正、负两脚上的电压如果相等,由于没有电势差,不产生电流,灯就熄灭;反之,存在电势差,有电流通过,灯就亮。
情形1:二极管的正极接 GPIO 口,负极接 GND (接地,始终是低电平,相对 0V 电势)。此时,如果GPIO口输出高电平,与 GND 之间存在对0V的电势差,二极管发光;反过来,如果GPIO口输出低电平,那么,0V与GND的0V位于同一参考值上,没有电势差,二极管不亮。
情形2:二极管的正极接 3.3V(供电接口始终输出高电平),负极接GPIO口。如果GPIO口输出低电平,就相当于GND的作用了,有电流通过,灯亮;如果GPIO口输出高电平,也是 3.3V,与供电口的相对电平相同,没有电势差,无电流通过,灯灭。
现在入重点了,高电平灯亮,低电平灯灭,那么高、低电平交替输出呢?也就是高 - 低 - 高 - 低 - 高 - 低……那灯就会一亮一灭,也就是在闪。但是,由于灯从亮到灭的过程会有很短的个延时,如果这延时足够短,人的眼睛就看不到灯的闪烁(不知道猫眼能不能看到),视觉延迟导致反应不过来,就没感觉了。所以,用PWM调亮度时,频率不要太低,50 - 60 Hz 明显看到闪烁;选 100-200 Hz 比较好,频率太高了效果也不好,频率高到比灯熄灭的延时还短的话,就等于灯是一直有充足的电流可用,这样它就不会暗下来了,调节亮度就没效果了。
上面说的都是基本理论,下面咱们动手干活。
先要看看在树莓派上怎么配置 PWM 功能。配置文件依然是 /boot 目录下的那个 config.txt。下面是文档说明:Name: pwm
Info: Configures a single PWM channel
Legal pin,function combinations for each channel:
PWM0: 12,4(Alt0) 18,2(Alt5) 40,4(Alt0) 52,5(Alt1)
PWM1: 13,4(Alt0) 19,2(Alt5) 41,4(Alt0) 45,4(Alt0) 53,5(Alt1)
N.B.:
1) Pin 18 is the only one available on all platforms, and
it is the one used by the I2S audio interface.
Pins 12 and 13 might be better choices on an A+, B+ or Pi2.
2) The onboard analogue audio output uses both PWM channels.
3) So be careful mixing audio and PWM.
4) Currently the clock must have been enabled and configured
by other means.
Load: dtoverlay=pwm,<param>=<val>
Params: pin Output pin (default 18) - see table
func Pin function (default 2 = Alt5) - see above
clock PWM clock frequency (informational)
这些文档最大的缺点是说得不清不楚,让你雾里看花,水中捞月。不过,根据文档的描述,树莓派有两路 PWM 引脚,所以以下这段很关键。
Legal pin,function combinations for each channel:
PWM0: 12,4(Alt0) 18,2(Alt5) 40,4(Alt0) 52,5(Alt1)
PWM1: 13,4(Alt0) 19,2(Alt5) 41,4(Alt0) 45,4(Alt0) 53,5(Alt1)
树莓派有 GPIO 0 到 GPIO 27,所以:
Legal pin,function combinations for each channel:
PWM0: 12,4(Alt0) 18,2(Alt5)
PWM1: 13,4(Alt0) 19,2(Alt5)
第一路 PWM 是引脚 GPIO 12 和 GPIO 18,板上的序号是 32、12;
第二路 PWM 是引脚 GPIO 13 和 GPIO 19,板上的序号是 33、35。
此处只需要调节一个灯,所以开启第一路 PWM 就可以。
说一下这些参数的含义,12,4(Alt0),表示使用 GPIO 12,后面的4要按说明来配置,此处就是数值 4 表示 Alt0。前面的文章中提过,为了扩展 GPIO 的功能,会定义引脚的重用(或叫复用),即你指定不同的 Alt 就会启用对应的功能。
老周手上这块 4B,用 GPIO 12 无法产生 PWM,串联万用表检测不到电流,只有 GPIO 18 能用。其他版本不知,因为老周没有买齐所有树莓派版本。所以大家可以多试试,反正第一路 PWM 只有 GPIO 12 和 GPIO 18 两个口,不行就换一个。
使用 Linux 自带的 Nano 应用打开 config.txt 文件。
cd /boot
sudo nano config.txt
记得加 sudo ,作用就不说了。
然后加上:
dtoverlay=pwm,pin=18,func=2
GPIO 18 启用 PWM 的 Alt 是 Alt5,所以 func 参数的值是2(参考刚刚上面说的),因为这个是所有树莓派版本默认支持的配置,故可以省略参数。
dtoverlay=pwm
按 Ctrl + X,退出,nano 提示是否保存,输入 Y,搞定。
下一步看看.NET 相关 API。
命名空间:System.Device.Pwm。
类:PwmChannel。
这是个抽象类,内部会根据平台实现不同类型,为了统一调用,公开一个静态方法——Create,定义如下:
static PwmChannel Create(int chip, int channel, int frequency = 400, double dutyCyclePercentage = 0.5);
chip 参数常为 0,即第一块控制芯片,channel 是第几路PWM通道,树莓派有两路,所以此参数可以用 0 或 1。本次咱们用的是第一路,所以值是 0。frequency 是频率,默认400 Hz。dutyCyclePercentage 是占空比,0.0 到 1.0,表示 0% 到 100%,默认 0.5(50%)。
调用这个静态方法后,得到一个 PwmChannel 实例,调用实例对象的 Start 方法就可以开始发生脉冲方波了,调用 Stop 方法停止脉冲。另外,Frequency 属性改变频率,DutyCycle 属性改变占空比,这两个属性都可以在 PWM 运作期间直接修改,不必重新 Start。
而咱们这次的调光实验就是通过改变占空比来实现的。占空比为 0%,始终是低电平,灯灭;占空比是 100% ,始终输出高电平,灯最亮;而亮度的改变就在 0% - 100% 之间的值。
代码灰常简单,老周直接上,你能看懂的。
PwmChannel pwmch = PwmChannel.Create(0, 0, 100, 0.0);
// 开始PWM
pwmch.Start();
int x = 5;
while(x-- > 0)
{
for (int i = 0; i < 100; i++)
{
pwmch.DutyCycle = i * 0.01d;
Thread.Sleep(20);
}
for (int i = 100; i > 0; i--)
{
pwmch.DutyCycle = i * 0.01d;
Thread.Sleep(20);
}
}
pwmch.Stop();
pwmch.Dispose();
DutyCycle 属性的有效值是 0.0 - 1.0,所以整型的百分比乘以 0.01,让它变成有效值。
接线方法:二极管的长脚(正)接 GPIO 18 引脚,短脚(负)接 GND(有很多个,随便挑一个),在 GPIO18 和二极管正极之间串联一个 200 欧姆的电阻。
最后,发布、上传,运行,效果类似于呼吸灯。
示例的代码链接,请用电钻扎这里。
调节小灯的亮度只是 PWM 的其中一个用途,该技术还有很多玩法。比如可以控制舵机的旋转角度,控制小风扇的转速,控制玩具喇叭唱歌(频率不同可以产生不同的音高)…… 下一篇烂文老周将介绍如何用 PWM 让小喇叭高歌一曲过大年。
【.NET 与树莓派】PWM 调节LED小灯的亮度的更多相关文章
- 单片机与android手机通信(控制LED小灯亮灭)
1.单片机实验板功能设计 为验证数据通信内容,让单片机板上的四个按键与android手机客户端上的四个LED灯相互控制:为达到上述基本实验要求,采用单字符传输数据即可,硬件需设计两块相同的单片机电路板 ...
- 嵌入式Linux LED小灯点亮实验
问:怎么写LED驱动程序? 1.搭建一个字符驱动的框架(上一节已经完成) 2.完善硬件的操作 问:驱动里操作硬件寄存器与单片机操作硬件寄存器有什么不一样的地方? 答:单片机操作的寄存器地址是物理地址, ...
- 浅浅的分析LED呼吸灯的实现和PWM的关系
前言 在本周,我们在python课上做了一个实验,用ARDUINO使小LED灯模仿出呼吸灯的效果,实验进行的很成功,但是机器当仅输出高/低电平的时候是怎么样才能做到渐亮渐暗(输出电压)的变化呢?在这里 ...
- 树莓派点亮LED灯需要几行代码?3行。小孩子都能学会
目录 点亮LED灯 硬件连接 代码 闪烁的LED灯 呼吸灯 其他 点亮LED灯 硬件连接 找一个LED灯,连接如上图,注意长短引脚,经过这些年的狂轰乱炸,大家对于这个应该不漠视,毕竟Arduino都进 ...
- 树莓派GPIO开发(二)RGB模块-PWM调节
配置环境 系统:Raspbian11(官方64位) 设备:树莓派CM4 一.PWM简单介绍 全称:Pulse-width modulation,脉冲宽度调制,简单的数模转换方法 1.基本原理 脉冲宽度 ...
- 树莓派GPIO开发(三):蜂鸣器-PWM调节
配置环境 系统:Raspbian11(官方64位) 设备:树莓派CM4 一.写在前面 关于PWM的基本介绍在上一篇博客已经说过了:树莓派GPIO开发(二)RGB模块-PWM调节 在RGB模块中,我们主 ...
- 树莓派GPIO控制LED彩灯
树莓派使用GPIO接口来控制LED灯,自制五彩炫光的节日彩灯. 1.硬件准备 a. 树莓派(Raspberry Pi)一个 b. 彩色RGB二极管 c. 杜邦线 d. 5V电源引脚 以上所有零件均可在 ...
- 学习笔记——单片机简介 & 点亮LED & 流水灯 & 电路基础【更新Ing】
视频地址:https://www.bilibili.com/video/av10765766 超详细!!!!!! 单片机内部三大资源 [资源:单片机可提供使用的东西] FLASH 可以重复擦写 断电后 ...
- 第一个FPGA工程—LED流水灯
这一章我们来实现第一个FPGA工程-LED流水灯.我们将通过流水灯例程向大家介绍一次完整的FPGA开发流程,从新建工程,代码设计,综合实现,管脚约束,下载FPGA程序.掌握本章内容,大家就算正式的开始 ...
随机推荐
- [SSL]在线检查服务器HTTPS安全
https://myssl.com/ SSL/TLS安全评估报告 https://www.ssllabs.com/ssltest/ SSL Server Test HTTPS开启工具(IIS) htt ...
- kubernets之服务资源
一 服务集群内部或者客户端与pod的通信桥梁 kubernets集群的内部pod访问为啥不能使用传统的IP:PORT的形式? pod是短暂的,它们会随时启动或者关闭,原因可能是pod所在的节点下 ...
- ctfhub技能树—彩蛋
彩蛋题建议大家首先自己动手去找一找 做 好 准 备 后 再 看 下 文 ! 1.首页 使用域名查询工具查询子域名 2.公众号 此题关注ctfhub公众号即可拿到,不过多赘述. 3. ...
- 使用SimpleUpdater实现现有程序升级功能
项目:https://github.com/iccfish/FSLib.App.SimpleUpdater C/S程式一般需要部署在多台机器上,如果程式有变动,需要一台一台重新安装,相当麻烦,如果我们 ...
- Oracle Rac to Rac One Node
=~=~=~=~=~=~=~=~=~=~=~= PuTTY log 2020.01.14 20:05:12 =~=~=~=~=~=~=~=~=~=~=~= [oracle@rac01 ~]$ srvc ...
- 力软最新版本与.netCore版本
功能强大,直接上图: 加微信或QQ交流开发技术:25489181 netcore版本 版本优势: .NET Core是适用于 Windows.Linux 和 macOS 的免费.开源托管的计算机软件框 ...
- win32 sdk 环境下创建状态栏
今天在学习状态栏,出了好多的问题,这里记录下. 要创建状态栏用:CreateStatusWindow CreateStatusWindow函数创建一个状态窗口,通常用于显示应用程序的状态.窗口通常显示 ...
- Redis连接池的相关问题分析与总结
https://mp.weixin.qq.com/s/juvr89lAvM0uuDmyWyvqNA 阿里干货课堂丨Redis连接池的相关问题分析与总结 原创 技术僧 Java进阶与云计算开发 2018 ...
- 如何设计一个亿级网关(API Gateway)?
1.背景 1.1 什么是API网关 API网关可以看做系统与外界联通的入口,我们可以在网关进行处理一些非业务逻辑的逻辑,比如权限验证,监控,缓存,请求路由等等. 1.2 为什么需要API网关 RPC协 ...
- 详解Go中内存分配
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 本文使用的go的源码15.7 介绍 Go 语言的内存分配器就借鉴了 TCMalloc 的 ...