面向疯狂科学家的-MicroBit-全-
面向疯狂科学家的 MicroBit(全)
原文:
zh.annas-archive.org/md5/544db862ae6ee791ffbd8afd2d451fb3译者:飞龙

前言
自 2016 年 BBC 发布 micro:bit 以来,数百万个 micro:bit 设备已被分发到世界各地。它们受到全球儿童和成人的喜爱。micro:bit 的设计目的是作为一种简便的方式教授孩子们编程技能。它的一个大优势是,使用它只需要一根 USB 电缆和一台计算机。此外,一旦编程完成,它可以断开电源并通过电池运行。
micro:bit 配备了一个小型 LED 显示屏以及光线、运动和磁场传感器,因此它具备了制作有趣项目所需的所有功能。当你准备好时,你可以通过鳄鱼夹轻松连接电动机、传感器和扬声器——无需焊接。换句话说,你的 micro:bit 可以成为许多项目和发明的大脑。

关于本书
在本书的这些页面中,你将找到各种实验和项目。实验展示了事物的工作原理,然后在项目中,你将使用这些知识制作有趣的东西。
本书共分为 10 章。第一章将告诉你如何连接和使用 micro:bit。你将在本书中的所有实验和项目中使用这些信息。接下来的每一章都涉及一个特定的主题,如光、声音和运动。你可以用 micro:bit 做很多有趣和有用的事情!
实验
这里列出了本书中的实验:
生成声音 学习让你的 micro:bit 播放音乐音符和其他声音。
它会说话! 教你的 micro:bit 学会说话!
感应光线 使用内置的光线传感器。
测量磁场 使用内置的磁力计感应磁铁。
手势 使用 micro:bit 的手势识别软件,当你摇晃、掉落或投掷它时,让设备执行不同的操作。
实时加速度绘图 了解 Mu 的数据显示功能。
将数据加速记录到文件 记录由 micro:bit 检测到的数据,方便你以后查看。
让伺服电机转动 尝试使用电动机!
计时 了解 micro:bit 如何计时。
你的神经反应有多快? 测试你的反应时间。
测量温度 使用 micro:bit 的温度传感器制作温度计。
找到无线电范围 学习如何使用 micro:bit 进行无线电通信。
项目
这里列出了本书中的项目:
音乐门铃 按下时播放你选择的旋律
声音测量仪 检测声音并显示声音的响度
自动夜灯 房间变暗时自动打开
光吉他 当你在 micro:bit 的 LED 灯上方挥动双手时,它会发出音乐
无限镜 利用光线创造无限深度的幻觉
指南针 一个真正工作的指南针!
磁性门警报 当你打开门时,磁铁与 micro:bit 分离,触发警报
刷牙监测器 测量你的刷牙动作,确保你的牙齿保持健康
加速度显示器 显示 micro:bit 加速度的计量表
仿生机器人头 一款具有活动眼睛和会说话的嘴巴的机器人头
机器人漫游车 一款双轮的 micro:bit 机器人!
二进制时钟 使用 LED 显示时间
语音时钟 每小时报时,并在你按下按钮时报时
谎言探测器 通过测量皮肤中的电流来判断某人是否在撒谎
温度与光照记录器 自动记录光照和温度水平
自动植物浇水器 当感知到土壤过于干燥时会自动给植物浇水(再也不用担心杀死植物!)
无线门铃 一款无线升级的门铃项目,使用无线电波
Micro:bit 控制的漫游车 一款无线版本的漫游机器人,通过无线电接收你的指令
代码与资源
用于编程 micro:bit 的两种最流行的计算机语言是 Makecode Blocks(本书中简称 Blocks)和 MicroPython 编程语言。
在可能的情况下,我为项目和实验提供了 Blocks 和 MicroPython 两种编程方式的程序。这意味着你无需亲自输入代码——除非你愿意。
你可以在本书的配套 GitHub 页面找到所有活动的代码: github.com/simonmonk/mbms/。我在第一章中提供了访问和使用代码的完整说明。

第一章:入门
本章将帮助你入门 BBC micro:bit。这也为接下来的实验和项目奠定了基础。我会给我们的疯狂科学家(就是你!)一些关于如何使用 micro:bit 的想法,并帮助你开始编程。你将学习如何使用 Blocks 代码和 MicroPython。
疯狂科学家通常太忙、太分心,无法输入大量代码,所以本书中使用的所有代码都可以下载。本章将解释如何获取和使用这些代码。
micro:bit 介绍
让我们快速了解一下 micro:bit 和它上面的内容。
顶部
图 1-1 展示了 micro:bit 的顶部。

图 1-1:micro:bit
在板子的顶部有一个 micro USB 插口,用来将 micro:bit 连接到电脑。你将在电脑上为 micro:bit 编写程序,因此你需要通过 USB 连接将程序传输到 micro:bit。这个 USB 插口也能为 micro:bit 提供电源。
左右两边各有一个按钮,分别标记为 A 和 B。我们可以编程这些按钮来触发某些操作,比如在 LED 上闪烁图像或发出门铃声。
在两个按钮之间,有一个由 25 个 LED 组成的网格,排列成 5 行 5 列。这是 micro:bit 的显示屏。尽管它只有 25 个 LED,这个显示屏仍然可以显示滚动的文本信息、小图像、图案——非常多的内容!
在 micro:bit 的底边有一条镀金(是的,真金!)的条形连接器,称为边缘连接器。这条连接器上有五个孔,标记为 0、1、2、3V 和 GND。这些较大的连接器可以让你使用鳄鱼夹将其他设备连接到 micro:bit。例如,你可以连接一个扬声器让 micro:bit 发出声音,或者连接一个电机让它运动。而更小的连接器,即孔与孔之间的缝隙,只能使用特殊的适配器连接。在本书中,除了两个需要适配器连接电机控制器的机器人项目外,我们将使用这些较大的连接器。

底部
现在让我们把 micro:bit 翻过来,看看它的底面(见图 1-2)。

图 1-2:micro:bit 的底面,版本 1.3B(左)和 1.5(右)
截至本书编写时,市面上有两种版本的 micro:bit。两种版本的工作方式相同,对于本书来说,你使用哪个版本都无所谓。最新的版本(1.5)只是设计略有简化。你可以在图 1-2 中看到两款板子的区别,区别在左下角。
最左边的连接器是 micro USB 连接器。紧接着右侧的是一个按键开关。这是 micro:bit 的复位按钮。按下这个按钮会导致 micro:bit 重新启动上面安装的程序。复位按钮右侧是电池连接器,可以让你将一个 3V 电池包连接到 micro:bit。
现在我们将仔细查看每个部分,从如何为 micro:bit 供电开始。
电源和 Micro:bit
你可以通过 USB 连接器或电池为 micro:bit 供电,取决于你希望如何使用它。
使用 USB
当你将 micro:bit 插入电脑时,USB 连接会为 micro:bit 提供 5V 电压。然而,micro:bit 只需要 3.3V,而不是 5V,过高的电压可能会损坏 micro:bit。因此,它有一个 USB 接口芯片,将 5V 电压转换为 micro:bit 所需的 3.3V。
当 micro:bit 通过 USB 连接时,你可以使用边缘连接器上的 3V 接口为低功耗电子设备供电,比如外部 LED 或设计为与 micro:bit 一起使用的扬声器。
注意 这个连接被标记为 3V 而不是 3.3V,部分原因是没有足够的空间再写一个数字,但也因为保护电路会将 3.3V 电压降低到接近 3V 的电压。
标有 GND 的连接是地或 0V 电源连接。当你为 micro:bit 供电时,电流从 3V 连接端流出,并且需要通过 GND 连接返回 micro:bit,才能完成电路。
使用电池
一旦你为 micro:bit 编写了程序,可能会希望将它移离电脑,这时你就需要电池。你可以使用 AAA 电池包,像图 1-3 中所示的那样。只需将电池包的两端连接到 micro:bit 底部的 3V 插座。

图 1-3:micro:bit 电池包
附录列出了一些你可以购买这些电池包的地方。内置开关很有用,因为你可以在不拔掉电池包的情况下关闭 micro:bit,这是一个相对复杂的操作。
不要使用可充电的 AAA 电池,因为它们的电压通常太低,无法为 micro:bit 提供足够的电力。这些电池如果发生意外短路,还可能导致危险的高电流。如果你想使用可充电电池,一个选择是像图 1-4 左侧所示的 USB 电池备份。

图 1-4:使用可充电电池为 micro:bit 供电
这些可充电电池允许你通过 USB 端口为 micro:bit 供电。低容量、价格便宜的备用电池通常比更昂贵的版本更适合为 micro:bit 供电。micro:bit 消耗的电流非常小,这些更先进的电池往往会在认为电池长时间未使用时自动关闭,因此它们可能会错误地认为没有连接设备。
图 1-4 右侧的项目是 Monk Makes 微型充电器。它使用一块锂聚合物(LiPo)电池,每当你通过 USB 线将充电器连接到计算机时,它会自动充电。当你希望使用电池运行 micro:bit 时,只需拔掉连接充电器的 USB 线。
你可以在附录中了解更多关于为 micro:bit 供电的选项。
警告 micro:bit 的早期版本在与 USB 电池和电源一起使用时容易受到损坏。如果你使用的是 V1.3B 或 V1.5 版本之外的任何板子,应该避免使用除计算机 USB 端口或 3V 电池组之外的任何电源。
早期的 micro:bit 没有版本号。翻转你的 micro:bit,查看底部右角靠近连接口 0 的地方。如果上面写的是V1.3B或V1.5,那么使用 USB 电池组和电源是可以的。如果你在这里看不到版本标识,最好不要使用这些电源。
无论如何,都应避免使用被描述为高功率的电源和 USB 电池。
你可以阅读 micro:bit 基金会的完整安全建议,地址是 microbit.org/guide/safety-advice/。
连接电子设备与输入/输出引脚
关于 micro:bit,有一件特别有趣的事情是,你可以利用它的连接口连接自己制作的电子设备。在本书中,你将构建一些项目,使用这些连接器来控制电机、灯光和扬声器。你还将使用它们作为输入,收集来自传感器的数据,这些传感器能够测量光线、声音和温度。
3V 和 GND 连接口用于供电。标有 0、1 和 2 的连接口通常被称为输入/输出引脚,你将在这些引脚上连接电子设备。
注意 你可能会好奇,为什么我们称这些为引脚,它们看起来和引脚完全不同。术语引脚来源于 micro:bit 连接的电路板上的芯片。该芯片上确实有引脚—每个引脚都有一个微小的腿形连接。
引脚 0、1 和 2 可以用于:
数字输出—例如,控制外部 LED 的开关
模拟输出—例如,用来控制 LED 的亮度
脉冲生成—例如,用来控制伺服电机
数字输入—例如,当外部按钮被按下时进行检测
模拟输入——例如,使用模拟温度传感器来测量温度
触摸输入——用于检测你是否触摸了引脚或连接到引脚的电线
数字输入和模拟输入
当你将引脚用作数字输出时,你可以在程序中编写命令来开启输出(设置为 3V)或关闭输出(设置为 0V),但只能是开或关——没有中间状态。数字输入也是如此:它们只能是开或关。当你的程序代码读取数字输入时,如果输入端的电压接近 3V 而非 0V,那么该输入被视为开启;否则,就是关闭状态。
然而,模拟输入的值可以介于开与关之间。micro:bit 上的模拟输入可以是 0 到 1,023 之间的任何值,这取决于引脚的电压。
生成模拟信号:脉宽调制
micro:bit 和所有其他电子设备一样,只能处理数字开关信号。为了获得 0 到 3V 之间的模拟信号,电子设备通过快速的数字脉冲序列来模拟模拟信号。脉冲持续时间越长,传递给连接到模拟输出的设备的功率就越大。这就是所谓的脉宽调制,或者PWM。图 1-5 展示了 PWM 的实际应用。

图 1-5:micro:bit 上的模拟输出提供不同量的功率
如果输出连接到一个 LED,并且脉冲只有 5%的时间保持在 3V,那么 LED 看起来会发出微弱的光。相比之下,如果脉冲有 90%的时间保持在 3V,那么 LED 看起来将接近全亮。
有趣的是,在这两种情况下,LED 实际上每秒闪烁 50 次,但人眼无法看见如此快速的闪烁。相反,我们只会感知到相对昏暗或明亮的光。
如果三个引脚 0、1 和 2 不足以满足你的项目需求,你可以使用适配器来访问这三个编号引脚之间的多个引脚。
内置外设
micro:bit 底部的文字为我们提供了一些关于 micro:bit 其他功能的线索。左下角的两个区域标记为指南针和加速度计。
这个指南针实际上是一个磁力计,意味着它可以测量磁场的强度。你可以将其用作指南针,但也可以用来检测磁铁的存在。
加速度计测量作用于加速度计芯片的力。由于重力是一个常量,始终拉向地面,通过测量作用在不同方向上的力,你可以利用加速度计检测 micro:bit 何时被倾斜,以及倾斜的程度,还可以检测它是否被摇晃或处于自由落体状态。
在底部,你还会看到BLE 天线字样。micro:bit 包含 BLE(蓝牙低能耗)硬件,使得你的 micro:bit 可以与其他 micro:bit 或蓝牙支持的手机进行无线通信。
请注意,micro:bit 之间的通信技术实际上并不是蓝牙;它只是使用相同的频率。第十章专门讲解了 micro:bit 的这一功能。
硬件必备
你需要一些东西来完成本书中的几乎所有实验和项目。它们包括:
Micro:bit
Micro USB 电缆 用于将 micro:bit 连接到计算机(确保这是标准的 micro USB 数据电缆,而不是充电电缆,因为充电电缆缺乏必要的通信连接。你不能使用充电电缆将程序加载到 micro:bit 上。)
鳄鱼夹电缆 最好不要超过 4 到 5 英寸,以避免缠绕。
3V AAA 电池组(包含两节 AAA 电池)
USB 电源 只有某些项目需要使用它。(参见之前的警告。)
每个项目或实验都会列出所需的所有物品,本书末尾的附录提供了如何获取这些物品的更多信息。
本书尝试保持项目构建简单明了,除了第六章中的巡逻机器人,其他项目不需要焊接。对于大多数项目,你只需使用鳄鱼夹电缆将各个组件连接起来。使用鳄鱼夹连接时,最好将电缆垂直夹入,这样夹子的齿部就像图 1-6 一样,这样可以大大减少电缆松动的可能性。

图 1-6:安全连接鳄鱼夹
编程 micro:bit
疯狂的科学家们可不以耐心著称,所以让我们让我们的 micro:bit 做点事情。首先,我们来编程我们的 micro:bit。
使用 micro:bit 的一个好处是,你只需要一根 USB 电缆和一台带有浏览器及互联网连接的计算机,就可以开始使用它。你可以使用运行 Windows、macOS 或 Linux 的计算机。只要你的设备有现代浏览器(如 Chrome),就可以正常工作。
我们将首先连接 micro:bit。然后我们将通过两种方法制作一个小程序:拖放式块代码和需要手动输入的 MicroPython。
连接你的 Micro:bit
首先,通过 micro USB 电缆将 micro:bit 连接到计算机。几乎所有的 micro USB 电缆都可以正常工作,但请记住,只有充电电缆没有必要的数据连接,因此无法使用。如果按照以下说明编程时遇到问题,请尝试使用不同的 USB 电缆。
一旦你连接了 micro:bit,操作系统应该会像你刚插入 USB 闪存驱动器一样做出反应。要将程序传输到 micro:bit,只需像找到闪存驱动器或其他插入设备一样,在文件系统中找到 micro:bit。然后将一个名为 hex 文件 的文件复制到 micro:bit 文件夹图标中,嘿,程序就安装好了。将程序加载到 micro:bit 上也叫做 刷机。
让我们创建一个.hex 文件并将其烧录到我们的微型:bit 上。
使用积木编程:Hello World
你可以通过微型:bit 官网来编写程序,无需下载任何软件。我们将编写一个程序,使一些文本在微型:bit 的 LED 显示屏上滚动。打开你的浏览器并访问* makecode.microbit.org*,你应该会看到一个类似于图 1-7 的窗口。

图 1-7: makecode.microbit.org 网页
这是你编写程序的编辑器。左侧是一个微型:bit 的图像,它像虚拟微型:bit 一样工作,运行你编写的任何程序。
中间的部分是类别列表,如 Basic、Input 和 Music。在这些类别中,你会找到可以拖到右侧工作区的积木。每个积木都是给微型:bit 的指令。通过拖动这些积木并将它们连接起来,你将使用积木语言编写代码。
你会注意到,当你打开编辑器时,编辑区已经有两个积木:on start和forever。任何位于on start积木内的代码会在微型:bit 第一次启动、上传新程序,或因为你按下重置按钮而重置时执行。任何位于forever积木内的代码将会一遍又一遍地运行,直到你停止程序。
对于我们的第一个程序,我们不需要forever积木,所以选择它并按 DELETE 删除它。接下来,你需要将show string积木添加到程序中——string是编程术语,表示文本。为此,点击Basic类别,将show string积木拖到编程区域,并将其放置在on start积木内,如图 1-8 所示。如果你的电脑有声音,你会听到积木拼接时发出的令人满意的咔哒声。
现在点击文本气泡并输入Hello World。你也可以输入不同的文本——任何你希望显示的内容。

图 1-8:用于显示 Hello World 的积木代码
一旦你将show string积木拖到合适的位置,显示区域左侧的虚拟微型:bit 应会在其显示屏上滚动你的信息,展示程序的效果。
现在让我们把你的程序传输到真实的微型:bit 上。使用 USB 线连接你的微型:bit,并点击网页左下角的下载按钮。

这将像从互联网上下载其他文件一样,从编辑器下载文件。文件保存的位置取决于你的操作系统和浏览器,但通常会保存在一个名为Downloads的文件夹中。找到这个文件夹,点击进入,你应该能找到一个名为microbit.hex的文件。使用文件管理器(或在 Mac 上使用 Finder),选择该文件并将其拖到 micro:bit 上,当它出现在你的文件系统中时(见图 1-9)。

图 1-9:将文件拖到你的 micro:bit 上
一旦你松开鼠标按钮,文件应该会开始自动安装到 micro:bit 上。你会知道它正在发生,因为 micro:bit 背面的 LED 将开始闪烁。当闪烁结束时,micro:bit 会重置自己并运行程序,文本会在显示屏上滚动。如果你错过了看到消息,按下 micro:bit 背面的重置按钮可以再次查看。
直接下载到你的 MICRO:BIT
大多数浏览器都提供了一个选项,可以在每次下载文件时选择文件保存的位置。你可以利用这个功能将文件直接下载到 micro:bit 上。这样你就不必先下载文件再复制到 micro:bit。
要在 Chrome 浏览器中设置此功能,请前往chrome://settings/,点击高级,向下滚动到下载部分,然后启用选项下载前询问每个文件的保存位置。这样,下次你在编辑器中点击下载时,就会提示你选择文件保存的位置,并且可以选择 micro:bit 文件夹作为目标。
在撰写本文时,通过 Chrome 浏览器将程序烧录到 micro:bit 上即将变得更加简单。你可以在这里阅读有关此功能的更多信息:support.microbit.org/support/solutions/articles/19000084059-beta-testing-web-usb。
添加图形
为了显示我们的消息,我们将一个show string模块添加到了on start模块中。on start模块是一种特殊类型的模块,称为事件模块,每当特定事件发生时,它会运行与之连接的代码。在这个例子中,事件是程序的启动。
让我们通过添加一个新的事件,使程序变得稍微复杂一点,这个事件将检测到按钮 A 被按下。当你做这个时,点击输入类别,将一个on button A pressed模块拖入程序区域。接着,从基础类别中拖动一个show leds模块到on button A pressed模块中。show leds模块中的方块表示 LED 显示器中的每个 LED。你可以通过点击方块使其变白来选择应该亮起的 LED。结果应该看起来像图 1-10 那样。

图 1-10:将 LED 图案添加到程序中
show icon模块有许多现成的 LED 图像,如果你想选择其中的某一个,可以直接选择。再次点击Download并将新的 hex 文件复制到你的 micro:bit 上。上传新程序后,你可以通过按下 A 按钮来测试它。按下后,show leds模块中选择的 LED 应该会在 micro:bit 上亮起,如图 1-11 所示。

图 1-11:在实际的 micro:bit 上显示 LED 图案
保存和共享
makecode.microbit.org网站会记住你的所有项目。为你的项目命名,可以在“保存”区域输入名称,按钮旁边会出现“保存”按钮,你的项目就会被保存。每当你修改程序时,它应该会自动保存,但为了确保,你也可以点击软盘图标手动保存。请注意,当你点击保存时,hex 文件也会被下载,但如果你不准备将程序刷入 micro:bit,只需点击取消即可。
请注意,你保存的程序实际上是保存在浏览器缓存中的,因此如果你删除了缓存,你将丢失程序。
要在程序之间切换并开始新的程序,点击页面顶部的Home。
要发布一个程序让其他人看到,点击“Projects”旁边的Share按钮。这将要求你确认是否愿意发布项目。再次点击Share,你将看到像图 1-12 中所示的链接。

图 1-12:共享项目
你可以将那个网址发送给任何人,当他们在浏览器中输入时,他们将获得你的程序副本供使用。请注意,因为这只是你程序的副本,所以他们不会破坏你原始代码的副本。
查找模块
我们到目前为止使用的show string和show leds模块比较容易找到,但模块编辑器包含了大量的模块,而且它会将你不常用的模块隐藏起来。这样一来,当你开始使用 micro:bit 时,你就不会看到令人困惑的选项。
这些模块有两种方式被隐藏。首先,你可能注意到,当你选择某个模块类别(如 Basic)时,会出现一个标记为. . . more的项目(见图 1-13)。

图 1-13:更多部分中的额外模块
在“Basic”类别中,更多部分包含诸如clear screen和show arrow等模块。如果你点击其他类别,你会发现它们都有一个“更多”部分,有些类别还包含了不少额外的模块。
顺便说一下,将鼠标悬停在某个模块上会打开一个小信息框,告诉你该模块的功能。花些时间熟悉各种模块,将激发你关于如何使用 micro:bit 的创意。
第二个可以找到隐藏块的地方是在“高级”类别中,位于数学后面(图 1-14)。选择该类别会显示更多包含 Blocks 语言高级特性的类别,从函数开始。同样,花些时间熟悉这些块。如果你不确定某些块的功能,不用担心。如果你对某个做特定事情的块感兴趣,可以使用搜索框来查找你想要的块。

图 1-14:高级块类别
在“高级”部分,你将频繁使用的类别是文本和引脚。在某些章节中,你还会使用到函数和数组。
使用 MicroPython 编程:你好,世界
Blocks 代码非常适合开始编程,因为你只需几个块就能完成一些非常令人印象深刻的事情。然而,许多人更喜欢编写文本程序,而不是拖动块。输入一行行的文本也更像常规的编程方式。
MicroPython 是一种 Python 3 编程语言的实现,包含了你编写 micro:bit 程序所需的一切。事实上,Blocks 代码中的许多块在 MicroPython 中都有直接的对应项,因此从 Blocks 编程切换到 MicroPython 是相当直接的。Python 是一种流行的初学者编程语言,因此通常在学校教授。
下载 MicroPython 编辑器
我们将使用 Mu 编辑器应用程序 (codewith.mu),它有很多功能。你可以直接将其下载到你的电脑上。Mu 还允许你将程序直接刷入 micro:bit,而无需拖动 hex 文件。Mu 的好处是,一旦下载了 Mu,你就不需要互联网连接也能刷入程序。
从 codewith.mu/#download 下载 Mu。Mu 有多个版本,因此确保你选择适合自己电脑的版本。下载页面会为不同操作系统提供不同的版本。如果你是 Windows 用户,请下载 Windows 安装程序下标注为 64-bit 的版本(图 1-15)。如果你是 macOS 用户,只有一个版本。

图 1-15:下载 Mu
运行安装程序,接受许可协议并选择所有默认选项。
第一次运行 Mu 时,它会提供你选择模式的选项。确保选择 BBC micro:bit 模式(图 1-16)。

图 1-16:选择正确版本的 Mu
Mu 会为你提供一个空白的编辑窗口,在这里你将编写你的第一个程序。
编写程序
让我们试试 Mu!在 Mu 窗口中添加以下代码:
from microbit import *
display.scroll("Hello World")
它应该看起来像是图 1-17。

图 1-17:在 Mu 中编写 MicroPython 程序
通过点击 Mu 窗口顶部的Save按钮保存程序。系统会提示你为程序输入一个名称:将其命名为 hello.py。
现在,连接你的 micro:bit 到计算机后,点击 Mu 窗口顶部的Flash按钮。这将启动将 hex 文件加载到 micro:bit 的过程,就像你拖动一个由 Blocks 编辑器生成的文件一样。一旦闪烁完成,Hello World 信息应该会在显示屏上滚动。
让我们仔细看看代码。这是第一行:
from microbit import *
你会在几乎每个 MicroPython micro:bit 程序的开头找到这一行代码,因为它告诉 MicroPython 包含所有使其与 micro:bit 的显示和其他硬件兼容的内置代码。此代码不会自动包含,因为 MicroPython 可以在许多不同的板子上使用,而不仅仅是 micro:bit。实际上,这行代码的意思是:从 microbit 库中导入一切(* 表示一切)。你也可以输入import microbit,但那样你就必须在每个命令前加上 microbit,这会多打很多字。
我们的最小程序中的唯一其他一行代码是在显示器上显示信息:
display.scroll("Hello World")
这一行使用了命令display.scroll,它告诉 micro:bit 在显示屏上滚动某些内容。接着,你加了一对括号,括号内有一些被引号括起来的文本。你使用括号是为了在命令中添加额外的信息。在这种情况下,额外的信息(也叫做参数)是你想要显示的文本。你还需要将文本放在双引号中,以表明程序应将其视为文本,而不是更多的编程命令。
如果在将程序刷入 micro:bit 时,你看到除了 Hello World 以外的内容(或者什么都没有),那么可能是你的代码中有错误。在使用基于文本的编程语言时,你必须准确地输入内容。例如,拼写错误如 display 或 scroll 将导致程序运行时出错。编程中的错误被称为bug。bug 只会在程序尝试在 micro:bit 上运行时才会显现出来。如果你遇到 bug,可以仔细对比你写的代码和书中的代码,确保它们完全一致。但还有另一种找到并修复 bug 的方法——你可以使用 REPL。
REPL
REPL(读取-评估-打印-循环)是 MicroPython 在 micro:bit 上的命令行接口——也就是说,它是一个让你直接向 micro:bit 发送 Python 命令的区域,而无需先将它们放入程序中。如果你在这里输入 1 + 2,REPL 会返回 3。类似地,如果 MicroPython 在尝试运行时遇到问题,它可以在 REPL 中报告这个问题,而不需要你等到 micro:bit 尝试显示某些内容。
为了实验 REPL,让我们故意在程序中引入一个错误,将 scroll 拼写成只有一个 l。删除一个 l,然后再次点击 Flash。尽管程序有错误,仍然会上传,但这次,micro:bit 显示屏将显示:AttributeError: 'MicroBitDisplay' object has no attribute 'scrol'。由于滚动显示此消息需要较长时间,为了更清楚地查看,点击 Mu 窗口顶部的 REPL 按钮,然后点击 micro:bit 背面的重置按钮。你应该能在 REPL 中完整看到错误信息(见 图 1-18)。

图 1-18:在 Mu 中使用 REPL 捕获错误
REPL 中的 >>> 提示符表示你可以在这里输入 Python 命令,并立即在 micro:bit 上运行。尝试在 >>> 提示符后输入以下内容,并在行末按 ENTER(这次正确拼写 scroll):
display.scroll("The REPL is useful")
你的 micro:bit 显示屏应该会立即滚动出消息,而不需要你上传程序。你不需要重复 import 命令,因为 MicroPython 已经执行了 import——它是在遇到拼写错误的 scroll 之前就执行过了。
注意 当你在输入 Hello World 程序时,可能注意到 Mu 尝试通过猜测你正在输入的内容来帮助你。例如,如果你输入 display 然后暂停,选项列表(clear、get_pixel、is_on、off、on、scroll、set_pixel 和 show)将会出现。你可以点击你想要的选项,省去一些输入工作。
添加图形
现在让我们像在 Blocks 代码中一样,为程序添加一些图形。我们需要再次检测按钮 A 是否被按下,然后显示图形模式。这在 MicroPython 中稍微复杂一些,因为这个语言没有像 Blocks 代码那样的事件概念。相反,我们必须编写一个循环,让其中的命令重复执行,直到停止。我们的程序中,这些命令会检查按钮是否被按下,如果发生了这个事件,就执行必要的操作。换句话说,程序不是被告知按钮 A 已被按下,而是必须不断检查它是否被按下。以下是代码:
from microbit import *
display.scroll("Hello World")
while True:
if button_a.was_pressed():
display.show(Image.CHESSBOARD)
while True代码行标志着循环的开始,循环将一直执行,直到有某些操作停止它,比如你拔掉 micro:bit 的电源,按下重置按钮,或在 REPL 中按 CTRL-C。每当你创建一个循环时,请确保将任何应在该循环中执行的代码行进行缩进。幸运的是,Mu 会识别你何时开始一个循环,并自动为下一行代码添加缩进。
循环中的第一行是一个if语句。它使用button_a.was_pressed函数来检查自从上次使用was_pressed以来按钮是否被按下。如果是,那么if语句下面缩进的代码将被执行。你会注意到,接下来的代码行会进一步缩进,这意味着这行代码只会在if语句为真时运行(也就是按钮确实被按下时)。在这种情况下,这行代码告诉显示器显示一个来自图像库的现成图形。我选择了CHESSBOARD图像。稍后我们将在第 29 页的“if 块”中详细讨论if命令。
在 Python 中,缩进非常重要,记得缩进可能是刚开始学习这门语言时的一个大难题。比如,在while或if命令中的缩进行必须精确地缩进相同的数量。在 Mu 中,这是四个空格。随着你不断练习 Python 编程,知道何时缩进将变得越来越容易。
编程概念
在这里,我们将介绍一些编程中的关键概念,特别是当你想修改一些项目代码或开始创建自己的项目时,这些概念非常值得理解。无论你使用的是“块编辑器”还是“MicroPython”,这些概念都是相同的,因此我们将分别介绍如何使用这两种方式来实现每个概念,先是用块代码,然后是对应的 MicroPython 代码。
变量
变量是与一个或多个值相关联的名称。当你想使用这个值时,可以在代码中调用这个名称。让我们通过一些例子来说明这个概念。
块代码
在“块编辑器”中,主要的类别之一是“变量”。通过点击块编辑器主页中的新建项目来开始一个新项目。删除永远块(我们不需要它),然后从“变量”类别中点击创建一个变量...。当提示输入新变量名称时,输入计数器。将将计数器设置为 0块拖到编程区,并将其点击到开始时块上。
接下来,在“输入”类别中添加一个按下按钮 A块。在这个块里面,添加一个来自“变量”类别的计数器加 1块,然后再添加一个来自“基础”类别的显示数字块。最后,从“变量”类别中拖出一个计数器块,将它点击到显示数字块中的0上,以替换掉0。
一旦你完成了这些编程,代码应该如下所示。

