树莓派 Pico 物理编程入门

树莓派 Pico 的 RP2040 微控制器在设计时考虑到了物理计算。它的众多通用输入/输出(GPIO)引脚让它与一系列组件交互,允许你建立项目,从照明 LED 到记录你周围世界的数据。

物理计算并不比传统计算更难学习,如果你能遵循本篇的内容,你会明白如何建立你自己的电 路,并对它们进行编程来执行你的命令。

第一个物理计算程序:Hello, LED!

就像在屏幕上打印「Hello, World」是学习编程语言的第一步,点亮 LED 是学习物理计算的经典入门。

你也可以在没有任何额外组件的情况下开始,Pico 电路板上就有一个小的 LED。

这个 LED 被通电时,它会发光;当它关闭电源,它就会熄灭。

板载 LED 连接到 RP2040 的 GP25 引脚上(如果你在使用 Pico W,板载 LED 不再是 GP25)。你可能还记得,这是RP2040上「缺失」的 GPIO 引脚之一。

打开 Thonny,连上你的 Pico。点击进入脚本编辑区域,用以下一行开始你的编程:

import machine

这一小行代码是在 Pico 上使用 MicroPython 的关键。它导入 MicroPython 代码集合,也称为库。在本例中是「machine」库。包含了 MicroPython 与 Pico 和其他 兼容 MicroPython 的设备通信所需的所有指令。如果没有这一行,你将无法控制任何 Pico 的 GPIO 引脚。

选择性导入
在 MicroPython 和 Python 中,都可以导入库的一部分,而不是整个库。这样做可以使你的程序使用更少的内存,并允许你混合和匹配来自不同库的函数。本教程中的程序导入了整个库,在其他地方,你可能会看到程序有类似于 from machine import Pin,这是告诉 MicroPython 只从「machine」库中导入「Pin」函数,而不是整个库。

machine 库公开了应用程序接口(API)。这个名称听起来很复杂,但是准确地描述了它的功能,它为你的程序提供了一种通过接口与 Pico 通信的方法。

程序的下一行提供了 machine 库的 API 示例:

led_onboard = machine.Pin(25, machine.Pin.OUT)

这一行定义了一个名为 led_onboard 的对象,代码的第二部分调用 machine 库中的 Pin 函数。顾名思义,这个函数是为处理你的 Pico 的 GPIO 引脚而设计的。第一个参数是 25,是你设置的引脚编号。machine.Pin.OUT 则是告诉 Pico 该引脚应该被用作输出而不是输入。

注意,如果你在使用 Pico W,板载 LED 不再是 GP25,请使用下面的代码:

led_onboard = machine.Pin("LED", machine.Pin.OUT)

这行代码只起到了设置引脚的作用,它并不会点亮 LED。要做到这一点,你需要告诉 Pico 打 开这个引脚。在下一行输入以下代码:

led_onboard.value(1)

这一行将 led_onboard 的值设置为 1(表示「开」),也可以将值设置为 0 (表示「关」)。

单击 Run 并将程序保存在 Pico 上,命名为 Blink.py。你会看到 LED 灯亮起来。祝贺你——你已经编写了你的第一个物理计算程序!

然而,你会注意到 LED 仍然是亮着的。这是因为你的程序告诉 Pico 打开它,但从来没有告诉它关闭 LED。你可以在程序的底部添加另一行:

led_onboard.value(0)

然而,这次运行程序 LED 似乎永远不会点亮。这是因为 Pico 的工作速度非常非常快,比你用 肉眼看到的速度快得多。LED 有被点亮,但在如此短的时间内,它似乎保持熄灭。要解决这个问题,你需要通过引入延迟来降低程序的速度。

转到程序的最上面,并单击第一行末尾,然后按回车键插入新行:

import utime

与 import machine 类似,这一行将一个新的 utime 库导入 MicroPython。这个库处理与时间有关的所有事情,从度量时间到向程序中插入延迟。

转到程序的底部,并单击 led_onboard.value(1) 行末尾,然后按回车键插入新行:

utime.sleep(5)

这将调用来自 utime 库的 sleep 函数,该函数将使你的程序暂停数为你输入的秒数,在本例中为 5 秒。

再次单击 Run。这次你会看到你的 Pico 上的 LED 灯亮了,保持亮 5 秒钟然后再熄灭。

最后,是时候让 LED 循环闪烁了。为此,你需要创建一个循环。重写你的程序:

import machine
import utime

led_onboard = machine.Pin(25, machine.Pin.OUT)

while True:
	led_onboard.value(1)
	utime.sleep(5)
	led_onboard.value(0)
	utime.sleep(5)

