将 Raspberry Pi Pico 变成温度数据记录设备,并将其与计算机断开连接,使其完全便携。

在本书中,您一直在使用通过微型 USB 端口连接到 Raspberry Pi 或其他计算机的 Raspberry Pi Pico。 但是,与所有微控制器一样,您的 Pico 没有理由必须以这种方式进行连接:它是一个功能齐全的独立系统,具有处理能力、内存以及独立工作所需的一切。 在本章中,您将学习如何使用文件系统来创建、写入和读取文件,从而允许您将 Pico 放在您喜欢的任何位置并让它记录数据以供以后访问——将其变成所谓的 数据记录仪。 为此,您只需要 Pico,如果您想在远离 Raspberry Pi 的地方使用它,则需要一个微型 USB 充电器或电池组; 完成本章后,如果您想扩展您的项目,您可以连接其他模拟传感器。

文件系统是 Pico 存储您编写的所有程序的地方。它的功能等同于 Raspberry Pi 中的 microSD 卡,或笔记本电脑或台式计算机中的硬盘驱动器或固态驱动器:它是一种非易失性存储形式,这意味着您保存在那里的任何内容即使在您拔下 Pico 的微型 USB 电缆。 将 Pico 连接到 Raspberry Pi 并加载 Thonny(如果尚未打开)。单击“打开”图标,然后在出现的弹出窗口中单击“Raspberry Pi Pico”。您将看到迄今为止编写的所有程序的列表,这些程序存储在 Pico 的文件系统中。您现在不会打开一个,因此请单击取消。 单击 Shell 区域底部的 以开始在交互模式下使用 Pico。类型:

file = open("test.txt", "w")

这告诉 MicroPython 打开一个名为 test.txt 的文件进行写入——指令的“w”部分。当您在行尾按 ENTER 时,您不会看到任何打印到 Shell 区域的内容,因为尽管您已经打开了文件,但您还没有对其进行任何操作。类型:

file.write("Hello, File!")

当您在该行的末尾按 ENTER 时,您会看到数字 12 出现(图 9-1)。这是 MicroPython 向您确认它已将 12 个字节写入您打开的文件。数一数你写的消息中的字符数:包括字母、逗号、空格和感叹号,一共有十二个——每个占一个字节。

当您写入文件时,您需要关闭它——这可确保您告诉 MicroPython 写入的数据实际上已写入文件系统。如果您不关闭文件,则数据可能尚未写入 - 有点像在 LibreOffice Writer 或其他文字处理器中写信而忘记保存。类型:

file.close()

您的文件现在安全地存储在 Pico 的文件系统中。单击 Thonny 工具栏上的打开图标,单击“Raspberry Pi Pico”,然后滚动文件列表,直到找到 test.txt。单击它,然后单击确定将其打开:您将在新的 Thonny 选项卡中看到您的消息弹出。 不过,您不必使用“打开”图标来读取文件:您可以直接在 MicroPython 中执行此操作。单击回壳区域的底部并键入:

file = open("test.txt")

你会注意到这一次没有“w”:那是因为你将读取它而不是写入文件。您可以将“w”替换为“r”,但 MicroPython 默认以读取模式打开文件——因此只需关闭该部分指令即可。 接下来,键入:

file.read()

您将看到写入文件的消息打印到 Shell 区域(图 9-2)。恭喜:您可以在 Pico 的文件系统上读写文件了!

在完成之前,请记住关闭文件——读取文件后正确关闭文件不像写入文件时那么重要,但无论如何都要养成一个好习惯:

file.close()

现在您知道如何打开、写入和读取文件,您拥有在 Pico 上构建数据记录器所需的一切。 单击“新建”图标以在 Thonny 中启动一个新程序,然后键入以下内容启动您的程序:

import machine 
import utime
sensor_temp = machine.ADC(machine.ADC.CORE_TEMP)
conversion_factor = 3.3 / (65535)
reading = sensor_temp.read_u16() * conversion_factor 
temperature = 27 - (reading - 0.706)/0.001721

您可能会认出这个代码:它与您在第 8 章中用于读取 Pico 板载温度传感器的代码相同。 来自传感器的读数是您将要记录到文件系统的数据,因此您不想像以前那样简单地将它们打印出来。 首先通过在底部添加以下行来打开一个文件进行写入:

file = open("temps.txt", "w")