你可以通过点击编辑器左侧虚拟的 micro:bit 来尝试这个程序,按下按钮 A 后,你应该会看到数字显示增加了 1。
让我们来看一下这里发生了什么。在on start块中,你创建了一个名为counter的变量,并给它赋予初始值 0。当on button A pressed块被激活时,change块通过加 1 来改变counter变量的值,然后在显示器上显示counter变量的值。
在这种情况下,我们的counter变量包含一个数字,但我们也可以设置变量来存储文本,甚至是数据集合。
MicroPython 代码
我们刚刚写的 MicroPython 版本程序如下所示:
from microbit import *
counter = 0
while True:
if button_a.was_pressed():
counter += 1
display.scroll(str(counter))
我们导入常用的 micro:bit 库,然后创建一个counter变量,并赋予它初始值 0。我们创建一个while循环,确保如果按下按钮 A,则会给counter加 1。为了加 1,我们使用+=,它等价于change counter块。
当我们想要显示新值时,我们必须使用str(counter)将数字值转换为文本字符串,因为display命令只接受字符串。
请注意,完全可以将一个命令嵌套在另一个命令中。所以在这里,我们通过将str命令放入括号中来在display.scroll命令内使用它。当你这样做时,最内层的命令(在这个例子中是str)会先执行并将一个值传递给下一个命令(在这个例子中是display.scroll)。
算术
在之前的示例中,你看到我们如何将一个数字加到变量中。除了加法,我们还可以在程序中使用所有常见的算术操作,包括减法、乘法和除法。
积木代码
假设我们想要将一个数字不断加倍,而不是按单位递增。我们可以修改之前的程序,使得counter的起始值为 1,并且on button A pressed块将counter乘以 2,如下所示。

现在,我们不再使用change counter by 1块,而是使用set counter to块,在里面使用一个乘法块(×)。在乘法块的第一部分,我们放入变量counter,在第二部分,我们放入数字2。现在,每次按下按钮 A 时,counter都会被赋值为其旧值的两倍。
当我们使用积木时,这样的数学运算很快会变得相当复杂,因为我们需要在积木中嵌套积木,再在其他积木中嵌套。如果我们有一个需要进行大量算术运算的程序,使用 MicroPython 编码可能会更好。
MicroPython 代码
在 MicroPython 中,我们使用算术符号,如+、-、*(乘法)和/(除法)。你还可以使用括号来改变数学运算的顺序,就像在数学课上那样。下面是我们如何重写刚刚制作的加倍程序:
from microbit import *
counter = 1
while True:
如果按下了 button_a 按钮:
counter = counter * 2
显示 counter 的值(以字符串形式滚动显示)
这里的关键行是 counter = counter * 2。变量名后的 = 符号表示后面的内容将被赋值给该变量,作为它的新值。在这种情况下,就是 counter * 2(counter 乘以 2)。你也可以使用简写形式 counter *= 2,就像我们之前做加法时所做的那样。
if 积木
程序可以看作是一系列由 micro:bit 执行的步骤。有时候,你需要让程序根据条件做出决策并执行特定的步骤。逻辑类别中的积木让你的程序能够做出决策。
我们将制作一个修改版的计数程序,它会计数到 10,然后回到 0,重新开始计数过程。
积木代码
尝试制作以下的积木程序。

首先,在 change counter by 1 积木后添加一个 if 积木。接着在 if 积木上放置一个比较积木,用来将 counter 的值与 10 进行比较。如果 counter 的值大于(>)10,程序将执行 if 语句内的积木。在这种情况下,if 语句内有一个积木将 counter 重置为 0。如果 counter 的值不大于 10,那么程序将继续在显示屏上显示当前的数字。
还有其他版本的 if 积木,它允许你在条件为真时执行一个动作,在条件为假时执行另一个动作。你将在后续章节中学到更多关于这些积木的内容。
MicroPython 代码
我们之前已经在 MicroPython 中使用过 if,检查按钮是否被按下。这里,我们不仅仅是用它来判断一个条件是成立还是不成立,而是将变量 counter 与值 10 进行比较。MicroPython 版的积木代码如下所示:
from microbit import *
counter = 0
while True:
如果按下了 button_a 按钮:
counter += 1
if counter > 10:
counter = 0
显示 counter 的值(以字符串形式滚动显示)
仔细看看这个程序的缩进:我们在一个 if 语句内嵌套了另一个 if 语句,而这个 if 又嵌套在一个 while 语句中。看看你是否能理解这段代码是如何工作的,可以参考积木版的解释。
字符串
记住,字符串是字符(数字、字母或标点符号)的序列,通常是一个单词。你在你的第一个 Hello World 程序中使用了字符串,在 图 1-8 中显示了消息 Hello World。
积木代码
大多数字符串相关的积木可以在“文本”类别中找到。其中最简单的是一个带有一对引号和一个空白的积木,你可以在其中添加自己的文本来创建字符串。你可以使用这个积木为变量赋值字符串,而不是数字。这里我们将 message 变量设为一个字符串。这个程序将显示字符串的长度。

我们使用一个on start块,在其中我们将变量message的值设置为某些文本。在show number块中,你可以看到一个length of块,在该块内是message变量。length of块将字符串message的字符数传递给show number,然后该块会在显示屏上滚动显示这个数字。
文本类别还有其他块,可以让你执行一些操作,例如连接两个字符串、剪切字符串的一部分以及将字符串转换为数字。
MicroPython 代码
在 MicroPython 中,字符串值与其他程序代码的区别是被双引号括起来的,就像在代码块中一样。我们会像这样在 MicroPython 中编写前面的代码块程序:
from microbit import *
message = "这段文本存储在一个变量中。"
while True:
display.scroll(str(len(message)))
这与代码块中的方式相同。注意,我们使用str命令将字符串长度len转换为字符串本身,以便能够显示出来。
数组和列表
到目前为止,我们使用的变量只包含单一的数据项,无论是数字还是字符串。但有时你需要在一个变量中保存一组值,通常是为了按顺序访问每个值,就像组成旋律的音符序列一样(你将在第二章中看到)。
在代码块中,一组值被称为数组,而在 MicroPython 中,它被称为列表。不过,两个的概念是相同的。
代码块
代码块编辑器有一个数组类别,其中包含与数组相关的块。最重要的是set list to,set text list to和get value at。前两个允许你创建包含数字或字符串的列表,而get value at让你访问数组中的特定元素。
以下这个小程序创建了一个名为colors的变量,并将其分配给一个包含四个字符串的array of。然后它从这个数组中随机选择一个元素进行显示。请注意,array of块有+和-按钮,可以在创建时调整数组中的项数。

我们添加一个on button A pressed块。在其中,我们添加一个show string块,在该块内添加一个get value at块。然后我们添加pick random(在数学类别中找到)来选择 0 到 3 之间的任意数字。总之,这意味着当按下 A 按钮时,pick random块会选择一个 0 到 3 之间的随机数,并获取该位置的数组元素,然后show string块会显示该元素。请注意,在代码块和 MicroPython 编程中,数组的编号从 0 开始,而不是 1,所以如果随机选择的是数字 0,那么数组的第一个元素会被显示出来。
MicroPython 代码
这就是你如何在 MicroPython 中编写前面代码块程序的方法:
from microbit import *
import random
numbers = ["orange", "yellow", "green", "blue"]
while True:
if button_a.was_pressed():
display.scroll(numbers[random.randint(0, 3)])
在 MicroPython 中,我们使用方括号[和]来包含列表的元素,并用逗号分隔列表元素。我们还使用方括号通过元素的位置来访问列表中的特定元素。在此例中,random.randint命令返回一个 0 到 3 之间的数字,它被包含在方括号内。
编程总结
这只是对 micro:bit 编程的一个快速介绍。本书的所有代码都可以下载,因此你无需在开始进行实验和制作项目之前掌握编程。随着你逐步阅读本书,你将接触到新的模块和 MicroPython 语言特性,我会在它们出现时进行解释。
有关 micro:bit 的 MicroPython 的更多信息,请参见microbit-micropython.readthedocs.io。如果你是 Python 新手,你可能会发现我的书《编程 micro:bit:MicroPython 入门》(麦格劳-希尔出版社,2018 年)是这本书的有用补充。
下载代码
本书中的一些程序很长且复杂,输入这些代码可能不是像你这样的疯狂科学家愿意做的事情。如果你不想自己编写程序,你可以直接下载它们并将其闪存到你的 micro:bit 上。
下载 Blocks 代码
所有的 Blocks 代码都发布在 GitHub 上,地址是github.com/simonmonk/mbms/。当你点击一个 Blocks 代码链接时,项目将在浏览器中打开。
向下滚动 GitHub 页面,直到你看到类似于图 1-19 的内容。你要寻找的是一个包含所有 Blocks 代码程序链接的列表。

图 1-19:本书中所有程序的 Blocks 代码链接
要打开其中一个程序,只需点击链接。例如,图 1-20 显示了点击音乐门铃项目链接的结果。

图 1-20:跟随链接到音乐门铃项目的 Blocks 代码
你会注意到,图 1-20 看起来不像正常的 Blocks 编辑器窗口。这是因为你只是要在这里查看代码并将其闪存到你的 micro:bit 上使用。如果你想编辑代码,或者只是想在更熟悉的编辑器中查看代码,请点击右上角的编辑按钮。这将为你创建一个原始程序的副本,然后你就可以编辑这个副本。
下载 MicroPython 代码
你可以从github.com/simonmonk/mbms/下载 MicroPython 程序。
如果你习惯使用 Git 软件,你可以将整个项目克隆到你的计算机上。对于非 Git 专家,这里有一个逐步的指南,帮助你获取所有的代码。
-
访问
github.com/simonmonk/mbms/,然后点击绿色的 克隆或下载 按钮,选择 下载 ZIP,如 图 1-21 所示。![图片]()
图 1-21:下载本书的代码
-
找到你刚刚下载的 ZIP 文件(mbms-master.zip),然后提取其中的所有文件。
提取文件的过程会有所不同,具体取决于你使用的是 Windows、macOS 还是 Linux。在 macOS 和大多数 Linux 发行版中,打开 ZIP 文件时会自动提取文件。如果你是 Windows 用户,请注意,尽管 Windows 允许你查看 ZIP 文件的内容而不需要将文件提取到单独的文件夹中,但除非提取文件,否则你无法使用这些文件。在 Windows 中提取文件,右键点击文件资源管理器中的压缩文件,然后选择“提取所有”选项(见 图 1-22)。
![图片]()
图 1-22:在 Windows 中提取 ZIP 压缩包文件
提取的文件将保存在一个名为 mbms-master 的文件夹中。在这个文件夹内,你将找到另一个名为 python 的文件夹,在里面你将找到本书的所有 MicroPython 程序,每个程序都是单独的文件,扩展名为 .py。
-
不幸的是,你不能只需双击程序在 Mu 中打开它。要打开程序,首先打开 Mu 并选择“加载”选项。然后找到你想要打开的 MicroPython 程序。作为快捷方式,我建议你将刚刚下载的 python 文件夹中的所有 MicroPython 程序移动到 Mu 通常寻找程序的文件夹中。默认情况下,这个文件夹位于你的主目录下,名为 mu_code。现在,当你在 Mu 中点击“加载”按钮时,你将立刻看到所有的 MicroPython 程序。
总结
现在我们已经了解了 micro:bit 的一些基础知识,是时候开始进行一些真正的疯狂科学实验和项目工作了。我们将从使用 micro:bit 制作和检测声音开始。

第二章:超音速
在本章中,我们将探讨如何使用 micro:bit 播放声音。我们将教 micro:bit 播放音乐,甚至模仿语音,并通过将其连接到麦克风来让它听到声音。你将尝试几个实验,并创建两个简单的项目:第一个项目是一个音乐门铃,通知疯狂科学家访客到达,第二个项目是一个喊声计,测量并显示它检测到的声音的音量。
将扬声器连接到 micro:bit
有几种方法可以从 micro:bit 听到声音。你应该选择哪一种,取决于你想发出多少声音。
安静方法:耳机
也许从 micro:bit 获取声音的最简单方法是使用鳄鱼夹电缆将 micro:bit 连接到一副耳机(参见 图 2-1)。

图 2-1:耳机连接的鳄鱼夹
如果你仔细观察耳机上的金属插头,你会看到它实际上由三个部分组成,这些部分之间由塑料环隔开。这意味着插头有三个连接点。最靠近耳机线的部分是接地连接。使用鳄鱼夹将其连接到 micro:bit 的 GND(0V)连接。
另外两个连接器是用于左耳和右耳的音频信号。如果你想让两只耳朵都能听到声音,将鳄鱼夹放置在两个连接器之间,这样声音就会传到两个耳朵。你也可以将鳄鱼夹连接到插头的尖端,这样就只会有一只耳朵听到声音(如 图 2-1 所示)。无论哪种方式,将鳄鱼夹的另一端夹到 micro:bit 上的任意三个引脚之一:0、1 或 2。micro:bit 用户通常使用引脚 0 来输出音频。
注意 设计用于与手机一起使用的耳机,如果带有麦克风,其插头将有四个连接器,而不是三个。这个差异不应影响使用。你仍然可以将插头的尖端作为音频连接,将离插头体最接近的连接器作为接地(GND)连接。

为了稍微升级这个方法,你可以使用像 图 2-2 中所示的 音频插孔适配器。只需将耳机直接插入适配器,将黑线连接到 GND,另一根连接到引脚 0。像这样的适配器直接安装到耳机上,提供比鳄鱼夹更可靠的连接。

图 2-2:连接鳄鱼夹到 3.5 毫米音频插孔的适配器
低预算音响方法:扬声器
使用像 图 2-3 中所示的放大扬声器,你可以使用之前描述的相同连接方法,产生更多的声音:直接连接到扬声器插头或使用音频插孔适配器。

图 2-3:将 micro:bit 连接到放大音响
一些扬声器是专为与 micro:bit 配合使用而设计的。它们中的一些扬声器带有以鳄鱼夹结尾的电缆,可以连接到你的 micro:bit,而其他扬声器,如图 2-4 中展示的 Monk Makes 为 micro:bit 设计的扬声器,则以类似 micro:bit 引脚的插头结尾,便于通过鳄鱼夹电缆连接两者。

图 2-4:Monk Makes 为 micro:bit 设计的扬声器
增强型扬声器需要电源。在某些情况下,增强型扬声器可能有自己的电池或 USB 电缆。否则,micro:bit 本身可以为扬声器供电,届时设备需要在三个地方连接:连接到 micro:bit 的 GND(0V)和 3V,以为扬声器供电,并连接到第 0 引脚(或其他引脚之一),用于传输来自 micro:bit 的音频信号。
无论你使用什么音频输出设备,我们来测试一下吧!
实验 1:产生声音

在这个实验中,你将学习如何使用 micro:bit 和扬声器或耳机生成声音。
你将需要的工具
进行这个实验,你只需要:
Micro:bit
扬声器或耳机
鳄鱼夹电缆
你可以在附录中找到这些设备的来源。
这里我们假设你使用的是 Monk Makes 为 micro:bit 设计的扬声器和一套鳄鱼夹,但之前列出的任何扬声器连接方法都可以使用。
构建
-
使用图 2-1 到图 2-4 中显示的方法之一连接扬声器。然后将 micro:bit 插入计算机。
-
访问
github.com/simonmonk/mbms/来进入本书的代码仓库,然后点击实验 1:产生声音的链接。一旦程序打开,点击下载,然后将.hex 文件复制到你的 micro:bit 上。如果遇到困难,返回第一章,那里详细讲解了如何将程序加载到 micro:bit 上的过程。如果你更喜欢使用 Python,可以从同一个网站下载代码。关于如何下载和使用本书示例的说明,请参见第 34 页的“下载代码”部分。本实验的 Python 文件是Experiment_01.py。
-
一旦成功编程 micro:bit,按下按钮 A。你应该能通过扬声器或耳机听到一个音调!
代码
这个实验不需要太多代码。无论你使用 Blocks 代码还是 MicroPython,都只是检测按钮 A 是否被按下,然后播放一个音调。
Blocks 代码
该实验的 Blocks 代码如下所示。

代码使用 on button A pressed 块来运行 play tone 块,每当按下按钮 A 时都会执行。你将 play tone 块放入 on button A pressed 块中,使其卡入到位。然后从下拉菜单中选择你想听的音调(在这种情况下是 中央 C)和音符的时长(1 拍)。
MicroPython 代码
这是代码的 MicroPython 版本:
from microbit import *
import music
while True:
如果按下按钮 A:
music.pitch(262, 1000)
Python 有大量的 库,它们是执行特定任务的代码集合。通过要求你的代码使用这些库,你可以访问许多功能,而不必自己编写复杂的代码。音乐库就是一个例子:它包含了可以让你的 micro:bit 发出声音的函数。为了让 MicroPython 使用音乐库,你首先需要使用 import music 命令导入该库。
虽然 Blocks 代码会自动处理一些事情,比如知道多长时间运行一次代码以及以什么顺序运行代码,但 MicroPython 要求你在代码中明确指示这些内容。在这里,你使用 while True: 循环来告诉 micro:bit 一直检查是否有人按下按钮 A。
当有人按下按钮 A 时,音符通过 pitch 命令播放,该命令需要两个信息:音符的频率(262 是中央 C)和音符的时长(在这种情况下是 1000 毫秒,或者 1 秒)。
尝试的事情
你可能想尝试改变产生的音调。如果你使用的是 Blocks 代码,请返回浏览器并点击 编辑 按钮来修改代码,然后点击 中央 C。这将打开一个迷你键盘,你可以选择一个不同的音符来播放。要在 MicroPython 中更改音符,请输入一个新的数字来代替 262 作为频率。然后再次点击 闪烁 按钮。在本章后面,你将学习一种更好的方法来选择使用 MicroPython 播放的音符。
你还可以尝试让按钮 A 和按钮 B 都播放音调,甚至让它们播放不同的音调——一个和弦!
原理:频率与声音
micro:bit 如何在扬声器中产生声音?本质上,micro:bit 以极快的速度开关电流(电流的流动),导致扬声器的一部分振动,从而产生声音。micro:bit 开关电流的速度决定了声音的 频率,也就是它产生不同音调的原因。我将详细解释这一点。
图 2-5 显示了扬声器的各个部分。一个坚固的、通常是金属的框架将锥形固定在适当位置。这个锥形的窄端是圆柱形的,且有一根线圈绕在上面。在线圈的周围,固定在扬声器框架上的,是一个强大的磁铁。
当电流通过线圈时,它——因此整个锥形——会非常快速地前后振动。这种振动在空气中产生压力波,我们听到的就是声音。

图 2-5:扬声器
要发出特定的声音,扬声器的振膜需要每秒前后移动一定次数。扬声器每秒移动的次数就是它的频率,单位是赫兹(简写为 Hz)。频率越高,声音的音调越高。262 Hz 的频率对应钢琴上的中音 C。高一个八度的 C 频率为 524 Hz,即双倍的中音 C。在音乐中,当你升高一个八度时,频率也会加倍。
micro:bit 通过快速开关引脚 0 来控制电流和频率。当引脚 0 关闭时,输出电压为 0V;当引脚 0 开启时,输出电压为 3V。如果你绘制输出电压与时间的关系图,它将像图 2-6 那样。
出于显而易见的原因,这种波形被称为方波。由于 micro:bit 的输出只能是开或关,这就是我们从 micro:bit 生成的唯一类型的波形。

图 2-6:方波
当 micro:bit 将信号传输到扩音器时,扬声器会从 micro:bit 接收低电流信号,并增加电流,以更大功率驱动扬声器,从而使声音变大。
现在让我们尝试制作声音。
实验 2:它会说话!

micro:bit 的 MicroPython 软件有一个非常棒的功能,允许你让 micro:bit 朗读短语。在这个实验中,我们将尝试这个功能,让 micro:bit 跟我们说话。
虽然生成语音的软件是为英语设计的,但通过调整拼写,你应该能够让这个库用其他语言发声。
目前(写作时),这个功能不能通过 Blocks 代码使用,因此我们将使用 MicroPython。
你将需要的材料
这个项目使用的硬件与实验 1 完全相同。
Micro:bit
扬声器或耳机
鳄鱼夹电缆
构建
-
使用图 2-1 到 2-4 中展示的方法连接扬声器。
-
这个项目使用了语音库,而该库在 Blocks 代码中不可用,因此这个实验代码仅适用于 Python。访问
github.com/simonmonk/mbms/并下载Experiment_02.py 文件。你还可以在 GitHub 页面上找到其他项目的代码以及下载和使用书中示例的说明。将程序烧录到你的 micro:bit 中。 -
一旦 micro:bit 成功编程,按下按钮 A,你应该能通过扬声器或耳机听到语音信息。疯狂科学家喜欢听这个声音,因为它让他们想起了他们亲爱的老朋友霍金教授,遗憾的是他已经不在人世了。
代码
实验的 MicroPython 代码如下:
from microbit import *
import speech
while True:
if button_a.was_pressed():
speech.say("疯狂科学家喜欢 micro:bit")
除了导入语音库外,让 micro:bit 发声只需要将要说的文本放入 say 函数中。
语音库相当先进——你甚至可以使用它来调整音调,使你的 micro:bit 唱歌!你可以在microbit-micropython.readthedocs.io/en/latest/tutorials/speech.html了解更多关于该库的信息。
项目:音乐门铃

难度:简单
疯狂科学家特别喜欢音乐门铃。事实上,你不会感到惊讶,科学家最喜欢的曲子之一就是《星球大战》中的《帝国进行曲》。
在第十章中,我们将重新审视这个项目,添加第二个 micro:bit,使门铃能够无线工作。
这个项目(如图 2-7 所示)是实验 1 的一个变体,区别在于当按钮被按下时,门铃播放的是曲子,而不是单一的音调。我们将让按钮 A 播放一首曲子,按钮 B 播放另一首。你可以通过这个短视频查看项目的实际效果:youtu.be/xmLupw4PxYQ/。

图 2-7:音乐门铃项目
给访客提供两首曲子供选择,可以让他们表达访问的紧急程度。如果疯狂科学家正忙,他们就可以选择忽略门口的人!
你需要的材料
对于这个项目,你将需要以下物品:
Micro:bit 作为这个项目的控制器,提供两个按钮供按压
3 × 鳄鱼夹电缆 用于将 micro:bit 连接到扬声器(较长的电缆会更方便)
USB 电源适配器或带电源开关的 3V 电池包 用于为 micro:bit 和扬声器提供电源
扬声器 播放门铃曲(我推荐使用 Monk Makes Speaker 与 micro:bit 配合使用)
粘合胶或自粘垫 用于将 micro:bit 固定在门框上,扬声器固定在门框内部

如果你使用电池进行这个项目,最好使用带电源开关的电池盒,这样在不使用时可以关闭门铃以节省电池电量。否则,电池在使用约一天后就会耗尽。USB 电源提供了一个长期的解决方案,可以一直保持开启状态。
构建
在构建新项目时,总是值得在桌面上先进行构建和测试,然后再将其安装到实际使用的地方。
-
使用三根鳄鱼夹电缆将扬声器连接到 micro:bit,如图 2-7 所示。
使用颜色编码来区分你的电缆是个好主意,黑色表示 GND,红色表示 3V,其他颜色用于从 micro:bit 的 0 引脚连接音频。使用不同的颜色将帮助你跟踪连接。
-
访问
github.com/simonmonk/mbms/以获取书中的代码库,并点击 Musical Doorbell 的链接。程序打开后,点击 Download,然后将 hex 文件复制到你的 micro:bit 上。如果你遇到困难,可以回到第一章,我们会详细讨论如何将程序加载到你的 micro:bit。如果你更喜欢使用 Python,可以从同一个网站下载代码,并附带下载和使用书中示例的说明。这个实验的 Python 文件是 ch_02_Doorbell.py。 -
一旦 micro:bit 成功编程,按下 按钮 A,你应该能听到一段旋律(斯科特·乔普林的《娱乐者》)。现在按下 按钮 B,你将听到弗雷德里克·肖邦的《葬礼进行曲》。
-
一旦一切都正常工作,断开 micro:bit 与电脑的连接,然后将其插入 USB 电源适配器或电池盒。再次测试,确保它能正常工作。然后将 micro:bit 部分固定在门的一侧,扬声器部分固定在门的另一侧。这里有几点需要注意:
首先,即使使用粘性胶垫将东西粘贴到墙上也可能弄得一团糟,所以如果需要,确保你获得了许可。如果你使用的是粘性垫,这一点尤为重要,因为它们可能会永久粘在油漆上。
其次,鳄鱼夹需要从门的一侧穿过到另一侧,以确保它们在门关闭时不会被夹得太紧。因此,在开始粘贴之前,先弄清楚它们应该放在哪里。在第十章中,我们将制作该项目的另一个版本,使用第二个 micro:bit 提供无线连接。
最后,如果你使用的是 USB 电源适配器,你需要一个足够靠近的电源插座,以便 USB 电源适配器能够连接到你的 micro:bit。
代码
现在让我们来讲解这个项目的代码。
Blocks 代码
这是 Blocks 代码。

代码与实验 1 相似,但有一些不同之处。首先,我们有两组代码:一组用于按钮 A,另一组用于按钮 B。其次,我们从 repeating 菜单中选择 once,因为我们希望旋律只播放一次。
第三,我们使用 start melody 块来播放一整段旋律,而不仅仅是一个单音符。注意,这些旋律已经在块中提供——你只需要从菜单中选择它们!
MicroPython 代码
这是该程序的 MicroPython 版本:
from microbit import *
import music
while True:
if button_a.was_pressed():
music.play(music.ENTERTAINER)
elif button_b.was_pressed():
music.play(music.FUNERAL)
这与 Blocks 代码的工作方式完全相同。music.play 方法等同于 start melody 块,而我们使用 if 语句来检查哪个按钮被按下。if 语句允许按钮 A 和按钮 B 播放不同的曲调。
相同的预定义音调可以在 Blocks 和 MicroPython 代码中播放。
尝试一下
从预定义的曲调中选择是很不错,但疯狂科学家可能有自己独特的音乐口味。他们可能想创作自己的曲子!
如果你使用的是 Blocks 代码,你可以通过创建一系列 play tone 块来制作自己的曲调,就像这里展示的例子一样。你填写你想播放的音符,每个音符依次播放。

所以,如果你知道一首特定曲调的所有音符,你可以像这样创建它。你还需要指定每个音符播放的时长。在你让音乐听起来正如你所期望的那样之前,你可能需要做一些实验。
现在让我们看看如何在 MicroPython 中创建一首曲调:
来自 microbit 的 导入 *
导入音乐
notes = ['A4:4', 'A', 'A', 'F:2', 'C5:2', 'A4:4', 'F:2', 'C5:2', 'A4:4']
while True:
if button_a.was_pressed():
music.play(notes)
MicroPython 的音乐库通过允许你使用特殊符号来编写自己的旋律,负责播放整个曲调。每个音符由一串字符组成(有关字符串的更多信息,请参见 第一章)。字符串的第一个字符是音符名称(字母 A 到 G)。接下来是一个八度数——中央 C 属于第 4 八度,所以你可能希望将曲调限制在 3、4 和 5 八度之间。八度数是可选的,如果你没有提供,Python 将默认使用第一个八度。
一旦你指定了一个八度数,音乐库将假定这个八度数适用于所有后续音符,直到你指定一个不同的八度数。
接下来,你可以选择性地添加一个冒号,后面跟着一个时长。时长是以四分音符为单位的。例如,要播放中央 C 的半音符,你可以写 C4:2。
要将多个音符串联起来,你需要创建一个 列表。到目前为止,我们使用的变量只包含单个元素。列表就像一个可以包含多个元素的变量,你可以独立地访问和使用每个元素。为了表示 notes 变量包含的是一个值列表,而不仅仅是一个单一的值,你需要用逗号分隔数组中的各个值,并将整个列表用 [ 和 ] 括起来。
在我们的数组中,每个元素都是一个音符字符串。要播放整个音符序列,您可以使用 play 函数,并提供要播放的音符列表。这个例子播放的是 星球大战 中的“帝国进行曲”开头几小节的音符。
在这里,我们导入了常规的 microbit 库,以及音乐库。我们将我们的旋律保存在一个名为 notes 的变量中。然后我们创建了另一个 while True: 循环,以便代码持续运行并检查按钮是否被按下。我们告诉程序,如果按下 A 按钮,它应该播放 notes 变量。
项目:Shout-O-Meter

难度:简单
疯狂的科学家喜欢测量事物。为此,本项目制作了一个简单的声音计,它可以指示噪音的音量。这样,科学家就可以因邻居制造过多噪音而斥责他们——并证明他们确实有过多噪音。
所需物品
本项目需要一个麦克风来接收声音,以便测量其音量。我将使用 Monk Makes Sensor 中内置的麦克风,它配备了多个传感器。声音的音量随后会显示在 micro:bit 的 LED 显示屏上。声音越大,点亮的 LED 越多。
本项目需要以下物品:
Micro:bit 作为本项目的控制器,提供两个按钮供按压
3 × 鳄鱼夹电缆 用于将 micro:bit 连接到扬声器(更长的电缆会使操作更方便)
任何 micro:bit 电源 可以是 USB 计算机电缆或电池盒
Monk Makes Sensor for micro:bit 用于提供麦克风
构建
-
使用三根鳄鱼夹将传感器板连接到 micro:bit,如图 2-8 所示。你需要将传感器上的 3V 连接到 micro:bit 上的 3V,GND 连接到 GND,并将带有麦克风图标的孔连接到 micro:bit 的引脚 0。
最好遵循电缆的颜色编码,黑色用于 GND,红色用于 3V,其他颜色用于从 micro:bit 引脚 0 连接到麦克风。
![Image]()
图 2-8:Shout-o-meter 项目
-
访问
github.com/simonmonk/mbms/获取本书的代码库,并点击 Shout-O-Meter 的链接。一旦程序打开,点击 下载,然后将 hex 文件复制到你的 micro:bit 上。如果你在此过程中遇到问题,请回到第一章,我们会详细讨论如何将程序加载到 micro:bit 上。如果你更喜欢使用 Python,那么可以从同一网站下载代码,以及下载和使用书中示例的说明。此实验的 Python 文件为 ch_2_Shoutometer.py。
-
编程完成后,尝试在麦克风附近吹口哨(见图 2-9),注意 LED 如何响应声音的强度。你也可以尝试轻拍麦克风。你可以在这里看到一个项目运行的视频:
youtu.be/6pGDSHmfFng/。![Image]()
图 2-9:Monk Makes Sensor for micro:bit 麦克风
代码
该代码的 Blocks 版本能够利用内置的 plot bar graph of 块,而 MicroPython 版本则更为复杂,因为我们必须实现自己的这一功能版本。
Blocks 代码
Blocks 语言包括一个名为 plot bar graph of 的有用块,它使得显示声音水平的代码变得非常简单。

我们放入了一个 forever 块,因此里面的代码会不断运行。然后,我们添加了 plot bar graph of 块,它将显示来自麦克风的响度。
如你所见,从 micro:bit 的引脚 0 读取的模拟值会减去 511,然后传递给 plot bar graph of 块,并且最大值设置为 up to,最大值为 512。这一部分数学运算的原因在《如何工作:麦克风输出》一节中讨论,详见 第 59 页。
获取正确的块组合可能有点棘手,特别是在涉及到数学运算时。幸运的是,编辑器允许你自由移动块,因此如果它们没有放在正确的位置以获得你想要的结果,你可以将它们拖动到应该放置的地方。有关编辑代码的更多信息,请参见 第一章。
MicroPython 代码
MicroPython 版本的代码比 Blocks 版本稍微复杂一些。MicroPython 没有内置的条形图显示功能,因此我们必须自己编写。在 Blocks 版本中,plot bar graph of 块提供了一个平滑的显示,尽管数据变化迅速。而要在 MicroPython 中获得相同的效果,我需要添加代码从 10 个样本中读取最大声音水平。
from microbit import *
def sound_level():
max_level = 0
for i in range(0, 10):
sound_level = (pin0.read_analog() - 511) / 100
if sound_level > max_level:
max_level = sound_level
return max_level
def bargraph(a):
display.clear()
for y in range(0, 5):
if a > y:
for x in range(0, 5):
display.set_pixel(x, 4-y, 9)
while True:
bargraph(sound_level())
sleep(10)
我们使用 sound_level 函数并创建一个 for 循环来采集 10 个声音样本。每个样本值(与 Blocks 版本的代码一样)都是从模拟值中减去 511 得到的。然而,在这个例子中,为了将点亮的行数缩放到 0 到 4,我们将得到的值除以 100。然后,我们将存储在 sound_level 变量中的声音级别与 max_level 变量进行比较,如果 sound_level 更大,则将 max_level 更新为 sound_level。当所有 10 个样本采集完后,最大的值将存储在 max_level 中,并且这个值将由函数返回。
bargraph函数接受一个值,表示为a,来进行显示。值越高,点亮的 LED 越多,表示噪音越大。该值应介于 0 和 4 之间。如果大于 4,也没有关系——显示屏上的所有 LED 会被点亮,但不会有其他变化。该函数通过遍历显示屏的每一行来工作,如果a的值大于该行的行号,那么该行上的每个 LED 都会被内部的for循环点亮,for循环会判断x是否在 0 到 4 的范围内。
所有主要的while循环要做的就是调用bargraph函数,并传入由sound_level函数返回的声音等级。
工作原理:麦克风输出
图 2-10 显示了麦克风在检测声音时输出的图形。电压位于纵轴,时间位于横轴。