记住,循环中的行需要缩进四个空格,这样 MicroPython 就知道它们构成了循环。再次点击 Run,你会看到 LED 点亮 5 秒,熄灭 5 秒,然后再次点亮的不断重复。LED 将继续闪 烁,直到你点击停止图标取消你的程序和重置你的 Pico。

还有另一种方法来处理同样的工作,即使用 toggle,而不是显式地将 LED 的输出设置为 0 或 1。删除程序的最后四行,并替换它们,如下面这这样:

import machine
import utime

led_onboard = machine.Pin(25, machine.Pin.OUT)

while True:
	led_onboard.toggle()
	utime.sleep(5)

再次运行程序。你将看到与之前相同的效果。板载的 LED 将点亮 5 秒,然后熄灭 5 秒,然后在无限循环中再次点亮。不过,这一次,你的程序缩短了两行,你已经优化了它。toggle() 可用于所有数字输出引脚,它只是在开和关之间切换:如果引脚当前是开的,toggle() 将其关闭;如果它是关闭的,toggle() 将它打开。

使用面包板

如果你使用面包板来保存组件并进行电气连接,那么本章中接下来的项目将会更容易完成。

面包片上面有很多间距 2.54 毫米的孔洞。在这些孔下是金属条,它们就像用跳线串连起来。

其中带有正负标志的两行通常用于接 Pico 的 5V/3.3V 和 GND 引脚。当然也可以用来接外部电源的正负极。用来给需要的元器件供电。

把电子元件加到面包板上很简单,只要把它们的引脚与孔对齐,然后轻轻插进去。你可以使用跳线再将引脚引入到 Pico 上。

把你的 Pico 插到面包板上,使它跨过面包板中间的空隙,microUSB 接口在最上面。在插入之前,请确保所有的排针都对准了孔位,否则可能很难插入或者折断 Pico 的引脚。

外接 LED

对于这个项目,你需要一个面包板,公对公跳线,一个 LED,和一个 330Ω 电阻(或接近 330Ω)。如果你没有面包板,你可以使用母对母杜邦线。

电阻在这里被当作限流电阻使用。它通过限制 LED 可以引出的电流量来保护你的 Pico 和 LED。如果没有它,LED 可能会拉出太多的电流而烧毁。330Ω 对大多数常见的 LED 都适用。数值越高,LED 越暗;数值越低,LED 就越亮。

如果没有电流限制电阻,千万不要把 LED 连接到 Pico 上,除非你知道 LED 有一个合适的内置电阻。

用手指握住 LED,你会看到其中一根导线比另一根长。较长的引线称为正极,较短的引线是 负极。正极需要通过电阻连接到你的 Pico 的 GPIO 管脚;负极需要连接到一个 GND 引脚。

从连接电阻器取一端(哪一端无关紧要),并将它插入到面包板的同一行,与 Pico 的 GP15 引脚在左下角。将另一端插入面包板下面的一个空置行中。

拿起 LED,把较长的支脚(正极)推到电阻器的末端所在的同一排。把较短的(负 极)放到同一行,但要穿过面包板中间的空隙,这样它就能对齐。最后,在 LED 短脚的同一行插入一根 M2M 跳线,然后将它直接连接到你的 Pico 的 GND 引脚上。如下图所示。

在 MicroPython 中控制一个外部 LED 和控制 Pico 板载的 LED 没有什么不同,只需要改变程序代码中引脚的编号。如果你关闭了 Thonny,重新打开它并加载前面的 Blink.py 程序。找到:

led_onboard = machine.Pin(25, machine.Pin.OUT)

编辑引脚号,将其从 25 改为 15。再把 led_onboard 修改为 led_external。最终代码如下:

import machine
import utime

led_external = machine.Pin(15, machine.Pin.OUT)

while True:
	led_external.toggle()
	utime.sleep(5)

输入:读取按键

对于这个项目,你将需要一个面包板,公对公跳线,和一个按钮开关。将他们按照图中示意的位置安装好。其中按钮有引脚的两侧分别插入面包板,并且横跨在面包板正中间(物理上隔断两侧引脚的连通)。

按钮的一侧接 Pico 的 3V3 引脚,另一侧接 Pico 的 GP14 引脚。

隐藏的内置电阻
与 LED 不同,按钮开关不需要限流电阻。它仍然需要一个所谓的上拉或下拉电阻,这取决于你的电路如何工作。如果没有上拉或下拉电阻,输入信号会有「噪声」,即使你没有按下按钮也会触发。