如果文件系统上不存在该文件,则会创建它; 如果是,它会覆盖它—— 清空它的内容,为你写新数据做好准备。

警告 在 MicroPython 中打开一个用于写入的文件将删除您已经存储在其中的任何内容。 如果您想保留它,请务必确保您已打开文件进行阅读并将内容保存在某处!

现在您需要向文件中写入一些内容——温度传感器的读数:

file.write(str(temperature))

不像之前那样在引号中写一个固定的字符串,这次你是将变量温度——它是一个浮点数,换言之,一个带有小数点的数字——转换成一个字符串,然后写成 到文件。 和以前一样,要确保写入数据,您需要关闭文件:

file.close()

单击运行图标并将您的程序作为 Datalogger.py 保存到 Raspberry Pi Pico。 该程序只需几秒钟即可运行; 当 »

> 提示再次出现在 Shell 区域的底部时,单击进入它并键入以下内容以打开并阅读您的新文件:

<

code python> file = open(“temps.txt”) file.read() file.close() </code>

您将看到程序读取的温度读数出现在 Shell 中(图 9-3)。 恭喜:您的数据记录器工作正常!

但是,仅记录单个读数(数据)的数据记录器并没有那么有用。为了使您的数据记录器更强大,您需要对其进行修改,使其需要大量读数。再次单击运行,并再次读取文件:。

file = open("temps.txt") 
file.read() 
file.close()

请注意文件中仍然只有一个读数。当您的程序再次打开文件进行写入时,它会自动擦除其先前的内容——这意味着每次您的程序运行时,它都会擦除文件并存储单个读数。 要解决这个问题,您需要修改您的程序。首先单击并拖动鼠标光标以突出显示线条:

reading = sensor_temp.read_u16() * conversion_factor 
temperature = 27 - (reading - 0.706)/0.001721

当您突出显示两行时 - 确保不要错过任何部分 - 松开鼠标按钮并按键盘上的 CTRL+X 剪切线;你会看到它们从程序中消失了。 接下来,转到程序底部并删除所有内容:

file = open("temps.txt", "w")

敲入:

while True:

在该行的末尾按 ENTER 后,按住 CTRL 键并按 V 键粘贴您之前剪切的两行。 你会看到它们出现,这样你就不必输入它们了——但只有第一行会正确缩进,所以它作为无限循环的一部分嵌套 你刚打开。 通过单击将光标放在下面一行的开头并按空格键四次以正确缩进该行,然后将光标移动到该行的末尾并 按 ENTER。 键入以下行,确保正确缩进:

file.write(str(temperature))

不过,现在你需要做一些新的事情。 如果您像以前一样关闭文件,则在不重新打开文件并擦除其内容的情况下将无法再次写入文件。 如果您不关闭文件,数据将永远不会真正写入文件系统。

解决方案:刷新文件,而不是关闭它。 类型:

file.flush()

当您写入文件但数据实际上并未写入文件系统时,它存储在所谓的缓冲区中——一个临时存储区域。 当您关闭文件时,缓冲区将在称为刷新的过程中写入文件。 使用 file.flush() 等效于 file.close(),因为它将缓冲区的内容刷新到文件中——但与 file.close() 不同的是,文件保持打开状态,以便您稍后向其中写入更多数据。 现在你只需要在阅读之间暂停你的程序:

utime.sleep(10)

您完成的程序将如下所示:

import machine import utime
sensor_temp = machine.ADC(machine.ADC.CORE_TEMP)
conversion_factor = 3.3 / (65535) file = open("temps.txt", "w") while True:
reading = sensor_temp.read_u16() * conversion_factor temperature = 27 - (reading - 0.706)/0.001721 file.write(str(temperature))
file.flush()
utime.sleep(10)

单击运行图标并数到 60,然后单击停止图标。 现在打开并阅读您的文件 脚本区:

file = open("temps.txt") 
file.read() 
file.close()

好消息是你的程序已经运行了,并且你已经在一个文件中记录了多个读数——大约六个,根据你计算的速度给出或取一些。 坏消息是它们都被挤在了一条线上(图 9-4)——这使得阅读变得困难。 要解决该问题,您需要在将数据写入文件时对其进行格式化。 回到程序中的 file.write() 行,修改它,使其看起来像:

file.write(str(temperature) + "\n")

