LED是一种将电能转换为光能的半导体器件,与白炽灯的钨丝发光与节能灯三基色荧光粉发光原理不同,LED采用的是电场发光,具有体积小、寿命长、光效高、辐射低、功耗低等特点。另外,它可以发出红、黄、蓝、绿、白等颜色的光,在指示标志、广告传媒、舞台背景、市政工程等方面具有广泛的应用。
用MicroPython让计算机显示“Hello,World!”很容易,使用两行代码就可以实现。
【例2.1】 滚动显示“Hello World!”。
打开Mu编辑器,输入如下代码:
from microbit import * display.scroll("Hello,World!")
程序解析如下。
(1)第一行代码用于告知MicroPython,micro:bit需要获取它所有的信息(“*”在Python中表示所有信息),并将这些信息都置于micro:bit模块中。这行代码的意思是需要使用micro:bit代码库中的所有内容。
在程序开发过程中,随着程序代码越写越多,文件中的代码会越来越长,越来越不容易维护。为此,需要把实现不同功能的代码进行分组,然后分别放到不同的文件里,使每个文件包含的代码相对较少。
Python中的.py文件称为模块(Module)或库。
使用模块最大的好处有两个:一是大大提高了代码的可维护性,二是编写代码时不必从零开始,当一个模块编写完毕,就可以在其他地方被引用。
在编写程序时,会经常引用其他模块,包括Python内置的模块和第三方模块。
所有与硬件交互直接相关的文件都存放在micro:bit模块中。为了便于使用,所有编写的程序开头都使用代码from microbit import*。
(2)第二行代码用于告诉MicroPython,使用LED点阵滚动显示字符串“Hello,World!”。
display是micro:bit模块中的一个对象,LED点阵通过display对象显示。
“.”用于告知LED点阵执行的事件,句点后面看起来像是命令,称为“方法”,方法能够有效地控制程序,此处引用的是scroll方法。
由于scroll方法需要知道在LED点阵上滚动什么字符,因此用括号内两个双引号之间的字符来表示,这些字符称为参数。
如果一个方法不需要任何参数,则需用“()”表示。
除了字符串(string)参数外,scroll还可以有其他参数,具体格式为scorll(string,delay=150,wait=True,loop=False,monospace=False),若省略,则为上述默认值。
delay参数决定了文本滚动的速度:按顺序显示图像或字符,并在它们之间设置一个以毫秒为单位的数delay(延迟)。
· 如果wait为True,则此函数将进入阻塞状态,直到显示完成再执行后续的命令,如果为False,则显示将在后台进行。
· 如果loop为True,则显示将永久重复。
· 如果monospace为True,则字符将全部占用5像素的列宽,否则每个字符在滚动时都会有一个空白像素列。
· display的另一个方法是show,对应scroll的基本格式为display.show(string)。
单击“保存”按钮,保存为ex1.py文件。
通过USB线将micro:bit连接到计算机,单击“刷入”按钮,将代码下载到micro:bit上。可在micro:bit的LED点阵上滚动显示“Hello,World!”,如图2.1所示的是滚动显示到字符串中“e”的状态。
图2.1 滚动显示到“e”的状态
(1)想办法改变显示的字符。
(2)让设备向你问好。
(3)在代码display.scroll("Hello,World!")的下一行添加代码display.show("123"),并修改display.scroll()中的参数值值值,下载到micro:bit,观察运行结果,总结这些参数不同值的作用。
对于5×5的红色LED点阵,可以通过MicroPython对显示屏做很多控制,从而生成各种有趣的效果。
MicroPython有大量的内置图像可以显示在屏幕上。
【例2.2】 显示内置HAPPY(笑脸)图案。
编写程序,代码如下:
from microbit import * display.show(Image.HAPPY)
通过display.show(image)显示图像。
具体格式是display.show(iterable,delay=400,wait=True,loop=False,clear=False)。
按顺序显示来自iterable的图像或字母,并在它们之间设置一定的时间间隔delay(单位:毫秒)。
参数wait、loop的作用与scroll相同。
如果参数clear为True,则在显示来自iterable的图像或字母后,将所有的LED亮度设置为0(关闭),相当于执行display.clear()。
除了scroll、show、clear 3个方法外,display还有下面的方法。
· get_pixel( x , y ):将第 x 列和第 y 行的LED亮度以0(关)和9(亮)之间的整数返回。
· set_pixel( x , y ,value):将第 x 列和第 y 行的LED亮度设置为value,该值必须是0~9的整数。
· display.on():调用on()以开启显示。
· display.off():调用off()以关闭显示(允许将与显示相关的GPIO引脚重新用于其他目的,详见第6章)。
· display.is_on():若显示处于开启状态,则返回True,否则返回False。
单击“刷入”按钮,将代码下载到micro:bit上,在micro:bit的LED点阵上显示如图2.2所示。
图2.2 显示“笑脸”图案
下面是一系列内置图像:Image.ANGRY、Image.ARROW_E、Image.ARROW_N、Image.ARROW_NE、Image.ARROW_NW、Image.ARROW_S、Image.ARROW_SE、Image.ARROW_SW、Image.ARROW_W、Image.ASLEEP、Image.BUTTERFLY、Image.CHESSBOARD、Image.CLOCK1、Image.CLOCK2、Image.CLOCK3、Image.CLOCK4、Image.CLOCK5、Image.CLOCK6、Image.CLOCK7、Image.CLOCK8、Image.CLOCK9、Image.CLOCK10、Image.CLOCK11、Image.CLOCK12、Image.CONFUSED、Image.COW、Image.DIAMOND、Image.DIAMOND_SMALL、Image.DUCK、Image.FABULOUS、Image.GHOST、Image.GIRAFFE、Image.HAPPY、Image.HEART、Image.HEART_SMALL、Image.HOUSE、Image.MEH、Image.MUSIC_CROTCHET、Image.MUSIC_QUAVER、Image.MUSIC_QUAVERS、Image.NO、Image.PACMAN、Image.PITCHFORK、Image.RABBIT、Image.ROLLERSKATE、Image.SAD、Image.SILLY、Image.SKULL、Image.SMILE、Image.SNAKE、Image.SQUARE、Image.SQUARE_SMALL、Image.STICKFIGURE、Image.SURPRISED、Image.SWORD、Image.TARGET、Image.TORTOISE、Image.TRIANGLE、Image.TRIANGLE_LEFT、Image.TSHIRT、Image.UMBRELLA、Image.XMAS、Image.YES。
(1)尝试将其他的内置图像在LED点阵上显示,观察效果。
(2)执行代码display.set_pixel(1,1,9),观察效果。
(3)改变display.set_pixel( x , y ,9)中的值,总结 x 、 y 对应LED点阵的位置。
(4)在display.set_pixel(1,1,9)下面两行添加代码temp=display.get_pixel(1,2)和display.show(str(temp)),理解display.get_pixel的作用(get_pixel返回的是整数,函数str()将其转换为字符串,这样display.show才能显示)。
除了在LED点阵上显示内置图像外,还可以在micro:bit上创建自己的图像。
显示器上的每个LED像素可以设置为10个值中的任何一个。如果像素设置为0,表示处于关闭状态,从字面上理解,即为0亮度;而设置为9,表示亮度最强。1~8表示关闭状态(0)和最强亮度(9)之间的亮度级别。
知道这些后,就可以创建一个新图像。
【例2.3】 创建图像“船”。
编写程序,代码如下:
Image类用于创建可以在LED点阵上显示的图像。
给定一个图像,就可以通过display对象的show方法将它显示出来。
对LED点阵起显示作用的每一行数字都在“""”之间并以“:”结尾,每个数字规定一个亮度。
一共有5行,每行有5个数字,对应LED上5行5列共25个LED的亮度值。
通过给定LED显示屏中每个像素的亮度,就可以创建新图像。
实际上,亮度代码不用分行写,可以合并成一行,例如:
boat=Image("09090:09090:09090:99999:09990")
行的结尾除了用冒号表示外,也可以使用换行符(\n)来表示行的结尾,如:
Image("09090\n")
程序运行效果如图2.3所示。
图2.3 自定义图像
(1)尝试使用set_pixel( x , y ,value)自定义“船”图像,并比较它们的不同。
(2)在display.show(boat)前一行添加语句boat=boat.shift_left(1),观察效果。
(3)改变shift_left( n )中 n 的值,包括正值和负值,观察效果。
(4)将shift_left( n )改变为shift_right( n )、shift_up( n )、shift_down( n ),观察效果并进行总结。
在观察景物时,光信号经人眼传入大脑,需经过一段短暂的时间。光的作用结束后,视觉形象并不会立即消失,这种残留的视觉称为“后像”,这一视觉现象称为“视觉暂留”。每个人都有“视觉暂留”,眼睛看到东西后,在0.34s内不会消失。利用这一原理,在一幅图像还没有消失前播放下一幅图像,就会给人造成一种流畅的视觉变化效果。它应用在了人们生活的很多方面,如电视、电影等。
动画是通过把连续图像分解后画成许多瞬间的图像,再用摄影机进行拍摄形成的一系列画面,给视觉造成连续变化的视觉效果。它的基本原理与电影、电视一样。
让静态的图像动起来十分有趣,用MicroPython实现起来相当简单,只需一个图像列表就能实现。只需告诉MicroPython动态显示一系列图像即可,例如内置图像分组Image.ALL_CLOCKS和Image.ALL_ARROWS。
【例2.4】 内置图像动画“时钟”。
编写程序,代码如下:
from microbit import* display.show(Image.ALL_CLOCKS,loop=True,delay=100)
和显示单张图像一样,通过display.show在LED点阵上显示一系列图像。
Image.ALL_CLOCKS包含了Image.CLOCK1~Image.CLOCK12的一组图像。
MicroPython将列表中的图像一个接一个地显示。
通过loop=True控制MicroPython循环显示列表中的图像。此动画会永久循环。
运行程序,动画部分效果如图2.4所示。
图2.4 “时钟”动画
(1)尝试动态显示Image.ALL_ARROWS列表。
(2)如何避免永久循环?
(3)如何改变动态显示的速度?
【例2.5】 自定义“沉船”。
编写程序,代码如下:
程序中创建了6个boat图像,然后将它们放入一个名为all_boats的列表中。
Python知道这是一个列表是因为它们在“[]”中。
列表中的各项用“,”隔开。
MicroPython将列表中的图像逐个显示。
Python可以将任何内容存储在列表中,如["hello!",1.234,Image.HAPPY],包含了字符串、数字和图像。
“沉船”动画的6个画面如图2.5所示。
图2.5 “沉船”动画
(1)如果在display.show(all_boats,delay=200)设置参数loop=True,会发生什么情况,合理吗?
(2)自己制作一个动画。
(3)尝试实现一个淡入淡出的动画效果。
【例2.6】 自定义动画“移动的数字”。
在城市中每天都能够看到各种各样的广告和宣传标语分布在车站、超市、宾馆、饭店等地方。同时,因为各种广告和宣传标语长短不一。人们看到的很多文字都是移动显示的。那么,它是如何实现的呢?可以模拟它实现的过程吗?
想实现数字移动显示,需要利用视觉暂留的原理。刚开始,只在LED点阵屏幕右侧的边缘出现数字左边的部分,然后把出现的部分向左移动一列,随后补齐数字后续需要显示的内容。这样一步一步进行操作,最后从屏幕左侧逐渐消失,就能够实现数字的移动显示。
因此程序实现的功能是,数字最左边一列的内容显示、数字最左边两列的内容显示、数字最左边三列的内容显示……数字最右边三列的内容显示、数字最右边两列的内容显示、数字最右边一列的内容显示、数字完全消失。
编写程序,代码如下:
运行程序,“移动的数字”动画画面如图2.6所示。
图2.6 “移动的数字”动画
(1)如何移动显示数字2?
(2)如何移动显示大写字母A?
(3)如何连续移动显示数字23?