那么电路中的电阻器在哪里?它藏在 Pico 芯片里。就像它有一个板载 LED,Pico 内置一个板载可编程电阻连接到每个 GPIO 引脚。可以根据需要在 MicroPython 中将其设置成下拉电阻或上拉电阻。

有什么区别呢?
下拉电阻将引脚连接到 GND,这意味着当按钮被按下时,读取到的输入值是 0。
上拉电阻连接引脚到 3V3,这意味着当按钮没有按下,读取到的输入值是 1。

本书中所有的电路都使用下拉模式下的可编程电阻。

打开 Thonny,然后在新的一行启动一个新程序:

import machine

接下来,你需要使用 machine API 设置一个引脚作为输入,而不是输出:

button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

这与你的 LED 项目的工作方式相同:创建一个名为「button」的对象,它包括引脚号 GP14,并将其配置为一个电阻设置为下拉的输入。不过,创建对象并不意味着它会自己做任 何事情,就像之前创建LED对象并不能使 LED 发光一样。

要真正读取按钮,你需要再次使用 machine API,这一次使用 value 函数读取,而不是设置引脚的值。输入以下一行:

print(button.value())

单击 Run 并将程序保存为 Button.py,记住以确保它保存在你的 Pico MicroPython device 里。你的程序将打印出从 GP14 读取到的值。因为输入端使用的是一个下拉电阻,这个值将是 0,让你知道按钮没有被按下。

用手指按住按钮,并再次按下 Run 图标。这一次,你将看到值 1 打印到 Shell。按下按钮就电
路导通并改变了从引脚读取的值。要连续读取按钮,你需要在程序中添加一个循环。编辑程序如下:

import machine
import utime

button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

while True:
	if button.value() == 1:
		print("You pressed the button!")
		utime.sleep(2)

再次单击 Run 按钮。你的 Pico 运行速度要比你的观察速度快得多,并且没有延迟,即使是简单地按一下按钮,也可以向 Shell 打印数百条消息!如果你按住按钮超过两秒的延迟,它会每两秒打印一条消息,直到你松开按钮。

输入和输出:同时使用

大多数电路都有不止一个元件,这就是为什么 Pico 有这么多 GPIO 管脚。现在是时候把你学 到的所有东西结合在一起,制作一个更复杂的电路了:一个用按钮开关 LED 的装置。

实际上,这个电路将前面的两个电路组合成一个。你可能记得你使用 GP15 来驱动外部 LED,GP14 来读取按钮。现在重建你的电路,使 LED 和按钮同时在面包板上,仍然连接到 GP15 和 GP14。别忘了 LED 的限流电阻。

在 Thonny 启动一个新程序,并开始导入你的程序需要的两个库:

import machine
import utime

接下来,设置输入和输出引脚:

led_external = machine.Pin(15, machine.Pin.OUT)
button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

然后创建一个读取按钮值的循环:

while True:
	if button.value() == 1:

不过,这一次你将根据输入引脚的值切换输出引脚上 LED 的状态,而不是将消息打印到 Shell。使用下面的代码:

led_external.value(1)
utime.sleep(2)

这足以让 LED 亮起来,但当按钮没有被按下时,你还需要再次关闭它。添加以下新行,删除 8 个空格中的 4 个,这意味着这行将不是 if 语句的一部分,而是无限循环的一部分:

led_external.value(0)

最终代码如下:

import machine
import utime

led_external = machine.Pin(15, machine.Pin.OUT)
button = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

while True:
	if button.value() == 1:
		led_external.value(1)
		utime.sleep(2)
	led_external.value(0)

单击 Run 并将程序保存为 Pico 上的 Switch.py。

起初,什么都不会发生。按下按钮,你就会看到 LED 灯亮起来。松开按钮两秒钟后,指示灯再次熄灭,直到你再次按下按钮。

祝贺你!你已经建立了你的第一个电路,它根据一个输入引脚控制另一个输出引脚,我们已经在 构建模块程序的路上跨越了一大步!

Pico 实验室注:
注意,对于树莓派 Pico W 来说,板载的 LED 引脚编号不是 GP25,在 Pico W 上驱动板载 LED 请参考下面的代码:

import machine
import utime

led = machine.Pin("LED", machine.Pin.OUT)
while True:
    led.on()
    utime.sleep(1)
    led.off()
    utime.sleep(1)

你还可以:
查看系列教程中的其他文章「树莓派 Pico 上手指南(在 Pico 上使用 MicroPython)」
购买本教程所用到的 Pico 上手套件



坐沙发

发表评论

你的邮件地址不会公开


*