图 2-10:声音样本
正如你从图表的左侧所看到的,在声音开始之前,传感器的输出电压大约在 1.5V 处平稳。当声音开始时,电压在 1.5V 之上和之下振荡,麦克风拾取到声音的压力波。micro:bit 上的 1.5V 读数对应的模拟值是 511。正因为如此,在将读数显示在 micro:bit 上之前,我们需要从读数中减去 511;否则,在没有声音的情况下,显示屏上会有一半的 LED 点亮。
总结
在本章中,疯狂科学家探索了声音的世界,既通过 micro:bit 产生音乐和语音,也通过麦克风检测声音。我们已经开始了对 micro:bit 的探索,进行了一些简单的项目。
在下一章,我们将看看光。我们将用一个特殊的传感器来测量光,并使用 micro:bit 的 LED 显示屏。接着,我们将进行一个大型项目,使用多色的 NeoPixel 显示屏,并将光与声音结合,制作一个光控乐器。之后,我们将进入其他更具挑战性的项目。

第三章:光照强度
在本章中,我们将使用 micro:bit 来进行光照实验。首先,你将学习如何感知光照强度,然后我们将制作一款光控吉他,根据感应到的光强度来演奏音符。接着,我们将使用光线创建一个光学幻觉的无限镜面,似乎可以一直延伸,帮助疯狂的科学家深入思考。由于 MicroPython 目前没有光感应功能,因此本章将使用 Blocks 代码进行编程。
实验 3:感知光线

让我们看看如何使用 micro:bit 来测量光照强度。一旦你掌握了这个方法,你就能制作各种光依赖的项目,包括本章后面提到的自动夜灯和光控吉他。
micro:bit 的开发者非常巧妙地在设备的软件中构建了一项功能,允许它通过 LED 灯来测量光照强度。我将在第 63 页的“原理”部分解释这一点。
所需材料
你只需要一个 micro:bit 和一个 USB 线就可以进行这个实验。
构建
-
访问本书的代码库:
github.com/simonmonk/mbms/,点击实验 3:感知光线的链接。点击下载,然后将.hex 文件复制到你的 micro:bit 上。如果遇到困难,可以回到第 11 页的“编程 micro:bit”部分,那里详细讲解了将程序下载到 micro:bit 上的过程。记住,这个实验只适用于 Blocks 代码,因此没有 MicroPython 代码可以下载。 -
一旦你成功编程了 micro:bit,屏幕上应该会显示一个 0 到 9 之间的数字,表示 micro:bit 正在检测的光强度。试着用手遮挡 micro:bit,或者将其放在光源下,看看数字如何变化。
代码
这是本实验的 Blocks 代码。

光照强度块从 micro:bit 的光传感器读取数据,并给出一个介于 0 和 255 之间的值,表示亮度。然而,如果数字超过一位数,micro:bit 的 LED 显示屏将需要滚动显示,速度较慢且不方便。通过将数字除以 26,结果总是小于 10。
在显示光照强度后,micro:bit 会暂停半秒钟,以便你有时间阅读显示内容。否则,当光照强度变化时,数字会快速闪烁,难以看清。
原理
micro:bit 没有专门的光传感器。相反,它利用一种巧妙的技巧,通过显示屏来计算光照强度。你可以在lancaster-university.github.io/microbit-docs/extras/light-sensing/上了解这个技巧。
项目:自动夜灯

难度:简单
尽管他们不太愿意承认,疯狂科学家有点害怕黑暗。这就是他们开发一个使用 micro:bit 显示屏作为夜间自动亮起的灯光的项目的原因。

这个简单的项目是基于实验 3 的,能够监控光照水平,并在光线变得过暗时点亮 micro:bit 显示屏上的所有 LED 灯。
所需材料
这个项目唯一需要的就是 micro:bit。
因为 micro:bit 需要长时间开启,最好使用 USB 电源适配器或 Monk Makes Power for micro:bit(请参见“为 micro:bit 供电”在第 248 页)来完成这个项目。电池太快就会没电。
构建
-
访问本书的代码库,在
github.com/simonmonk/mbms/点击自动夜灯的链接。然后点击下载并将 hex 文件复制到你的 micro:bit 中。如果你在这过程中卡住了,可以返回到“编程 micro:bit”在第 11 页,那里我们完整地讨论了如何将程序传输到 micro:bit。 -
一旦你编程好了 micro:bit,屏幕应该会在你用手遮住 micro:bit 时亮起。当你移开手时,屏幕应该会熄灭。
代码
这个项目的 Blocks 代码如下所示。

这段代码使用了两个if块。第一个检查光照水平是否低于 10,这意味着环境非常黑暗。如果满足这个条件,代码会使用show leds块打开所有 LED 灯。
第二个if块会在光照水平大于 50 时将 LED 灯关闭。我们在 10 和 50 这两个光照水平之间留出了间隔,以确保当光照接近这两个值时,LED 不会闪烁。开关值之间的差异的技术名称是滞后现象。
项目:光吉他

难度:中等
现在是时候制作一个光控吉他了!当你在 micro:bit 前挥手时,这把吉他将播放不同的音调。你可以在www.youtube.com/watch?v=OFUYxIYCXQs观看这个项目的实际演示视频。
我建议将 micro:bit、扬声器和电池固定在一个吉他形状的纸板剪影上。(疯狂科学家在艺术方面不太擅长,所以图 3-1 中的相似度只是勉强能够体现。)

图 3-1:micro:bit 变成了一个乐器。
连接 micro:bit 和扬声器的电缆隐藏在纸板后面,以保持整洁。
所需材料
对于这个项目,你需要以下物品:
Micro:bit
3 × 鳄鱼夹电缆 用于连接 micro:bit 和扬声器
3V 电池包 用于为 micro:bit 和扬声器供电(带开关的类型效果最佳)。
用于 micro:bit 的扬声器 用来播放声音(可以使用 Monk Makes 扬声器,或者参见 第二章 获取其他扬声器选项)。
Blu-Tack 或自粘垫 用于将 micro:bit 固定在纸板剪影上
纸板 用于制作吉他主体(你可以使用一块拆开的纸箱)。
纸胶(PVA 或喷胶) 用于将纸质轮廓粘贴到纸板上
带吉他轮廓的纸(可选) 你可以选择自己在纸上画吉他,或者直接剪裁和装饰纸板。
剪刀 用于剪裁吉他的轮廓
构建
在将 micro:bit 固定到纸板之前,先创建并测试程序是个好主意,因此我们先进行这一步。
-
使用三条鳄鱼夹电缆将扬声器连接到 micro:bit,如 图 3-2 所示。
为了便于记忆不同的电缆,建议使用不同的颜色编码。黑色代表 GND,红色代表 3V,其他任何颜色都可用于连接 micro:bit 引脚 0 的音频连接。
![Image]()
图 3-2:将 micro:bit 连接到扬声器
-
打开
github.com/simonmonk/mbms/,点击 Light Guitar 项目。实验打开后,点击 下载,然后将 hex 文件复制到你的 micro:bit 中。 -
一旦你编程完成,micro:bit 应该会在你靠近它并遮挡部分光线时发出不同的音符。如果音符的范围不是很大,可能需要调整它的灵敏度(请参阅 第 71 页 了解如何调整)。
-
断开 micro:bit 与 USB 数据线的连接。在
github.com/simonmonk/mbms/,你会找到一个名为 other downloads 的文件夹,里面包含了吉他形状的 PDF、PNG 和 SVG 格式图纸。你可以自己画吉他,或打印出这个模板。 -
将吉他图纸粘贴到纸板上,如 图 3-3 所示。
![Image]()
图 3-3:将纸模板粘贴到纸板上
-
使用剪刀围绕吉他轮廓剪裁。还要剪出吉他主体上两个矩形区域,用于放置连接 micro:bit 和扬声器的电线。最终效果应如 图 3-4 所示。
![Image]()
图 3-4:围绕模板剪裁
-
使用小球状的 Blu-Tack,将扬声器和 micro:bit 固定在吉他上,确保它们的边缘连接器能够通过矩形插槽访问。同时,也要将电池盒固定好,如 图 3-5 所示。
![Image]()
图 3-5:将 micro:bit、扬声器和电池盒连接起来
当吉他上的三个部件都连接好后,项目应该像 图 3-6 中那样。
![Image]()
图 3-6:micro:bit、扬声器和电池盒已经连接到吉他上。
-
翻转整个设备,按照图 3-7 连接 micro:bit 和扬声器。如果你需要连接帮助,可以参考图 3-2。
![图片]()
图 3-7:连接 micro:bit 到扬声器
-
将电池盒连接到 micro:bit 上的电池连接器。你准备好开始演奏了!
代码
这个项目的块状代码使用了数组。

我们将需要在 micro:bit 启动时才运行的代码放入on start块中。这会创建一个音符数组。数组是一个值的列表,而不是单个值。我们使用数组来提供 micro:bit 可播放的八个可能音符。不同的光线水平会触发不同的音符。on start块中的第一行定义了一个名为notes的新数组,最初只包含音符中音 C。随后的add value块将数组中再添加七个音符,以便变量notes最终包含我们需要的所有八个音符。

forever块中的代码将不断执行。这段代码告诉 micro:bit 读取光线水平,然后根据这个信息选择要播放的音符。为此,代码首先使用light level块读取光线水平,并将读取值除以 25。如果你没有听到所有八个音符,可能需要通过稍微调低这个 25 的值来调整灵敏度。
set to块将结果值命名为note number。由于note number是光线水平除以 25,所以它的值将在 1 到 10 之间。
但将最大光线水平设置为 10 会导致问题。在访问数组中的项时,你需要指定要访问项的位置。我们在这个数组中可以指定的最大位置是 7(八个音符的编号是从 0 到 7)。我们希望吉他在光线较暗的室内工作。但是,如果光线非常明亮,那么note number可能会变成 10,这将超出数组的范围。为了确保我们不会超过note number的最大允许值,我们添加了if命令来检查note number是否大于 7。如果大于 7,代码将其设置为 7——问题就解决了。
play tone块访问notes数组中对应note number值位置的项,并播放该音符,持续时间为 1/8 拍。
项目:无限镜子

这个看似神奇的镜子(图 3-8)一定能给任何来访的疯狂科学家留下深刻印象。它内置在一个小相框中,镜子看起来比实际要深得多。

图 3-8:micro:bit 控制的无限镜子
您的 Micro:bit 将控制一个安装在相框内的 30 个 LED 灯带,我们会在 LED 灯带的两侧贴上反射膜,从而创造有趣的光效
您可以在* www.youtube.com/watch?v=-4Ud47OkIyY *查看此项目的演示视频。
注意 这个项目有点棘手,因为反射膜可能难以平滑处理。但如果坚持下去,效果是值得的!
所需物品
对于这个项目,您需要以下物品:
Micro:bit
0.5 米可寻址 LED 灯带(NeoPixels) 一条 WS2812B RGB 5050 SMD 灯带应每米 60 个 LED,总长度为 0.5 米,背面有自粘胶层
3 个鳄鱼夹到公跳线 用于将 Micro:bit 连接到 LED 灯带
Monk Makes 电源适配器 为 Micro:bit 和 LED 灯带供电。请注意,USB 电源无法提供足够的电流来支持此项目,而 AAA 电池包仅在电池非常新鲜时才足够提供电力
6V 直流墙插电源适配器 提供足够的电力给 LED 灯带。电源适配器的末端应有一个直流圆柱插头。(详见《为您的 Micro:bit 供电》第 248 页)
深型 7×5 英寸相框 见下文有关相框的更多信息。您需要一个带有塑料间隔器的相框,深框通常会包含此类间隔器
两块 7×5 英寸的反射窗膜 反射窗膜样品
工艺刀 用于切割反射膜并在相框间隔器上为 LED 灯带的电线制作槽口
肥皂水 用于清洁玻璃并贴上薄膜
尺子或塑料卡 用作刮板
胶带 用于从反射窗膜上移除背膜
寻找一个 7×5 英寸(17.5×12.5 厘米)的相框,里面设计有适合 6×4 英寸照片的插槽。相框的重要特性是它有足够的深度,因此请寻找像图 3-9a–b 所示的相框。我使用的相框深度为 1.25 英寸。还要确保相框正面有玻璃。玻璃背后应有一个塑料间隔器(我们将在其上粘贴 LED 灯带),然后是背板

图 3-9:无限镜深框相框:(a)正面和(b)移除背面后
反射膜反射光线,因此它像镜子一样工作。通常,它是大卷的,用于贴在建筑物的窗户上。幸运的是,销售这种膜的人通常也会提供小样品,这些样品足够满足我们的需求。您可以通过在 eBay 或 Amazon 上搜索银色反射镜窗膜来轻松找到它,然后浏览列表,直到找到提供样品尺寸的人
你需要两块至少为 7 × 5 英寸的材料,但我建议多准备一些;将膜贴在相框玻璃上并去除气泡有点棘手,因此最好有几张备用材料,以防第一次尝试失败。
最容易找到可寻址 LED 灯带的地方是 eBay,但它也可以通过像 Adafruit 和 SparkFun 这样的硬件网站购买。使用搜索词 WS2812B RGB 5050 LED Strip。你需要购买每米 60 个 LED 的灯带。这个项目需要半米长,所以总共 30 个 LED。这些 LED 灯带有两种类型:防水型(用于户外)或自粘背胶型。你需要的是带有自粘背胶的类型。
构建
现在你已经准备好材料,我们将把 LED 灯带和反光膜固定到框架上。编程 LED 灯带后,光线将看似永远向框架内部延伸,制造出框架比实际更深的错觉。
-
在你开始构建项目硬件之前,确保 LED 灯带与 micro:bit 兼容是值得的。为了测试它,使用三根鳄鱼夹跳线将 LED 灯带连接到 micro:bit。
请注意,也可以使用公对公跳线和普通鳄鱼夹连接灯带。
同时连接 DC 电源适配器和 Monk Makes Power for micro:bit 板,如图 3-10 所示。
![Image]()
图 3-10:使用 micro:bit 测试 LED 灯带
鳄鱼夹跳线的引脚将插入连接到 LED 灯带的三路连接器。你的 LED 灯带可能与图 3-10 中显示的颜色线不同,因此最好查看灯带本身,看看线缆连接的位置。一根线会标记为 GND;将其连接到 micro:bit 的 GND 接口。第二根线会标记为 5V;将其连接到 micro:bit 的 3V 接口。中间的最后一根线会标记为 DIN(数据输入)或指向 LED 的箭头。将这根线连接到 micro:bit 的引脚 0。
-
访问
github.com/simonmonk/mbms/并点击 Magic Mirror 链接。点击 下载 下载代码,然后将 hex 文件复制到你的 micro:bit 上。如果遇到问题,请返回第 11 页的“编程 micro:bit”部分,在那里我们详细讨论了如何将程序上传到 micro:bit。如果你更喜欢使用 Python,那么可以从同一个网站下载代码。关于如何下载并使用本书中的示例,参见第 34 页中的“下载代码”。这个项目的 Python 文件是 ch_03_Magic_Mirror.py。
-
一旦你将程序加载到 micro:bit 上,你应该能看到 LED 灯带随即随机闪烁。
图 3-11 展示了如何从相框构建无尽镜。
![图片]()
图 3-11:无限镜的构造方式
以下步骤将指导你完成这个部分的项目构建。
-
拆开相框并取出塑料插入件。使用工艺刀,小心地在插入件的一个角落切出一个槽,正如图 3-12 所示,供 LED 条带的电缆通过。
警告 工艺刀非常锋利,因此请小心使用,并请求成人帮助。
![图片]()
图 3-12:在塑料插入件上切割电线槽
-
在不去掉背胶的情况下,将 LED 条带放置在塑料插入件的边缘。如果条带不够长,你可以将其拉伸过角落,正如图 3-13 所示。确保它合适后,撕下背胶膜并将 LED 条带固定在插入件的内侧。
![图片]()
图 3-13:将 LED 条带固定到塑料插入件上
-
现在将插入件放到一旁。下一步是将反射膜附着到玻璃上。小心地取下框架的玻璃并用肥皂水清洗。擦干一面,并将其湿面朝上放下。
拿起反射膜。膜的粘性面上会有一层透明塑料背纸。要分离这层薄透明层,可以在膜的两侧贴上胶带并将其拉开(图 3-14)。
![图片]()
图 3-14:去除反射窗膜的塑料背纸
将反射膜的粘性面朝下放置在湿玻璃上。使用塑料卡片或尺子,将膜与玻璃之间的气泡推到玻璃边缘以去除它们(图 3-15)。
![图片]()
图 3-15:去除反射窗膜上的气泡
-
让膜干燥大约一小时。然后将玻璃翻转过来,使用工艺刀将膜修剪成与玻璃相同的大小(图 3-16)。
![图片]()
图 3-16:修剪反射窗膜
-
将框架的背板放在第二块反射膜上,并将膜剪裁成与背板框架相同的大小(图 3-17)。除非膜在重新组装框架时无法平整地贴合,否则不需要去除保护膜或将膜粘贴到背板上。
![图片]()
图 3-17:为背板修剪反射窗膜
-
现在是时候组装框架了。
将玻璃放回框架中,玻璃面朝外。这样可以保护膜并使镜面效果更佳(图 3-18a)。如果你的相框里有一张薄纸板是为了配合更小的照片使用的,你可以在玻璃后面放入这块纸板。
接下来,将塑料插入物放回框架中,让电缆从一角穿出(见图 3-18b)。如果插入物有一个较宽的平面设计来支撑照片,应确保平面面朝外,远离玻璃。
最后,将纸板放回框架上,让电缆从一角穿出(见图 3-18c)。固定背板,并将完成的框架翻转过来(见图 3-18d)。
![Image]()
图 3-18:重新组装框架
-
重新连接你的 micro:bit,魔镜应该开始运行。
代码
我们希望编程使 LED 随机闪烁。为此,代码会随机选择一个 LED,然后生成一个随机颜色并将该颜色设置为该 LED 的颜色。
Blocks 代码
以下是该项目的 Blocks 代码。

当使用可寻址的 LED(在 Blocks 代码中称为 NeoPixels)时,你需要将 NeoPixel at 块赋值给一个变量,在此我们称之为 leds,并将其放入 on start 块中。你必须为 NeoPixel at 块提供控制 LED 的引脚。在此案例中,我们使用引脚 P0。然后指定 LED 条上的 LED 数量,我们这里是 30 个。最后,告诉 NeoPixel at 如何定义颜色。在此案例中,颜色使用标准的 RGB 格式。
我们再次使用 forever 块来使代码不断运行。在 forever 块中,我们首先使用 pick random 块生成一个 0 到 29 之间的随机数字,并将其分配给变量 led。这会随机选择一个 LED。然后,将 color 变量赋值为随机的红色、绿色和蓝色值(范围为 0 到 255)。
show 块会更新 LED 条以反映我们刚刚做出的更改。
尝试修改代码来改变 LED 颜色。
MicroPython 代码
这是代码的 MicroPython 版本。
from microbit import *
import neopixel, random
leds = neopixel.NeoPixel(pin0, 30)
while True:
led = random.randint(0, 29)
color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
leds[led] = color
leds.show()
sleep(5)
这段代码与 Blocks 版本的工作原理非常相似。请注意,程序顶部需要包含 neopixel 和 random 库,以便访问 LED 条并生成随机数字。
MicroPython 的 neopixel 库首先将 LED 条定义为使用 pin 0,这就是我们将其连接到的 micro:bit 引脚,并且长度为 30 个 LED。它通过命令 leds = neopixel.NeoPixel(pin0, 30) 来完成这个定义。
然后,while 循环执行与 Blocks 版本中的 forever 块相同的操作,随机选择一个 LED 并将其设置为随机颜色。
原理
图 3-19 展示了无限镜像是如何工作的。

图 3-19:光线在无限镜像项目中反弹
来自 LED 的光朝四面八方传播(见图 3-19 中的 A)。其中一些光向上传播,朝画框的前方。镜面薄膜将其中一部分光反射回到画框后部的镜子(B)。剩余的光逃出画框(C),其中一些光会进入你的眼睛后部,在那里形成影像。
与此同时,一些射向镜子(B)的光会再次反射向前玻璃(D)。其中一部分光将完全从画框中逃逸,并进入你的眼睛,剩余的光将进行另一次反射。正是这种光的来回反射,导致 LED 灯看似不断消失在镜子中,每次都会因部分光线丧失而变得越来越暗。
总结
在本章中,你已经学会了如何用你的 micro:bit 进行光的测量和产生。在第四章中,疯狂科学家将注意力转向磁性。

第四章:神奇的磁力
正如你在第一章中看到的,micro:bit 有一个内建的磁力计,可以用于多种目的。在这一章中,我们将用它将你的 micro:bit 变成一个指南针,告诉你你面朝哪个方向。我们还将测量钕磁铁的磁场。接着,我们将制作一个磁力报警器,门一打开就响。
项目:指南针

难度:简单
在这个项目中,如图 4-1 所示,你将使用 micro:bit 内建的磁力计作为指南针。它会在屏幕上显示一个箭头,指向磁北。

图 4-1:用 micro:bit 指南针寻找北方
与传统的指南针不同,这款指南针并不总是指向北方。相反,它会显示你需要转向哪个方向才能面朝北方。
转动直到箭头正对前方,且你正面朝北!
所需材料
对于这个实验,你将需要:
Micro:bit
电池组
你只需要一个 micro:bit 就可以制作这个指南针,但如果你计划在户外导航,那么你还需要一个电池组。

构建
-
访问
github.com/simonmonk/mbms/来访问本书的代码库,并点击Compass链接。程序打开后,点击下载,然后将.hex 文件复制到你的 micro:bit 上。如果你在这部分遇到问题,请返回第一章,那里有完整的将程序加载到 micro:bit 的过程说明。如果你更喜欢使用 Python,那么可以从同一网站下载代码,并附带下载和使用本书示例的说明。此实验的 Python 文件是ch_04_Compass.py。
-
一旦你将程序加载到 micro:bit 上,你将看到一个提示信息,指示你以某种方式移动 micro:bit。请按照指示进行操作。每次你将使用磁力计的程序闪存到 micro:bit 上时,这个提示都会出现。
以这种方式移动你的 micro:bit 的目的是为了校准其磁力计。micro:bit 上的磁力计芯片对局部磁场变化非常敏感。通过改变磁力计的方向,你帮助它的内部过滤软件补偿地球磁场的局部扭曲。这就是为什么如果你把 micro:bit 带到室外,远离常见的室内金属物体时,最好重新校准你的指南针。另外,电池组可能会影响磁力计,因此最好使用最终项目中将要使用的硬件进行校准。
校准 micro:bit 的磁力计有点像做拼图。当你移动 micro:bit 时,更多的 LED 灯会亮起(参见图 4-2)。
![Image]()
图 4-2:校准你的 micro:bit 磁力计
-
要使用指南针,请将电池包连接到 micro:bit,并将其带到户外,远离计算机和家用电器等物品。保持 micro:bit 水平(即平放)。如果箭头指向右或左,慢慢转动,直到箭头指向正前方。当箭头指向正前方时,表示你正面朝磁北。
如果指南针未指向北方,请尝试再次按A 键进行校准。
代码
Blocks 和 MicroPython 版本的代码遵循相同的模式。heading或bearing(micro:bit 指向的方向)被测量,然后程序决定应该显示哪一个箭头(北、东或西)来引导用户朝正确的方向前进。
Blocks 代码
这是这个项目的 Blocks 代码。

在这个项目中,我们将设置代码,以便你可以随时通过按 A 键来校准磁力计。
calibrate compass块位于on button A pressed块内。calibrate compass块将显示我们之前用于校准磁力计的点。你可以像我们在项目开始时那样,围绕显示屏旋转它。
在forever语句块中,将compass heading的值(0 到 359 度)赋给名为heading的变量,该变量将保存这个方向值。
然后创建一个大的if语句块,其中包含if、else if和else。这个大语句块将测试 micro:bit 的朝向,并在 LED 显示屏上显示一个箭头,告诉你应该转向哪个方向以面朝北方。
如果你自己编写这段代码,你会注意到 Blocks 代码库似乎只提供两种类型的if语句块:if then和else。要添加else if then部分,请点击图 4-3 中的+号。

图 4-3:向 if 语句块添加另一部分
大的if语句块的第一行用于测试heading是否在 10 到 180 度之间,其中 0 度表示北方。因此,heading值在 10 到 180 之间表示你正面朝东。在这种情况下,micro:bit 会显示指向左侧的西方箭头。这个箭头告诉你向左转,以便面朝北方。
如果heading不在 10 到 180 之间,则else if部分会测试heading是否大于等于 180 并且小于 350 度。如果是,那么 micro:bit 会显示东箭头,告诉你向右走。
如果heading在 350 到 10 度之间,那么if语句块的else部分会显示指向前方的北方箭头——你走在正确的道路上!图 4-4 展示了这一工作原理(数字是heading的可能值)。

图 4-4:箭头将指向三个方向之一,引导你朝北方。
MicroPython 代码
这是该项目的 MicroPython 代码:
from microbit import *
while True:
heading = compass.heading()
if heading > 10 and heading < 180:
display.show(Image.ARROW_W)
elif heading >= 180 and heading < 350:
display.show(Image.ARROW_E)
else:
display.show(Image.ARROW_N)
if button_a.was_pressed():
compass.calibrate()
这段代码使用与其块编程等效的逻辑:它检查磁力计的读数,并告诉 micro:bit 显示箭头。同样,如果方向在北方 10 到 180 度之间,micro:bit 会显示一个指向西方的箭头;如果在 180 到 350 度之间,micro:bit 会显示一个指向东方的箭头;如果方向在北方 20 度以内,箭头会指向正上方,告诉你继续沿着这个方向前进。
可尝试的操作
看看你能否用一个磁铁让指南针混淆北方的方向。
工作原理:地球的磁场
地球的磁北极和磁南极具有强大的电荷,形成了一个环绕地球的磁场,如在图 4-5 中所示。

图 4-5:地球的磁场
micro:bit 的磁力计测量地球磁场的强度,从而推断出 micro:bit 面对的方向。
有趣的是,磁北极并不完全位于地球自转球体的顶部。根据你所在的位置,磁场的中心可能会偏离地理北极多达 20 度。
关于磁极的另一个有趣事实是,它们每年以大约 6 英里(10 公里)的速度移动。某一天,磁极将完全翻转,意味着磁北将位于地球的南端。这个过程大约每 45 万年发生一次。
实验 4:测量磁场

难度:中等
如我们刚刚看到的,micro:bit 内置的磁力计足够灵敏,你可以用它作为指南针来找到北方。它还是测量附近磁铁强度的好工具。在这个实验中(如图 4-6 所示),你将测量不同距离下磁场的强度。
你将需要的材料
在这个实验中,你将需要以下设备:
Micro:bit
强力钕磁铁
直尺(最好能显示毫米)
你可以在 eBay 上找到各种形状和大小的磁铁。正如在图 4-6 中所示,我使用的是一个直径为 10 毫米的圆盘形磁铁,但任何类似大小的钕磁铁都应该可以使用。请注意,我在磁铁的一侧贴了一小块标有N的胶带(稍后会详细介绍)。

图 4-6:用于实验 4 的钕磁铁
警告 钕磁铁非常强大,处理时要小心。如果两个磁铁粘在一起,分开它们可能会很困难。
构建
该程序会反复在 micro:bit 的显示屏上滚动一个数字。这个数字表示磁力计检测到的整体磁场强度。我们将测量磁铁在不同距离下的磁场强度。
-
请访问
github.com/simonmonk/mbms/以访问书籍的代码库,并点击 实验 4:磁场 的链接。程序打开后,点击 下载,然后将 hex 文件复制到你的 micro:bit 中。如果在这个过程中遇到困难,请返回第一章,那里详细解释了如何将程序传输到 micro:bit。如果你更喜欢使用 Python,可以从同一网站下载此项目的代码,并按照说明下载和使用书中的示例。此实验的 Python 文件是 Experiment_04.py。
-
将磁铁放置在平坦的表面上,使其平衡地摆放在弯曲的边缘上。由于钕磁铁的磁力非常强,如果将它这样放置,它会自行与地球的磁场对齐(通过旋转直到一面朝北),就像指南针的指针一样。让磁铁自行对齐,然后在朝北的一侧贴上胶带。(你可能需要使用本章早些时候提到的指南针项目来找到北方,避免误标记南方。)
-
调整尺子,使 0 厘米标记指向北方,30 厘米标记指向南方,如图 4-7 所示。尺子帮助确保磁铁持续朝北,以保持地球磁场的影响不变。
![图片]()
图 4-7:将尺子放置在南北方向,确保磁铁持续朝北。
-
将磁铁放置在尺子上的 1 厘米标记旁边,确保北面朝向 micro:bit。将 micro:bit 朝南并使其边缘与 0 厘米标记对齐。记录显示在 micro:bit 上的读数,并将其写入下表的 1 厘米行。磁场强度的单位是 特斯拉(非常非常强的磁场),因此 micro:bit 的读数以 微特斯拉(即特斯拉的百万分之一,符号为µT)表示。
micro:bit 到磁铁的距离(厘米) 磁场强度(µT) 1 ___________________________________ 2 ___________________________________ 3 ___________________________________ 4 ___________________________________ 5 ___________________________________ 6 ___________________________________ 7 ___________________________________ 8 ___________________________________ 9 ___________________________________ 10 ___________________________________ -
将磁铁移动到刻度尺上的 2 cm 标记旁边。在表格中的相应行输入 micro:bit 上显示的新数字。对于所有的读数,直到 10 cm,都重复这个过程。请注意,当你将磁铁从 micro:bit 移开时,磁场强度会迅速减小。
-
一旦你完成了所有的读数,试着绘制一个结果图。让纵轴,即Y 轴,显示磁场强度(单位:µT),并将磁铁距离 micro:bit 的距离(单位:cm)绘制在横轴,即X 轴上。
你可以手动在纸上绘制这个图表,或者,如果你愿意,你可以复制我为这个实验创建的 Google 表格,并将我的读数替换为你刚刚记录下的数字。你可以在
github.com/simonmonk/mbms/上找到这个表格的链接。打开这个链接后,在表格菜单中选择 文件▸创建副本 来创建你自己的副本。图 4-8 显示了完成的表格,下面是一个包含读数的图表。请注意,你的读数可能不同,因为你的磁铁可能比我的强或弱。
![图片]()
图 4-8:绘制你的结果图表。
我们将在“工作原理:磁铁的强度”部分讨论这些结果,详见 第 99 页。
代码
这个实验的代码很简单。它读取数据,显示结果,然后重复。
积木代码
这是这个项目的积木代码。