加号 (+) 告诉 MicroPython 您要附加后面的内容,将两个字符串连接在一起; “\n” 是一个称为控制字符的特殊字符串——它相当于按下 ENTER 键,这意味着数据日志中的每一行都应该在自己单独的行上。 单击运行图标,再次数到 60,然后单击停止。 打开并阅读您的文件:

file = open("temps.txt") 
file.read() 
file.close()

您已经取得了进步,但仍然不对:\n 控制字符的作用不像按 ENTER 键,而是打印为两个可见字符(图 9-5,背面)。 那是因为

file.read() 

引入了文件的原始内容,并没有尝试为屏幕格式化它。 要解决格式问题,您需要将读取的文件包装在一个 print() 函数中:

file = open("temps.txt") 
print(file.read()) 
file.close()

这一次,您会看到每个读数都单独打印出来,格式整齐且易于阅读(图 9-6)。 恭喜:您已经构建了一个数据记录器,它可以获取多个读数并将它们存储在 Pico 的文件系统中!

文件存储 Pico 的文件系统大小为 1.375MiB,这意味着它可以容纳 1,441,792 字节的数据。 您保存在 Pico 上的每个文件,包括数据记录器的存储文件,都会占用空间。 填充存储需要多长时间取决于您拥有多少其他文件以及您的数据记录器保存读数的频率:每 10 秒每次读取 9 个字节,您将在大约 18.5 天内填充 1.375MiB; 如果你每分钟读一次,你的数据记录器可以运行大约 111 天; 如果您每小时只阅读一次,您的数据记录器可以运行超过 18 年!

无论您的 Pico 文件系统是否连接到您的 Raspberry Pi 或另一台计算机,它都可以正常工作。如果您有微型 USB 电源充电器或带有微型 USB 电缆的 USB 电池组,您可以将数据记录器带到您家中的任何房间并让它自行运行——但您需要一种方法来运行您的程序无需单击 Thonny 中的运行图标。 为了在没有连接计算机的情况下使用 - 称为无头操作 - 您可以将程序保存在一个特殊的文件名下:main.py。当 MicroPython 在其文件系统中找到一个名为 main.py 的文件时,它会在每次开机或重置时自动运行该文件——您无需单击运行。 在 Thonny 中,如果程序正在运行,则停止后,单击文件菜单,然后单击另存为。在出现的弹出窗口中单击“Raspberry Pi Pico”,然后在单击“保存”之前键入“main.py”作为文件名。起初,似乎什么都不会发生:那是因为 Thonny 将您的 Pico 置于交互模式,这会阻止它自动运行您刚刚保存的程序。 要强制程序运行,请单击 Shell 区域底部并按住 CTRL 键,按 D 键,然后松开 CTRL 键。这会向您的 Pico 发送一个软重置命令,这将使其退出交互模式并启动程序运行。找点别的事情做五分钟左右,然后按停止图标并打开您的数据日志:

file = open("temps.txt") 
print(file.read()) 
file.close()

即使您没有单击“运行”图标,您也会看到温度读数列表——因为当 Pico 重置时,您的程序会自动运行。 如果您有微型 USB 充电器或 USB 电池组,请将 Pico 与 Raspberry Pi 断开连接,将其带到另一个房间,然后将其连接到充电器或电池组。 把它放在那里十分钟,然后回来拔掉它。 将它带回您的 Raspberry Pi,重新插入,然后再次阅读您的文件:您将看到另一个房间的读数,证明您的 Pico 可以在没有您的 Raspberry Pi 帮助的情况下完美运行。 恭喜:您的数据记录器现在功能齐全且完全便携,可以随身携带,随时随地记录数据!

警告 每次 Pico 开机时,您的数据记录器程序都会运行,而无需连接到 Thonny。 如果你不想发生这种情况,你可以简单地在 Thonny 中打开 main.py 并在再次保存之前删除其中的所有代码。 使用空的 main.py,您的 Pico 将再次坐下等待指令。

挑战 您能否更改程序以记录来自连接到 Pico ADC 引脚之一的外部传感器的数据? 你可以让你的程序在文件的开头写一个标题,这样更容易看出这些值的含义吗? 你能写一个程序来记录按下按钮开关的次数吗? 您能想出一种方法,例如复制粘贴,将数据导入 LibreOffice Calc 或其他电子表格程序以创建图表吗?