1.2. 呼吸灯¶
前一节中我们已经掌握从hiibot_bluefi.basedio中导入LED类,并实例化为led,然后对red和white两个属性赋不同的值,分别实现 红色LED和白色LED的亮/灭控制,或者调用led对象的两个函数:redToggle()或whiteToggle()分别控制红色LED和白色LED的状态切换, 也能达到指示灯闪烁的目的。
如果我们能够改变LED指示灯的亮度,使用LED指示灯输出更多种计算机系统状态,譬如工作状态、空闲状态、故障状态等。这一节我们来学习 控制LED亮度的方法。
我们首先以BlueFi的白色LED为例,实现其亮度控制。BlueFi的白色LED主要作用是为集成光学传感器提供辅助光,根据不同的光照环境, 能够调节辅助光的亮度是基本的需求。
1.2.1. 白色LED的亮度控制¶
我们已经知道REPL可以帮助我们了解一个实体对象的具体属性和函数等信息,我们在执行下面示例程序前,可以首先点击MU编辑器的“串口” 按钮,并在串口控制台窗口按下“Ctrl+C”键,让BlueFi进入REPL模式,在REPL提示符“>>”后输入依次以下语句:
- >>from hiibot_bluefi.basedio import PWMLED
- >>led=PWMLED()
- >>led.
- red white
当输入“led.”再按下Tab键后,REPL将为我们列出led对象的全部属性和函数。显然,PWMLED类的实体对象led仅有两个属性,再无其他接口! 然后,仍在REPL模式输入以下语句,并按“Enter”键后观察白色LED的亮度:
- >>led.white = 100
- 观察白色LED的亮度
- >>led.white = 1000
- 观察白色LED的亮度
- >>led.white=65535
- 观察白色LED的亮度
- >>led.white=0
- 观察白色LED的亮度
现在可以在“>>”提示符后按“Ctrl+D”键退出REPL模式。如果你真的动手试验过,相信你会得到这样的结论:赋予led.white属性的值越大 白色LED灯越亮。当led.white=0时,白色LED灯完全灭掉。
显然,我们能够用程序来控制白色LED灯的亮度,只要赋予led对象的white属性不同的值,亮度随着值的大小变化。这种控制LED亮度的 原理是什么?
1.2.2. PWM¶
PWM, 脉冲宽度调制(Pulse-Width Modulation)的英文缩写。这是一种计算机系统内常用的特殊数字信号,这种信号的形式是方波, 频率是固定不变的,但是高电平的宽度与周期的比值是可调节的,俗称“脉冲(高电平)宽度(可)调变”信号。根据前一节的所知道的, led.white=1时白色LED灯亮,为0时灭。PWM方法调节LED亮度的原理是,以固定的周期,如1000ns,其中500ns让LED亮,500ns让 LED灭,LED的实际亮度为最大亮度的1/2;其中250ns亮,750ns灭,LED的实际亮度为最大亮度的1/4;如果0ns亮,1000ns灭,实际 上LED是灭掉的;如果1000ns亮,0ns灭,实际上LED处于最亮状态;..。
由此,我们可以推断出:PWM控制LED亮度的数学计算如下:
- 亮度 = (高电平的宽度)/(PWM周期) * 最大亮度
当高电平的宽度刚好等于PWM周期时,LED最亮;当高电平的宽度为0时,LED灭;当高电平宽度为PWM周期的1/4时,LED亮度就是最大亮度的 1/4。
在hiibot_bluefi.basedio模块的PWMLED类中,PWM周期固定为1ms(正好1000ns),每一个周期被分割为2^16(即65536)份,也就是所说 PWM信号的高电平宽度定义为“v*(1000ns/65536)”,当v=65535时,高电平宽度几乎等于PWM信号的一个周期(即LED最亮)。我们习惯上把 这里的“v”称作占空比,其有效的取值范围为:0~65535。
至此,你能与REPL模式下执行”led.white=v”时随着v的大小亮度随之变化的规律对上了吗?
1.2.3. 红色LED的亮度¶
打开MU编辑器,将下面的程序复制-粘贴到MU编辑器中,并保存到/CIRCUITPY/code.py文件,让BlueFi执行这个示例的程序,观察红色LED 亮度的变化规律:
1 2 3 4 5 6 7 8 9 10 | import time from hiibot_bluefi.basedio import PWMLED led = PWMLED() b=0 while True: led.red = b b = b+655 if b>65535: b=0 time.sleep(0.01) |
仔细观察本示例程序的执行效果,感觉到BlueFi在给你眨眼了吗?红色LED灯的亮度逐渐编导最亮,然后立即熄灭,再逐渐变为最大,如此往复。 为什么有这种效果?下面我们逐行来分析每行脚本程序的效果。
示例代码分析:
- 第1行,导入一个Python内建的模块“time”
- 第2行,从“/CIRCUITPY/lib/hiibot_bluefi/basedio.py”模块中导入一个名叫“PWMLED”的类
- 第3行,将导入的“PWMLED”类实例化为一个实体对象,名叫“led”
- 第4行,声明一个变量“b”,并赋值0
- 第5行,开始一个无穷循环的程序块
- 第6行(无穷循环程序块的第1行),led对象的red属性(led.red)设置为变量b的值
- 第7行(无穷循环程序块的第2行),将变量b的值增加655
- 第8行(无穷循环程序块的第3行),判断变量b的值是否大于65535
- 第9行(无穷循环程序块的第4行),如果b>65535,则b=1
- 第10行(无穷循环程序块的第5行),执行time的sleep方法,参数为0.01秒(即10ms)
这个示例中,我们在无穷循环的程序块中不停地将变量b增加655,一直增加到b>65535之后再把b重新赋值为0,如此重复,而且每重复一次就 把b的值赋给led对象的white属性。
变量,允许在程序中改变的量!在本示例中,变量b的值不停顺序取{0, 655, 1310, .., 41920}数据集中的一个值,并把这个数值当作 红色LED的占空比赋值给“led.red”属性。红色LED亮度的变化规律正好与数据集中的数值变化规律一致。
1.2.4. 呼吸灯¶
以下示例的程序执行结果具有特殊的医学效果:催眠。运行本示例程序时,切勿直视BlueFi的白色LED,直视白色LED太久,你可能会被催眠。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import time from hiibot_bluefi.basedio import PWMLED led = PWMLED() b=0 d=1 while True: led.white = b b += 655 if d==1 else -655 if b>65535: b=65535 d=0 if b<0: b=0 d=1 time.sleep(0.01) |
你被催眠了吗?这个示例程序的执行效果俗称“呼吸灯”。白色LED的亮度从灭逐渐变为最亮,然后又逐渐灭掉,如此重复。这样的周期如果正好与 你的呼气-吸气的周期一致,据说很容易把你催眠。
这段程序能够让白色LED亮度随着我们呼吸节奏改变亮度,其中的关键之处是变量b的变化规律。第8~14行程序都是在增加或减少b变量的值。你能 列举出变量b取值的完全数据集?
你能用一句既贴切又合适的话来概括变量b的变化规律?
总结:
- PWM信号
- PWM信号的周期、频率和占空比
- 实体对象的属性赋值
- 变量
- 变量赋值
- 变量自增/自减
- 本节中,你总计完成了14行代码的编写工作
重要
PWMLED类的接口
- red (属性, 可读可写, 有效值:0~65535), BlueFi红色LED亮度控制
- whilte (属性, 可读可写, 有效值:0~65535), BlueFi白色LED亮度控制