show number 块显示 magnetic force 块的结果,并且位于 forever 块内。
magnet force 块有四个选项,你可以在该块的下拉菜单中查看。你可以选择获取 X、Y 或 Z 维度中任意一个维度的单独读数,或者获取三个维度的组合力测量值。我们将使用组合测量值,即下拉菜单中的 strength 选项。
MicroPython 代码
这是该项目的 MicroPython 版本代码:
from microbit import *
while True:
display.scroll(str(int(compass.get_field_strength() / 1300)))
在 MicroPython 中,get_field_strength 函数从 micro:bit 的磁力计中获取读数。与积木代码中的 magnetic force 块不同,MicroPython 代码没有指定返回结果的单位,但我们得到的读数大约是 magnetic force 块返回读数的 1,300 倍。因此,需要将该数值除以 1,300,然后使用 int 函数将其转换为整数。
使用 str 函数将数字转换为文本字符串,以便 scroll 函数能够将其显示在 micro:bit 屏幕上。
可尝试的操作
使用实验 4 的程序,尝试将磁铁移得更远,以查看磁铁能移多远,但仍能在 micro:bit 上显示。
工作原理:磁铁的强度
图 4-8 中的图表显示,当你将磁铁移远 micro:bit 时,磁场强度最初会迅速下降,然后逐渐趋于平稳。事实上,磁场强度和磁铁之间的距离之间的关系遵循所谓的 反平方定律。也就是说,磁场强度与磁铁距离的平方根的倒数成正比。
这意味着,当磁铁与 micro:bit 之间的距离加倍时,磁场强度将下降到之前强度的四分之一。
地球的磁场强度在地面上测量时范围为 25 至 65 微特斯拉(µT)。当你测量没有附近磁铁时的磁场力,应该会得到这个范围内的读数。即使是实验中使用的超强钕磁铁,在几厘米的距离下,磁场强度也只有几百微特斯拉。用于磁共振成像(MRI)扫描时查看人体内部的磁铁,通常其磁场强度(即人躺的位置)为 0.5 至 1.5 特斯拉(T)。这比钕磁铁强几千倍。这就是为什么你进入 MRI 扫描仪时必须摘下身上的所有金属物品!
项目:磁性门铃报警器

难度:中等
我们将创建一个门铃报警系统!通过将磁铁安装在门上,并将 micro:bit 安装在门框上,疯狂科学家就能在客人到达时收到提醒。当 micro:bit 检测到磁场强度变化时,它将发出报警声音。这正是当有人打开门时,磁铁远离时发生的情况。
图 4-9 显示了项目安装在疯狂科学家门上的样子。

图 4-9:磁性门铃报警器
所需材料
对于这个项目,您将需要以下物品:
Micro:bit
3 × 鳄鱼夹连接线 用于将 micro:bit 与扬声器连接。这些线缆至少应该长 15 厘米(6 英寸)。
USB 电源适配器或带开关的 3V 电池包 用于为 micro:bit 和扬声器供电。有关为 micro:bit 提供电源的其他选项,请参见附录。
扬声器 您可以使用在第二章中讨论的任何方法将声音从 micro:bit 输出。在这里,我使用了一个 Monk Makes 扬声器。
粘性腻子或自粘垫片 用于将 micro:bit 和扬声器固定到门框上,并将磁铁固定到门上
钕磁铁 如实验 4 中使用的磁铁
构建
在将项目安装到门上之前,确保先进行测试,因为你需要进行一些实验来确定使用的正确磁场强度。你还需要在将其粘贴到门框之前校准磁力计。
-
如图 4-9 所示,使用三根鳄鱼夹连接线将扬声器连接到 micro:bit。
最好通过使用黑色电缆连接 GND,红色电缆连接 3V,其他颜色连接 micro:bit 的引脚 0 来进行电缆配色。这样,你就不会忘记哪个电缆是哪个。你需要将扬声器至少放置 15 厘米远离 micro:bit,因为扬声器有强大的磁铁,会干扰 micro:bit 的磁力计。
-
访问
github.com/simonmonk/mbms/获取书籍的代码仓库,并点击 磁性报警 的链接。一旦程序打开,点击 下载,然后将 hex 文件复制到你的 micro:bit 上。如果在此过程中遇到问题,可以返回到 第一章。如果你更喜欢使用 Python,你可以在同一网站上找到该代码,并查看如何下载和使用书中的示例。这个实验的 Python 文件是 ch_04_Magnetic_Alarm.py。
-
一旦你编程完成 micro:bit,当你将磁铁靠近 micro:bit 时,扬声器应该保持静音。然后当你将磁铁移开几英寸时,警报应该响起。程序正常工作后,断开 micro:bit 与计算机的连接,并将其连接到 USB 电源适配器或电池包上。然后将 micro:bit 和扬声器固定在门框上。将磁铁固定在门上,距离 micro:bit 不超过一英寸(2.5 厘米)。
警告 粘合剂可能会弄得一团糟,因此在开始将物品粘贴到门和门框上之前,确保获得许可。
如果你使用的是 USB 电源适配器,确保有一个靠近门的电源插座,以便 USB 电源适配器能连接。

代码
在这两个版本的代码中,首先读取磁场强度,然后与阈值进行比较。如果超过阈值,就会播放一个音符。
块代码
这是该项目的块代码。

这段代码基本上是说,如果 micro:bit 读取到的磁力强度小于 100 µT,它应该播放一个特定的音符,持续 4 拍。由于地球表面的磁场强度范围是 25 到 65 µT,将阈值设置为 100 µT 应该能确保我们检测到的是磁铁,而不是地球的磁场。
MicroPython 代码
这是该程序的 MicroPython 版本:
from microbit import *
import music
while True:
if compass.get_field_strength() < 160000:
music.pitch(523, 1000)
这段代码与 Blocks 代码的工作方式相同,但由于get_field_strength的单位与magnetic force块的单位不同,触发警报的阈值与 Blocks 代码版本不同。get_field_strength返回的磁场强度单位在其文档中没有明确说明 (microbit-micropython.readthedocs.io/en/latest/compass.html),因此我通过反复试验选择了 160,000 作为阈值。
我们通过命令 music.pitch 来指定产生的音调频率。与 Blocks 代码不同,在这里我们需要指定声音波的频率,而不是音符的名称。523 赫兹(Hz)是高 C 的频率。music.pitch命令还需要指定播放音符的时间长度。在这里,我们告诉 micro:bit 播放这个音符 1,000 毫秒,即 1 秒。
尝试的事项
小偷能突破你的新警报吗?试着将第二个磁铁放在门框的另一侧,正对着 micro:bit。如果第二个磁铁足够接近 micro:bit,你可能能够在不触发警报的情况下打开门。
你也可以通过改变频率来更改警报音调。下表显示了一些音符及其对应的频率(四舍五入到最接近的整数)。
| 音符 | 频率(Hz) |
|---|---|
| 中央 C | 262 |
| D | 294 |
| E | 330 |
| F | 349 |
| G | 392 |
| A | 440 |
| B | 494 |
| 高 C | 523 |
你可以在 www.liutaiomottola.com/formulae/freqtab.htm 找到完整的音符及其频率表。
总结
micro:bit 的磁力计不仅可以用来判断你朝哪个方向。 在这一章中,我们探索了如何利用它感应磁铁的存在,甚至通过测量磁场强度来做一些科学实验。
在下一章,我们将探索 micro:bit 的另一个内置传感器——加速度计。

第五章:神奇的加速度
加速度计可以说是 BBC micro:bit 内置传感器中最有用的一个。它可以让你测量作用在 micro:bit 上的力的方向和强度,比如重力。
你可以用加速度计做很多事情,包括:
检测摇晃等手势,甚至检测到你的 micro:bit 正在掉落
学习 micro:bit 的倾斜方向和幅度,并使用这些控制你的 micro:bit
测量 micro:bit 加速的速度(例如,你可以在计步器中使用它来查看你一天走了多少步。)

实验 5:手势

micro:bit 的软体包括手势识别,因此它可以响应加速度计感应到的特定动作,如倾斜或摇晃。在本节中,你将编写程序,使 micro:bit 在摇动时显示一个笑脸。
在本章稍后的部分,你将学习如何处理直接来自加速度计芯片的原始数据,以便你可以测量加速度。
你需要的东西
在本实验中,你只需要你的 micro:bit。
构建
-
访问
github.com/simonmonk/mbms/获取书中的代码库,并点击链接进入 实验 5:手势。程序打开后,点击 下载,然后将 hex 文件复制到你的 micro:bit 上。如果你更喜欢使用 Python,可以从同一网站下载代码。关于下载和使用书中的示例的说明,请参见 第 34 页 的“下载代码”部分。本实验的 Python 文件是 Experiment_05.py。 -
程序启动后,摇动你的 micro:bit,你应该能看到一个笑脸出现在屏幕上,然后消失。
代码
在程序中使用手势在 Blocks 和 MicroPython 中是相似的。两种语言都有相同的手势类型。主要的区别在于,MicroPython 没有事件机制来处理事件;相反,你需要在循环中不断检查手势。
Blocks 代码
这是本实验的 Blocks 代码。

在 Blocks 代码中可用的加速度手势作为事件工作,就像按按钮一样。首先使用一个on块。点击三角形以访问可能手势的下拉菜单,如图 5-1 所示,选择shake。

图 5-1:选择不同的手势
不同的手势
摇晃手势会响应任何显著的摇晃动作。接下来的两个手势,logo 向上和 logo 向下,分别响应 micro:bit 前后倾斜。此代码所指的 logo 是印刷在 micro:bit 板上、靠近 USB 接口的图标。
屏幕向上和屏幕向下的手势响应 micro:bit 的方向。例如,如果你将其屏幕朝下放置,你就会触发屏幕向下事件。
左倾和右倾事件在你将 micro:bit 向左右倾斜超过约 60 度时触发。你需要大幅度倾斜它才能触发这些事件。
最后的四个事件与加速度计上的总力有关,而不是某个特定方向的力。例如,如果 micro:bit 处于自由落体状态,那么自由落体将触发自由落体事件。手势 3g、6g 和 8g 检测加速度计上作用的不同力,单位为g(即重力加速度,或称g 力)。例如,你可以检测到手指轻拍 micro:bit。轻拍 micro:bit 时并不会使其移动很多,因此你可能认为涉及的力不大,但事实上,轻拍可以施加相当高的 g 力。
MicroPython 代码
以下是此实验的 MicroPython 代码:
来自 microbit 的 import *
while True:
if accelerometer.was_gesture('shake'):
display.show(Image.HAPPY)
sleep(500)
display.clear()
你会认出大部分代码。我们导入了常见的库,然后启动一个while True循环,使主代码持续运行。这个循环检查 micro:bit 是否检测到摇晃,如果检测到,则显示笑脸!
因为 MicroPython 没有“事件”这个概念,所以你必须在 while 循环中使用 was_gesture 函数来检查摇晃手势。你还可以将 shake 替换为 up、down、left、right、face up、face down、freefall、3g、6g 或 8g。
可以尝试的事项
尝试在实验 5 中为程序添加更多手势。你甚至可以让每个手势触发屏幕上的不同图标。
在 第十章中,你将再次使用手势检测来控制 micro:bit 驱动的机器人漫游车!
工作原理:力、加速度与重力
我们一直在谈论力、加速度和重力,好像加速度计能测量所有这些,但它实际上只是测量某个质量的位移距离。然后它计算出其他相关的测量值。让我们看一看加速度计芯片实际执行的操作,以更好地理解这三个术语的含义。

图 5-2:micro:bit 的加速度计
图 5-2 展示了微型加速度计芯片的大致示意图,该芯片附加在你的 micro:bit 上。
想象一下,一个小质量 m 附着在弹簧上。(这个质量在 图 5-2 中画成一个球形,但它的形状并不重要。)通常情况下,质量处于位置 A,但如果它受到某种力(例如重力)的拉动,便会移动到其他位置,我们称之为位置 B。力越强,A 和 B 之间的差距越大。通过测量这个距离,加速度计可以计算作用在质量上的力。
通过查看 图 5-2,你可以看到仅重力的作用会使质量向下拉。但弹簧被拉伸得越多,它对质量的反向拉力也就越大。所以,重力对质量施加向下的力,拉伸弹簧,而弹簧则施加向上的力。当这两股力相等但方向相反时,B 和 A 之间的距离就能衡量作用在 micro:bit 上的重力大小。A 和 B 之间的距离越大,作用在质量上的力就越大。
记住,重力加速度与由于重力作用而发生的加速度有关。加速度是速度的增加。换句话说,如果你把 micro:bit 从高楼上扔下,加速度 g 是指每秒 micro:bit 的速度增加的米数。如果你把 micro:bit 扔进真空中,没有空气来减慢它的速度,在这种情况下,micro:bit 的速度每秒增加约 9.8 米。所以,如果它从 0 速度(就像你手里拿着它一样)开始,然后自由下落 10 秒钟,它的速度将达到 98 米每秒(约 220 英里每小时)。
此外,当 micro:bit 以 220 英里每小时的速度撞击地面时,它可能会被摔得粉碎。
然而,如果你在真空中丢下 micro:bit,它的加速度计会显示 0,尽管它明显在以每秒 9.8 米的加速度加速。这是因为加速度计实际上并没有测量加速度。如你在 图 5-3 中所看到的,它是在测量作用在 micro:bit 内部质量上的力。如果质量和弹簧的加速度相同,那么加速度计读取的力将为零,因为它们的加速度相同。
如果你处在太空中,远离天体的引力作用,那么加速度将等于作用在物体上的力除以物体的质量。由于质量始终不变,只要有任何力量作用在 micro:bit 上,加速度计就能告诉我们它的加速度。
加速度计芯片实际上比 图 5-2 所示的更先进,因为它内含三个测量力的装置,分别测量三个方向上的力,这些方向互相垂直。换句话说,芯片测量作用在它上面的三维力,分别是 X、Y 和 Z 方向,如 图 5-3 所示。

图 5-3:micro:bit 的加速度计测量三维力。
如果你的 micro:bit 平放在桌面上,X 维度将沿左右方向,Y 维度将沿前后方向,Z 维度将沿桌面上下方向。所以,如果 micro:bit 完全水平放在平坦的桌面上,重力的作用力只会作用在 Z(上下)维度,而 X 和 Y 维度的加速度为 0。现在,如果你稍微倾斜 micro:bit,那么部分重力将作用在 Y 维度上,因此 Y 值将不再是 0。这也意味着,作用在 Z 维度上的重力会稍微减少,因此 Z 值会略微下降。
从目前的描述来看,你可能认为加速度计仅用于测量重力。然而,看看图 5-2,很容易想象,当你摇动 micro:bit 或对其施加任何类型的加速度时,会改变质量的位置。
实验 6:实时加速度绘图

Mu 有一个很棒的功能,可以实时绘制来自 micro:bit 的数据。在这个实验中,你将使用绘图仪功能查看当你移动 micro:bit 时加速度数据如何变化。
注意 在撰写时,绘图仪功能仅在 Windows 和 Mac 版本的 Mu 编辑器中可用。该实验还向你展示了如何获取加速度的整体测量值,以及 X、Y 和 Z 维度的单独读数。
所需材料
对于这个实验,你只需要一块通过 USB 线连接到计算机的 micro:bit。
构建
-
本项目使用了 Mu 的绘图仪功能,这需要使用 Python,因此这里没有 Blocks 代码。你可以在
github.com/simonmonk/mbms/找到代码。这个实验的 Python 文件是Experiment_06.py。将程序刷入你的 micro:bit。 -
点击 Mu 工具栏中的绘图仪图标以打开 Mu 的绘图仪,显示在图 5-4 中。如果你想查看 Mu 用于创建图表的原始数据,请点击REPL按钮。
![Image]()
图 5-4:使用 Mu 绘制加速度计数据
-
将 micro:bit 朝不同方向倾斜,观察绘图仪中的变化。
如图 5-4 所示,有四个图形,每个图形用不同的颜色绘制。每个维度有一个图形(X 为蓝色,Y 为绿色,Z 为橙色)。还有一个紫色图形代表总加速度,它是所有三个维度的力的组合。我们将在“工作原理:计算总加速度”部分的第 11 页解释如何计算总加速度。
如果你发现屏幕上的 REPL 区域没有显示读数,可能是你的 micro:bit 版本较旧,需要更新才能正常工作。如果是这种情况,请按照support.microbit.org/support/solutions/articles/19000019131-how-to-upgrade-the-firmware-on-the-micro-bit/上的说明更新你的设备。
代码
这是将加速度计数据发送到 Mu 的绘图工具的 Python 代码:
from microbit import *
from math import sqrt
while True:
x, y, z = accelerometer.get_values()
net = sqrt(xx + yy + z*z)
all = (x, y, z, net)
print(all)
sleep(100)
导入常规的 micro:bit 库。然后从 Python 的 math 库中导入平方根函数sqrt。我们将使用这个函数来计算净加速度。
添加一个while循环,使用get_values方法一次性从加速度计获取 X、Y 和 Z 三个维度的读数。这一行将返回一个元组,它是一种可以容纳多个值的数据结构。将这个元组赋值给三个变量:x、y和z,分别存储三个值。我们使用这些变量来计算净加速度,并将其赋值给变量net。
接下来,将净加速度值以及 X、Y 和 Z 三个维度的单独加速度值发送给 Mu 进行绘图。Mu 要求你要绘制的值以元组的形式传递,因此创建一个新的元组all,包含这四个值。
最后,打印元组,这不仅会在 Mu 的 REPL 中显示这些值(有关详细信息,请参见第 23 页的《REPL》),还会将这些值提供给 Plotter。你可以在图 5-6 的左下角看到打印出来的值。
工作原理:计算净加速度
要计算 X、Y 和 Z 三个维度上的净加速度,你需要使用一些古老的希腊技术:毕达哥拉斯定理。
为了理解这一点,可以把加速度力想象成一条带箭头的线。箭头表示力的方向,线的长度表示力的强度。像这样的线称为向量,在物理学中经常使用它们。

图 5-5:二维向量
在二维空间中,向量比在三维空间中更容易理解。图 5-5 显示了 X 和 Y 维度上的一些二维向量。沿 X 轴的蓝色向量强度为 4,沿 Y 轴的绿色向量强度为 3。
紫色向量,等于绿色和蓝色向量的合成效应,就是我们程序之前计算出来的净向量。净向量非常有用,因为它的长度告诉你力的整体强度。要计算净向量的强度,你可以使用毕达哥拉斯定理。
勾股定理指出,在直角三角形中(即有一个直角的三角形),斜边(三角形的最长边)的平方等于其他两边的平方和。
看图 5-5,你可以看到我们确实有一个直角三角形,因为蓝色和绿色向量在一个直角处交汇。利用勾股定理,我们可以说紫色线的长度平方等于 32 + 42。即 9 + 16,结果是 25。所以,紫色线的长度是 25 的平方根,等于 5。
这个数学原理不仅适用于二维,也适用于三维。要计算 X、Y 和 Z 维度的网向量的长度,只需将这三个向量的平方和开方。
图 5-6 展示了在某一时刻,X、Y 和 Z 维度中的三个力。

图 5-6:三维空间中的加速度力向量
这是计算替代 X、Y 和 Z 向量的单一向量长度的代码行。
net = sqrt(xx + yy + z*z)
X、Y 和 Z 值分别可以在由accelerometer.get_values()返回的元组中的a[0]、a[1]和a[2]找到。
如果 X、Y 和 Z 向量的长度分别为 4、3 和 2,如图 5-6 所示,那么计算网向量的长度平方应如下:
4 × 4 + 3 × 3 + 2 × 2 = 16 + 9 + 4 = 29
所以,向量的长度将是 29 的平方根,约为 5.4。
项目:牙刷监测器

难度:简单
疯狂科学家通常会被进行中的有趣实验分散注意力,因此他们需要一些帮助,以彻底刷牙。这就是为什么疯狂科学家使用 micro:bit 创建了一个牙刷监测器(图 5-7),它可以计算牙刷刷动的次数。

图 5-7:牙刷监测器
牙刷监测器在显示屏上显示一个从 0 到 9 的得分。每刷 50 次牙刷,得分增加 1。当得分达到 10 时,它会显示一个笑脸图标,表示疯狂科学家已经刷完牙——直到下次。
警告 不要让你的 micro:bit 沾水—它可能会坏掉!
你需要的材料
对于这个项目,你将需要以下物品:
Micro:bit
3V 电池包 为 micro:bit 提供电源。(建议使用可开关类型的电池盒。)
手动牙刷 不是电动牙刷
2 × 弹性带 用于将 micro:bit 和电池包固定在牙刷上
该项目是针对手动牙刷设计的。电动牙刷无法用于此项目。
构建
-
访问
github.com/simonmonk/mbms/以获取本书的代码仓库,然后点击Toothbrushing Monitor的链接。程序打开后,点击下载,然后将 hex 文件复制到你的 micro:bit 上。如果你更喜欢使用 Python,可以从同一个网站下载代码。有关如何下载和使用本书示例的说明,请参见第 34 页的“下载代码”。本实验的 Python 文件为ch_05_Toothbrush_Monitor.py。
-
将电池包插入 micro:bit,并使用橡皮带将电池和 micro:bit 固定在牙刷上,如图 5-7 所示。
在固定带子时,确保它们不会遮挡显示屏,并且你仍然可以触及电池包的开/关开关。此外,检查带子是否覆盖了 micro:bit 背面的重置开关。
-
打开电池包。一旦电池包开启,micro:bit 应该显示 0。用力刷牙,过一会儿,显示应该变为 1。
代码
该项目的程序会测量加速度,如果加速度超过某个特定水平,它会将计数变量加 1,以记录刷牙次数。
当刷牙次数足够多,达到另一个积分要求时,得分会增加并显示出来。
最终,当得分达到 10 时,微笑图标会显示在 micro:bit 的显示屏上。
Blocks 代码
这是该项目的 Blocks 代码。

这可能是本书中最复杂的程序。on start模块定义了四个变量。以下是它们各自的作用:
每个积分的刷牙次数 这指定了提高你得分所需的刷牙次数。如果你是一个懒得刷牙的人,那么你可以减少这个数字,这样积分会更快增加,且你能更快得到微笑奖励。然而,请注意,你下次去看牙医时可能不会很愉快。
得分 这是一个随着你完成每 50 次刷牙而增加的数字,直到达到 10。
计数 这个变量用于跟踪自从你获得积分以来完成的刷牙次数。它从 0 开始,每次得分增加时会重置。
旧 mg 该变量保存上次检查刷牙次数时的加速度值(以毫重力为单位)。程序将比较这个值和新值,以检测刷牙动作。
我们创建一个forever模块,并在其中使用一个set XX to模块。从下拉菜单中选择mg,这样这个模块会将整体加速度读数放入名为mg的变量中。在加速度 (mg)模块的下拉菜单中,选择strength,它会为你计算勾股定理。(如果你使用 MicroPython,你需要自己计算。)
然后,set change in mg 块通过将当前的加速度强度与之前的加速度强度(存储在old mg中)相减,计算加速度强度的变化。如果变化大于 800—表示开始刷牙动作—则count增加 1。800 的值是通过查看图 5-8 选定的,图中展示的是短时间剧烈刷牙的净加速度曲线。

图 5-8:刷牙过程中的净加速度曲线
在图表中,每一个峰值代表一次刷牙动作,最大净加速度出现在刷牙改变方向时。800 的值足以捕捉大部分刷牙动作,因为大多数刷牙动作产生的加速度变化约为 1000。如果你刷牙的力度较轻,可能需要降低这个阈值,否则你可能会永远刷牙,得不到足够的分数来停止。
接下来,放置第一个if块来检测足够大的加速度,表示刷牙动作,并在其中放置第二个if块来检查count的值。如果值超过了你在strokes per point中设置的数量,程序会将score加 1,并显示新的score值。最后,程序会检查score是否大于 9,如果是,它会显示一个笑脸图标。
MicroPython 代码
下面是 MicroPython 版本的代码。
from microbit import *
from math import sqrt
strokes_per_point = 50
old_mg = 0
count = 0
change_in_mg = 0
score = 0
mg = 0
display.show(str(score))
while True:
x, y, z = accelerometer.get_values()
mg = sqrt(xx + yy + z*z)
change_in_mg = mg - old_mg
old_mg = mg
if change_in_mg > 800:
count += 1
if count > strokes_per_point:
score += 1
display.show(str(score))
count = 0
if score > 9:
display.show(Image.HAPPY)
MicroPython 代码几乎完全复制了 Blocks 代码,不同之处在于需要计算力的总强度,因为 MicroPython 没有内建函数来处理 micro:bit 的这个功能。
尝试的事项
你可以将这个项目用作计步器—一种测量你走路或跑步时步数的设备。为此,尝试简化代码,去掉score变量,因为我们现在只关心步数(等同于刷牙时的刷次数)。你需要让代码记录步数,并在按下 A 按钮时显示你走了多少步。为了测试,试着把这个项目放进你的袜子里(先拿掉牙刷),然后走动,同时在脑海中计算步数。然后看看计步器显示你走了多少步。如果测量不准确,可能需要调整加速度阈值,从 800 调整,来使计步器更或更少灵敏。
实验 7:将加速度记录到文件

Mu 内置的绘图工具非常适合如果你不介意将 micro:bit 通过 USB 数据线连接到计算机。然而,有时疯狂科学家会发现远程记录 micro:bit 上的读数,以便后续分析,非常有用。
在这个实验中,你将使用 micro:bit 在保存到 micro:bit 上的文件中记录加速度计读数。你可以挥动 micro:bit 并进行各种测试,然后查看测量到的加速度的图表。

该程序每秒会进行大约 60 次读数,它可以记录约 45 秒的样本,直到 micro:bit 的内存用尽。
你需要的工具
对于这个实验,你需要:
Micro:bit
3V 电池组
构造
-
本项目使用 micro:bit 的本地文件系统,而在本文编写时,Blocks 代码无法使用该功能。这意味着你需要使用 Python 来进行这个实验。从
github.com/simonmonk/mbms/下载代码,并查看下载和使用书中示例的说明。这个实验的 Python 文件是 Experiment_07.py。将程序加载到你的 micro:bit 上。 -
当你打开 micro:bit 时,它的显示屏将显示一个 X。这意味着它没有记录任何读数。当你点击 A 按钮时,图标将变为对勾,micro:bit 开始记录。再次按下 A 按钮时,它将停止记录,并将加速度计读数保存到一个文件中,你可以将该文件传输到你的计算机。
为了测试这一点,按下 A 按钮,挥动 micro:bit,然后再次按下 A 按钮。
-
要将包含读数的文件传输到你的计算机,请使用 Mu 的 Files 功能。用 USB 数据线将 micro:bit 连接到你的计算机,然后点击 Mu 工具栏中的 Files 图标(见 图 5-9)。
窗口底部现在有两列。左侧是保存在 micro:bit 上的文件。在 图 5-9 中,只有一个文件,data.txt。右侧是 Mu 的代码目录中的文件,该目录位于你的主目录下的 mu code 文件夹中。
![Image]()
图 5-9: Mu 的文件功能操作
要从 micro:bit 复制文件,只需将其从 Mu 窗口左侧区域拖到右侧区域。
如同本章前面实验 6 中提到的,如果 Mu 中的 Files 功能无法使用,可能是你使用的 micro:bit 需要更新。此时,按照
support.microbit.org/support/solutions/articles/19000019131-how-to-upgrade-the-firmware-on-the-micro-bit/中的说明更新你的设备。 -
一旦你将数据从 micro:bit 传输到你的计算机,你将通过将文件导入电子表格(如 Excel 或 Google Sheets)来绘制数据。
根据你使用的电子表格软件,程序的步骤会有所不同。我将向你展示如何使用免费的 Google Sheets。你只需要登录到 Google 帐号即可。
访问
docs.google.com/spreadsheets/,然后点击 开始新电子表格 区域中的 空白 选项。接着,在 Google Sheets 菜单中选择 文件▸导入。在弹出的窗口中,选择 上传 标签并导航到你已经复制到电脑中的 data.txt 文件。录制的数据应该出现在电子表格的第一列中。选择这一列并点击 插入▸图表,就能生成数据图表,像 图 5-10 中显示的那样。

图 5-10:在 micro:bit 上绘制的数据图表
代码
这是此实验的 MicroPython 代码:
from microbit import *
from math import sqrt
import os
filename = 'data.txt'
recording = False
display.show(Image.NO)
while True:
if button_a.was_pressed():
recording = not recording
if recording:
display.show(Image.YES)
try:
os.remove(filename)
except:
pass
fs = open(filename, 'w')
else:
display.show(Image.NO)
fs.close()
if recording:
x, y, z = accelerometer.get_values()
net = sqrt(xx + yy + z*z)
fs.write(str(net))
fs.write('\n')
sleep(10)
micro:bit 只能保存有限量的数据,因此需要导入 os 包,这样你就可以删除 micro:bit 上已经存在的任何数据。
将数据文件名设置为 data.txt。你可以通过修改 filename 变量的值来更改文件名,但我建议在程序工作正常之前保持原名。
创建一个名为 recording 的变量来跟踪项目是否正在录制数据。每次按下 A 按钮时,这个变量会在 True 和 False 之间切换,从而控制数据的录制开始和停止。这就是 recording = not recording 这一行的作用:如果 recording 为 True,代码会将其设置为 False,反之亦然。
创建一个 while True 循环,让程序永远运行。在这个循环中有两个 if 语句。第一个指示 micro:bit 在按下 A 按钮时该做什么,第二个检查我们是否处于录制模式。当第一次按下 A 按钮时,录制开始,屏幕显示 YES 图像,os.remove 方法会删除现有的数据文件。
我们将 remove 命令放入了 try: except: Python 结构中。这样可以确保如果发生任何错误(特别是如果数据文件无法删除,因为它不存在),程序会忽略这个错误并继续运行,而不会崩溃。
程序接着以 w 模式打开文件,这意味着你可以在文件中写入内容。当按下 A 按钮时,屏幕会显示 NO 图像,文件随之关闭。
主 while 循环中还包含另一个 if 块,只要 recording 为 True,就会将加速度计的读数写入文件。如果程序运行时间过长,填满所有文件空间,它会给出错误。但是,它在空间不足之前写入的数据仍然可用。
录制结束时的 sleep 命令会减缓录制过程,这样你就不会太快耗尽内存。
尝试的事情
这个实验可以让你在各种实际情况下测量加速度。例如,你可以记录在将 micro:bit 扔到空中时它的加速度。如果你打算尝试这一点,最好采取一些预防措施:
选择一个软的地面环境。这样,如果你没能接住 micro:bit,它可能会幸存下来。在这样的实验中,电池松动或从支架中掉出的情况并不罕见。
不要把你的 micro:bit 随便扔到可能会打到别人头部的地方。
将 micro:bit 附着在电池包上。弹力带是个不错的选择。
把你的 micro:bit 放进一个外壳里。带有 MI:power 电池背包的 Kitronik MI:pro 外壳(如 图 5-11 所示)是一个很好的选择。如果你使用这个外壳,你就不需要额外的电池包,因为外壳里已经包含了一个小型的 3V 电池。

图 5-11: 带 MI:power 电池背包的 Kitronik MI:pro 外壳
你也可以通过将一根绳子牢固地绑在 micro:bit 上,并轻轻地在空中做圆周摆动来测量加速度。但同样要小心,因为 micro:bit 很容易从绳子上脱落,可能会损坏或伤害到周围的人。
micro:bit 使用的文件系统非常有限,它的存储空间大约只有 40KB。因此,每次你向 micro:bit 刷写新程序时,之前的文件可能会被擦除。
项目:加速度显示

难度:简单
如 图 5-12 所示,这个项目允许你在显示屏上看到 micro:bit 的加速度。当 micro:bit 处于静止状态时,显示屏的中间一行 LED 会亮起。如果你快速将 micro:bit 向上移动,LED 行会像电梯一样在显示屏上向上移动,响应净力的增加。类似地,如果你快速将 micro:bit 向下移动,LED 行会向下移动,表示重力效应减弱,仿佛你在电梯里向下加速。

