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亮度控制