2021年1月底的时候,树莓派基金会发布了一个重磅消息,推出了进军微控制器领域的树莓派Pico。
功能强劲,价格便宜的特性让Pico受到了全世界创客们的关注,这篇文章就来给大家介绍一下Pico这个小玩意儿。
文章原文来自DroneBot Workshop,负责人是一个非常和蔼的老爷爷。有条件的小伙伴可以去油管关注一下他。
这篇文章使用MicroPython在树莓派 Pico上编程,一起来看看三十块的微控制器究竟能做些什么。
树莓派基金会发布微控制器本身就是一个大消息,毕竟在这之前,这个世界上最流行的单板电脑的制造商从来没有表示过对微控制器的兴趣。
不仅仅是树莓派Pico的公布让人感到意外,这次树莓派还自己打造了一款新的芯片。他们没有在现有代码的基础上,支持基于ESP32或SAMD21的设计,而是选择创建自己的微控制器。
所以谈到Pico时,我们都是新手。
树莓派也在官网发布了一大堆技术文档,还有一本名为《Get Started with MicroPython on Raspberry Pi Pico》的说明书。它有纸质版,也有PDF版下载。
除此之外,目前还没有关于Pico更深入的资料。不过随着时间的推移,这种情况很快就会改变,树莓派已经授权包括Adafruit在内的其他厂商在自己的设计中使用RP2040芯片。假以时日,就会给我们带来更多的代码和开发工具。
我们先来尝试一下,给Pico连接上一堆东西,会发生什么有趣的事情吧!
Pico是一块小小的板子,大小和Arduino Nano差不多。和所有树莓派一样,包装非常简陋,只是一个塑料包装内的Pico,而塑料包装本身就是从一条条的包装上剪下来的,非常像小时候吃的咪咪虾条或者是糖果的包装。
四刀买到的就仅仅是这么一款裸板,没有多的,就是这么环保。
裸板不带针脚,需要自己焊。这是一块做工精良的电路板,也可以作为SMD元件,直接焊接到印刷电路板上。
从顶部看,Pico是这样的。
板上最主要的功能是一端的microUSB连接器。它既用于通信,也用于给Pico供电。
在microUSB连接器旁边安装了一个板载LED,它内部连接到GPIO针脚25。
值得注意的是,这是整个Pico板上唯一的LED。
开机按钮安装在离LED稍低一点的地方,它可以让你改变Pico的启动模式,这样你就可以在上面加载MicroPython,进行拖拽式编程。
在板子的底部,你会看到三个连接点,这些连接点是用于串行Debug选项的,我们今天是入门,暂时不探讨这个问题,高级开发者会比较感兴趣。
在板子的中央是整个板子的“大脑”——RP2040 MCU,我们一会儿就会研究它的功能。
板子上有好几个地线,8个地线加上3针Debug连接器上的一个附加地线。
这些引脚很容易发现,它们是均匀的,而且是方形的,而不是像其他连接的圆形。
其中一个位于33号针脚的地线也被指定为模拟地线。
Pico是一个3.3V的逻辑器件,但由于内置了电压转换器和稳压器,它可以用一系列电源供电。
所有与电源相关的引脚都被安排在了一起,靠近microUSB连接器。
VBUS - 这是来自 microUSB 总线的电源,5 V。如果Pico不是由microUSB连接器供电,那么这里将没有输出。
VSYS - 这是输入电压,范围为 2 至 5 V。板载电压转换器将为 Pico 将其改为 3.3 V。
3V3 - 这是 Pico 内部调节器的 3.3 伏输出。只要将负载保持在 300ma 以下,它就可用于为其他组件供电。
还有几个输入可以让你控制 Pico 的电源。
3V3_EN - 你可以使用此输入禁用 Pico 的内部电压调节器,从而关闭 Pico 和由其供电的任何组件。
RUN - 可以启用或禁用 RP2040 微控制器,也可以将其复位。
树莓派 Pico板上有26个裸露的GPIO连接。
它们的排列顺序很好,在GPIO 22和GPIO 26之间有一个 "空隙"(这些 "缺失 "的引脚在内部使用)。
这些引脚都有多种功能,你可以为PWM配置多达16个引脚。
有两个I2C总线,两个UART和两个SPI总线,这些可以配置使用多种GPIO引脚。
Pico有三个模数转换器,还有一个内部用于板载温度传感器的转换器。
ADC的分辨率为12位。
你也可以在ADC_VREF
引脚上提供一个外部精密电压参考。其中一个接地点,即33脚上的ADC_GND被用作该参考点的接地点。
树莓派 Pico是围绕基金会的新芯片RP2040微控制器而设计的。下面是它的参数:
双核32位ARM Cortex -M0+处理器
运行在48MHz,但可以超频到133MHz。
30个GPIO引脚(26个暴露)
可支持USB主机或设备模式
8 可编程I/O(PIO)状态机
RP2040能够支持高达16MB的片外闪存,不过在Pico中只有4MB。
树莓派基金会对这款芯片有很多计划,也已经授权给了很多其他厂商。
你可以使用两种编程语言之一开始使用 Pico。
MicroPython - 一种专门为微控制器制作的解释语言。
C++ - 许多微控制器用户都熟悉C++,因为它被用于Arduino和ESP32板上。
虽然我急于将C++与Pico一起使用,以榨取它的每一克性能,但还是决定与大多数人一样,使用MicroPython。在这个早期的开发阶段,C++的工具还在进行最后的开发,期待着Pico成为PlatformIO和Arduino IDE板系列的一部分。
当我们拿到Pico板时,它被包装在一个塑料载体中,没有额外的零件。
除非你有计划将 Pico 表面贴装,或者你的唯一目的是只是点个灯,否则我们都需要一些引脚。
Pico 有 40 个引脚,每侧 20 个。另外三个针脚用于调试端口。
标准的公头针脚有 40 个针脚带,因此可以将其中一个针脚带减半,作为 Pico 的针脚使用。如果你想在 Debug 连接器上安装针脚,你需要另一个 3 针的公头,可以是直的或 90 度的。
在开始对 Pico 进行编程之前,我们需要进行一些焊接工作!除了杜邦公头引脚之外,我们还需要合适的烙铁和一些焊料。
电烙铁的头需要精细一点,我们还需要一块清洁海绵和一个支架。
此外,我们还需要想办法在焊接Pico引脚时把它固定住,因为它们需要以精确的90度角安装到电路板上,这样才能装入无焊料面包板。
许多实验都使用无焊面包板来固定引脚,虽然这种方法可行,但有可能因热力或焊料飞溅而损坏面包板。
所以最好的解决方法是,你有一块老旧的面包板,用它作为针座。
我个人喜欢用几块便宜的灌注板、打孔实验板。我说的 "便宜 "是指单面的东西,没有排孔,只有一面是裸铜的。
两片这种东西很适合固定引脚,每当要焊接一个小模块或者单片机的时候,我就经常用这个。
把电烙铁加热到一定温度,然后加热引脚与焊盘的连接处,在另一面涂上焊料,千万不要直接涂到电烙铁上。加热零件,而不是焊料。
如果你想焊接Debug的3个引脚连接器(这是可选的),你可能应该先做。这些引脚的方向与GPIO引脚的方向相反。我用了一个小的便签垫来固定电路板,因为Debug连接器与GPIO引脚在网格上并不一致。
之后就是焊接40个引脚了,一次20个! 真的不需要太长的时间,只需要用尽可能多的焊料,避免出现焊桥,完成后再检查一下。
我喜欢在焊接完我的PCB后清洗它们,以去除焊料核心中的助焊剂和树脂。它表现为焊接连接处周围的褐色污渍。
这一步完全是可有可无的,因为助焊剂和树脂对元件的运行或寿命没有任何不利影响。它只是看起来更好看!
如果你想克隆你的板子,你需要一些PCB板清洗剂或Flus Remover。由于它也往往会留下一点残留物,我用异丙醇来清理。
PCB板清洗剂可以到网上购买。异丙醇可以在当地药店找到,一定要买纯酒精和水的混合物(70%),不要买有香味的。
我用一把旧牙刷和一些塑料容器,在一个盆子里进行工作。记得最好要准备好口罩、手套和护目镜。
我用牙刷蘸PCB清洁剂擦洗引脚,然后用牙刷蘸异丙醇冲洗。
让板子自然风干,也可以使用空气软管,这样之后,我们将拥有一个闪闪发光的新Pico!
现在Pico的引脚已经连接好了,我们可以开始对它进行实验了。
建议你把它放在一个无焊的面包板上,以迎接我们即将到来的实验。
虽然有许多IDE可以让我们选择与我们的新Pico一起工作,但我的建议是使用树莓派推荐的Thonny IDE。
Thonny自称是 "Python IDE for Beginners",它适用于Windows、Mac OSX和Linux。
它也是树莓派操作系统(以前的Raspbian)的一部分。
我将在树莓派操作系统上使用Thonny IDE,运行在8GB的树莓派 4上,作为我今天实验的开发平台。当然,你可以使用任何你能运行Thonny的平台,但我想让它在树莓派家族中运行--另外,由于Thonny已经安装在新构建的树莓派操作系统上,所以上手非常简单。
我们需要做的第一件事是将MicroPython安装到Pico上。
将microUSB连接到Pico上,并准备将另一端插入电脑。在插入之前,先按下Pico上的Boot Select(开关)按钮。
按住BOOTSEL键,将Pico插入电脑的USB端口。按住BOOTSEL键几秒钟,然后松开。
你应该会看到一个新的驱动器在你的电脑上可用,信息看起来会有所不同,这取决于你所使用的操作系统,但它类似于你将U盘插入电脑时得到的信息。
打开新的 "驱动器",你会看到一个名为 RPI-RP2
的文件夹。在这个驱动器里,你会看到几个文件,其中一个是网页文档index.htm
。
点击该网页文件,浏览器就会打开,你会被重定向到树莓派 Pico入门页面。
点击MicroPython入门的标签。你会看到一个链接来下载一个UF2文件,这就是可下载的MicroPython文件。把这个文件下载到你的电脑上。
现在将下载的文件拖到Pico的RPI-RP2文件夹中。一旦这样做了,文件夹就会消失,Pico将以MicroPython模式启动。
在Pico仍然被连接的情况下,打开Thonny IDE,如果你和我一样使用树莓派操作系统,你会在编程工具菜单下找到Thonny。
一旦Thonny打开,请看右下角的状态栏,它可能会显示一个Python的版本。这是当前在你的计算机上运行的Python版本,对于我们的实验来说,这一点并不重要。
点击该消息,应该会出现一个下拉菜单,还有其他环境可以选择。其中一个应该是MicroPython (树莓派 Pico)。选择那一个。
你会注意到底部打开了一个新的Shell,在这个Shell中,你应该会看到一些文字,表明你已经连接到Pico。
是时候开始编程了!
Shell是Pico的 "命令行",你可以直接在这里执行代码。
一个简单的测试是输入以下内容(这也是查看你是否正确连接到 Pico 的好方法),然后按 Enter 键。
print(“Hello World”)
你应该在shell中看到 "Hello World "被打印出来了,当然这是你告诉Pico要做的。
当然,你不会直接在shell中输入你的程序,一来,一旦你执行了程序,它们就会消失,二来,对于任何相当大的程序来说,也是不方便的。
你要用编辑器来输入你的程序,也就是shell上面的大文本区域,在Thonny IDE的屏幕上占主导地位。
进入这个编辑器,输入和刚才一样的文字,用一个漂亮的 "你好 "来迎接编程世界。
点击 "运行 "按钮(绿色带箭头的那个),系统会提示你先保存程序。你可以选择将其保存在本地电脑或Pico上,尝试保存在Pico上。给你的程序起个带".py "后缀的名字,比如 "hello.py"。
程序将被保存并运行,你将在shell中看到 "Hello World "的问候语。你可以按 "运行 "按钮再次看到它,再按一次。
所以,现在你知道了如何编写和保存MicroPython程序,我们就可以开始我们的实验了!
基本的数字I/O功能可以很容易地用LED和开关来说明,这正是我们开始Pico冒险的方式。
但请注意我们如何给开关布线,我们将以不同的方式进行操作。
最简单的输出设备可能是LED。当在正确的方向上施加足够的电流时,这种输出设备就会工作。虽然简单,但它可以用来说明I/O技术,这些技术可以应用于其他设备,如继电器或晶体管。
我将使用一个Common-Cathode RGB LED,但你也可以使用三个分立的LED来代替。无论哪种方式,你都还需要三个降压电阻,我在实验中使用了330欧姆的电阻。
如果你选择像我这样使用RGB LED,一定要买一个标准的RGB LED,而不是一个可编程的。
这是最简单的输入设备。我用的是一对瞬时常开按钮开关
一个红色和一个黑色,但在其他方面是相同的。
我们再次使用一个简单的输入设备来测试我们的小Pico的I/O能力。我们将以不同的方式为两个开关布线,使其更加有趣,而且我们也不会使用任何上拉或下拉电阻。
这里是我们的LED和开关的连接图,请记住,如果你没有共阴极RGB LED,你可以使用三个独立的LED。
请注意,这两个开关的接线方式不同。
黑色按钮开关的一侧连接到Pico的GPIO引脚,另一侧连接到地。
红色开关则相反,它的一侧连接到GPIO引脚,另一侧连接到3.3伏,这是Pico的工作电压和逻辑电压。
我们要做的第一个实验是我们自己的Arduino "Blink "草图的变体。是的,从技术上讲,我们已经看到了如何闪烁板载LED,但由于我们现在有一个RGB LED在我们的支配下,我们当然可以找到另一种方法来点灯!
在Thonny中打开以下代码。
# 树莓派 Pico RGB Blink
# rgb-blink.py
# RED LED - Pico GPIO 10 - Pin 14
# GREEN LED - Pico GPIO 11 - Pin 15
# BLUE LED - Pico GPIO 14 - Pin 19
# DroneBot Workshop 2021
# https://dronebotworkshop.com
import machine
import utime
led_red = machine.Pin(10, machine.Pin.OUT)
led_green = machine.Pin(11, machine.Pin.OUT)
led_blue = machine.Pin(14, machine.Pin.OUT)
while True:
led_red.value(1)
led_green.value(0)
led_blue.value(0)
utime.sleep(2)
led_red.value(0)
led_green.value(1)
led_blue.value(0)
utime.sleep(2)
led_red.value(0)
led_green.value(0)
led_blue.value(1)
utime.sleep(2)
led_red.value(1)
led_green.value(1)
led_blue.value(0)
utime.sleep(2)
led_red.value(1)
led_green.value(0)
led_blue.value(1)
utime.sleep(2)
led_red.value(0)
led_green.value(1)
led_blue.value(1)
utime.sleep(3)
led_red.value(1)
led_green.value(1)
led_blue.value(1)
utime.sleep(2)
print("End of Loop")
led_red.value(0)
led_green.value(0)
led_blue.value(0)
utime.sleep(2)
这是一个简单的脚本,肯定可以改进,但它可以很好地说明我们的观点。
我们先导入 machine 和 utime 库。你会发现,任何涉及I/O端口的活动都需要用到machine,而只要我们想使用时间函数,就需要用到utime。
然后,我们定义三个 LED 元件的连接,请注意,它们是以 GPIO 编号而非 Pico 上的物理引脚编号来表示的。我们将所有这些引脚定义为 machinePin.OUT,这意味着这些引脚现在被设置为输出引脚。
while True条件类似于Arduino草图中的Loop,这里的代码是连续执行的。
在本节中,我们对LED进行寻址,并将它们设置为开(值为1)或关(值为0)。我们通过一个序列,在最后一个序列,我们打印到控制台。
然后我们再做一遍。
将脚本加载到Pico上,然后观察LED,你应该会看到一个彩色的闪烁。
我们接下来的脚本是对两个开关进行一个非常基本的测试,我们用这样一个奇怪的方式来接线。
你会观察到的第一件奇怪的事情是它们的接线不同,黑色的开关将输入端连接到地,而红色的开关将输入端连接到3.3伏,用于逻辑HIGH。
另一个有趣的事情是,这两个开关都没有采用上拉或下拉电阻,它们显然需要这些电阻,黑色开关需要上拉,红色开关需要下拉才能正常工作。
我们将在代码中加入所需的电阻!
# 树莓派 Pico Switch Test
# switchtest.py
# RED BUTTON - Pico GPIO 15 - Pin 20
# BLACK BUTTON - Pico GPIO 2 - Pin 4
# DroneBot Workshop 2021
# https://dronebotworkshop.com
import machine
import utime
button_red = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_black = machine.Pin(2, machine.Pin.IN, machine.Pin.PULL_UP)
while True:
if button_red.value() == 1:
print("Red")
if button_black.value() == 0:
print("Black")
utime.sleep(0.25)
请注意定义按钮的行的语法,你会看到它们是如何被定义为Inputs的,以及如何添加了下拉和上拉电阻。
在while True: 循环中,你还会注意到我们是在监测不同的条件,红色的开关触发了一个HIGH输入,而黑色的开关触发了一个LOW。
最后的微小时间延迟是一种简单的debouncing形式,如果你喜欢,你可以实验一下这个值。
这个脚本会在控制台中打印所有的结果,所以在你按下按钮的时候要注意。
接下来的实验引入了几个有用的概念。第一个,也可以说是这两个概念中最重要的,就是 "中断"。
中断就像它的声音一样,是一个 "中断 "程序正常流程的事件。在我们的情况下,我们处理的是外部硬件中断,这意味着在程序继续运行之前,需要处理一个信号或状态变化。
在Pico上,我们按照以下方式创建一个中断。
我们将一个引脚定义为 "中断输入", 我们定义该点上的状态变化被认为是一个中断。在 Pico 上,我们可以使用任何 GPIO 引脚来实现这一点,而且我们可以定义多个引脚。
我们创建了一个 "中断处理程序 "函数,我们希望在检测到中断时运行该函数。
我们将 "中断处理程序 "与 "中断输入 "配对。
现在,每当中断输入条件发生时,Pico 将停止它正在做的任何事情,并执行 "中断处理程序"。然后它将恢复到原来的位置。
虽然不像中断那样基本,但仍然非常有用。“切换”只是将 Pico 上的输出状态反转。
因此,如果输出为高电平,而我们应用 "切换",它就会变为低电平。
我们不需要知道输出的当前状态,我们只需要知道当我们应用一个切换器时,它将变为相反的状态。
自然,这是写另一个Blink程序的理想函数,所以我们会这么做。只有我们的Blink程序才会有被中断的风险!
# 树莓派 Pico Interrupt & Toggle Demo
# interrrupt-toggle-demo.py
# RED LED - Pico GPIO 10 - Pin 14
# GREEN LED - Pico GPIO 11 - Pin 15
# RED BUTTON - Pico GPIO 15 - Pin 20
# DroneBot Workshop 2021
# https://dronebotworkshop.com
import machine
import utime
led_red = machine.Pin(10, machine.Pin.OUT)
led_green = machine.Pin(11, machine.Pin.OUT)
led_red.value(0)
led_green.value(0)
button_red = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_DOWN)
def int_handler(pin):
button_red.irq(handler=None)
print("Interrupt Detected!")
led_red.value(1)
led_green.value(0)
utime.sleep(4)
led_red.value(0)
button_red.irq(handler=int_handler)
button_red.irq(trigger=machine.Pin.IRQ_RISING, handler=int_handler)
while True:
led_green.toggle()
utime.sleep(2)
在这个MicroPython脚本中,我们将闪烁我们的RGB LED的绿色部分,使用一个切换器来改变它的状态。在正常的操作下,LED状态将每两秒钟切换一次。
然而,我们可以通过按下红色按钮来中断闪烁。这将导致一个中断,这将关闭绿色的LED,然后打开红色的。它将保持四秒,之后程序控制权将被恢复,因此我们可以继续进行绿色闪烁。
我们通过导入machine
和utime
库来开始我们的脚本,就像我们之前一样。
LED段和红色按钮的定义和之前的脚本一样。LED在程序启动时被关闭。
然后我们定义一个函数,这是我们的中断处理程序,叫做 "int_handler"。在这个函数中,我们做了以下工作。
关闭中断,这样我们就不会有多个中断了。
将 "中断检测 "打印到Shell上
打开红色LED段。
关闭绿色LED段。
睡眠四秒。
关闭红色段。
重新建立中断
退出
处理函数后的那一行将中断 "粘 "到我们定义为红色按钮输入的引脚上。需要注意的是,它指定了 "IRQ_RISING",这意味着如果输入从0(地)上升到1(3.3伏),它将触发一个中断。这与我们红色按钮的接线方式一致。
在True循环中,我们只需使用定义为输出的任何GPIO引脚可用的 "toggle "功能来闪烁LED。
将它发送到Pico上,观察RGB LED,它应该开始闪烁绿色。观察一段时间,然后按下红色按钮。LED应该变成红色,Shell应该显示 "Interrupt Detected"。四秒钟后,绿色闪烁将重新开始。
既然我们一直在研究开关和LED,我们不妨把它们结合起来,再编写一个简单的脚本。
# 树莓派 Pico Switch & RGB LED Demo
# switch-led-demo.py
# RED LED - Pico GPIO 10 - Pin 14
# GREEN LED - Pico GPIO 11 - Pin 15
# BLUE LED - Pico GPIO 14 - Pin 19
# BLACK BUTTON - Pico GPIO 2 - Pin 4
# DroneBot Workshop 2021
# https://dronebotworkshop.com
import machine
import utime
led_red = machine.Pin(10, machine.Pin.OUT)
led_green = machine.Pin(11, machine.Pin.OUT)
led_blue = machine.Pin(14, machine.Pin.OUT)
led_red.value(0)
led_green.value(0)
led_blue.value(0)
button_black = machine.Pin(2, machine.Pin.IN, machine.Pin.PULL_UP)
while True:
if button_black.value() == 0:
led_red.value(1)
led_green.value(0)
led_blue.value(0)
utime.sleep(1)
led_red.value(0)
led_green.value(1)
led_blue.value(0)
utime.sleep(1)
led_red.value(0)
led_green.value(0)
led_blue.value(1)
utime.sleep(1)
led_red.value(0)
led_green.value(0)
led_blue.value(0)
这个很简单,现在大家应该对它的操作很熟悉了。我们用machine
库函数定义RGB LED和黑色按钮。
记住,黑色按钮是由我们定义的上拉保持HIGH的,当按钮被按下时,它就会变LOW,因为另一边是接地线的。
所以在True循环中,我们寻找一个 "0 "的值,以表示按钮被按下。一旦我们检测到这个条件,我们就会通过它们的颜色循环LED段。
正如我所说,很简单的东西。
现在我们来谈谈模拟输入。
树莓派 Pico有三个模拟输入,它们都有12位的分辨率。
这三个输入端如下。
GPIO 26 - ADC0 (31针)
GPIO 27 - ADC1 (针脚 32)
GPIO 28 - ADC2 (针脚34)
还有第四个ADC用于内部温度传感器。
在我们的测试中,我们将使用一个电位器在模拟输入端呈现一个可变电压,然后我们将读取该电压。我们将使用ADC0作为我们的电位计输入,但你也可以使用其他两个中的一个。
请注意,虽然我将23号针脚显示为地线,这只是为了方便,但你可以使用任何Pico地线针脚。在33号针脚处还有一个特殊的模拟地,你可以使用。在我的面包板上,我将33号针脚与其他一些地线相连。
我们要做的第一个实验是简单地读取我们在模拟输入端得到的值,这个值应该根据我们电位器的位置而波动。
# 树莓派 Pico Analog Input Test
# analog-input.py
# POT - Pico GPIO 26 ADC0 - Pin 32
# DroneBot Workshop 2021
# https://dronebotworkshop.com
import machine
import utime
potentiometer = machine.ADC(26)
while True:
print(potentiometer.read_u16())
utime.sleep(2)
这是一个简单的脚本,像往常一样,首先导入用于GPIO操作的machine
库和用于时间函数的utime
库。
然后我们定义我们的电位器连接。请注意我们如何使用 "ADC "来表示我们要将GPIO 26针作为模拟输入。当然这只适用于具有模拟输入能力的三个GPIO引脚。
在True循环中,我们只需打印从电位器上得到的值,然后延迟几秒钟再做一次。
需要注意的是,我们用 "read_u16 "函数得到的值的类型是一个无符号的16位整数。这意味着它将在0和65,535之间变化,而不是你可能期望从12位ADC中得到的4095。
这可能看起来很奇怪,但正如我们将在下一个脚本中看到的那样,能够传递具有相同数值数据类型的值实际上是有用的。
运行脚本并观察Shell,你应该会看到那里的数值随着你移动电位器轴而改变。
让我们在之前的脚本基础上进行扩展,使用电位器的输出来控制LED的亮度。
当然,我们将使用PWM进行控制,这个任务在MicroPython中非常简单。
# 树莓派 Pico LED PWM Test
# led-pwm.py
# POT - Pico GPIO 26 ADC0 - Pin 32
# RED LED - Pico GPIO 10 - Pin 14
# DroneBot Workshop 2021
# https://dronebotworkshop.com
import machine
import utime
led_red = machine.PWM(machine.Pin(10))
potentiometer = machine.ADC(26)
led_red.freq(1000)
while True:
led_red.duty_u16(potentiometer.read_u16())
在这个脚本中需要注意的一个关键项目是我们定义 "led_red "的方式。我们将其定义为 "PWM",而不是输出。
电位器的定义与上一个脚本中的方式完全相同。
现在我们已经给输出赋予了 "PWM "的属性,它继承了许多其他参数。其中之一是PWM频率,我们将其设置为1000 Hz。
在true循环中,我们不断地从电位器中获取无符号的16位值,并将其传递给LEDs占空比,也方便地指定为无符号的16位整数。
这就说明了两者保持相同的编号方案的价值,不需要将模拟值,真的是0到4095,映射到占空比,真的是0到100。
运行程序,你应该可以顺利地控制红色LED段的亮度。
我们将进行的下一个实验是将一个OLED显示器连接到我们的Pico上,当然,也可以在上面打印一些东西。
我们将使用 I2C 显示屏,因此我们也将看到 Pico 如何使用 I2C 连接工作。记住,Pico有两条I2C总线。
我们的OLED是标准的1602型OLED显示器,到处都有。如果你愿意,也可以使用与我的显示屏尺寸不同的显示屏,只需在代码中更改尺寸即可。
这是我们如何把这些东西都挂起来的,只有四根线。
我们的显示器需要一个库,我们可以使用Thonny ID安装。你可能会发现在全菜单模式下比在基本模式下更容易,但这两种方式都可以。
点击 "工具 "菜单
点击 "管理包"
搜索 "ssd1306"
找到 "ssd1306.py "并安装它。
现在我们已经安装了库,我们可以看一下演示OLED显示屏的脚本。
# 树莓派 Pico OLED Display Test
# Uses ssd1306 module
# display-ssd1306-test.py
# DroneBot Workshop 2021
# https://dronebotworkshop.com
import machine
import utime
sda=machine.Pin(20)
scl=machine.Pin(21)
i2c=machine.I2C(0, sda=sda, scl=scl, freq=400000)
from ssd1306 import SSD1306_I2C
oled = SSD1306_I2C(128, 32, i2c)
print(i2c.scan())
oled.text('Welcome to the', 0, 0)
oled.text('Pi Pico', 0, 10)
oled.text('Display Demo', 0, 20)
oled.show()
utime.sleep(4)
oled.fill(1)
oled.show()
utime.sleep(2)
oled.fill(0)
oled.show()
while True:
oled.text("Hello World",0,0)
for i in range (0, 164):
oled.scroll(1,0)
oled.show()
utime.sleep(0.01)
我们的 OLED 显示屏是一个 I2C 设备,所以你会注意到,在脚本的开头,我们将两个 GPIO 引脚定义为 SDA (GPIO 20) 和 SCL (GPIO 21)。
Pico有两条I2C总线,你可以使用几种不同的GPIO引脚来连接它们。但它们并不是随便的引脚,例如某些引脚被指定为总线0的SDA,只有它们才能用于SDA总线0。
然后我们使用机器库的I2C函数定义一个I2C连接。我们需要给它提供以下参数。
I2C总线号,在我们的例子中是0。
SDA引脚
SCL引脚
I2C总线频率--在我们的例子中是400KHz。
然后我们添加OLED库,并创建一个I2C OLED对象。我们将大小参数和I2C连接信息传递给它。
注意,我们没有传递I2C地址。SD1306 OLED显示器有一个固定的I2C地址,所以我们不需要指定它。
不过,我在这里添加了一行与显示器无关的内容,但可以让你扫描I2C总线,并打印出它发现占用的地址。请注意,在Shell中打印出来的是十进制,而不是你更可能习惯看到的十六进制。
回到OLED脚本!
我们开始在显示屏上打印,几行文字。注意我们如何指定每行开始的像素位置。
实际上,我们并没有直接打印到显示屏上,而是将数据发送到一个缓冲区。oled.show()
这一行将把该缓冲区的数据传输到显示器上。
在打印完欢迎信息并按住它四秒钟后,我们再执行oled.fill(1)
。这将打开显示器中的每一个像素,或者更准确地说,是缓冲区中的每一个像素。然后我们做一个oled.show()
来显示填充。
我们将填充物保持在显示屏上两秒钟,然后执行oled.fill(0)
,当我们显示它时,它将关闭显示屏中的每个像素。
现在进入True循环。
我们再次输入一些文本,经典的 "Hello World"。但我们没有进行 "显示 "来显示它,而是开始一个for-loop。在这个循环中,我们使用led.scroll(1,0)将显示水平移动1像素(垂直移动0像素,这就是另一个参数)。
然后我们在屏幕上显示,然后休眠一段很短的时间。然后我们再做一次。
结果将是显示屏在屏幕上滚动。你可以在for-loop中使用参数来改变它。
将脚本加载到你的Pico上,然后观看显示。你应该看到欢迎文字,然后是显示填充,然后是空。之后,只要你让实验运行,滚动的 "Hello World "就会继续。
微控制器比较流行的应用之一是驱动一个或几个直流电动机。
这是通过使用H-Bridge来实现的,H-Bridge是一种功率晶体管或MOSFET的排列方式,可以处理电机电流,同时允许你控制电机的方向和速度。
我们将只用一个电机来实现这一点。我们将使用TB6612FNG H-Bridge和树莓派 Pico来控制一个小型直流电机。
TB6612FNG H-Bridge是我们之前使用过的,一款基于MOSFET的H-Bridge,相比老款备用的L-298N有很多性能上的优势。
该设备其实有两个通道,我们只用通道A来演示。
通道A有三个输入。
AI1 - 方向和模式
AI2 - 方向和模式
PWMA - 一个PWM输入,用于控制电机速度。
在它们之间,AI1和AI2引脚控制电机方向和模式。模式包括短制动和停止模式。在我们的简单演示中,我们将只处理方向模式。
TB6612FNG H-Bridge在板子的另一侧还有电源和电机的连接。
下面是我们将使用TB6612FNG H-Bridge和树莓Pico的连接方式。
请注意,由于我使用的是6V电机,我已经为它提供了一个6V电源。不要试图使用Pico的输出电压来为你的电机供电,单独的电源是必要的。我使用了四节AA型电池,这是一种简单而安全的安排。
电机的极性其实并不重要,它只是决定了哪条路是向前的,哪条路是向后的。
一旦它被全部连接起来,我们就需要一些代码来运行它。我建议这样做。
# 树莓派 Pico Motor Test
# motor-test.py
# POT - Pico GPIO 26 ADC0 - Pin 32
# RED BUTTON - Pico GPIO 15 - Pin 20
# BLACK BUTTON - Pico GPIO 2 - Pin 4
# RED LED - Pico GPIO 10 - Pin 14
# GREEN LED - Pico GPIO 11 - Pin 15
# BLUE LED - Pico GPIO 14 - Pin 19
# DroneBot Workshop 2021
# https://dronebotworkshop.com
import machine
import utime
potentiometer = machine.ADC(26)
mtr_AI1 = machine.Pin(8, machine.Pin.OUT)
mtr_AI2 = machine.Pin(7, machine.Pin.OUT)
mtr_PWMa = machine.PWM(machine.Pin(6))
button_red = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_black = machine.Pin(2, machine.Pin.IN, machine.Pin.PULL_UP)
led_red = machine.Pin(10, machine.Pin.OUT)
led_green = machine.Pin(11, machine.Pin.OUT)
led_blue = machine.Pin(14, machine.Pin.OUT)
led_red.value(0)
led_green.value(0)
led_blue.value(1)
mtr_PWMa.freq(50)
mtr_AI1.value(1)
mtr_AI2.value(0)
while True:
mtr_PWMa.duty_u16(potentiometer.read_u16())
if button_red.value() == 1:
mtr_AI1.value(0)
mtr_AI2.value(1)
led_red.value(1)
led_green.value(0)
led_blue.value(0)
if button_black.value() == 0:
mtr_AI1.value(1)
mtr_AI2.value(0)
led_red.value(0)
led_green.value(1)
led_blue.value(0)
utime.sleep(0.25)
我们要利用电位器、两个开关和RGB LED,以及电机控制器。电位器将控制电机的速度,开关将控制电机的方向,而LED将用彩色指示灯显示当前的方向。
我们使用我们的之前的两个库,并像以前一样设置电位器。
接下来,我们将Pico与TB6612FNG H-Bridge的连接定义为输出。GPIO 6上的PWMA输出被定义为PWM,它将控制电机速度。
LED和按钮的设置与之前相同。
PWM频率设置为50Hz,这是一个任意的选择。随意实验一下,看看是否能提高电机性能。
电机AI1和AI2输入被设置为正向旋转,所以电机将以正向启动。请注意,当我们启动时,RGB LED的蓝段也会被打开。
在True循环中,我们读取电位器的值,并将其传递给电机PWM信号,以控制电机的速度。我们还要看按钮的状态。
如果红色按钮被按下,我们设置AI1和AI2信号,使电机反转。我们也会点亮红色LED段。
如果黑色按钮被按下,我们设置电机方向正向,并打开绿色LED段。
加载、检查代码。它应该用一个蓝色的LED启动,你应该能够控制电机的速度。按下按钮可以控制方向,还可以改变 LED 的颜色。
剩下的就是把所有的东西放在一起做一个大的最终演示。这一点我们已经做得不远了,因为在上一个脚本中,我们使用了所有的东西,除了OLED显示屏。
所以让我们把OLED显示屏添加到这个组合中。下面是我们需要做的代码。
# 树莓派 Everything Test
# everything.py
# POT - Pico GPIO 26 ADC0 - Pin 32
# RED BUTTON - Pico GPIO 15 - Pin 20
# BLACK BUTTON - Pico GPIO 2 - Pin 4
# RED LED - Pico GPIO 10 - Pin 14
# GREEN LED - Pico GPIO 11 - Pin 15
# BLUE LED - Pico GPIO 14 - Pin 19
# DroneBot Workshop 2021
# https://dronebotworkshop.com
import machine
import utime
potentiometer = machine.ADC(26)
mtr_AI1 = machine.Pin(8, machine.Pin.OUT)
mtr_AI2 = machine.Pin(7, machine.Pin.OUT)
mtr_PWMa = machine.PWM(machine.Pin(6))
button_red = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_DOWN)
button_black = machine.Pin(2, machine.Pin.IN, machine.Pin.PULL_UP)
led_red = machine.Pin(10, machine.Pin.OUT)
led_green = machine.Pin(11, machine.Pin.OUT)
led_blue = machine.Pin(14, machine.Pin.OUT)
sda=machine.Pin(20)
scl=machine.Pin(21)
i2c=machine.I2C(0, sda=sda, scl=scl, freq=400000)
from ssd1306 import SSD1306_I2C
oled = SSD1306_I2C(128, 32, i2c)
oled.text('Pico Motor Test', 0, 0)
oled.show()
utime.sleep(2)
led_red.value(1)
led_green.value(0)
led_blue.value(0)
utime.sleep(2)
led_red.value(0)
led_green.value(1)
led_blue.value(0)
utime.sleep(2)
led_red.value(0)
led_green.value(0)
led_blue.value(1)
mtr_PWMa.freq(50)
mtr_AI1.value(1)
mtr_AI2.value(0)
while True:
speedvalue = int((potentiometer.read_u16())/500)
mtr_PWMa.duty_u16(potentiometer.read_u16())
if button_red.value() == 1:
mtr_AI1.value(0)
mtr_AI2.value(1)
led_red.value(1)
led_green.value(0)
led_blue.value(0)
if button_black.value() == 0:
mtr_AI1.value(1)
mtr_AI2.value(0)
led_red.value(0)
led_green.value(1)
led_blue.value(0)
oled.fill_rect(1,15,speedvalue,25,1)
oled.show()
oled.fill_rect(1,15,speedvalue,25,0)
utime.sleep(0.25)
现在你应该能认出这段代码的大部分内容了,基本上就是之前的脚本,加上了I2C OLED显示屏的库和设置。除此之外,前几行都是一样的,都是LED颜色的序列,一切设置好后,会有一个Display print。
在True循环中,我们看到正在计算一个名为 "speedvalue "的整数。这个变量将用于设置OLED上条形图显示的大小。
红色和黑色的按钮和之前的操作完全一样。
然后,OLED在其标题线下画一个矩形,并填入矩形。矩形的长度由 "speedvalue "决定,所以随着速度的增加,矩形会变长。
从某种意义上说,我们是把OLED当做一个粗略的速度指示器,或者说是一个速度表!
装上所有的东西,看演示效果。它的操作应该和之前的实验一样,只是这次我们除了有一个显示电机速度的显示器外,还有一个指示其方向的RGB LED。
到目前为止,我们所做的一切都是从 Thonny IDE 将程序加载到 Pico 上运行的。
但是,一旦你开发了程序,你就会希望它能够独立运行,由 microUSB 端口或通过 Pico VSYS 电源输入供电。
你的程序或程序已经存储在 Pico 上。那么我们如何让它在开机时运行程序呢?
答案是,我们更改程序名称!
当 Pico 启动时,它会查找名为 main.py 的程序。如果它找到了它,就会加载它并在启动时运行它。
因此,如果你想让你的程序在无人看管的情况下运行,你需要将其保存为main.py。稍后,如果你愿意,你可以将main.py改成其他程序,或者完全删除它。
首先将你希望在启动时运行的程序加载到Thonny IDE中。现在点击 "文件",然后选择 "另存为"。
你会被问到是否要保存在本地计算机上或Pico上,你肯定要保存在Pico上。
现在把你的程序保存为 "main.py"。就像这样,全部用小写。
现在从电脑上拔下 Pico 的插头,并将其插入合适的电源,如 USB 适配器。你会看到Pico重新开机,并运行你保存为 "main.py "的程序。
这显然只是树莓派Pico的开始。
我很希望看到PlatformIO和Arduino IDE能够为树莓派 Pico提供支持,因为目前为Pico创建C++程序的方法有些繁琐,特别是对于初学者来说。
但它是进入MicroPython的一个很好且廉价的入口,你会在这里看到更多的东西。
所以尽快拿起Pico开始实验吧!
Pico代码[1] - 本文中使用的所有MicroPython代码,放在一个方便的ZIP文件中。
树莓派 Pico[2] - 树莓派 Pico的官方公告页面。
Pico Pinout[3] - Pico Pinout的树莓派 PDF文件。
Pico Datasheet[4] - 包含Pico技术规格和评级的PDF文档。
RP2040 Datasheet[5] - 包含RP2040微控制器所有规格的PDF文件。警告,这是一个非常大的文档
Pico MicroPython SDK[6] - 在树莓派Pico上使用MicroPython的良好PDF指南。
Pico C++ SDK[7] - Pico上的C++的PDF指南。这也是一个非常大的文档。
译文首发于DF创客社区:https://mc.dfrobot.com.cn/thread-308442-1-1.html
原文链接:https://dronebotworkshop.com/pi-pico/
转载请注明出处与作者信息文中所有的PDF文档获取两种方式:1、直接复制下方参考资料内的链接,粘贴到浏览器下载;2、公众号后台回复“Pico文档”获取,我们帮大家打包好了一份。同时,也欢迎小伙伴们在下方留言区一起讨论!
[1]
Pico代码: http://dbot.ws/picocode
[2]树莓派 Pico: https://www.raspberrypi.org/blog/raspberry-pi-silicon-pico-now-on-sale/
[3]Pico Pinout: https://datasheets.raspberrypi.org/pico/Pico-R3-A4-Pinout.pdf
[4]Pico Datasheet: https://datasheets.raspberrypi.org/pico/pico-datasheet.pdf
[5]RP2040 Datasheet: https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf
[6]Pico MicroPython SDK: https://datasheets.raspberrypi.org/pico/raspberry-pi-pico-python-sdk.pdf
[7]Pico C++ SDK: https://datasheets.raspberrypi.org/pico/raspberry-pi-pico-c-sdk.pdf