💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[Toc] # 第11章 micro:bit 今天,墨博士向小墨介绍了一种开发板:micro:bit,这是一种可以使用Python直接操作的硬件。在本章中,墨博士就向小墨展示了Python操作micro:bit的方法,并做出了几个小应用,一起来看看吧。 ## 11.1 micro:bit是什么 墨博士:小墨,你来看这是什么东西? ![](http://p7moyixbi.bkt.clouddn.com/%E5%9B%BE11.1.jpg) 图11.1 micro:bit 小墨:这个……,没见过。 墨博士:这个东西叫micro:bit,是一款由英国广播电视公司(BBC)推出的专为青少年编程教育设计的微型电脑开发板。我看很不错,就入手了一个,正好咱们可以一块玩玩。 小墨:这个micro:bit能做什么呀? 墨博士:你可别小看它。它虽然很小,但集成了种类丰富的电子模块:5x5的LED显示屏,两颗可编程按键,加速度计,电子罗盘,温度光线传感器等。 ![](http://p7moyixbi.bkt.clouddn.com/%E5%9B%BE11.2.png) 图11.2 micro:bit电子模块介绍 小墨:这么强大呢! 墨博士:除了自身集成的电子模块外,它还能外接很多电子元件,让你轻松完成如电子游戏、遥控小车、音乐播放、可穿戴设备等场景下的开发。 小墨:厉害厉害!那这个东西到底怎么玩呢? ## 11.2 micro:bit在线开发平台 墨博士:micro:bit的常用开发方式有两种。一种是使用MakeCode,这是微软为micro:bit提供的在线编程平台,如下图11.3所示。 ![](http://p7moyixbi.bkt.clouddn.com/%E5%9B%BE11.2.png) 图11.3 MakeCode在线编程平台 它最大的特点是提供了图形化的编程方式,让新手也能很快上手制作出一些好玩的程序来。 另一种方式是使用PythonEditor,这也是一个在线编程平台,如图11.4所示。 ![](http://p7moyixbi.bkt.clouddn.com/%E5%9B%BE11.4.png) 图11.4 PythonEditor在线编程平台 从PythonEditor的名字就可以看出,这个编程平台其实就相当于一个Python的编辑器,也就是说它使用Python作为开发语言。这是它与MakeCode最大的区别。 **注意**:严格来说PythonEditor使用MicroPython而不是Python作为开发语言,而MicroPython可以看做是Python语言应用在硬件领域的特殊版。 > 墨博士提醒:你可能需要使用最新版的谷歌浏览器chrome来访问PythonEditor。 小墨:我们今天用哪种方式呢? 墨博士:你已经学习了很多Python的知识,可以直接选择第二种方式了,代码的方式也比图形化的方式更灵活、更强大。 小墨:好,正好练练手。不过我们编写的程序如何运行到micro:bit上去呢? 墨博士:首先通过usb线将micro:bit连接到你的电脑上,此时电脑中多了个MICROBIT的盘符。如图11.5所示。 ![](http://p7moyixbi.bkt.clouddn.com/%E5%9B%BE11.5.png) 图11.5 micro:bit连接上电脑后,就跟插了一个U盘一样 然后你看PythonEditor的左上角有个download按钮,它的作用是将你编写好的代码转成micro:bit能识别的格式并下载下来。下载好后把下载的文件直接拷贝到MICROBIT磁盘中,这样你写的程序就自动运行起来了。 小墨:哦,那如果我写了好多个程序呢? 墨博士:当新的程序被拷贝到MICROBIT磁盘后,micro:bit就开始运行新的程序了,这个过程就相当于新程序把老程序给覆盖了,也即同一时刻只能运行一个程序。 好了,我们实际来操作一下,看看这个平台的使用。 ## 11.3 micro:bit的使用 老规矩,我们还是从micro:bit的Hello World说起。 ### 11.3.1 Hello World 在PythonEditor中编写如下代码: ``` from microbit import * display.scroll("Hello, World!") ``` 第1句表示将microbit中的所有内容全部导入。这个microbit就是MicroPython中自带的操作micro:bit的库。 第2句的表示在显示器上滚动显示字符串“Hello,World!”。 编写好代码后可以在右侧输入框中输入一个名称,比如我这里写成hello,如图11.6所示。 ![](http://p7moyixbi.bkt.clouddn.com/%E5%9B%BE11.6.png) 图11.6 在PythonEditor中编写代码并保存为hello 这个名称将作为你下载或保存的文件的名称。 点击download按钮,就会下载一个hello.hex文件,将此文件拷贝到MICROBIT磁盘中,就可以在micro:bit上看到程序的运行结果了。 除了scroll外,另外一个常用来显示字符的方法是show(): ``` display.show("Hello, World!") ``` 它和scroll的区别是scroll是滚动显示“Hello, World!”的每个字符,而show是逐个显示“Hello, World!”中的每个字符。 > 动动手:动手实际操作比较下scroll和show的区别。 ### 11.3.2 内置图案 除了字符外,还可以显示一些小图案在屏幕上。MicroPython内置了很多小图案,比如: ``` from microbit import * display.show(Image.HAPPY) ``` 就用于在屏幕上显示一个笑脸。运行结果如图11.7所示。 ![](http://p7moyixbi.bkt.clouddn.com/%E5%9B%BE11.7.png) 图11.7 笑脸显示在micro:bit的显示器上 其他常用内置小图案有: ``` # 内置图案 Image.HEART Image.HEART_SMALL Image.HAPPY Image.SMILE Image.SAD Image.CONFUSED Image.ANGRY Image.ASLEEP Image.SURPRISED Image.SILLY Image.FABULOUS Image.MEH Image.YES Image.NO …… ``` ### 11.3.3 自定义图案 小墨:博士,除了能显示这些内置的图案外,我们自己能控制屏幕上的这25个LED灯吗?如果可以的话我们就能自己画一些图案出来了。 墨博士:你想画什么呢? 小墨:我想画一辆坦克,或者一挺冲锋枪。 墨博士:自定义图案,使用类似如下代码: ``` from microbit import * my_img = Image("00900:00900:09990:09990:09990") display.show(my_img) ``` my_img就是我们自定义的图案了。这里的“00900:00900:09990:09990:09990”就对应25个LED灯,每五个一组,一共分五组。每个LED对应的数字可以取0~9中的任意一个,表示LED的亮度。数字越大表示越亮,数字为0表示灯是暗的。 上述的“00900:00900:09990:09990:09990”其实就是一个坦克的图案,如图11.8所示。 ![](http://p7moyixbi.bkt.clouddn.com/%E5%9B%BE11.8.png) 图11.8 自定义坦克图案 > 动动手:请帮助小墨显示一挺机枪的图案出来。 ### 11.3.4 动画 墨博士:小墨,你听说过逐帧动画吗? 小墨:听墨哥哥说过。据他所说,有些动画片就是一帧一帧画出来的。 墨博士:如果我们在micro:bit的显示屏上交替显示两种图片,也就变成了逐帧动画了: ``` from microbit import * my_img_0 = Image("00900:09990:00900:09090:90009") my_img_1 = Image("00900:09990:00900:00900:00900") img_list = [my_img_0, my_img_1] display.show(img_list, delay=500, loop=True) ``` 你来运行一下,看看效果。 小墨:一个小人儿走路的动画!这个跟红绿灯路口人行道交通灯中的小人儿差不多。如图11.9和11.10所示 ![](http://p7moyixbi.bkt.clouddn.com/%E5%9B%BE11.9.png) 图11.9 站立的小人儿 ![](http://p7moyixbi.bkt.clouddn.com/%E5%9B%BE11.10.png) 图11.10 行走的小人 墨博士:来看看实现的过程:show()的第一个参数是两个图案组成的list;第二个参数delay=500表示两张图的替换间隔,单位是毫秒,一秒等于一千毫秒;第三个参数loop=True表示两张图一直交替显示,就相当于死循环。事实上,我们确实也可以使用死循环来制作这种动画效果。 比如我们来模拟一个萤火虫的发光过程:把这25个LED灯整体看做是一个萤火虫,然后让它逐渐从暗到亮,到最亮后再逐渐从亮到暗,如此反复。 分析一下:萤火虫从暗到亮,其实是LED灯对应的数字由“00000:00000:00000:00000:00000”变成“11111:11111:11111:11111:11111”、“22222:22222:22222:22222:22222”,然后再逐渐变成“99999:99999:99999:99999:99999”的过程。萤火虫从亮变暗的过程反之。我们可以先定义一个函数,用于产生这些数字: ``` def get_image(n): result = '' for i in range(5): for j in range(5): result += str(n) result += ':' return result[0:len(result)-1] ``` 这里的参数n就是LED灯的亮度,可以打印测试一下: ``` print(get_image(1)) ``` 输出结果为: ``` 11111:11111:11111:11111:11111 ``` 来分析一下这段代码,它使用了双重for循环来生成数据,程序的运行流程为: ``` # 外层循环开始第一轮循环 # 内层循环开始第一轮循环,产生了5个相同的数字并且拼接在一起 # 此时内层循环第一轮循环结束 # 将产生的5个数字后面拼接上一个冒号 # 此时结束外层循环的第一轮 # 开始外层循环的第二轮循环 # …… 后面过程省略 # 外层循环的第5轮结束。 ``` 双重for循环结束,我们会得到类似“11111:11111:11111:11111:11111:”的字符串,也就是最后面多了个冒号。 把这个冒号去掉方法很多,但最简单的是使用切片操作符。切片操作符用于取list或tuple中的部分元素,比如: ``` list_name = ['墨小小', '墨小妹', '墨大元', '墨当归', '墨鱼儿'] print(list_name[0:2]) ``` 输出结果为: ``` ['墨小小', '墨小妹'] ``` 这里的list_name[0:2]就是对list_name的切片操作。[0:2]表示从下标为0的元素开始切,切到下标为2的元素为止,但是**不包括**下标为2的元素。也即切出来了第1个和第2个元素,所以输出结果是墨小小和墨小妹。 小墨:这个就像墨妈妈切黄瓜,我只吃头不吃把儿,她就把黄瓜头切给我。 墨博士:跟切黄瓜差不多,指定开始和结束位置就行了。如果是想从头开始切,第一个数可以不写。比如list_name[:2]一样可以得到墨小小和墨妹妹。而如果我想从某个下标开始一直切到最后,则后面一个数可以不写。比如list_name[3:]就表示从下标为3的元素开始切到最后,得到的结果是墨当归和墨鱼儿。 小墨:切片的规则还真是灵活呀,指定头和尾的下标,如果从头开始就头部坐标不指定,如果切到最后就最后下标不指定。 墨博士:还有更强大的:Python中的list支持负下标。负下标是从-1开始的,倒数第一个元素的负下标是-1,倒数第二个元素的负下标是-2,以此类推。 小墨:这个前面曾说过,list_name[-1]会得到墨鱼儿、list_name[-2]就得到墨当归。 墨博士:是的。同样的,切片也可以使用负坐标。比如list_name[-3:-1]就表示从下标为-3的元素取到下标为-1的元素,不包括下标为-1的元素本身,得到墨大元和墨当归。list_name[-3:]则表示从下标为-3的元素开始取到最后,会得到墨大元、墨当归和墨鱼儿。 小墨:我知道了。list_name[:-3]就表示从开头取到下标为-3的墨大元,会得到墨小小和墨小妹,没错吧博士? 墨博士:没错。回到我们模拟萤火虫的程序,现在得到的字符串是“11111:11111:11111:11111:11111:”,如何把最后一个冒号去掉呢? 小墨:这个字符串长度是30,所以使用result[0:29]从0切到29就可以了。哦,原来这就是你写的result[0:len(result)-1]。我再想想……,还可以使用负下标切,从开始切到最后一位,用result[:-1]就可以了。 等等,博士,关于产生25个LED对应的数字的方式,我突然有个新思路: ``` def get_image(n): result = '' for i in range(1, 26): result += str(n) if i % 5 == 0: result += ':' return result[:-1] ``` 你看,就不需要写两个for循环了。或者我可以直接拼接29次,省去切片的麻烦: ``` def get_image(n): result = '' for i in range(1, 30): if i % 6 == 0: result += ':' else: result += str(n) return result ``` 怎么样博士?我厉害吧? 墨博士:厉害!青出于蓝而胜于蓝,维护世界和平,哦不,人工智能的未来,就靠你们了。 回到我们的萤火虫程序,现在get_image()函数已经能生成LED对应的数字了。想让萤火虫能从暗到亮,可以使用循环生成0~9,然后调用get_image()方法得到对应的LED的数字,显示在显示屏上。 ``` for i in range(10): img = get_image(i) display.show(Image(img)) sleep(200) ``` 这里的sleep(200)和小人儿走路程序中的delay=500作用一样,表示暂停200毫秒,这样配合着循环我们就能看到萤火虫逐渐变亮的过程了。 然后再来写一个循环,产生9~0对应的数字并显示在显示屏上,就能让萤火虫由亮变暗了。 最后,在两个for循环外套一层死循环,就能让萤火虫一直不停的由暗变亮,由亮变暗了。完整代码如下: ``` from microbit import * import random def get_image(n): result = '' for i in range(1, 30): if i % 6 == 0: result += ':' else: result += str(n) return result while True: for i in range(10): img = get_image(i) display.show(Image(img)) sleep(200) for i in range(10): img = get_image(9 - i) display.show(Image(img)) sleep(200) ``` > 动动手:策划一个下雨的动画场景,并使用micro:bit模拟。 ### 11.3.5 按钮 除了25个LED组成的显示屏外,micro:bit还提供了两个按钮可供我们编程控制。左边按钮称为A,右边按钮称为B。见图11.2所示。 现在我们来写个程序,完成下面功能: 当点击A键时,屏幕上一直快速的在动态变化显示0~9; 当点击B键时,动态变化停止,屏幕上固定显示一个0~9间的数字。 小墨:这个可以和墨妹妹一起玩,我们俩每人一次,最后看谁停住的数字大谁就赢了。 墨博士:不错的主意!另外,我们还可以让游戏能一直玩下去: ``` from microbit import * import random def get_image(): return str(random.randint(0,9)) while True: if button_a.is_pressed(): while True: my_img = get_image() display.show(my_img) if button_b.is_pressed(): break ``` 这里的“get_image”用于随机获取字符串类型的0~9。“if button_a.is_pressed():”就表示如果按下了A键。在“if button_a.is_pressed():”后又跟了一个死循环,用于屏幕一直动态刷新,在此过程中如果按了B键,则内部死循环结束,屏幕上显示最终定格的数字。 ## 11.4 本章小结 墨博士总结:关于micro:bit介绍到这里就结束了。你可以访问micro:bit的官网继续深入的了解和学习。另一方面,你看本章操作micro:bit的几个案例,用的都是很简单的Python基础知识,从这方面来说,你现在的Python水平已经能做出各种各样有趣的东西了。