图 5-12: Micro:bit 加速度显示
你将需要的东西
对于这个项目,你只需要一个 micro:bit。然而,如果你想让这个项目更具移动性,带上电池包会更方便。
你也可以使用 图 5-11 中展示的 MI:pro 外壳和 MI:power 电池包组合。
构造
-
访问*
github.com/simonmonk/mbms/*来访问书本的代码库,并点击加速度显示的链接。程序打开后,下载并将 hex 文件复制到你的 micro:bit 上。如果你更喜欢使用 Python,可以从同一个网站下载代码。有关下载和使用书中示例的说明,请参见第 34 页的“下载代码”部分。此实验的 Python 文件是ch_05_Acceleration_Display.py。
-
尝试将你的 micro:bit 上下移动,观察加速度在各个方向上如何影响读数。如果你能带着 micro:bit 乘电梯,观察显示屏上是否显示你在上升或下降。
代码
这段代码首先读取加速度数据,然后使用一些数学运算来决定显示屏上点亮哪一行。
Blocks 代码
这是本项目的 Blocks 代码。

本项目的所有代码都包含在forever区块中。它首先读取净加速度,然后计算y的值。这里,y代表显示屏上将点亮的行。当 micro:bit 静止时,唯一作用于它的力是重力,净力为 1,000 mg(1 g)。因此,程序从净加速度中减去 1,000,然后将结果除以 100,这样每 1/10 的 g 会导致显示屏上的一行变化。最后,我们将 2 加到这个结果,以默认显示第 2 行(如果从 0 开始计数的话,就是 LED 的中间行)。
使用两个if区块来确保y的值保持在 0 和 4 之间(对应 5 行)。为了绘制正确的行,首先清除屏幕,以免旧的行与新的读数一起显示。然后,使用for循环遍历该行的每个 LED,这些 LED 由x值表示,用于点亮它们。
MicroPython 代码
这是代码的 MicroPython 等效版本:
来自 microbit 的导入*
from math import sqrt
while True:
x, y, z = accelerometer.get_values()
acc = sqrt(xx + yy + z*z)
y = int(2 + (acc - 1000) / 100)
display.clear()
if y < 0:
y = 0
if y > 4:
y = 4
for x in range(0, 5):
display.set_pixel(x, y, 9)
这段代码类似于 Blocks 代码,但你需要自己计算净加速度。
总结
micro:bit 的加速度计为检测 micro:bit 的运动或方向提供了许多项目的机会。在这一章中,你已经探索了使用加速度计的一些有趣方法。
你还学会了如何使用 Mu 的绘图工具绘制来自 micro:bit 的数据,并将读数记录到文件中,稍后可以绘图并进行分析。

第六章:疯狂的运动
在这一章中,你将使用几种不同类型的电机,制作本书中最令人印象深刻的两个项目:一个可以转动眼睛并说话的仿生头,以及一个遥控的机器人漫游者。这些玩具能让疯狂的科学家玩上几个小时。
实验 8:使伺服电机运动

让事情开始运动的一种方法是使用伺服电机,像 图 6-1 所示的那样。

图 6-1:伺服电机连接到 micro:bit
伺服电机 是一种小型低功率电机,配有可以通过程序控制的臂。与大多数其他电机不同,伺服电机不会完全旋转。相反,它们具有 180 度的运动范围。你的程序可以将电机臂设置到特定的角度。
在这个实验中,你将学习如何将伺服电机连接到 micro:bit,并研究伺服电机的运动方式。

你将需要的材料
Micro:bit
伺服电机 理想的伺服电机是 9 克的伺服电机。micro:bit 仅有足够的电力来驱动一个小型伺服电机,但对于全尺寸的伺服电机来说则不够。请选择一个兼容 3V 的伺服电机。更多详情请参见 附录。
鳄鱼夹-公头跳线电缆 这些电缆将 micro:bit 连接到伺服电机。(你也可以使用公对公跳线电缆;见下文。)
USB 连接到计算机,Monk 为 micro:bit 或 USB 电池包提供电源 一个 AAA 电池盒可能(取决于伺服电机)能工作,但 AAA 电池可能无法提供足够的电压来驱动伺服电机。有关为 micro:bit 提供电源的选项,请参见 附录。
你也可以使用更常见的公对公跳线电缆,而不是使用鳄鱼夹-公头跳线电缆,只需将电缆的一端插入伺服电机连接器,另一端夹上鳄鱼夹。但你需要确保连接不会意外短路。通常,鳄鱼夹-公头跳线电缆将是你 micro:bit 工具箱中的一项有用物品,所以值得准备一些。
构建
将伺服电机连接到你的 micro:bit。
-
前往
github.com/simonmonk/mbms/访问本书的代码库,点击 实验 8:伺服电机 的链接。程序打开后,点击 下载,然后将 hex 文件复制到你的 micro:bit 上。如果你在这方面遇到困难,请返回查看 第一章。如果你更喜欢使用 Python,可以在同一网站上找到相应的代码。有关下载和使用书中示例的说明,请参见 第 34 页中的“下载代码”部分。本实验的 Python 文件是 Experiment_08.py。
-
伺服电机有不同种类的手臂,可以连接到电机的齿轮状轴上。对于这个项目,选择一个简单的手臂,如图 6-1 所示。
注意 你的伺服电机应该附带一个小螺丝。这个螺丝用于将手臂更稳固地固定在轴上。如果你计划制作仿生头项目,请将螺丝放在手边;否则,放在安全的地方以备后用。
-
使用鳄鱼夹将你的 micro:bit 连接到伺服电机,如图 6-2 所示。
![Image]()
图 6-2:一个连接到 micro:bit 的伺服电机
-
伺服电机有三个连接,按颜色编码:
控制 橙色或黄色(这个引脚控制伺服电机手臂的位置。)
+V 红色线是正电源线。伺服电机理想情况下使用 5V,但大多数小型伺服电机也可以在 micro:bit 的 3V 上工作。
GND 通常是棕色的,有时是黑色的(这是负电源线。)
-
一旦通电,伺服电机的手臂应该跳到 90 度位置,与伺服电机垂直。micro:bit 将使用这个位置作为参考点。如果手臂不是 90 度位置,请将其取下并重新安装,使其处于 90 度位置,如图 6-1 所示。如果你计划制作仿生头,请使用小螺丝将手臂固定在位置上。
-
现在你已经有了一个功能正常的伺服电机!按下按钮 A 应该使伺服手臂向一个方向移动 10 度。按下按钮 B 应该使伺服手臂向另一个方向移动 10 度。如果同时按下两个按钮,手臂的当前角度应该会在 micro:bit 的显示屏上滚动显示。
代码
两个程序遵循相同的方式,首先将伺服电机的角度设置为 90 度,然后等待按钮按下,增加或减少角度,或者显示角度。
块代码
这是此实验的块代码。

我们使用一个名为 angle 的变量来记住伺服电机的当前角度。我们在 on start 块中定义 angle 变量,并赋予它初始值 90。在下一次运行 servo write pin 块时,它将把伺服电机的手臂移动到 angle 中设置的位置,从而使手臂在上电时跳到 90 度位置。
如果按下按钮 A,将调用 on button A pressed 块。如果按下按钮 B,将调用 on button B pressed 块。这两个按钮的工作方式类似。按钮 A 的块首先检查角度是否仍大于或等于 10,如果是,则从角度中减去 10,将手臂向一个方向移动。按钮 B 的块检查角度是否小于或等于 170,如果是,则向角度添加 10,并将手臂向相反方向移动。两个块都使用 servo write pin 来设置伺服电机的新角度,作为按钮按下后的结果。
MicroPython 代码
这是 MicroPython 版本的代码。
从 microbit 导入 *
def set_servo_angle(pin, angle):
duty = 26 + (angle * 51) / 90
pin.write_analog(duty)
angle = 90
set_servo_angle(pin2, angle)
while True:
if button_a.was_pressed() and angle >= 10:
angle -= 10
set_servo_angle(pin2, angle)
if button_b.was_pressed() and angle <= 170:
angle += 10
set_servo_angle(pin2, angle)
if button_a.is_pressed() and button_b.is_pressed():
display.scroll(str(angle))
MicroPython 代码与 Blocks 代码的工作方式非常相似。但与 Blocks 代码不同的是,MicroPython 中没有预定义的函数来将伺服电机设置为特定角度。幸运的是,我们可以使用一些数学和 PWM 模拟输出(参见 第 8 页的“制作模拟信号:脉宽调制”),编写自己的方法,生成伺服电机所需的脉冲(稍后会详细介绍)。
工作原理:伺服电机与脉冲
你可以通过发送一系列重复的电脉冲来控制伺服电机——在本例中,脉冲来自 micro:bit。脉冲通过快速打开和关闭一个引脚来生成。伺服电机根据脉冲保持高电平(3V)的时间来判断如何动作。信号处于高电平的时间比例,即引脚打开的时间比例,称为 占空比。这与信号高电平的实际持续时间不同,后者称为 脉冲宽度。我们将这一段时间(以毫秒为单位)称为 宽度,因为我们可以将脉冲可视化为方波(参见 图 6-3)。波形的总长度(每个 开 脉冲之间)称为 周期。

图 6-3:控制伺服电机的脉冲
伺服电机期望每 20 毫秒接收到一个脉冲,或者每秒 50 个脉冲。每个脉冲的宽度在 0.5 毫秒和 2.5 毫秒之间。
如你在 图 6-3 中看到的,脉冲的长度决定了伺服电机臂的位置。如果脉冲宽度为 0.5 毫秒,伺服电机的臂将处于范围的一端(0 度)。如果脉冲宽度为 1.5 毫秒,臂将处于中心位置(90 度)。如果宽度为 2.5 毫秒,臂将处于 180 度位置。
方便的是,micro:bit 的模拟输出默认频率(参见 第一章)是 50Hz——正好是伺服电机所需的频率。然而,即使是最长的脉冲,也只有 2.5 毫秒,占总周期 20 毫秒的十分之一,这意味着最长的脉冲只有大约十分之一的时间是高电平。
图 6-4 有助于解释如何计算 MicroPython 中 set_servo_angle 函数使用的数字。占空比是传递给 set_servo_angle 函数的数字。该值必须在 0 到 1023 之间,其中 0 表示没有脉冲,1023 表示脉冲持续的时间长到下一周期才结束。

图 6-4:占空比值与脉冲宽度与伺服臂角度的对应关系
图 6-4 的顶部显示了伺服臂在 0 到 180 度范围内的位置。代码必须将这个范围转换为另一组数字,从 0.5 到 2.5,这些数字是与这些角度对应的脉冲宽度。
要将角度(以度为单位)转换为脉冲宽度(以毫秒为单位),我们从以下信息开始:一个长度为 0.5 毫秒的脉冲等于 0 度的角度,长度为 2.5 毫秒的脉冲等于 180 度的角度。然后,我们可以通过将度数范围(180)除以脉冲长度范围(2)来计算每毫秒的度数,从而得出每毫秒 90 度。接着,为了计算新角度的脉冲长度,我们从基准值 0.5 毫秒开始,并加上我们使用的角度除以每毫秒的度数(90)。
我们来考虑一个例子。如果角度为 0 度,脉冲长度将为 0.5 毫秒(0.5 + 0/90 = 0.5)。如果角度为 90 度,脉冲长度将为 0.5 + (90/90) = 1.5 毫秒。如果角度为 180 度,脉冲长度将为 0.5 + (180/90) = 2.5 毫秒。
现在我们有了一个关于角度的脉冲长度公式:
pulse_length = 0.5 + angle/90
但再次参考图 6-5,我们需要将脉冲长度(毫秒)转换为 0 到 1023 之间的占空比值,因为set_servo_angle函数需要这个范围的值。
占空比值(0 到 1023)是通过将脉冲长度(毫秒)乘以每毫秒的步数(1023/20 ≈ 51)来计算的。例如,一个 1.5 毫秒的脉冲长度将需要一个占空比值为 1.5 × 51 ≈ 77。
换句话说:
duty_value = pulse_length × 51
将这两个公式结合起来,我们得到:
duty_value = (0.5 + angle/90) × 51
这也可以写成(四舍五入后):
duty_value = 26 + angle × 51/90
因此,write_analog函数中使用的值在 26 到 128 之间。这个范围反映了脉冲与最大占空比值 1023 相比非常短的事实。
项目:动画头(MIKE THE MICRO:BIT 机器人)

难度:难
这个动画头,如图 6-5 所示,是一个非常适合万圣节展示的项目。一个伺服电机将一对乒乓球眼睛从左到右移动,它还使用 micro:bit 的显示屏作为嘴巴。当头部讲话时,灯光模拟出嘴唇移动的简单动画。

图 6-5:动画头
你将需要的材料
对于这个项目,你将需要以下物品:
Micro:bit
伺服电机 一款小型 9 克伺服电机是理想选择。
放大扬声器 用于头部的声音(Monk Makes 扬声器是一个不错的选择。)
3 × 鳄鱼夹到公头跳线 用于连接伺服电机
3 × 鳄鱼夹电缆 用于连接扬声器
2 × 乒乓球 用作眼球(没有任何文字或标志的球更易于装饰。准备几个备用球,以防万一。)
厚纸板 大约是字母纸或 A4 纸,厚度在 3 毫米或以上
纸张和打印机 用于打印框架的模板
2 × 3 英寸(75 毫米)回形针 用于制作允许眼球旋转的轴,以及连接眼球与伺服电机的框架。理想情况下,这些回形针直径为 1.5 毫米。
胶带 用于将纸板粘合在一起,并将各种物品粘贴到纸板上
蓝丁胶粘土 用于将扬声器固定在纸板上
纸胶水 用于将模板粘贴到纸板上
剪刀和/或美工刀
画笔或马克笔 用于绘制眼球
带有 5/64 英寸(#47)或 2 毫米钻头的电钻 用于在乒乓球上钻孔
钳子 用于弯曲线材
构建
我们将从制作眼球开始。
-
拿两个乒乓球(图 6-6),准备装饰。画眼球的最佳方法是先找到两个小圆物品,一个稍大于另一个(也许是牙膏盖和一个环),然后用圆物品和铅笔在乒乓球表面上描出两个同心圆。完成后,将外圈(虹膜)和内圈(瞳孔)涂上两种不同的颜色。
![图片]()
图 6-6:装饰眼球
-
当你在两个乒乓球上画好眼球图案后,在每个球上钻三个孔,用来穿线。用铅笔做三个标记:以瞳孔朝向自己时,在球的底部、顶部和瞳孔的背面分别做一个标记。顶部和底部的孔将用于将眼球固定在垂直的线材上,保持其位置。背面的孔将用于连接第二根线,用于左右移动眼球。
警告 使用电钻可能会有危险!在项目的这一部分,应该由一位负责任的成年人使用电钻,或至少进行监督。主要的安全措施是将乒乓球放在平坦的表面上,双手握住两侧。然后从上方钻孔,如图 6-7 所示。如果有台钳固定球体,那就更好了。
![图片]()
图 6-7:钻孔眼球
-
当你对标记的位置满意后,拿一个钻头,直径稍大于回形针的线径,开始在乒乓球上钻孔。对于 1.5 毫米的回形针,5/64 英寸(#47)或 2 毫米的钻头非常合适。
-
制作眼球框架。首先将回形针完全拉直。然后按照图 6-8 中的 A、B、C 三处弯曲。
![图片]()
图 6-8:如何弯曲回形针以制作眼球框架
-
先做 A 和 C 两个弯曲。两者都应为 90 度。这些弯曲将使眼球保持直立。接下来,在电线的中心处做一个轻微的弯曲——这就是弯曲 B。弯曲 B 将提供一个可以粘贴到你接下来将制作的纸板底盘上的地方。将眼球按图 6-9 所示放置在框架上。
![Image]()
图 6-9:将眼睛放置在框架上
-
一旦你安装了眼球,可以将电线的 10 毫米尖端弯曲到眼球上方,以防它们掉落,如图 6-9 所示。使用钳子以避免伤到手指。
注意 这些弯曲第一次做得不必完美。在制作项目的过程中,你可以进行一些调整。
-
现在让我们开始组装底盘,它将把所有部件固定在一起。为了让这一步更容易,我提供了一个可以与书籍代码一起下载的模板。模板位于 其他下载 文件夹中,名为 Animatronic_Head_Template。它有 PDF、PNG 和 SVG 格式可供选择。下载后,打印出来并将其固定在稍大的纸板上,如图 6-10 所示。
![Image]()
图 6-10:将纸模板粘贴到纸板上的过程
-
除了图 6-10 中标出的地方外,沿着线条切割。这将得到图 6-11 中所示的纸板件。大多数切割使用剪刀就可以,但你需要一把工艺刀来切割插槽和伺服电机的开口。
![Image]()
图 6-11:底盘的纸板零件
警告 仅在成人监督下使用工艺刀。工艺刀非常锋利,使用时很容易不小心割伤自己。
-
将 micro:bit 固定到前面的纸板上,通过板上标记的小圆圈对打孔。然后,对于每一对孔,背面用鳄鱼夹夹住。这些夹子不仅可以帮助你建立电气连接,还能将 micro:bit 安全地固定在纸板上。
按照图 6-12 中建议的顺序连接鳄鱼夹:红色连接到 3V,黑色连接到 GND,黄色连接到 0 引脚。确保每个 GND 和 3V 连接各连接两个鳄鱼夹。
![Image]()
图 6-12:连接电缆到 micro:bit
-
要将 micro:bit 连接到伺服电机,你需要使用三根带公头跳线的鳄鱼夹。一端将一根黄色鳄鱼夹夹到第 2 针上。然后,拉开已经连接到 3V 的红色鳄鱼夹的绝缘外皮,暴露出一些金属部分,将红色鳄鱼夹连接到红色夹子上。对黑色的 GND 电缆执行相同的操作,拉开 GND 黑色鳄鱼夹的绝缘外皮,将黑色鳄鱼夹连接到公头跳线(参见 图 6-13)。
![Image]()
图 6-13:将 micro:bit 附加到纸板的前面
-
现在将底部纸板插入前部纸板,并使用粘合带将其固定在位(参见 图 6-14)。
![Image]()
图 6-14:将底部卡片连接到前部卡片
-
现在将扬声器固定到背部卡片上;使用粘合带或胶泥将其固定。将你已连接到 micro:bit 的三根鳄鱼夹(黑色、红色和黄色)连接到扬声器的相应端口(分别为 GND、3V 和 0)。使用粘合带将背部卡片固定到底部卡片上。如 图 6-15 所示,你的底盘现在应该是 U 形的。这里的红色、蓝色和黄色鳄鱼夹等待与伺服电机连接。
![Image]()
图 6-15:背部卡片和扬声器
-
将伺服电机臂固定在 90 度位置(如有需要,请回顾实验 8 的末尾),然后将伺服电机穿过顶部卡片(圆形面),首先穿过伺服电机的电缆。注意,伺服电机的轴并不位于伺服电机的中心,而是偏向一端;这一端应位于靠近顶部卡片中心的伺服电机切口位置(参见 图 6-16)。
![Image]()
图 6-16:连接伺服电机
-
将公头跳线插针连接到伺服电机的插座上,如实验 8 中所述。
-
当所有部件连接完毕后,将顶部纸板附加到其余的底盘部分。顶部纸板上标示眼睛位置的两个圆圈应面朝 micro:bit 所在的一端(参见 图 6-5)。
-
现在将眼球和金属框架固定到顶部卡片上,如 图 6-17 所示。调整金属框架中间的弯曲部分,使眼球居中放置在顶部卡片上的两个圆圈上。然后使用粘合带将金属线固定。轻轻转动眼球,确保它们可以自由旋转。
![Image]()
图 6-17:连接眼球
-
要将伺服电机连接到眼球,你需要按照 图 6-18 中的示意图将另一根回形针弄直。
![Image]()
图 6-18:制作伺服电机和眼球之间的连接器
-
为了制作电线中间的环,将电线紧紧地绕在一个小螺丝刀的轴上(如图 6-19 所示)。我使用的螺丝刀直径大约是 3 毫米,这样环的外径大约是 5 毫米。使用一个比轴细的尖端螺丝刀,否则弯曲后就很难把电线从螺丝刀上滑下来。确保如图所示将电线的两腿拉直。
![Image]()
图 6-19:使用螺丝刀弯曲伺服电机到眼球连接器中的环
注意 螺丝刀很锋利,且弯曲厚电线需要很大的力量,所以你可能需要大人的帮助来完成这个部分。
-
通过弯曲回形针来调整连接器,直到两臂与眼球后面的孔的距离相同。然后,将电线挂到眼球的后面。使用伺服电机提供的一个螺丝将环固定在伺服电机臂的尖端,如图 6-20 所示。根据伺服电机是否合适地安装在上卡片的切口中,你可能需要用胶带将电机固定,以防止它移动。
![Image]()
图 6-20:将伺服电机-眼球连接器安装到卡片上
现在连接你的 micro:bit 的 USB 数据线并尝试这个项目!
代码
首先,我们将使用实验 8 中的代码来测试我们的机制是否都在正常工作。一旦确认一切都运作良好,再切换到这个项目的代码。
使用实验 8 中的代码进行测试
访问 github.com/simonmonk/mbms/ 并点击 实验 8:伺服电机 的链接。一旦程序打开,点击 下载,然后将 hex 文件复制到你的 micro:bit 上。如果你更喜欢使用 Python 进行测试,可以从同一网站下载 Python 文件,Experiment_08.py。
一旦代码加载完成,尝试按下 A 和 B 按钮,让伺服电机的臂部左右移动。你可能需要稍微调整连接线的位置,以确保眼球对准并能自由地左右移动。只需将伺服电机的臂部带动到 90 度位置的几步之内,否则连杆可能会卡住。
使用真实项目代码
一旦你确定眼球的运动方式正确,你就可以切换到真实项目的代码。
因为这个项目使用了语音库,所以只能以 MicroPython 形式提供。访问 github.com/simonmonk/mbms/ 下载 Python 文件 ch_06_Animatronic_Head.py。
将它上传到你的 micro:bit 上,然后轻轻戳一下机器人。加速度计应该能检测到运动并指示你的机器人头转动眼睛,说些俏皮话,然后再直视前方。关于这个项目的视频,可以访问我的 YouTube 频道 (www.youtube.com/watch?v=FAJTS2Z8ZDA)。
这个项目的软件做了两件事:它检测头部是否被戳到,并在随机时间经过后触发说话事件。代码比较长,因此我不会展示全部,只会突出关键部分。如果你想跟着做,可以将代码加载到 Mu 中。
为了让你的机器人头看起来像有思维一样,我们使用 Python 的随机库来生成随机数,触发随机事件:
import random
与其让头部的眼睛自由移动,我们将可能的眼睛角度保存在数组 eye_angles 中。当我们想让眼睛朝随机方向看时,只需使用随机库的 random 函数从这个数组中选择一个角度。
如果你玩过这个机器人,你可能会注意到它并不知道太多句子。它说的短语都包含在数组 sentences 中,如下所示:
sentences = [
"你好,我叫 Mike",
"你叫什么名字",
"我在看着你",
"消灭 消灭 消灭",
"第五号正在活跃"
"我做不到,Dave",
"daisee daisee give me your answer do"
]
和眼睛角度一样,当我们想要一个句子时,我们就从这个数组中选择。正如你在代码中看到的那样,对于机器人扬声器,有时拼写一个单词的音标比正确拼写更好。
三个用于语音动画的嘴唇图像作为自定义 Image 对象创建。这里是用于静止嘴唇动画的一个水平线:
lips0 = Image("00000:"
"00000:"
"99999:"
"00000:"
"00000")
Image 中的每一行是一个字符串,表示显示屏的一行;字符串中的每个数字代表一个特定 LED 的亮度,从 0 到 9。
嘴唇的图像保存在变量 lips 的数组中:
lips = [lips0, lips1, lips2]
speak 函数控制着说话和嘴唇动画,它接受一个参数 sentence,即要说的句子:
def speak
(句子):
words = sentence.split()
for i in range(0, len(words)):
display.show(random.choice(lips))
speech.say(words[i])
display.show(lips0)
为了确保嘴唇动画与说出的单词同步,我们使用 split 方法将句子分解成单个单词列表 words。然后,对于列表中的每个单词,我们随机选择一个嘴唇图像(使用随机库的 choice 方法)并让 speech 说出该单词。当所有单词都被说完时,嘴唇显示会恢复为默认的 lips0 图像。
接下来,我们定义一个 act() 函数:
def act():
set_servo_angle(pin2, random.choice(eye_angles))
sleep(300)
speak(random.choice(sentences))
set_servo_angle(pin2, 90)
sleep(2000)
act函数完成三件事:它通过将伺服电机设置为一个随机角度来随机移动眼睛,它通过调用speak选择一句话来播放,并通过将伺服电机角度重置为 90 度来重置眼睛。为了在每个步骤之间留出一些时间,代码会调用sleep函数。
下面是我们代码的主体部分,包含了所有的变量和函数:
while True:
new_z = abs(accelerometer.get_z())
if abs(new_z - base_z) > 20:
base_z = new_z
act()
if random.randint(0, 1000) == 0:
act()
sleep(50)
在代码的主体部分,我们有一个while True循环,这意味着命令会一直执行,直到收到停止信号。这对于需要代码持续响应输入的情况非常有用。在这里,我们希望准备好应对机器人头部被敲击时加速度的突然变化。首先,循环会注册来自加速度计的加速度。然后,它使用abs函数获取加速度的大小——在这个例子中,我们不关心方向,只关心加速度有多大。
在第一个if语句中,我们检查加速度值是否发生了超过 20 毫伽(毫重力)的变化。如果是这样,基础加速度会更新为新的加速度(确保下一次循环时,加速度必须变化超过另外20 毫伽),并调用act函数。
在第二个if语句中,我们为机器人的头部添加了一些随机性。代码会在 0 到 1,000 之间随机选择一个数字。如果数字等于 0(1/1,001 的机会),则调用act函数。尽管这个概率非常低,但由于该值每秒检查数百次,头部会每分钟跳跃几次。
尝试的事项
尝试使用 USB 电池或 AAA 电池盒来为头部供电,而不是通过 USB 电缆将其连接到计算机。
如果你想改变头部的语音,可以进入代码并向sentences数组中添加更多句子。
语音库产生的语音相当安静且不清晰。你可以通过连接一个更大功率的扬声器来稍微改善这一点。
如果你想给项目增加一些内容,可以看看这里的代码示例:microbit-micropython.readthedocs.io/en/latest/tutorials/speech.html。在这段代码中,语音库被用来产生唱歌的效果。
项目:机器人探测车

难度:困难
在这个项目中,我们将创建一个机器人探测车。通过使用一个名为 Bitty Controller 的巧妙应用程序,你可以通过安卓手机控制这个小型越野车(图 6-21)。疯狂科学家喜欢用这个探测车给实验室助手送消息。
警告 我们将在这个项目中使用一些低成本底盘套件,但这些套件附带的电线通常比较松散——这意味着你需要将电线焊接到电机上。这是本书中唯一需要焊接的项目。焊接不难,但它很危险,你很容易被烫伤。所以请找一位成年人来完成这一部分。

图 6-21:一个由 micro:bit 控制的巡航机器人
所需物品
对于这个项目,你需要以下物品:
Micro:bit
安卓手机
Kitronik Motor Driver Board for micro:bit (V2) 用于控制电机
低成本机器人底盘套件 包括两个齿轮电机和一个 4 × AA 电池盒
4 × AA 电池
Bitty Controller 安卓应用 从 Google Play 商店下载(约 $5)
各种螺丝刀 适用于底盘上的螺母和螺栓,以及电机控制板上的接线端子
焊接设备 用于将电线连接到齿轮电机
Blu-Tack 粘合膏 用于将电机控制板和 micro:bit 固定到底盘上
如果你在 eBay 或 Amazon 上搜索机器人底盘,你会找到像图 6-22 所示的低成本机器人底盘套件。寻找那些包含 4 × AA 电池盒和两个齿轮电机(带内置齿轮箱的电机)的套件。

图 6-22:该疯狂科学家使用的低成本机器人底盘
构造
这个项目中最棘手的部分可能就是底盘套件的组装。将螺丝和螺栓放到正确的位置需要精确和技巧。
不是所有的底盘都相同,所以我不会逐步带你进行组装,而是给你一些高层次的建议。你的底盘应该会附带说明书,尽管它们可能有些难以理解。一般来说,你需要连接齿轮电机、万向轮(能够自由转动的轮子)、电机控制器和 micro:bit。
-
将提供的电线焊接到电机接线端子上,如图 6-23a–c 所示。如果你工作迅速,可以通过将大量焊锡熔化到电机接线端子上,然后用烙铁将电线按压到焊锡的顶部来制作一个良好的焊接点(见图 6-23a)。
![Image]()
图 6-23:将电线焊接到电机上
-
红色电线连接到哪个端子并不太重要。只要确保两台电机之间保持一致。如果你决定将红线连接到一台电机的右侧端子上,那么另一台电机的红线也要连接到右侧端子。
-
去除覆盖底盘的纸层。图 6-24a–e 展示了组装过程的大致步骤。你可能会发现你的底盘与展示的不同。
![Image]()
图 6-24:组装底盘
在组装底盘时,有几个事项需要记住:
不要过度拧紧螺母和螺栓,因为这样可能会导致塑料底盘开裂。
安装齿轮电机时,将螺母朝向底盘的内部,这样突出在螺母外的电机固定螺栓就不会妨碍车轮。
如果螺栓不能顺利旋入螺母中,可以试着将螺栓逆时针旋转一点,找到螺母的螺纹起始位置。你可以用一把小钳子抓住螺母,然后用螺丝刀转动螺丝。 -
一旦底盘安全组装好,将 micro:bit 安装到 Kitronik 电机驱动板上,确保 micro:bit 的屏幕朝外,如 图 6-25 所示。小心对准 micro:bit 的边缘连接器与电机控制器上的插座,并将其牢固按入到位。当你的控制器看起来像 图 6-25 时,使用粘性粘土将其固定到底盘上,粘土在 图 6-25 中也有展示。
![Image]()
图 6-25:安装 micro:bit
-
现在是接线电机和电池盒的时候了。首先,查看 图 6-26 了解你要实现的连接。旋松相关端子的螺丝,将电线牢固地放入端子中,然后将螺丝重新旋紧。
![Image]()
图 6-26:接线
-
进行以下连接:
从电池盒引出的红色(正极)电线连接到电机控制器上标记为 RED +的螺丝端子
从电池盒引出的黑色(负极)电线连接到电机控制器上标记为 BLACK -的螺丝端子
从左侧电机(从后方看)引出的红线连接到电机控制器上的螺丝端子,标记为 MOTOR1 P12
从左侧电机引出的黑线连接到电机控制器上的螺丝端子,标记为 MOTOR1 P8
从右侧电机引出的红线连接到电机控制器上的螺丝端子,标记为 MOTOR2 P0
从右侧电机引出的黑线连接到电机控制器上的螺丝端子,标记为 MOTOR1 P16 -
在本项目中,你将使用 Android 应用通过蓝牙控制车载机器人。你可以在
www.bittysoftware.com/downloads.html#controller上找到运行在 micro:bit 上的代码。点击链接 micro:bit hex 文件用于 Kitronik Buggy - 无需配对 并下载 hex 文件。该文件也可以在 其他下载 文件夹中与书籍下载一起获取。接下来,通过 USB 将 micro:bit 连接到电脑,并将下载的 hex 文件复制到你的 micro:bit 中。此时你还不需要电池。 -
要在你的安卓手机上安装应用程序,打开 Google Play 并搜索Bitty Controller。你需要为该应用支付几美元。下载并安装该应用。
-
我们离试验这个项目只差一步了!把四节 AA 电池放入电池盒中。这些电池将为电动机和你的 micro:bit 提供电力,这意味着你可以拔掉 USB 电缆——是时候让你的探测器自由了。
打开 Bitty Controller 应用程序(图 6-27),点击扫描。这应该能够找到你的 micro:bit。在图 6-27 中,它被称为BBC micro:bit [gaviv]。点击它后,RC 风格的控制器(见图 6-28)应该会出现。micro:bit 的显示屏上也应该会显示一个C,表示它已连接到你的手机。

图 6-27:启动 Bitty Controller

图 6-28:双 D-pad 控制器
使用顶部和底部的方形按钮来控制探测器的前进和后退。要让探测器向左和向右转动,使用左右圆形按钮。
第一次测试时,做点简单的事:将探测器翻到背面,用应用程序控制车轮。它们会转动吗?一旦探测器通过了这一测试,就把它放到地板上,尝试驾驶它。如果你不喜欢控制器布局,可以前往 Bitty Controller 应用中的“选项”来寻找其他布局。
如果你的探测器在你让它后退时却向前进,反之亦然,说明你的电线接错了:交换电机 1 和电机 2 的红线和黑线。如果你的探测器绕圈行驶,交换其中一个电机的电线对。
当你想关闭你的探测器时(这是一种延长电池使用寿命的好方法),只需将电池架中的一端电池抬起。瞧!你现在就有了一个粗糙的开关。
工作原理:电动机与电流流动
齿轮电动机的方向由流经它们的电流方向控制——如果你反转电流方向,电动机的转向也会反转。如图 6-29 所示,当连接 A 为正,连接 B 为负时,电动机顺时针转动。如果 A 和 B 反向连接,使得 A 为负,B 为正,则电动机反向旋转。

图 6-29:控制电动机的方向
Kitronik 马达控制器包含一个芯片,控制两个电动机的电流方向。它还提供电动机所需的相对较高电流。
总结
在这一章中,我们涵盖了很多内容。首先,我们了解了伺服电动机以及如何使用 micro:bit 设置一个伺服电动机。然后,我们构建了两个复杂的项目:动画头和遥控探测器。在这个过程中,我们学习了 PWM 和电流流动,还掌握了一些基本的编程技巧。
现在你知道如何让物体移动了,你可以开始考虑其他你想要制作的项目了。你希望哪些物体能够自动移动呢?在下一章,我们将探讨如何处理时间。

第七章:时间旅行
好的,虽然我们在本章中不会真正建造时光机,但你将通过制作一个二进制时钟和一个可以说话的时钟来衡量时间。我们还将进行一个实验来测试你的 micro:bit 保持时间的能力。本章中的所有实验和项目仅使用 MicroPython。
实验 9:保持时间

这个实验的目的是制作一个能够精确计时的 micro:bit 时钟。也就是说,编程让 micro:bit 每秒精确地滴答一次。

一种实现方式是使用sleep函数,如这里展示的代码。请注意,这段代码不是一个完整的程序,因此不要尝试运行它。sleep命令会让 micro:bit 在指定的时间内什么都不做。在我们的例子中,延迟是 1000 毫秒(1 秒)。
seconds = 0
while True:
sleep(1000)
seconds += 1
在这个例子中,每过 1 秒,程序就会将seconds变量加 1,记录经过的秒数。这个循环会无限重复,作为标记时间的一种方式,它能工作一段时间。
问题在于,时钟会逐渐滞后,因为我们没有考虑到 micro:bit 为seconds变量加 1 所花费的时间。在这个例子中,给变量加 1 几乎不花时间,但如果程序变得更长——例如,要求时钟同时显示时间,甚至说出时间(我们稍后会尝试)——那么延迟可能变得显著。这也是不可预测的,因为每次程序循环时丢失的时间可能不同。
因此,一个更好的保持时间的方法是使用running_time函数。该函数返回自 micro:bit 上次重置以来经过的毫秒数,且不受代码其他部分执行时间的影响。
在这个实验中,我们将使用running_time函数来计算我们的 micro:bit 时钟运行得有多慢或多快。
你需要的材料
要进行这个实验,你只需要两样东西:
Micro:bit
USB 电缆
构造
-
在
github.com/simonmonk/mbms/查找代码。这个实验的 Python 文件是Experiment_09.py。打开程序并通过 Mu 闪存到你的 micro:bit 上。 -
一旦你成功编程 micro:bit,按下按钮B。你应该会发现 micro:bit 将秒数设置为 0,并从 0 开始计数。
-
设置手机或其他设备上的计时器,精确到 16 分钟 40 秒。启动计时器的同时,按下按钮B重置 micro:bit 的秒数计数。在计时结束时,按下按钮A冻结时钟并记录显示的秒数。
因为这个实验涉及的是计时,所以重要的是在按下 B 按钮时准确启动计时器,并在计时器响起时立刻按下 A 按钮。如果有朋友帮助,会更容易:你们可以一人操作计时器,另一人操作 micro:bit。
设置计时器为 16 分钟 40 秒的原因是因为这正好是 1,000 秒。如果 micro:bit 的秒数大于 1,000,说明时钟走得太快;如果秒数小于 1,000,说明时钟走得太慢。我的 micro:bit 的秒数为 989,表明 micro:bit 的内部时钟比正常时间慢了大约每千分之一的 11 个部分。
记下你的 micro:bit 的秒数。在本章的项目中,你将用它来提高时钟的准确性。
代码
这是实验 9 的 MicroPython 代码:
from microbit import *
seconds = 0
last_time = 0
while True:
now = running_time()
elapsed_ms = now - last_time
if elapsed_ms >= 1000:
seconds += 1
last_time = now
if button_a.was_pressed():
display.scroll(str(seconds))
if button_b.was_pressed():
seconds = 0
display.show("0")
sleep(100)
display.clear()
程序使用了两个变量:
last_time 用来跟踪时钟上次滴答的时间
seconds 用来跟踪自 micro:bit 上次重置并开始计时以来已过去的秒数
我觉得将时钟滴答作响就像普通时钟一样是有用的。也就是说,它会在固定的间隔时间内做一些事情。
主while循环使用running_time函数来计算 micro:bit 已运行的毫秒数。它将这个数字存储在一个名为now的变量中。然后,通过将now减去last_time来计算自上次计时以来经过了多少毫秒。
如果经过的毫秒数大于或等于 1,000——换句话说,大于或等于 1 秒——那么seconds变量将增加 1。然后,我们将已过的毫秒数重置为 0,以便重新开始计时。
我们使用两个if语句来编程 A 按钮和 B 按钮。如果按下 A 按钮,micro:bit 会显示seconds,即自程序开始运行以来经过的时间。如果按下 B 按钮,秒数计数会重置为 0。
工作原理:保持时间
micro:bit 的处理器使用晶体振荡器(用于精确计时的电子元件),其精度应当达到每百万分之 30。然而,在我的 micro:bit 上,它由于某种原因不准确,偏差为每百万分之 11,000。
要获得一个真正精确的时钟,你需要使用专用的 RTC(实时时钟)芯片和独立的晶体振荡器。在写本文时,尚未推出专门针对 micro:bit 的 RTC 芯片。虽然可以通过一定的手段让它与 micro:bit 配合使用,但这个过程相当复杂。因此,最好不要过于依赖本章中构建的任何一个时钟,但这些项目很有趣,并且会教会你重要的技能。
项目:二进制时钟

难度:简单
在这个项目中,如图 7-1 所示,你将创建一个显示二进制时间的时钟。二进制是计算机使用的一种计数系统。你可以在第 176 页的《工作原理:用二进制告诉时间》一节中了解更多关于它的信息。二进制时钟在 micro:bit 的 LED 显示器上分别以二进制数字显示小时、分钟和秒数。

图 7-1:Kitronik MI:Pro 外壳中的二进制时钟
图 7-2 展示了 micro:bit 上的二进制计数系统。一开始它看起来可能有点困惑,就像一组随机的 LED 图案,但我会很快解释它是如何工作的。而且,疯狂的科学家喜欢通过展示自己读取二进制时钟的技巧来给朋友们留下深刻印象!

图 7-2:读取二进制时钟
如何读取二进制时钟
我们的二进制时钟是一个 24 小时制时钟。要读取时钟,从图 7-2 所示的顶部 LED 行开始。这一行代表小时。每一列的 LED 代表一个数字。从右到左,这些列分别代表数字 1、2、4、8 和 16。通过将这五个数字相加,你可以创建从 1 到 24 之间的每个可能的值。要计算小时数,请加上那些亮着的 LED 列对应的数字。在图 7-2 中,亮着的列是 1、2 和 8,它们加起来是 11。所以,时间是 11 点。
接下来的两行表示分钟数,底部的两行表示秒数。分钟和秒数通过具有相同 1、2、4、8 和 16 个 LED 的行来表示。然而,由于我们需要能够计算到 60(分钟和秒),这些值通过前一行的一个附加 LED(值为 32)来指示。如图 7-2 所示,分钟的 32 个 LED 是从顶部数起第二行最左边的 LED,而秒钟的 32 个 LED 是从顶部数起第四行最左边的 LED。
在图 7-2 中,4 和 1 分钟的 LED 亮着,表示 5 分钟。2 和 1 秒钟的 LED 亮着,表示 3 秒钟。合起来,这个显示表示的时间是 11:05:03。
按住 A 按钮将使时钟上的数字迅速前进,允许你设置时间。你只需要准备好在时钟显示正确时间时立即停止它。
你可以观看这个时钟运作的视频,包括如何设置时间,视频链接是 www.youtube.com/watch?v=v26gYo5OG0g。
你需要的材料
对于这个项目,你只需要你的 micro:bit 和一个电源。
如果你计划让时钟持续运行,那么应该为 micro:bit 使用 USB 电源适配器或其他长期电源(参见附录),以节省电池。你可能还想为 micro:bit 配一个外壳,让时钟看起来更漂亮。
记住,时钟不会保持完美的时间,所以你需要相对频繁地重置它。
构建
-
这个项目的代码是用 MicroPython 编写的,因为所需的数学运算用 Blocks 代码实现起来会非常复杂。你可以从
github.com/simonmonk/mbms/下载代码。这个项目的文件是 ch_07_Binary_Clock.py。 -
在将程序加载到你的 micro:bit 上之前,请在 Mu 中打开它并更改当前时间,以确保它准确无误。你应该将其设置为当前时间之前的几分钟,以确保安全。稍后你可以通过按住 A 键来调整时间。
通过修改以下几行来更改时间。记住,这是 24 小时制的时钟,所以,例如,晚上 6:00 是 12 + 6 或 18 小时。
hours = 8
minutes = 25
你还应该将
adjust变量的值更改为你的 micro:bit 时钟慢或快的千分之一。我的 micro:bit 在 1,000 次中慢了 11 秒,所以我将adjust设置为 -11 来稍微加快它(注意负号)。如果 micro:bit 比如每 1,000 次快 10 秒,那么我会将adjust设置为 10,以略微减慢它的速度。
代码
这个项目涉及了相当多的数学。我们还会使用一些更高级的编程特性,例如二维数组,在 Python 中比在 Blocks 代码中更容易实现。
让我们将代码分成几个部分,首先是为每个 LED 分配正确的二进制值的几行代码:
hhhhh
m
mmmmm
s
sssss
sec_leds = [[4, 4], [3, 4], [2, 4], [1, 4], [0, 4], [0, 3]]
min_leds = [[4, 2], [3, 2], [2, 2], [1, 2], [0, 2], [0, 1]]
hour_leds = [[4, 0], [3, 0], [2, 0], [1, 0], [0, 0]]
adjust = -11
代码的前四行其实并不是程序的一部分。它们是注释行,或者说是提示,提醒你哪些 LED 显示的是小时、分钟和秒。这些注释可以作为设置后续数组中 LED 坐标的有用参考。
接下来的三行是前面提到的二维数组。这些数组将适当的 LED 坐标分配给秒、分钟和小时。记住,数组就像变量,只不过它们包含多个元素。我们这里使用的数组被称为二维数组,因为它们的元素也是数组。例如,第一个数组sec_leds的第一个元素是[4, 4]。这表示用于显示秒数的第一个 LED 的坐标是 x=4 和 y=4,也就是显示器右下角的那个 LED。图 7-3 展示了构成显示的单个 LED 的坐标。

图 7-3:LED 显示坐标
如你所见,左上角的 LED 坐标是[0, 0],右下角是[4, 4]。

接下来,我们有hours、minutes和seconds变量来保持当前时间:
hours = 8
minutes = 25
seconds = 1
adjust = -11
我们将使用adjust变量来修正时钟的速度。如果你不确定如何操作,可以参考第 167 页中的“构造”部分。
这是一个将 LED 灯开关控制为二进制显示的函数:
def display_binary(value, num_bits, leds):
v = value
for i in range(0, num_bits):
v_bit = v % 2
display.set_pixel(leds[i][0], leds[i][1], int(v_bit * 9))
v = int(v / 2)
我们有三个单独的二进制数字(小时、分钟和秒)需要显示,display_binary函数适用于所有这些。它接受一个要显示的数字(value)、显示数字所用的 LED 数量(num_bits)和 LED 的数组(leds)。它使用这三个值来在 micro:bit 上显示时间的三个部分——秒、分钟和小时。
为了跟踪时间,使用了两个变量:
last_time = 0
tick = 1000 + adjust
变量last_time记录时钟上次滴答的时间,变量tick保存时钟滴答的时长(毫秒)。tick的默认值是1,000 + adjust,但当你按下 A 按钮设置时间时,这个值会发生变化。
这是更新时间的代码:
def update_time():
global hours, minutes, seconds
seconds += 1
if seconds > 59:
seconds = 0
minutes += 1
if minutes > 59:
minutes = 0
hours += 1
if hours > 23:
hours = 0
update_time函数每次调用时会将秒数增加 1。当seconds超过 59 时,秒数会重置为 0,分钟数加 1。对小时数也是如此。我们通过嵌套的if语句来实现这个功能。
这是以二进制方式显示小时、分钟和秒数的代码:
def display_time():
display_binary(seconds, 6, sec_leds)
display_binary(minutes, 6, min_leds)
display_binary(hours, 5, hour_leds)
我们将这段代码放入display_time函数中,该函数调用之前定义的display_binary函数。
这是主要的 while 循环,它使时钟在按下按钮 A 时快速运行,其他情况下正常运行。它还包含保持时间的代码。
while True:
如果 button_a.is_pressed():
tick = 10
否则:
tick = 1000 + adjust
now = running_time()
elapsed_ms = now - last_time
如果 elapsed_ms 大于或等于 tick:
更新时间()
display_time()
循环的第一部分检查是否按下了按钮 A。如果按下,则代码将 tick 设置为 10 毫秒。否则,将其设置为 1000 + adjust。
最后,我们编写了使时钟保持运行的代码。running_time 函数返回自上次重置 micro:bit 后经过的毫秒数。每次程序循环时,我们计算自上次时钟滴答声以来已过去的时间。循环执行以下操作:
-
获取当前的
running_time并将其存储在名为now的变量中 -
通过计算
now和last_time之间的差值来得出elapsed_ms的值 -
如果
elapsed_time大于我们的tick时间(1 秒),则更新时间 -
将
last_time设置为now,重置毫秒计数为零
工作原理:用二进制表示时间
使用这个二进制时钟来查看时间有点棘手。尤其是秒数,可能在代码计算出来之前就已经改变了。但是,二进制系统之所以存在是有原因的。
我们大多数人都熟悉十进制数字系统。十进制是拉丁语中表示 10 的词,在十进制系统中,我们使用 10 个不同的符号(数字 0 到 9)。如果我们需要写一个大于 9 的数字——比如 15——那么我们就用两位数字。因为数字 15 中 1 的位置,我们知道它实际上代表的是 10。
下表显示了从 0 到 10 的二进制数。注意,在十进制中,我们不写前导零。例如,我们不会将 15 写成 0015。但在二进制中,习惯上会加上前导零,使数字长度一致。这就是计算机科学家的一种做法。所以在这种情况下,所有二进制数都是四位数。
| 十进制 | 二进制 |
|---|---|
| 0 | 0000 |
| 1 | 0001 |
| 2 | 0010 |
| 3 | 0011 |
| 4 | 0100 |
| 5 | 0101 |
| 6 | 0110 |
| 7 | 0111 |
| 8 | 1000 |
| 9 | 1001 |
| 10 | 1010 |
理论上,计算机可以使用 10 种不同的电压来表示数字 0 到 9,但它们并不这么做。相反,计算机使用一种叫做二进制的系统。二进制中的数字(也叫做 比特)只有两种可能的状态,可以是 0 或 1。计算机使用二进制是因为它们使用的 晶体管 很擅长表现“关(0)”或“开(1)”的状态。也就是说,晶体管只有 2 种状态,这比给它们提供 10 种状态要容易得多。而且,二进制逻辑背后的数学原理使得计算机在处理二进制数字时能够进行可靠的算术运算,比起处理十进制数字要轻松得多。
就像熟悉的十进制系统一样,二进制系统通过组合数字来表示更大的数字。而在十进制中,每个数字的位置是按 10 的倍数增加的——从 1 到 10,再到 100——而二进制中的每个数字则按 2 的倍数增加——从 1 到 2,再到 4,以此类推。例如,四位二进制数 1010 在 16 位和 2 位位置上是 1,在其他位置上是 0。换算成十进制,就是 16 + 2,等于 18。
事实证明,你并不需要很多二进制数字就能表示一些非常大的数字。例如,八位二进制数字组合在一起(称为 字节)可以表示从 0 到 255 之间的十进制数。如果是 16 位,那么数字范围可以达到 65,535。如果是 64 位的计算机,它能使用这 64 位数字做所有的运算,并且能够表示 0 到 18,446,744,073,709,551,615 之间的数字。顺便提一下,micro:bit 拥有一颗 32 位处理器,能够表示 0 到非常可观的 4,294,967,295 之间的数字。我们一直在使用的 MicroPython 函数 running_time 使用的是 32 位数字。这意味着它在 4,294,967,295 ÷ 1,000 ÷ 60 ÷ 60 ÷ 24 = 49.7 天内不会用完数字。
项目:会说话的时钟

难度:简单
有时候疯狂科学家忙于试管、化学品和浓烟,以至于无法查看时间。然后他们忘记吃饭!这时,一款会说话的时钟就派上用场了。这个项目(图 7-4)每小时报一次时间,或者当你按下 A 按钮时也会报时。

图 7-4:会说话的时钟
你可以在 www.youtube.com/watch?v=iNjXEK8RUtU 上看到这个项目的实际效果。
你需要的东西
对于这个项目,你需要以下物品:
Micro:bit
3 根鳄鱼夹电缆 用于将 micro:bit 连接到扬声器
micro:bit 扬声器 用于播放声音(可以使用 Monk Makes 扬声器,或者参考 第二章 了解其他扬声器选项。)
电源适配器 参见 附录,了解如何使用不需要电池的方式为 micro:bit 供电。
如果你打算保持时钟运行,那么使用 USB 电源适配器或其他长期电源解决方案,以节省电池。
你可能想为时钟制作一个外壳,或者将 micro:bit 和扬声器固定在你用于第三章光控吉他项目的同一块纸板上。
构建
-
这个项目的代码是用 MicroPython 编写的,因为在 Blocks 代码中当前无法使用语音库。从
github.com/simonmonk/mbms/下载代码。此项目的文件是ch_07_Talking_Clock.py。 -
在将程序加载到你的 micro:bit 之前,打开 Mu 文件并将小时和分钟更改为当前时间。还要将
adjust更改为你想调整时钟的时间量。如果你不确定如何操作,请参见第 167 页二进制时钟项目中的“构建”部分。 -
使用一个鳄鱼夹将扬声器连接到 micro:bit 的 0 号引脚,另一个鳄鱼夹连接到扬声器上的 IN 引脚。使用另外两个夹子为扬声器提供电源,如图 7-4 所示。
-
等待步骤 2 中设置的时间到达。然后将 micro:bit 连接到电源。请注意,在这个项目中,没有其他机制来设置时间。
代码
为了更清楚地说明,我们将分段处理这段代码。
这是做时间保持的代码——换句话说,它确保小时和分钟是正确的。它几乎与上一个项目中的时间保持代码相同。主要的区别是,代码不会在 LED 显示屏上显示时间,而是通过语音播报当前时间。
digits = ["no", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen"
"sixteen", "seventeen", "eighteen", "nienteen"
tens = ["no", "no", "twenty", "thirty", "forty", "fifty"]
preamble = "The time is "
am = "aye em"
pm = "pee em"
我们使用多个变量和数组来保存 micro:bit 将要说的一组词。
语音库包含一些常见单词的录音。它可以说出 1、2 或 3 这样的单个数字,但对于 10 及以上的数字,它会分别发音每个数字,这不是我们希望时钟说的方式。因此,我们必须拼写出大于 10 的数字。注意,nineteen被拼写成nienteen,这样在合成语音说出时才听起来正确。名为digits的数组保存了 0 到 19 的每个数字的文本。时钟永远不会读出 0,所以我们将它设置为单词no。
tens数组在处理 10 的倍数时做类似的工作。我们已经通过 digits 数组考虑了所有小于 19 的数字,因此我们不需要担心tens数组中的前两个元素,它们永远不会被说出来。我们将它们也设置为no。
preamble 变量包含在 micro:bit 每次播报时间之前会说的文本。am 和 pm 变量包含 AM/PM 指示符的音标版本。在读取时间后,micro:bit 将说出这些中的一个。
这是带有实际说出时间的函数的代码。它的名字非常贴切,叫做speak_the_time。
def speak_the_time():
h = hours
am_pm = am
if h >= 12:
am_pm = pm
if h > 12:
h = h - 12
if minutes == 0:
当前时间是十二点整
speech.say(preamble + digits[h] + " "
- am_pm + " exactly")
else:
if minutes < 10:
当前时间是十二点四分下午
speech.say(preamble + digits[h] + " o "
- digits[minutes] + " " + am_pm)
elif minutes < 20:
当前时间是十二点十八分下午
speech.say(preamble + digits[h] + " "
- digits[minutes] + " " + am_pm)
else:
mins_tens = int(minutes / 10)
mins_units = minutes % 10
if mins_units == 0:
当前时间是十二点二十分钟下午
speech.say(preamble + digits[h] + " "
- tens[mins_tens] + " " + am_pm)
else:
当前时间是十二点二十四分下午
speech.say(preamble + digits[h] + " "
- tens[mins_tens] + " " + digits[mins_units] + " " + am_pm)
这个函数相当复杂,因为它必须处理我们表达时间的不同方式。
这个时钟使用 12 小时制语音播报,但以 24 小时制存储小时,因此start_the_time函数首先会判断当前时间是 AM 还是 PM。当hour值大于或等于 13 时,它会从hour中减去 12。
接下来,嵌套的if语句处理以下几种情况:
如果时间正好整点,可以说类似当前时间是十二点整。
否则,如果分钟数小于 10,可以在分钟前加上o,说出类似当前时间是十二点四分下午的内容。
对于小于 20 的两位数分钟,可以使用digits数组并说出类似当前时间是十二点十八分下午的内容。
对于其他大于 20 的两位数分钟,可以使用tens数组说出类似当前时间是十二点二十分下午的内容。
如果分钟数不是 10 的倍数,应该说类似当前时间是十二点二十四分下午的内容。
最后是主while循环:
while True:
if button_b.is_pressed():
speak_the_time()
now = running_time()
elapsed_ms = now - last_time
if elapsed_ms >= tick:
elapsed_seconds = int(elapsed_ms / tick)
update_time(elapsed_seconds)
blink()
last_time = now
这个循环会检查是否按下了 B 按钮或一小时已经过去,如果发生其中任何一个事件,就会播报时间。它还调用了一个叫做blink的函数,用于闪烁屏幕上的心形图标,提醒你时钟正在运行,即使大部分时间它保持沉默。
它是如何工作的:教 Micro:bit 说话
MicroPython 语音库为你的项目提供了各种可能性,正如你在第六章中看到的那样。音质虽然不是完美的,但它确实为你的项目增添了许多乐趣。
语音库本身基于音素的概念:声音的构建块。当你使用say函数时,要说的文本首先会被转换成一系列音素。由于口语语言的特殊性,这个过程常常不能完美执行——因此在这个项目的代码中,nineteen这个词的拼写被故意更改,以帮助say函数更准确地发音。
你可以在microbit-micropython.readthedocs.io/en/latest/tutorials/speech.html上阅读更多关于这个语音库的内容。
总结
希望你现在已经对如何使用 micro:bit 制作时钟并用它来显示或直接告诉你时间有了一个很好的理解。
在下一章中,疯子科学家将把注意力转向心理学实验。

第八章:疯狂科学家的脑力游戏
在本章中,疯狂科学家将注意力转向了他们天才的源泉——大脑!首先,你将通过测试你对刺激反应所需的时间来了解你的神经系统。接着,你将制作一个测量皮肤电阻的测谎仪,这也是多道测谎测试中的一个因素。用它来测试你的朋友。如果他们在你询问时变得热乎乎、满头大汗,那他们可能在撒谎哦!
实验 10:你的神经反应有多快?

难度:中等
人体通过神经细胞或神经元来处理刺激。神经是人体的电线,传递从大脑到身体其他部位的信号,并返回。当你触碰到热炉子时,似乎立刻感到疼痛。但与大多数电子产品中的铜线相比,神经的传递速度实际上比较慢。
通过测量大脑对信号反应所需的时间,你可以估算该信号在神经中传输的速度。在这个实验中,每当 micro:bit 屏幕变空时,你将用手或脚按下 A 按钮,micro:bit 会测量你反应所需的时间。
我们将制作一个纸板踏板围绕 micro:bit,这样你可以按下按钮而不遮挡显示屏(图 8-1)。

图 8-1:将 micro:bit 变成脚踏开关

你需要的材料
对于这个项目,你需要:
Micro:bit
约 8 英寸 × 4 英寸(20 厘米 × 10 厘米)纸板 厚实且坚固的纸板效果最佳。不需要完全符合这个尺寸。
工艺刀 用于切割和打标纸板
Blu-Tack 粘合膏 用来将 micro:bit 固定到纸板上
构建
我们将从制作一个纸板踏板开始,这个踏板将围绕 micro:bit 对折。
-
在纸板上大约从中间开始画出两条平行线,间隔约 1/4 英寸(5 毫米),如图 8-2 所示。你将沿着这些线条对折纸板。同时,标记出你要切割的矩形部分。确保你要切割的孔足够大,可以容纳 micro:bit 的屏幕。
-
沿着铰链的线条用刀切割,只切到纸板的一半。这叫做打标纸板。小心不要切割完全。然后切掉你标记的矩形部分。
![图片]()
图 8-2:制作铰链并切出 micro:bit 显示屏的位置
警告 使用工艺刀可能很危险!在这个项目的这部分,应该由一个负责任的成人使用工艺刀,或者至少进行监督。
-
将 micro:bit 放入折叠的纸板中,以便你可以看到它的屏幕。将小块 Blu-Tack 粘贴在 micro:bit 的中央,然后将 micro:bit 粘贴到纸板上。当你轻轻按压铰链的顶部时,你应该能感觉到 A 按钮的点击(见图 8-1)。检查按下开关时,是否不会不小心按到 micro:bit 背面的重置按钮。如果按到了,尝试使用更大的 Blu-Tack 块。
-
本实验仅使用 MicroPython。代码可以在
github.com/simonmonk/mbms/找到。本实验的 Python 文件是 Experiment_10.py。在 Mu 中打开该文件并将其加载到 micro:bit 上。
测试你的神经系统
控制此实验的程序使用 Mu 的 REPL 来报告结果并给出指令。(如果你需要复习 REPL 的工作原理,请回顾第一章。)因为它使用 REPL,这是一个你需要通过 USB 电缆将 micro:bit 连接到计算机的实验。我们将使用 micro:bit 的显示屏和 A 按钮来测量反应时间。
打开 Mu 的 REPL。REPL 窗口中的指令会要求你在 micro:bit 显示十字形时按住 A 按钮,并在显示屏变空时尽可能快地释放它。
下面是你在典型运行中可能会看到的 REPL 内容。为了清晰起见,指令被分成了几个部分。
测试 1 - 使用你的手
当十字形显示时,按住开关。
当显示屏变空时,暂时释放按钮。
重复 5 次。
准备好开始测试时按 ENTER
要开始第一次测试,使用你的主手按住开关,并在计算机上按一次 ENTER。屏幕上应该会出现一个十字形。在 3 到 7 秒之间的随机延迟后,显示屏会变空。当它变空时,尽可能快地释放按钮。REPL 应该显示显示屏变空和你释放开关之间的毫秒数。例如:
252
十字形应该会在另一个随机时间段内点亮,因此按住开关再试一次。实验应该重复五次。
如果你在显示屏变空之前松开开关,REPL 会显示消息 You let go too soon。这将记录一个 0 的时间,导致实验无效,你需要重新开始整个过程。如果发生这种情况,重置 micro:bit,方法是拔掉它的 USB 电缆并重新插上。
完成五次测试后,micro:bit 的显示屏应保持空白,REPL 会显示你每次的反应时间以及所有时间的平均值。例如:
252
264
264
282
使用手时的平均时间是 262.7999 毫秒
然后你需要使用脚重复实验。将 micro:bit 踏板放到地板上。这次,将你的脚放在 micro:bit 上,轻轻地用脚按下开关。掌握这一点可能需要一些练习。
现在重复脚的测试。一旦你捕获了五次反应时间,REPL 应该会显示平均值,然后提示你输入以下两个测量值,像这个示例一样:
使用脚的平均时间是 368.3999 毫秒
输入从脖子到手指的距离(单位:厘米):107
输入从脖子到脚趾的距离(单位:厘米):188
程序将使用这些测量值计算大脑意识到显示器已消失的时间(毫秒为单位),即思考时间。它还会计算信号传输到手或脚的速度(米/秒),即传输速度。
思考时间(毫秒):123.3036
传输速度(米/秒):13.03703
《工作原理:测量你的反应时间》一章在 第 191 页 会解释这些计算是如何进行的,以及它们的意义(或没有意义)。
代码
我们使用变量 n 来保存每个测试所需的反应时间读取数量。在此例中,共进行五次读取。
from microbit import *
import random
n = 5
def run_full_test():
print("测试 1 - 使用你的手")
t_hand = run_test()
print("使用手的平均时间是 " + str(t_hand))
- " 毫秒")
print("现在重复脚的测试")
t_foot = run_test()
print("使用脚的平均时间是 " + str(t_foot))
- " 毫秒")
➊ d_hand = int(input("输入从脖子到
从脖子到手指的距离(单位:厘米):"))
➋ d_foot = int(input("输入从脖子到
从脖子到脚趾的距离(单位:厘米):"))
thinking_time = (d_foot * t_hand - d_hand * t_foot)
/ (d_foot - d_hand)
transmission_speed = 10 * (t_foot - thinking_time) / d_foot
print("思考时间(毫秒): " + str(thinking_time))
print("传输速度(米/秒): " + str(transmission_speed))
run_full_test 函数依次运行手和脚的测试。(稍后我们会定义这两个测试的代码。)代码的最后四行是计算思考时间和传输速度,这些内容将在《工作原理:测量你的反应时间》一章的 第 191 页 进行解释。
此函数还通过 input 函数提示你输入脖到手和脖到脚的距离。程序能够使用这些信息,因为它将输入存储在变量中。我们将脖到手的距离存储在 d_hand ➊ 中,将脖到脚的距离存储在 d_foot ➋ 中。
input 函数显示你作为参数提供的文本字符串,然后等待你输入一些文本。它返回你输入的内容作为字符串,而 int 函数将该字符串转换为整数,以便我们在计算中使用。
以下是run_test函数的代码:
def run_test():
print("在交叉图形显示时按住开关,并
释放时稍微放开,当显示屏变空时")
print("重复 " + str(n) + " 次。")
input("准备好开始测试时按回车")
total = 0
for i in range(0, n):
t = get_reaction_time()
if t > 10:
print(t)
total += t
else:
print("你松开得太早")
return total / n
run_test函数运行单次测试,提供必要的指示,并通过调用get_reaction_time来收集所需数量的反应时间读数。如果反应时间小于 10 毫秒,这意味着超人般的反射速度,程序会告诉你松开得太早。否则,它会显示你的反应时间。
def get_reaction_time():
display.show(Image.NO)
sleep(random.randint(3000, 7000))
display.clear()
t0 = running_time()
while pin5.read_digital() == False: # 按钮 A 按下
pass
t1 = running_time()
t = t1 - t0
return t
run_full_test()
get_reaction_time函数显示交叉图像,然后在 3 到 7 秒之间随机休眠一段时间。然后它清除屏幕并将变量t0设置为当前的运行时间,这样程序就知道何时开始计时反应测试。
当你松开按钮 A 时,程序退出while循环,并在t1中记录停止的时间。我们通过从t1中减去t0来计算反应时间。
你可能会想,为什么代码使用pin5.read_digital来检查按钮 A 是否被按下,而不是使用button_a.is_pressed。答案是,is_pressed函数的操作速度不如read_digital快,因此会为反应时间测量增加一些不必要的额外时间。我们使用pin5是因为 micro:bit 的电路将引脚 5 直接连接到按钮 A。事实上,micro:bit 有许多其他引脚,而不仅仅是我们与鳄鱼夹一起使用的引脚 0 到 3。然而,在本书中,我们专注于那些易于访问的引脚。
尝试的事项
为了进一步研究人类神经系统,可以尝试比较不同人的结果或在不同时间进行测试。
原理:测量你的反应时间
当你看到交叉图形消失时,你的身体会发生两件事,每件事都需要一定的时间:
-
你的眼睛和大脑注意到变化并决定采取行动。
-
一个信号从你的大脑通过神经传递到控制手或脚的肌肉,然后手或脚离开开关。
对于这个实验,我们假设思考时间,即你注册变化的时间,无论是移动你的手还是脚,都是相同的。
我们还假设大脑与手部和大脑与脚部之间的神经信号传输速度是相同的。实际上,这两个假设都不完全准确,但疯狂科学家可以稍后解决这些问题。
基于这些假设,信号在神经系统中传播的速度等于总反应时间减去思维时间,再除以信号必须传播的距离。
通过测量这两个距离,我们可以粗略地计算出思维时间和信号速度。以下是我们将在计算中使用的变量:
t_hand 手部的总反应时间(思考 + 动作)
t_foot 脚部的总反应时间
d_hand 信号需要沿神经从大脑到手部传播的距离
d_foot 大脑到脚的距离
thinking_time 注册事件并开始向手或脚发送信息所需的时间
transmission_speed 信号从大脑到手或脚的传播速度
现在进入数学部分。对于手部,我们可以使用以下方程:

同样地,对于脚部,我们可以使用以下公式:

这意味着我们还知道以下内容:

现在我们可以使用代数重新排列公式,以便计算思维时间和传输速度。我们可以将两边都乘以以下内容:
(t_hand – thinking_time)
然后得到这个结果:

如果我们将两边都乘以以下内容:
(t_foot – thinking_time)
我们得到了这个结果:
d_hand (t_foot – thinking_time) = d_foot (t_hand – thinking_time)
将括号内的内容相乘,得到以下结果:
d_hand × t_foot – d_hand × thinking_time
= d_foot × t_hand – d_foot × thinking_time
所以:
d_hand × t_foot – d_foot × t_hand
= d_hand × thinking_time – d_foot × thinking_time
d_hand × t_foot – d_foot × t_hand
= thinking_time (d_hand – d_foot)
最后,我们可以通过以下公式计算思维时间:

现在我们得到了思维时间,我们可以用它来计算信息沿神经传播的速度,像这样:

这个结果的单位是厘米/毫秒。要将其转换为米/秒,我们需要乘以 1000 并除以 100。换句话说,乘以 10,就得到了传输速度。
项目:谎言探测器

难度:中等
疯狂科学家不喜欢惊喜派对,他们想弄清楚他们的实验室助手是否为他们的生日准备了派对。他们需要使用谎言探测器(图 8-3)来查明这一点!

图 8-3:谎言探测器
本项目测量皮肤电阻(GSR),即皮肤对电流流动的电阻。为了测量 GSR,我们将使用 micro:bit 和一对金属勺子。
你需要的东西
对于本项目,你需要以下内容:
Micro:bit
2 × 鳄鱼夹电缆 用于将勺子连接到 micro:bit
2 × 勺子
你将使用勺子与手掌接触。鳄鱼夹将连接到勺子的把手,可能会刮伤勺子,因此不要使用你最好的勺子!
构造
-
访问
github.com/simonmonk/mbms/,进入本书的代码库并点击Lie Detector链接。程序打开后,点击Download,然后将 hex 文件复制到你的 micro:bit 上。如果遇到问题,请返回第一章,复习如何将程序加载到 micro:bit 上。如果你更喜欢使用 Python,那么从同一网站下载代码。有关如何下载并使用书中示例的说明,请参见第 34 页中的“下载代码”部分。此实验的 Python 文件是ch_08_Lie_Detector.py。
-
使用一个鳄鱼夹将其中一个勺子的把手连接到针脚 2,另一个鳄鱼夹将另一个勺子连接到 GND,如图 8-3 所示。
要使用测谎仪,你需要两个人:一个操作员提出棘手问题,另一个是受试者回答问题。受试者需要握住勺子,使弯曲面完全接触到他们的手掌。
当操作员按下按钮 A 时,micro:bit 显示屏上的点应该移到 LED 的中心。如果受试者出汗导致皮肤电阻下降,点会向屏幕上方移动。如果皮肤电阻上升,点会向下移动。
如果点在屏幕的顶部或底部似乎被卡住,操作员需要按下按钮 A 以将显示内容居中。即使没有遇到任何难题,读数也会逐渐漂移。
提问后,操作员应该等待三到四秒钟,然后再查看显示屏上的读数。
代码
本项目包含了 Blocks 和 Python 代码。完整的解释位于 Blocks 代码之后,因此如果你现在跳到 Python 代码,确保稍后回来看解释。
Blocks 代码
以下是本项目的 Blocks 代码。

在on start块中,我们放置set pull pin块,这将启用内置的 12kΩ上拉电阻。(默认情况下,上拉电阻是禁用的。)
同样在on start块中,我们从针脚 2 读取数据,针脚 2 连接到其中一个勺子,并将结果存储在baseline变量中。程序将把任何新的读数与这个基线值进行比较,看看受试者的皮肤电阻发生了多少变化。
然后,我们使用forever循环从针脚 2 获取新的模拟读数,该读数代表受试者在回答你提出的问题后的皮肤电阻反应。该循环将baseline读数从新的reading读数中减去,并将结果除以 10,以便大约减少到合适的程度。
它使用这个数字来确定应该点亮哪一个 LED 灯。这个数字必须在-2 到 2 的范围内,否则会发生错误。完成这一步后(使用几个if语句),显示屏被清空,并且在2 + change这一行的中间列的 LED 灯被点亮,使用的是plot块。
按下 A 按钮会重置baseline。

MicroPython 代码
这里显示的是 MicroPython 版本的代码:
from microbit import *
pin2.set_pull(pin2.PULL_UP)
baseline = pin2.read_analog()
while True:
if button_a.was_pressed():
baseline = pin2.read_analog()
reading = pin2.read_analog()
change = int((reading - baseline) / 10)
if (change > 2):
change = 2
if (change < -2):
change = -2
display.clear()
display.set_pixel(2, 2 + change, 9)
这与 Blocks 代码的工作方式非常相似,只是有一些不同之处。在这里,我们使用int函数将读数变化值转换为整数。
然后我们使用set_pixel方法告诉 micro:bit 显示屏点亮哪个 LED。这种方法不同于plot块,因为它不仅要求提供 x 和 y 坐标,还需要你提供一个 0 到 9 之间的亮度级别。我们选择 9,以使其尽可能明亮和显眼。
工作原理:通过汗水、电压和电阻检测谎言
皮肤电阻是多通道测谎仪常用的测量指标,这种测谎仪在电影中经常出现。
如果你开始出汗或脸红,就像在压力下那样,皮肤对电流的电阻会发生变化。但测试皮肤电阻反应(GSR)并不总是有效。你提问的方式以及提问的问题可能会影响一个人的反应,或者让他们感到紧张,从而导致 GSR 在不同的人之间差异较大。相反,那些与自己情感较为疏离的人可以学会如何躲避测谎仪。但对于疯狂科学家的调查,探讨可能的惊喜派对,这个测谎仪恰到好处。
该项目将 GSR 的读数转换为电压。大多数金属的电阻较低,因为金属导电性好,而塑料等材料的电阻较高,因为电流通常难以通过塑料流动。我们使用 micro:bit 的引脚来测量电阻,它作为一个模拟输入工作(参见第一章),并且通过两个电阻器组成一个叫做电压分压器的电路(见图 8-4)。

图 8-4:电压分压器的原理图
电阻的单位是欧姆(Ω),我们通常将 1000Ω简写为 1kΩ。在图 8-4 中,连接到引脚 2 的 12kΩ电阻是 micro:bit 处理器内置的电阻。这个电阻将引脚 2 的电压拉向 3V(可以将这个电阻看作是弹簧);如果你没有握住勺子,这个拉力将是唯一作用在引脚上的力,导致引脚读取到 1023 的最大值,即 3V。
然而,一旦受试者抓住勺子,另一个电阻——受试者的皮肤——便开始发挥作用。这会抵消 12kΩ电阻,通过将第 2 引脚的电压拉回到 0V。如果你的皮肤电阻正好是 12kΩ,那么两个电阻会平等拉动,第 2 引脚的电压将是 1.5V。
如果受试者出汗,他们的皮肤电阻下降,导致电压降低。相反,当他们恢复时,皮肤电阻增加,使得 12kΩ的电阻拉高电压。
总结
在这一章中,我们对人类神经系统进行了几项实验。我们完成的实验和项目可能科学严谨性不足,但希望你在过程中有所收获。
在下一章,我们将对环境进行测量。具体来说,我们将研究光线和温度,它们对疯狂科学家的舒适度至关重要。

第九章:环境疯狂
疯狂科学家喜欢测量各种事物。在本章中,我们将跟随科学家的脚步来测量温度。我们将设计一个温度和光照记录仪,提供有价值的环境实验数据。接着,我们将创建一个植物浇水项目,利用一个小型泵在植物土壤开始变干时自动浇水。
实验 11:测量温度

难度:简单
疯狂科学家除了实验室外套外并没有其他衣物,并且在秘密实验室的隔热预算上也没怎么花钱,于是决定建造一个定制的加热系统。为了实现这一目标,他们需要知道实验室每个房间的确切温度。不幸的是,他们很快发现,使用 micro:bit 测得的温度并不够精确。
micro:bit 在 Blocks 和 MicroPython 代码中都有一个名为temperature的函数,可以返回以摄氏度为单位的温度读数。然而,传感器本身是内置在 micro:bit 的处理器中的,因此实际上它报告的是 micro:bit 的芯片的温度,而不是 micro:bit 周围环境的温度。
在大约 20 摄氏度(68 华氏度)的正常室温下,如果 micro:bit 没有运行太长时间,传感器会提供相当准确的读数。然而,如果 micro:bit 的处理器已经忙碌并开始升温,我们无法确保温度读数是否准确。
在这个实验中,你将研究忙碌的 micro:bit 与空闲的 micro:bit 之间温度读数的差异。
你需要的材料
要进行这个实验,你只需要两样东西:
Micro:bit
USB 数据线
你可能还需要一个单独的温度计来核对你的读数。你需要的唯一其他物品是一些耐心,因为你需要让程序运行半个小时才能得到准确的读数。
构建
-
这个项目使用了 Mu 的绘图工具,需要 Python 支持,所以没有使用 Blocks 代码。你可以在
github.com/simonmonk/mbms/找到代码。这个实验的 Python 文件是 Experiment_11.py。将程序上传到你的 micro:bit 上。此代码将每 20 秒读取一次温度。它还会每 10 分钟启动一次 micro:bit 活动,然后停顿 10 分钟,让你观察 micro:bit 忙碌与空闲状态下的温度差异。 -
打开 Mu 的 REPL 和 Plotter 视图,并按下 micro:bit 上的重置按钮以开始读取过程。每 20 秒,Plotter 和 REPL 中都会记录新的温度读数以及 micro:bit 是否处于忙碌或空闲状态。micro:bit 的忙碌/空闲状态每 10 分钟切换一次。图 9-1 显示了记录 40 分钟数据的结果。

图 9-1:绘制温度读数和处理器活动
蓝线显示由temperature函数报告的温度,绿线表示 micro:bit 是否处于忙碌或空闲状态。当处于忙碌状态时,micro:bit 开启显示屏和无线电接口,并反复显示消息Busy。
如图 9-1 所示,当 micro:bit 处于忙碌模式时,报告的温度上升了约 3 摄氏度。当它回到空闲模式时,温度下降。需要注意的是,房间中的温度(通过单独的温度计测量)在整个实验过程中保持在 20.0 摄氏度。
代码
该实验的 MicroPython 代码需要完成两件事情:每 10 分钟翻转一次 micro:bit 的忙碌状态(保存在变量busy中),并且每 20 秒报告一次温度。
设置变量
我们的代码使用last_busy_flip和last_log_time变量来记录这两件事(翻转和记录)最后一次发生的时间:
busy = False
last_busy_flip = 0
busy_period = 600000
last_log_time = 0
log_period = 20000
变量busy_period指定了每次在忙碌和空闲状态之间翻转的时间(以毫秒为单位);600,000 毫秒等于 600 秒,也就是 10 分钟。变量log_period保存温度报告之间的时间(以毫秒为单位);20,000 毫秒等于 20 秒。代码busy = False表示 micro:bit 一开始是处于空闲状态。
使其处于忙碌状态
如果 micro:bit 处于忙碌模式,显示屏和无线电都会开启,并显示Busy消息。否则,显示屏和无线电会关闭。
while True:
if busy:
➊ display.on()
➋ radio.on()
display.show("Busy")
else:
display.off()
radio.off()
now = running_time()
if now > last_busy_flip + busy_period:
busy = not busy
last_busy_flip = now
now = running_time()
if now > last_log_time + log_period:
print((temperature(), busy * 10))
last_log_time = now
在while循环中,我们规定如果busy变量为True,micro:bit 应该开启显示屏➊和无线电➋。否则,它们应该关闭。
然后,我们有两个测试用来检查是否该翻转忙碌状态或记录数据到 REPL 和 Plotter:代码检查当前运行时间与busy_period和log_period变量中的值。
为了方便在与温度数据相同的图表上看到处理器是否处于忙碌状态(见图 9-1),我们将busy的布尔值True或False乘以 10。Python 允许我们这样做!而不是报告错误,Python 将False解释为 0,将True解释为 1。由于 Python 将布尔值视为数字,它允许我们进行乘法运算。于是,图表上的值就不是 0 或 1,而是 0 或 10。
工作原理:为什么处理器会发热?
像 micro:bit 使用的处理器芯片,包含数十万甚至数百万个 晶体管。这些晶体管是电子开关,可以处于开或关的状态(用二进制的 1 和 0 表示)。晶体管在特定状态下使用极少的电流(无论是开还是关),但是需要少量额外的能量来改变状态。这就是为什么在进行处理器密集型操作时,电脑风扇会加速运转——它们正在移除由于大量开关操作而产生的多余热量。
一个忙碌的处理器会更热。但其他因素也会影响处理器的温度。在这个实验中,显示器使用的 LED 会产生一些热量,打开和关闭无线电时也会产生热量。因此,尽管我们定义的 忙碌 有点误导,因为它包括了打开和关闭无线电以及显示器,但微型计算机的温度读数仍然受到 micro:bit 当前操作的影响。
项目:温度与光照记录仪

难度:中等
作为一个彻底的完美主义者和不可救药的植物学家,疯狂科学家希望找到一种方法来测量实验室中所有植物的理想位置。因此,温度与光照记录仪应运而生。
在实验 7 中,我们将加速度读数写入文件以供后续分析。在那种情况下,我们希望立即进行读取。而在这里,我们希望在一段时间内记录数值,例如一天的时间。

图 9-2 显示了完整的项目。正如你所看到的,我们已将其制作成透明的食品容器,以保护它免受外界环境的影响,以防我们想要在户外使用它。

图 9-2:温度与光照记录仪
你可以使用这个记录仪对你的院子进行调查,并确定不同植物的最佳生长位置。
你需要的材料
在这个项目中,你将需要以下物品:
Micro:bit
Monk Makes 传感器适用于 micro:bit 其他温度与光照传感器也可以使用。
4 × 鳄鱼夹连接线
AAA 电池包
透明塑料食品容器 如果你打算在户外使用该项目,这是必需的。容器应足够大,以容纳项目设备,包括电池包。
构建
-
该项目使用了 micro:bit 的本地文件系统,而该文件系统在 Blocks 代码中尚不可用。因此,这个项目只能使用 Python 完成。代码可以在
github.com/simonmonk/mbms/中找到。这个实验的 Python 文件是 ch_09_Logger.py。将程序刷入你的 micro:bit 中。 -
如图 9-3 所示,将 micro:bit 连接到传感器板。
![图片]()
图 9-3:将 micro:bit 连接到 Monk Makes 传感器
-
将所有物品放入食品容器中,确保传感器和 micro:bit 在顶部,靠近盖子。从电路板背面连接鳄鱼夹将有所帮助。
-
打开电池包。当你准备开始记录时,按下按钮A,然后盖上容器的盖子。显示屏将切换为显示一个点。
-
日志器可以保存大约 2,000 条读取数据,因此以每秒一个样本的速率,它可以运行 33 小时,直到内存耗尽。这大约是 AAA 电池组的使用时长。
当你准备停止读取时,再次按下按钮A。然后,你可以将 micro:bit 连接到计算机,并使用 Mu 的 Files 功能将文件 data.txt 传输到计算机,就像你在第五章的实验 7 中做的那样。
-
为了理解数据,你可能想将其导入到电子表格中,并绘制类似于图 9-4 中的图表。请参考第五章中的实验 7,了解如何将 data.txt 文件中的数据导入到 Google Sheets 中。

图 9-4:温度与光线图表
在图 9-4 中,光线图中的线急剧下降表示夜幕降临。
代码
对于这个项目,我们需要导入 os 库,它将用于删除可能已经存在于 micro:bit 上的任何数据文件。我们这么做是为了为新的读取数据腾出空间。我们还需要导入 log 来自数学库,用于编写计算温度的代码。Log(或 对数)是一个数学概念,在 Steinhart-Hart 方程中用来将热敏电阻的电阻值转换为温度。如果你对数学感兴趣,可以在这里阅读更多关于对数的内容:www.mathsisfun.com/algebra/logarithms.html。
设置变量
这个项目的代码会等待按钮 A 被按下,然后依次记录温度和光照数据。两个数据都将写入文件中,以便在日志记录完成后,可以将它们传输到计算机。
sample_period = 60000
filename = 'data.txt'
temp_pin = pin1
light_pin = pin2
last_sample_time = 0
recording = False
display.show(Image.NO)
我们将变量 sample_period 设置为 60000 毫秒,或 1 分钟。这个周期告诉 micro:bit 每分钟记录一次数据。默认情况下,记录的数据将保存在名为 data.txt 的文件中。你可以通过更改 filename 变量的值来更改文件名。
我们告诉 micro:bit 哪两个引脚连接到传感器板的温度和光线输出,分别存储在 temp_pin 和 light_pin 变量中。在 last_sample_time 变量中,我们记录了上次读取环境数据的时间。
我们使用变量recording来跟踪项目是否正在录制。每次按下按钮 A 时,该变量在True和False之间切换。
读取温度
我们创建了read_c函数来读取温度。这涉及到相当复杂的数学运算。
def read_c():
r0 = 100000.0
r2 = 100000.0
b = 4250.0
v33 = 3.3 # 实际结果与此值无关
V = temp_pin.read_analog() * v33 / 1023.0
R = r2 * (v33 - V) / V
t0 = 273.15 # 0 摄氏度的开尔文温度
t25 = t0 + 25.0 # 25 摄氏度的开尔文温度
斯坦哈特-哈特方程(可以 Google 查找)
inv_T = 1/t25 + 1/b * log(R/r0)
T = (1/inv_T - t0)
返回 round(T, 1)
我们不会详细讲解这些数学公式,但它们在这里,方便你查阅。
该函数测量temp_pin(引脚 1)上的电压,并使用该电压计算摄氏度的温度。有关如何工作的更多信息,请参阅第 211 页中的“如何工作:传感器”部分。
如果你想要华氏温度,可以使用read_f函数,它会调用read_c并将温度转换为华氏度:
def read_f(self):
return read_c() * 9/5 + 32
读取光照水平
温度读数以摄氏度或华氏度为单位。然而,光照水平没有以特定的单位表示。光照读数只是来自引脚 2 的直接模拟读数。实际上,我们定义了自己的单位。如果你愿意,你可以给它们起个名字,也许叫光度?
使用标准的勒克斯单位(lux)来测量光强对于这种传感器来说很困难。但如果你有一个经过校准的勒克斯计,你可以进行实验,比较在不同照明强度下的勒克斯和光度。
while 循环
主while循环(如果你在 Mu 中跟着代码走的话,在代码的最后)检查按钮 A 是否被按下,每次按钮按下时,recording会在True和False之间切换。当录制开始时,会显示一个点,并且我们用os.remove删除现有的数据文件。remove命令被包含在try: except:的 Python 结构中。这确保如果发生错误(可能是因为数据文件不存在而无法删除),错误会被忽略,不会使程序崩溃。删除旧文件后,新的文件会以w模式打开以进行写入。
当按钮 A 被再次按下时,NO 图像会显示,并且文件关闭。
在主while循环中,还有一个if块,只要recording为True并且自上次采样时间以来已经经过足够的时间,它就会将来自光照和温度传感器的读数写入文件。
while True:
如果按钮 A 被按下:
recording = not recording
如果录制中:
display.show(".")
try:
os.remove(filename)
except:
pass
fs = open(filename, 'w')
否则:
display.show(Image.NO)
fs.close()
now = running_time()
如果当前时间 > 上次采样时间 + 采样周期:
last_sample_time = now
如果录制中:
temp = read_c()
light = light_pin.read_analog()
fs.write(str(temp) + "," + str(light))
fs.write('\n')
原理:传感器
热敏电阻是一种特殊类型的电阻(见第八章中的测谎仪项目),其电阻会随着温度的变化而变化。在 micro:bit 的 Monk Makes 传感器中使用的热敏电阻是NTC(负温度系数)类型。负部分意味着当温度升高时,电阻会减小。我们使用电阻来测量温度。
我们的热敏电阻传感器通过电阻来测量温度。然而,micro:bit 无法直接测量电阻。相反,电阻必须首先转换为电压,然后可以通过作为模拟输入的 micro:bit 引脚读取。为了做到这一点,我们需要使用电压分压器,正如在第八章的测谎仪项目中所做的那样。不过这次提供可变电阻的将是热敏电阻,而不是人的皮肤(见图 9-5)。请注意,Monk Makes 传感器板上内置了 100kΩ的电阻。

图 9-5:使用热敏电阻测量温度的电路图
热敏电阻的电阻值不会在每次电阻变化几个欧姆时就发生变化,表示温度变化了一度。正如你在之前的代码中看到的,计算热敏电阻电阻的公式很复杂,涉及到对数运算。
当你购买热敏电阻时,它会指定两个参数:
热敏电阻在 25 摄氏度时的电阻值(在我们的代码中称为r0,对于传感器板而言,其值为 100kΩ)
一个常数叫做beta,或者有时只是B,它对于不同的热敏电阻是不同的(在我们的代码中,它叫做b。对于传感器板上的热敏电阻,b是 4250。beta的值通常会在热敏电阻的数据表中注明。)
你可以在代码中看到如何进行计算。如果你想了解更多关于这个公式的信息,可以在网上搜索“Steinhart-Hart 方程”。
由于引脚 1 的电压取决于热敏电阻与固定电阻的电阻比,因此它与供电电压无关。这样也好,因为 micro:bit 的 3V 连接口电压可以从 3.3V 到大约 2V 不等,取决于你如何为 micro:bit 供电以及电池的电量。这就是为什么在read_c函数中你会看到注释解释v33(3.3V)对结果没有影响。实际上,它在数学计算中会被抵消掉。它的存在只是为了让数学计算稍微容易理解一点。
项目:自动植物浇水器

难度:难
因为忙于参加会议,常常不能待在秘密实验室,疯狂科学家发明了这款自动植物浇水器。该项目通过监测土壤的电阻来判断土壤的湿润程度。如果土壤过干,它会启动水泵。按下按钮 A 可以读取土壤的干湿程度,按下按钮 B 则会进行测试,运行水泵 10 秒钟。

图 9-6:自动植物浇水器项目
你需要的物品
对于这个项目,你将需要以下物品。更多关于这些物品的获取信息,请参见附录。
Micro:bit
micro:bit 继电器板 用于开关水泵(你也可以使用像我们在第六章的漫游车项目中使用的 Kitroniks 板那样的电机控制器。)
12V 水族箱计量泵 这些泵虽然较慢,但非常可靠。
管道和连接件 用于将水从水库传输到植物盆
大塑料瓶 用作植物的水库
12V 水泵电源 12V,1 安培或更高
micro:bit 的 USB 电源或 Monk Makes Power for micro:bit 及交流适配器 这是一个长期项目,所以你不希望仅通过电池供电。关于长期 micro:bit 电源选项,请参见附录。
1kΩ电阻
母型直流桶插座到螺丝端子适配器 用于将继电器和电池连接到水泵的电源
7 × 鳄鱼夹电缆 用于将钉子连接到 micro:bit
回折式文件夹夹子 用来固定浇水管
2 × 5 英寸钉子 用作植物盆中的电极(注意,6 英寸钉子也完全适用。镀锌(锌涂层)钉子最佳,因为它们不会生锈。)
盆栽植物

你需要的水泵是蠕动泵,有时也叫定量泵。你可以在 eBay 上花几美元买到一个。这些泵通常配有短的进出口管,你需要延长这些管道,使其可以从水库连接到花盆。管道的直径通常是 4 毫米,这是园艺灌溉系统中常见的尺寸。你可以在 eBay、五金店、热带鱼店或园艺中心找到这种管道和连接件。
你需要更长的鳄鱼夹电缆来将 micro:bit 连接到钉子上。一个合适的长度大约为 1 英尺(30 厘米)。
水库可以是任何能容纳足够水量的物品(旧的牛奶容器就可以)。
构建
在构建这个项目时,你需要特别小心,因为它既包含电子组件,又包含机械组件。而且,它还会泵送水,因此如果你没有正确连接管道,可能会在你的秘密实验室里造成一场大混乱!
图 9-7 展示了电子设备的连接方式,帮助你了解在按步骤进行操作时要达到的效果。

图 9-7:自动植物浇水项目的接线图
-
打开
github.com/simonmonk/mbms/,点击Plant Waterer的链接。点击下载,然后将 hex 文件复制到你的 micro:bit 上。如果你卡住了,可以回到第一章,那里详细解释了将程序传输到 micro:bit 的过程。Python 版本的代码在ch_09_Plant_Waterer.py中。 -
将 1kΩ电阻的引脚绕在 micro:bit 的 1 号和 2 号引脚上。
-
参照图 9-7,将鳄鱼夹接到 micro:bit、继电器板、桶形插座和水泵上。暂时不要将黄色和绿色电缆连接到钉子上,也不要连接水管到水泵。为了将鳄鱼夹连接到 DC 桶形插座适配器的螺丝端子上,可以用螺丝刀将螺丝端子完全打开。如果你的鳄鱼夹钳口太大,无法放入螺丝端子孔,你可以将直的回形针插入螺丝端子中,然后将鳄鱼夹夹在回形针上。
-
将 12V 电源适配器插入桶形插座适配器,然后按下你的 micro:bit 上的B按钮。你应该能听到水泵运转 10 秒钟后停止。如果没有,请仔细检查接线。
-
将钉子插入植物盆土中,间隔约 3 或 4 英寸(8 到 10 厘米)。留出足够的钉子长度在土壤上方,以便你可以连接绿色和黄色的鳄鱼夹,如图 9-8 所示。
![Image]()
图 9-8:钉子在土壤中的位置
-
现在,按下你的 micro:bit 上的A按钮,屏幕上应显示一个滚动的数字。这是土壤干燥程度的衡量标准。土壤越干,数字越高。尝试给盆栽加点水,等几秒钟后,再按下A按钮。你应该看到数字减少。但不要让土壤变得太湿,因为那样土壤需要很长时间才能再次干燥,并且你将无法看到自动浇水器的工作效果。
现在,你需要给植物提供适量的水。你可能需要请教一个有绿色拇指的人,他们了解你的特定植物。找出你的植物土壤应该保持的湿度后,继续少量添加水,直到土壤湿润为止。然后按下A按钮,记下数字。这就是你为自动植物浇水器设置的目标干燥度。
-
现在我们准备开始该项目的湿润部分。首先,从水泵上量取适当长度的管道。你需要足够的管道,能够将一根管道从储水瓶顶部放入并伸到底部,另一根管道从水泵伸到植物花盆。在连接管道之前,你需要弄清楚水泵的哪个喷嘴是 进水口,哪个是 出水口。为了做到这一点,按下按钮 B,并用手指覆盖每根水泵管道。你会感觉到进水口正在吸你的指尖。记下每根管道的功能。
使用管道连接器将这些管道段连接到水泵的短管上。
-
将文件夹夹夹住花盆的侧面,并将管道穿过夹子的手柄,如 图 9-9 所示。
![Image]()
图 9-9:将管子固定到植物的花盆上
-
填满储水瓶,并将延长的进水管推入瓶中,直到底部。
-
通过按下按钮 B 几次来测试水泵。如果水能顺利到达花盆且没有滴水或泄漏,水泵就几乎准备好了。如果没有,检查并调整连接点以密封泄漏。
-
在你让植物浇水器进行繁琐工作的最后一步之前,调整
dry_threshold的值。将dry_threshold设置为你在第 6 步记录的值,然后再次将程序闪存到你的 micro:bit 上。
代码
这个项目的代码相当复杂。除了监控土壤的湿度外,它还需要处理按钮按下事件,并确保水泵不会过度运转而导致实验室被淹。
块代码
这是该项目的块代码。

在 on start 块中,我们定义了三个变量:
dry_threshold 我们将第 6 步中的值放在这里。如果植物变得比这个值还干,它将会被浇水。
on_time_ms 这是水泵在浇水时运行的时间(单位为毫秒)。保持这个值较小(例如 10 秒),可以避免植物被过度浇水。这还可以防止可能导致小规模洪水的意外发生!
check_period_ms 水需要一些时间才能在花盆中扩散并均匀湿润土壤。这个变量设置了每次干燥检查之间的延迟。默认值为 3,600,000(即 1 小时的毫秒数)。
如果我们设置 on_time_ms 为 10,那么植物一天内能接收到的最大浇水时间是 24 × 10 秒,即 4 分钟。使用这种水泵,植物大约能获得一品脱(500 毫升)水量。这已经相当多了,但如果你的花盆特别大,你可能需要减少 check_period_ms 或增加 on_time_ms,以便让植物获得更多的水分。我们将在 第 222 页的“尝试的事情”部分进一步讨论这一点。
除了这三个变量外,我们还有两个函数,check_dryness 和 water_the_plant。check_dryness 函数会从 pin 2 读取新的土壤湿度值并更新 干燥度 变量。注意,这个函数还会在读取期间打开 pin 1。我们将在“工作原理:测量土壤湿度”中解释为什么要这样做,详见 第 222 页。
water_the_plant 函数会打开 pin 0 来激活继电器,打开泵并根据 on_time_ms 中指定的时间持续工作,并在 micro:bit 上显示向下箭头,表示正在浇水(有点像下雨)。
使用 forever 循环,首先检查自上次检查以来是否已经经过足够的时间(默认是 1 小时)。如果时间足够,循环会调用 check_dryness 并将其读数与 干阈值 进行比较。如果土壤过于干燥,则调用 water_the_plant。
检查完成后,dont_water_until 变量被设置为当前时间加上 check_period_ms,以安排下一次检查。然后,dryness 通过 plot bar graph of 块在显示器上显示。显示器上的 LED 层级越高,表示土壤越干燥,意味着需要更多的水。
接下来是检查按钮 A 是否被按下并做出相应反应的代码。此代码会调用 check_dryness,然后显示其值,再次显示条形图。按钮 B 的处理程序会调用 water_the_plant,然后显示 干燥度 水平。
MicroPython 代码
下面是代码的 MicroPython 版本:
from microbit import *
干燥度 = 0
干阈值 = 500
on_time_ms = 10000
check_period_ms = 3600000
dont_check_until = 0
def water_the_plant():
pin0.write_digital(1)
display.show(Image.ARROW_S)
sleep(on_time_ms)
pin0.write_digital(0)
def check_dryness():
global 干燥度
pin1.write_digital(1)
干燥度 = pin2.read_analog()
pin1.write_digital(1)
def bargraph(a):
display.clear()
for y in range(0, 5):
如果 a > y:
for x in range(0, 5):
display.set_pixel(x, 4-y, 9)
while True:
如果 button_a.被按下():
check_dryness()
display.scroll(str(干燥度))
bargraph(干燥度 / 200)
如果 button_b.被按下():
water_the_plant()
check_dryness()
bargraph(干燥度 / 200)
如果 running_time() > dont_check_until:
check_dryness()
如果干燥度 > 干阈值:
water_the_plant()
dont_check_until = running_time() + check_period_ms
bargraph(干燥度 / 200)
由于 MicroPython 没有类似于 plot bar graph of 块的功能,我们使用 第二章中 Shout-o-meter 的 bargraph 函数来显示 干燥度 水平。
尝试的事情
因为植物浇水器能够保持植物的湿度相对恒定,所以你可以通过查看水箱中剩余的水量来测量植物消耗的水量。
在你给水箱加水时,使用量杯并记录需要多少水才能填满它。一旦你知道你的植物每天通常需要多少水,就可以计算出水箱在需要补充之前能维持多长时间。这在你度假时保持植物存活将非常重要。
工作原理:测量土壤湿度
含杂质的水(如土壤中的水)具有比空气低得多的电阻。换句话说,土壤越干,其电阻越高,土壤中的水分越多,电阻越低。通过测量两个钉子之间的电阻,我们可以测量土壤的干燥程度。
如果你回顾一下图 9-7,你会看到引脚 1 和引脚 2 之间有一个电阻器。为了更容易地理解电路图,图 9-10 展示了另一种电路图的可视化方式。

图 9-10:测量土壤电阻的电路图
注意,图 9-10 中的电路图几乎与图 8-4 中的电路图相同,后者出现在第 198 页,我们当时在测量皮肤电阻(而不是土壤电阻)时使用了该电路图,进行的是测谎仪项目。唯一的区别是,固定的 1kΩ电阻器的顶部不是永久连接到 3V,而是连接到引脚 1。当我们测量土壤湿度时,我们首先将引脚 1 设置为高电平(3V)进行测量,然后将引脚设置回 0V。
使用引脚 1 而不是 3V 连接的原因是我们希望允许电流仅间歇性地流经土壤。如果电阻器连接到 3V,电流将始终流经土壤,导致读数不准确,并加速钉子的腐蚀。这个过程被称为电解作用。通过仅在测量时短暂开启引脚 1,我们避免了这个问题。
总结
在本章中,我们探讨了如何测量温度,创建了一个温度和光照强度数据记录器,并制作了一个自动植物浇水器。在下一章中,我们将看到疯狂科学家如何使用 micro:bit 的内置无线电库。

第十章:无线电活动
疯狂科学家交到了一个朋友。在一次疯狂科学大会上聊得很投机后,他们决定通过 micro:bit 继续交流,当然了,得用 micro:bit 来传递消息。micro:bit 内建了一个无线电发射器和接收器,统称为 收发器,可以与蓝牙设备通信。我们在 第六章的流动机器人项目中见过它的应用。
这个无线电收发器还可以用来与其他 micro:bit 通过特定的简单消息发送和接收协议进行通信。在本章中,我们将探讨 micro:bit 之间的通信,因此你需要有两块 micro:bit 或者一个拥有 micro:bit 的朋友。

实验 12:寻找无线电范围

难度:简单
疯狂科学家和他的朋友想知道,他们之间可以相隔多远,直到 micro:bit 通信器停止工作。
所需材料
你将需要一对 micro:bit,每个都配有电池包。你还需要一个朋友来交流,以及一个开放的场地或其他你们可以互相走开的地方。
构建
-
访问
github.com/simonmonk/mbms/并点击 实验 12:无线电范围 的链接。将 hex 文件复制到两块 micro:bit 上。如果你遇到困难,第一章会详细解释如何将程序上传到 micro:bit。如果你想运行此实验的 MicroPython 版本,那个文件是 Experiment_12.py。 -
给两块 micro:bit 都装上电池——你现在应该已经习惯了。
在你们外出之前,按下其中一个设备上的 A 按钮,检查两块 micro:bit 是否都已准备好。一个上箭头应该出现在那个 micro:bit 上,另一个 micro:bit 上应该出现一个勾号。通过按下另一个 micro:bit 上的 A 按钮重复此测试(图 10-1)。
![Image]()
图 10-1:测试 micro:bit
-
找一个你和你的朋友有足够空间互相移动的地方。相距大约一米(或一码)站立,面对面。你应该持有一块 micro:bit,而你的朋友持有另一块。
-
现在你或你的朋友按下 A 按钮在 micro:bit 上发送信号。然后挥手示意对方信号已发送(以防他们没有收到)。当他们的设备接收到信号时,他们应该挥手回应。假设信号已成功发送,彼此相隔几步并重复测试。
-
到某个时刻,消息将无法接收!发送方应再次按下按钮并挥手。如果消息仍然没有收到,你们都知道应该更近一步。
-
一旦你确定了无线电的范围,发送方通过预先安排的信号告知接收方向他们走去,并计算他们走了多少步。
-
测量接收者每步的步长,并将其乘以他们走的步数。得出的值就是 micro:bit 无线电的视距范围。提示:为了获得较为准确的步长,可以让人走五步,使用一条长的卷尺测量总的行走距离,并将这个距离除以 5。
疯狂科学家测试了两台 micro:bit 的范围,发现其范围为 192 步。五步覆盖了 12 英尺(3.65 米),这意味着每步是 2.4 英尺。因此,范围为 192 × 2.4,约为 460 英尺(140 米)。
有人做过这个实验并报告了超过 1,100 英尺(350 米)的范围。请注意,如果你的身体或你朋友的身体位于两个 micro:bit 之间,范围将大大减少。
代码
无论你是使用积木还是 MicroPython,范围测试的代码都相对简单。
积木代码
这是该项目的积木代码。

你可以控制无线电使用的功率。on start积木使用radio set transmit power积木将功率设置为 7(最大值)——更高的功率意味着更大的范围。set radio group积木为无线电设置一个组。在这种情况下,我们使用组 1,这意味着所有设置为无线电组 1 的 micro:bit 都会接收传输。因此,如果你计划同时用多对 micro:bit 进行这个实验,那么每一对实验者应选择一个 0 到 255 之间的不同数字,并将无线电组设置为该数字。这样,不同的实验对就不会互相干扰。
我们使用on button A pressed积木与radio send积木来传输一个简单的test消息。这将闪烁North箭头图标,表示消息已经发送。
我们通过on received block处理传入的消息,并指定一个变量名来存放任何传入的消息。在这个例子中,每当 micro:bit 的无线电接收到消息时,它会将消息放入变量receivedString中。如果这个消息是test,那么屏幕上会短暂显示一个勾选图标。
MicroPython 代码
这是 MicroPython 版本的代码。请注意,MicroPython 中消息的发送方式与积木代码中的方式略有不同,因此用于此实验的两台 micro:bit 应该都使用积木或 MicroPython 编程。
from microbit import *
import radio
radio.on()
radio.config(power=7, group=1)
while True:
if button_a.was_pressed():
radio.send("test")
display.show(Image.ARROW_N)
sleep(1000)
display.clear()
message = radio.receive()
if message == 'test':
display.show(Image.YES)
sleep(1000)
display.clear()
要在 MicroPython 中设置无线电的功率和无线电组,我们需要使用 radio.config 方法。这个方法还允许你控制其他一些选项。你可以在 bbcmicrobitmicropython.readthedocs.io/en/latest/radio.html 上阅读相关信息。
代码的 Blocks 版本完全包含在处理程序中。在 MicroPython 中,我们没有处理程序,因此我们必须不断检查按钮是否按下或是否有消息到达。我们通过在一个始终运行的 while True 循环中使用一组 if 语句来实现这一点。
首先,我们检查自上次检查以来按钮 A 是否被按下。如果按下了,我们发送 test 消息并显示北箭头。
为了检查我们是否接收到消息,我们不断调用 message.receive。当无线电接收到消息时,它会将消息放入队列。如果没有消息在等待,那么 message.receive 会返回 None。但是,如果有一个或多个消息,message.receive 会返回最旧的消息并将其从队列中移除。
我们只关心消息是否为test,所以我们检查这个条件。如果消息是test,我们让 micro:bit 显示“YES”图标一秒钟。
工作原理:无线电信号
在户外,micro:bit 的无线电范围可能远大于室内,因为墙壁会阻碍信号的传播。
设备之间发送消息的系统被称为 数据包无线电,因为发送的是小的数据包。在这个项目的代码中,这些数据包是文本命令。
项目:无线门铃

难度:中等
被实验分散注意力,并且下属不听话的疯科学家经常错过快递的到达。为了解决这个问题,他们决定在实验室里建立一个扬声器,在门铃响起时播放声音。
我们将在第二章中构建的门铃项目基础上进行扩展。在这个版本的项目中,我们将使用两个 micro:bit:一个连接到扬声器,负责播放曲调,另一个作为门铃按钮(见图 10-2)。当第二个 micro:bit 上的一个按钮被按下时,它会向发声的 micro:bit 发送无线消息,告诉它播放曲调。由于 micro:bit 的无线电信号范围相当好,播放声音的 micro:bit 可以离门有一段距离,因此可以放得更靠近你。

图 10-2:无线门铃项目
所需材料
对于这个项目,你需要以下材料:
2 × Micro:bit 一个作为门铃按钮,另一个播放曲调
3 × 蝰蛇夹电缆 用于将 micro:bit 连接到扬声器
2 × USB 电源适配器或带电源开关的 3V 电池组 用于为 micro:bit 提供电力
扬声器 为了播放门铃曲调,我推荐使用 Monk Makes Speaker for micro:bit。
Blu-Tak 粘土或自粘垫片 用来将其中一个 micro:bit 安装到门框上
构建
-
访问
github.com/simonmonk/mbms/并点击 无线门铃 的链接。将 hex 文件复制到两个 micro:bit 上。如果你需要复习如何将程序上传到 micro:bit,第一章 解释了整个过程。如果你想运行该实验的 MicroPython 版本,文件是 ch_10_Wireless_Doorbell.py。 -
将扬声器连接到其中一个 micro:bit。你可以使用在 第二章 中音乐门铃项目中使用的扬声器(如果遇到困难,可以查看该项目的说明)。
-
通过按下门铃 micro:bit 上的 A 按钮来测试扬声器。连接扬声器的 micro:bit 应立即开始播放曲调 “The Entertainer”。当它播放完毕后,尝试按下 B 按钮,应该会播放 “Funeral March”。
-
使用 Blu-Tak 粘土或垫片将没有扬声器的 micro:bit 安装到门外。
代码
两个版本的代码都依赖于通过无线电发送 db1 或 db2 消息,具体取决于按下哪个按钮。接收的 micro:bit 根据接收到的消息播放其中一首曲调。
与实验 12 类似,你不能混用 MicroPython 和 Blocks 版本的代码,因此请选择使用其中一个版本。
Blocks 代码
这是该项目的 Blocks 代码。

你会注意到这里的代码与实验 12 中的代码类似。如果按下 A 按钮,则发送字符串 db1(门铃 1),并显示一个北箭头,表示消息已经发送。当按下 B 按钮时,处理程序会发送消息 db2。
接收代码检查接收到的消息是 db1 还是 db2,并播放相应的曲调。
MicroPython 代码
这是 MicroPython 版本的代码:
from microbit import *
import radio, music
radio.on()
radio.config(power=7, group=1)
def send_message(message):
radio.send(message)
display.show(Image.ARROW_N)
sleep(1000)
display.clear()
while True:
if button_a.was_pressed():
send_message("db1")
if button_b.was_pressed():
send_message("db2")
message = radio.receive()
if message == 'db1':
music.play(music.ENTERTAINER)
elif message == 'db2':
music.play(music.FUNERAL)
在该版本的代码中,我们定义了函数 send_message,它通过无线电发送消息并显示北箭头一秒钟。
与实验 12 中的代码一样,我们使用 while True 循环持续检查按钮按下情况和接收到的消息。
尝试的事项
尝试更换不同的曲调。或者你也可以尝试修改代码,使得在接收到 db1 或 db2 时,曲调播放多次。这样疯狂科学家更有可能听到它!
工作原理:发送与接收
你可能会想,为什么我们对发送器和接收器使用相同的代码。如果我们按下带有扬声器的 micro:bit 上的 A 按钮,难道它不应该接收自己的消息并播放一首曲子吗?事实证明,当 micro:bit 的无线电在忙于传输时,它无法接收任何信息。此外,使用一个程序可以避免混淆哪个程序应放在哪个 micro:bit 上。
项目:Micro:bit 控制的漫游车

难度:难
没有一个可以提供指令的机器人,任何秘密实验室都不完整。在第六章中,我们制作了一个可以通过蓝牙用手机控制的机器人漫游车。这个项目使用了相同的基本漫游车,但不是通过手机和蓝牙来控制漫游车,而是使用第二个 micro:bit 和 micro:bit 自身的无线通信方式。你将通过倾斜控制的 micro:bit 来操控漫游车,向左、向右、前进或后退。图 10-3 展示了这个项目,你可以在* youtu.be/Qqr0fknoPQ4/* 上看到它的实际演示。

图 10-3:一个 micro:bit 控制的漫游车
所需物品
对于这个项目,你将需要以下物品:
2 × Micro:bit
Kitronik Motor Driver Board for micro:bit (V2) 用于控制前进和后退的电机
低成本机器人底盘套件 包括两个齿轮电机和一个 4 × AA 电池盒
4 × AA 电池
micro:bit 的 AAA 电池包 为作为遥控器的 micro:bit 供电
螺丝刀 适用于底盘上的螺母和螺栓以及电机控制板上的螺丝端子
焊接工具 用于将导线连接到齿轮电机上
Blu-Tack 粘土 用于将电机控制板和 micro:bit 固定到底盘上

构建
使用你在第六章中制作的漫游车,或者如果你还没有制作漫游车,可以回到该项目并按照步骤 1 到 4 进行制作。不过我们将使用不同的软件,因此一旦底盘完成,按照这里的说明操作。不要安装电池,否则你的漫游车可能会不小心自己驶出桌子!
-
首先,我们将为项目中的漫游车部分安装程序。访问
github.com/simonmonk/mbms/并点击Rover的链接。将 hex 文件复制到连接到漫游车底盘的 micro:bit 上。如果需要更详细的说明如何将程序上传到 micro:bit,请回到第一章。 -
现在安装用于作为遥控器的 micro:bit 的程序。访问 Github 页面,点击Rover Controller的链接,点击下载,然后将 hex 文件复制到 micro:bit 上。
-
在让你的机器人在实验室中自由活动之前,最好先测试一下你的项目,不让轮子接触地面。你可能需要交换一些电动机电线,这样探测车就能正确地按照你发送的命令行驶。插入电池后,将探测车翻转过来,这样你就能看到轮子在做什么,而不必担心它会自行移动。
将控制微型计算机(micro:bit)向左倾斜,你应该会看到两个 micro:bit 显示屏上都出现相同的左箭头。与此同时,两个轮子应该朝相同的方向转动。当你从上方观察时,右轮应该转得比左轮快。如果其中一个轮子转向错误,可以交换该电动机的红色和黑色电线。
-
尝试驱动探测车四处行驶。记住,如果车辆卡住,你可以通过将控制器 micro:bit 置于水平位置来停止它。
代码
软件使用两个程序,一个用于控制器,另一个用于探测车 micro:bit。这个项目只能使用 Blocks 代码。
控制器代码
这是遥控器 micro:bit 的代码。

你会注意到在 on start 块中,我们使用了一个 radio set group 块。这个块让 micro:bit 仅监听来自同一组(这里是组 1)中其他 micro:bit 的消息。这可以防止你的 micro:bit 接收到来自同一区域其他科学家(可能也在使用相同的无线电组)发来的杂散消息,从而导致不可预测的行为。如果你想添加其他的 micro:bit 配对,可以将 radio set group 块中的数字更改为不同的值,然后每对 micro:bit 将配对到一个控制器。你可以选择介于 0 和 255 之间的任意数字。
程序的其余部分由 on gesture 块组成,这些块处理探测车可能的运动命令。例如,在 on start 块下方,你有一个 on tilt left 块,当微型计算机倾斜时,它会传输字符串 L 并显示一个 东 向箭头。以下是可以发送的命令的完整列表:
S 停止
L 左转
R 右转
B 后退
F 前进
探测车代码
这是接收这些命令的代码。

与控制器代码类似,我们有一个 on start 块,它将无线电组设置为 1。记住,如果你决定更改无线电组代码,必须在两个 micro:bit 上都进行更改!
其余的代码包含在 on radio received 块中。这个块内部有一系列 if 语句,用来检测接收到的命令字母,并执行该字母表示的动作。例如,如果接收到 L 命令,会显示左箭头,然后将电动机 1 设置为 50% 前进,电动机 2 设置为 100% 前进(全速)。这将使电动机 2(右电动机)比左电动机转得更快,从而使探测车向左弯曲行驶。
尝试的事项
尝试为这对程序添加额外的命令。你现在的手势种类有些不足,但你可以添加一个D(表示dance)命令,指示探测器在控制器 micro:bit 被摇动时执行一小段动作序列。
你还可以添加一个C(表示circle)命令,指示探测器原地旋转,通过让一个电机全速向前,另一个电机全速反向。这个命令可以通过按下 A 或 B 按钮触发。
工作原理:电机驱动模块
你可能已经注意到,当你打开探测器的代码时,Blocks 代码中出现了一个新类别的模块:电机驱动模块。这些模块是由 Kitronik 公司创建的,该公司提供了项目中使用的电机控制器。
如果你正在启动一个新项目并希望使用这些模块,首先需要将它们添加到项目中。为此,点击块类别列表底部的扩展。这将打开一个对话框,类似于图 10-4 所示。如果在搜索后没有列出该软件包,请刷新浏览器页面并再次尝试搜索。

图 10-4:在 Blocks 编辑器中管理扩展
在顶部标有搜索或输入项目 URL...的字段中输入以下内容:github.com/KitronikLtd/pxt-kitronik-motor-driver/。为了确保你输入的网址正确,首先在另一个浏览器标签页中输入它。当你找到页面后,将浏览器地址栏中的 URL 复制并粘贴到字段中。
一旦输入了 URL,你应该会看到kitronik-motor-driver,如图 10-5 所示。点击它,你会发现你的 Blocks 编辑器现在有了一个新类别,包含了你可以拖入代码中的电机控制模块。

图 10-5:在 Blocks 编辑器中管理扩展
一旦将该软件包添加到你的项目中,它将永久存储在项目中。除非你启动一个新项目并希望在其中使用该软件包,否则你无需再次安装它。因为软件包存储在项目中,你可以轻松地与他人共享该项目,无需对方安装软件包。
总结
在本章中,你测试了 micro:bit 内建无线电的范围,制作了一个更好的门铃,并制作了一个遥控探测器。凭借其良好的范围,无线电使得 micro:bit 之间的通信变得容易,它非常适合各种通信项目。
这是本书的最后一章。随后的附录将为你提供一些关于构建本书项目所需零件的信息,以及你可以从哪里获得它们。
micro:bit 社区是一个充满活力和活跃的社区。你会发现许多有趣的项目可以制作,实验可以进行,涉及到你的 micro:bit。如果你想要一些灵感,看看 microbit.org/ideas/,作为一个疯狂科学家,你或许会从中获得下一个项目的灵感。

附录: 获取部件
本书中的项目使用了很多部件,不幸的是,没有一个供应商能够提供所有这些部件。如果你找到一个想要制作的项目或一个想要尝试的实验,仔细查看“你需要的物品”部分,并记录下你没有的东西。这将是你的购物清单。
本附录中的表格将帮助你找到清单上的物品。如果你在寻找某个物品时遇到困难,可以通过物品的名称或描述在互联网上进行搜索,通常你会找到可以购买它的地方。
Monk Makes Electronics Starter Kit for micro:bit(* monkmakes.com/mb_kit/ *)将为你提供鳄鱼夹电缆以及本书中多个项目使用的 Monk Makes 扬声器和传感器板。
实用工具
本书中的大多数项目和实验只需要用手进行操作。然而,还是有一些工具是每个疯科学家应该拥有的。你可能家里已经有很多这样的工具了。
| 物品 | 描述 | 一些来源 |
|---|---|---|
| 剪刀 | ||
| 胶带 | ||
| 螺丝刀 | 平头和十字头 | |
| 电钻(用于第六章) | ||
| 焊接工具包(用于第六章) | 一套低成本的工具包就可以。你不需要任何花哨的东西。 | Ladyada 的电子工具包:* www.adafruit.com/product/136 *。要寻找低成本的替代品,可以在亚马逊和 eBay 上搜索“焊接工具包”。 |
| 工艺刀 | 用于从纸板中切割形状 | 工艺/爱好店 |
| 钳子 | 中型通用钳子适用于弯曲电线。 | 五金店 |
| 尺子(英寸和厘米) | 办公用品店 | |
| Blu-Tack/粘合剂填充物 | 非常适合将 micro:bit 粘贴到物体上,且不永久性粘贴。 | 办公用品店 |
只有第六章中的流动机器人项目需要焊接。如果你不打算制作这个项目,你就不需要焊接工具。
同样在第六章中,机械动画头项目要求你使用电钻在乒乓球上打孔。否则,你不需要这项设备。
常用部件
以下是本书中许多项目和实验使用的一些部件。许多 micro:bit“入门”套件包括其中的一些或全部物品,这些物品中的一些也列在这里。
| 物品 | 描述 | 一些来源 |
|---|---|---|
| USB 到 micro USB 数据线 | 为 micro:bit 供电和编程 | 这些电缆通常用于给手机充电,因此你可能会有一根。如果没有,它们在销售手机或计算机的商店很容易找到。它们也包含在 micro:bit Go 套件和 Pimoroni micro:bit 配件包中。 |
| 鳄鱼夹电缆 | 用于将 micro:bit 连接到各种设备 | www.adafruit.com/product/1592 shop.pimoroni.com/products/crocodile-leads-set-of-10/
www.kitronik.co.uk/2407-crocodile-leads-pack-of-10.html |
| 鳄鱼夹到公头电缆 | 用于将 micro:bit 连接到伺服电机 | www.adafruit.com/product/3255 thepihut.com/products/adafruit-small-alligator-clip-to-male-jumper-wire-bundle-6-pieces-ada3448/ |
|---|
下面是一些包含这些或全部物品的套件。
| 物品 | 描述 | 一些来源 |
|---|---|---|
| Pimoroni micro:bit 配件套件 | 包括 USB 电缆和电池盒 | shop.pimoroni.com/products/micro-bit-accessories-kit/ |
| BBC micro:bit Go 套件 | 包括 micro:bit、USB 电缆和电池盒 | www.adafruit.com/product/3362 |
| Monk Makes Electronics Starter Kit for micro:bit | 包括鳄鱼夹电缆和多个配件板 | www.eduporium.com/store/monk-makes-electronics-starter-kit-for-micro-bit.html thepihut.com/products/electronics-starter-kit-for-micro-bit/ |
为你的 micro:bit 供电
这是一些可以为你的 micro:bit 提供电源的选项。
| 物品 | 描述 | 一些来源 |
|---|
| 2 × AAA 电池包 | 用于放置 AAA 电池 | 包含在 micro:bit Go 套件中: www.adafruit.com/microbit shop.pimoroni.com/products/battery-holder-2-x-aaa-with-switch/
你也可以在 eBay 上找到这些。
| Kitronik MI:power 电路板 | 为你的 micro:bit 提供硬币电池电源 | www.kitronik.co.uk/5610-mipower-board-for-the-bbc-microbit.html |
|---|
| Monk Makes Power for micro:bit | 为 micro:bit 提供 4.5V 至 12V 的直流电源,适用于长期供电 | www.kitronik.co.uk/46144-monk-makes-power-board-for-microbit.html shop.pimoroni.com/products/power-for-micro-bit/
www.robotshop.com/en/monk-makes-power-module-microbit.html |
| ElecFreaks micro:bit 电源模块 | 与 micro:bit 的电源概念相同(请注意,连接电缆不包括在内) | www.elecfreaks.com/estore/micro-bit-power-supply-module-3-3v-2a.html |
|---|---|---|
| micro:bit 充电套件 | micro:bit 的可充电电池和外壳套件 | www.monkmakes.com/mb_charger/ |
| USB 备用电池 | 一种有用的可充电电池选项(不适用于高电流项目) | www.adafruit.com/product/1959 你也可以在手机或电脑店、eBay 和 Amazon 找到这些产品。 |
micro:bit 配件
本书广泛使用 micro:bit 配件,如扬声器和传感器。以下是一些配件的选项。
| 项目 | 描述 | 一些来源 |
|---|
| Monk Makes micro:bit 扬声器 | 用于与声音相关的项目的扬声器 | www.eduporium.com/store/monk-makes-speaker-for-micro-bit.html shop.pimoroni.com/products/speaker-for-micro-bit/
www.kitronik.co.uk/46124-powered-speaker-board-for-microbit.html |
| Mini.Mu 扬声器 | 用于与声音相关的项目的扬声器 | shop.pimoroni.com/products/mini-mu-speaker/ |
|---|
| Monk Makes micro:bit 传感器 | 声音、温度和光传感器 | www.eduporium.com/store/monk-makes-sensor-for-micro-bit.html www.kitronik.co.uk/46122-sensor-board-for-microbit.html
shop.pimoroni.com/products/sensor-for-micro-bit/ |
| Adafruit MEMS 麦克风扩展板 | 高级声音感应选项(需要焊接) | www.adafruit.com/product/2716 |
|---|---|---|
| Kitronik 电机驱动板 for BBC micro:bit (V2) | 用于第六章的机器人巡逻项目 | www.kitronik.co.uk/5620-motor-driver-board-for-the-bbc-microbit-v2.html |
杂项
除了附加配件,你还需要一些其他物品。
| 项目 | 描述 | 一些来源 |
|---|---|---|
| 钕磁铁(10 毫米圆盘) | 非常强大的圆盘磁铁 | 你可能会在爱好/工艺品商店找到这些,但 eBay 可能是你的最佳选择。搜索“钕磁铁”。 |
| 3V 伺服电机 | 低功耗伺服电机,能在 3V 下运行 | www.adafruit.com/product/169 www.kitronik.co.uk/2565-180-mini-servo.html |
| 12V 水族馆计量泵 | 用于第九章中的植物浇水器项目 | 热带鱼商店或 eBay,搜索“12V 水族馆计量泵” |
| 1kΩ电阻器 | 用于第九章中的植物浇水器项目 | www.sparkfun.com/products/14492/ www.kitronik.co.uk/c3003-resistor-pack-of-100.html(版本 3003-1k) |
| 女性 DC 插座到螺丝端子适配器 | 用于第九章中的植物浇水器项目 | www.adafruit.com/product/369 shop.pimoroni.com/products/male-dc-power-adapter-2-1mm-plug-to-screw-terminal-block/ |
| 用于植物浇水器项目中的 12V 泵供电器 | 可以供应 12V 和 1A 的适合您国家的交流插座类型的供电器 | 美国: www.adafruit.com/product/798 英国: shop.pimoroni.com/products/power-supply-12v-1a/ |
Micro:bit for Mad Scientists设定为 Century Schoolbook,Filmotype Candy,Housearama Kingpin 和 TheSansMono Condensed 字体。
资源
访问www.nostarch.com/microbitformad/获取资源,勘误表和更多信息。
更聪明的孩子的更智能的书籍! 

学习用 RASPBERRY PI 制作机器人
建造和编程您自己的移动,感应,思考机器人
由 MATT TIMMONS-BROWN 撰写
2019 年 1 月,240 页,24.95 美元
ISBN 978-1-59327-920-2
全彩

创造自己的 SCRATCH 游戏!
由 ANNA ANTHROPY 撰写
2019 年 7 月,192 页,17.95 美元
ISBN 978-1-59327-936-3
全彩

使用 MINECRAFT 编程
建造更高,农场更快,挖掘更深,并自动化无聊的事情
由 AL SWEIGART 撰写
2018 年 5 月,256 页,29.95 美元
ISBN 978-1-59327-853-3
全彩

20 个简单的树莓派项目
玩具,工具,小玩意以及更多!
由 RUI SANTOS 和 SARA SANTOS 撰写
2018 年 4 月,288 页,24.95 美元
ISBN 978-1-59327-843-4
全彩

官方 SCRATCH 编码卡
为孩子们创造编程活动
由 NATALIE RUSK 和 SCRATCH TEAM 撰写
2019 年 5 月,76 张卡片,24.95 美元
ISBN 978-1-59327-976-9
全彩,礼盒装

给孩子的 PYTHON
编程的嬉戏介绍
由 JASON R. BRIGGS 编写
2012 年 12 月,344 页,$34.95
ISBN 978-1-59327-407-8
全彩
1.800.420.7240 或 1.415.863.9900 | sales@nostarch.com | www.nostarch.com
适合 10 岁及以上年龄段
打造属于你自己的 秘密实验室!

BBC micro:bit 是一款微小、廉价且出乎意料地强大的计算机,你可以用它来制作酷炫的东西并进行代码实验。
这本书中的 30 个简单项目和实验将教你如何使用 micro:bit 构建一个秘密的科学实验室——包括机器人、门铃、测谎仪等等——同时学习基础的编码和电子学技能。
这里列出的是你将要制作的一些项目:
一种通过挥手即可演奏的光控吉他
一个工作的测谎仪
一款自动浇水的植物护理系统
一款双轮机器人
一款带有活动眼睛的会说话机器人头
一个由磁铁制作的门铃
学会像疯狂科学家一样编写代码!
关于作者
西蒙·蒙克(Simon Monk)经常为创客撰写有关电子学的文章。他是《树莓派食谱》、《编程 Arduino》和《电子学黑客》的作者。与此同时,他还是《发明家实用电子学》的合著者,并与他的儿子马修·蒙克共同编写了《Minecraft 精通指南》。
涵盖 MicroPython 和 MakeCode 块
30 个编码与电子项目

最棒的极客娱乐™



















































浙公网安备 33010602011771号