差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
mp_temp_gauge [2021/10/04 14:17] gongyusu |
mp_temp_gauge [2022/02/26 21:29] (当前版本) gongyusu [5. 用PWM使LED衰减] |
||
---|---|---|---|
行 1: | 行 1: | ||
## 测量温度 | ## 测量温度 | ||
- | 使用 Raspberry Pi Pico 的内置 ADC 转换模拟输入,并读取其内部温度传感器 | + | 使用[[rpi_pico|Raspberry Pi Pico]]的内置[[ADC]]转换模拟输入,并读取其内部[[temp_sensor|温度传感器]] |
- | 在前面的章节中,您一直在使用 Raspberry Pi Pico 上的数字输入。数字输入打开或关闭,二进制状态。当按下按钮开关时,它会将引脚从低、关、高、开改变;当被动红外传感器检测到运动时, | + | 在前面的章节中,我们一直在使用Raspberry Pi Pico上的数字输入。数字输入只有打开(on)或关闭(off)两种状态,当按下按钮开关时,它会将引脚从低(关)到高(开)改变;当被动红外传感器检测到运动时,它也一样。 |
- | 它也一样。 | + | |
- | 不过,您的 Pico 可以接受另一种类型的输入信号:模拟输入。而数字是 | + | 不过,我们的[[rpi_pico|Pico]]可以接受另一种类型的输入信号:模拟输入, 数字信号是只有打开或关闭两种状态,而模拟信号可以是从完全关闭到完全打开的任何值 - 一系列可能的值。模拟输入用于从音量控制到气体、湿度和温度传感器的所有内容,它们通过称为[[adc|模数转换器 (ADC)]]的硬件工作。 |
- | 只有打开或关闭,模拟信号可以是从完全关闭到完全打开的任何值——一系列可能的值。模拟输入用于从音量控制到气体、湿度和温度传感器的所有内容,它们通过称为模数转换器 (ADC) 的硬件工作。 | + | |
- | 在本章中,您将学习如何在 Pico 上使用 ADC - 以及如何利用其内部温度传感器来构建数据记录热量测量小工具。您还将学习一种创建类似模拟输出的技术。为此,您需要 Pico;任何颜色的 LED 和 330 Ω 电阻器;一个 10 kΩ 电位器;以及一系列公对公 (M2M) 跳线。您还需要一根微型 USB 电缆,并将 Pico 连接到 Raspberry Pi 或其他运行 Thonny MicroPython IDE 的计算机。 | + | 在本章中,我们将学习如何在[[rpi_pico|Pico]]上使用[[ADC]],以及如何利用其内部[[temp_sensor|温度传感器]]来构建数据记录热量测量小工具, 我们还将学习一种创建类似模拟输出的技术。 |
+ | |||
+ | ### 1. 模数转换器 | ||
+ | Raspberry Pi Pico的[[RP2040]]微控制器是一种数字设备,就像所有主流微控制器一样, 它由数千个晶体管、类似开关的微型设备组成,这些设备可以打开或关闭。因此,我们的Pico无法真正理解模拟信号 - 可以是完全关闭和完全打开之间的任何数值 - 不依赖额外的硬件:模数转换器(ADC )。 | ||
+ | |||
+ | 顾名思义,[[adc|模数转换器]]将模拟信号转换为数字信号。不过Pico的ADC在板上找不到,因为它是内置于[[RP2040]]芯片内部的,其实许多[[mcu|微控制器]]都有自己的[[ADC]],就像[[RP2040]]一样,而那些没有的可以使用连接到一个或多个数字输入的外部ADC上。 | ||
+ | |||
+ | [[ADC]]有几个关键的技术指标: | ||
+ | * 以数字位为单位的分辨率; | ||
+ | * 以sps为单位的转换率 | ||
+ | * 通道数 - 它可以同时接受和转换多少路模拟信号; | ||
+ | |||
+ | [[rpi_pico|Pico]]中的[[ADC]]具有12位的分辨率,这意味着它能够将输入端的模拟信号转换为从0到4095的数字信号,尽管在MicroPython中的处理范围为16位 - 从0到65,535,因此它的行为与其它 MicroPython微控制器上的ADC相同。RP2040具有4个连接到GPIO引脚的通道:GP26、GP27、GP28和GP29,对应于模拟通道0、1、2和3,它们也被称为GP26_ADC0、GP27_ADC1、GP28_ADC2、GP29_ADC3。其实还有第5个ADC通道,它连接到RP2040内置温度传感器,在树莓派Pico核心板/硬禾Pico核心板上GP26、GP27和GP28被引出到外扩的管脚上,GP29则被用于监测板上电压,不能用户扩展使用。 | ||
+ | |||
+ | {{ :pico_adc.png |}}<WRAP centeralign>树莓派RP2040控制器内部的ADC </WRAP> | ||
- | 模数转换器 | ||
- | Raspberry Pi Pico 的 RP2040 微控制器是一种数字设备,就像所有主流微控制器一样:它由数千个晶体管、类似开关的微型设备组成,这些设备可以打开或关闭。因此,您的 Pico 无法真正理解模拟信号 - 可以是完全关闭和完全打开之间的任何频谱 - 不依赖额外的硬件:模数转换器(ADC )。 | ||
- | 顾名思义,模数转换器将模拟信号转换为数字信号。无论您仔细观察,您都不会在 Pico 上看到 ADC:它内置于 RP2040 本身中。许多微控制器都有自己的 ADC,就像 RP2040 一样,而那些没有的可以使用连接到一个或多个数字输入的外部 ADC。 | ||
- | ADC 有两个关键特性:以数字位为单位的分辨率,以及它的通道,或者它可以同时接受和转换多少模拟信号。 Pico 中的 ADC 具有 12 位的分辨率,这意味着它可以将模拟信号转换为数字信号作为范围从 0 到 4095 的数字——尽管这是在 MicroPython 中处理的,转换为范围从 0 到 16 位的数字65,535,因此它的行为与其他 MicroPython 微控制器上的 ADC 相同。它具有三个连接到 GPIO 引脚的通道:GP26、GP27 和 GP28,对于模拟通道 0、1 和 2,它们也称为 GP26_ADC0、GP27_ADC1 和 GP28_ADC2。还有第四个 ADC 通道,它连接到RP2040内置温度传感器;您将在本章后面找到更多相关信息。 | ||
<WRAP center round tip 60%> | <WRAP center round tip 60%> | ||
- | 为什么是 65,535? | + | **为什么是 65,535?** |
- | 乍一看,数字“65,535”看起来很奇怪——为什么会这样,为什么不是简单的 0-100? 答案与您的 Pico 在二进制数系统上工作的事实有关,其中一个数字的唯一可能值是 0 或 1。一个 16 位二进制数被制作 | + | 乍一看,数字“65,535”看起来很奇怪,为什么会这样,为什么不是简单的0-100? 答案与我们的Pico采用在2进制数系统有关,一个1位数字的唯一可能值是0或1,一个16位二进制数 |
- | 最多 16 位,最大可能值是 16 个:1111111111111111。如果将其转换回十进制数,人类使用的 0-9 计数系统,您会得到 65,535。 | + | 最多16位,最大可能值是16个:1111111111111111,如果将其转换回十进制数,也就是我们人类常用的十进制计数系统,就会得到65,535。 |
</WRAP> | </WRAP> | ||
- | 读取电位器 | + | ### 2.读取电位器 |
- | 连接到 Pico 模数转换器的每个引脚也可以用作简单的数字输入或输出; 要将其用作模拟输入,您需要一个模拟信号——您可以使用电位计轻松制作一个。 | + | 连接到Pico模数转换器的每个引脚既可以用作简单的数字输入、输出,也可以将其用作模拟输入,这时候我们需要一个模拟信号,比较简单的方式就是用[[potentiometer|电位器/电位计]]制作一个。 |
- | 有多种类型的电位器可供使用:有些,例如您在第 7 章中使用的 HC-SR501 被动红外传感器上的电位器,设计为可以用螺丝刀调节; 其他的,通常用于音量控制和其他输入,有旋钮或滑块。 最常见的类型有一个小的,通常是塑料的,从顶部或前面伸出的旋钮:这被称为旋转电位器。 | + | |
- | 拿起你的电位器,把它翻过来:你会看到它有三个插在面包板上的针脚。 根据您如何连接这些引脚,电位计以两种不同的方式工作。 首先将电位计插入面包板,小心不要弯曲引脚。 使用公对公 (M2M) 跳线将中间引脚连接到 Pico 上的 GP26_ADC0 引脚,如图 8-1 所示——如果 Pico 插入最顶部的面包板,它会 | + | 可以使用的电位计有多种,例如我们在第7章中使用的HC-SR501被动红外传感器上的电位器,它被设计为可以用螺丝刀调节;其它的通常用于音量控制和其它输入可以用旋钮或滑块来调节。 |
- | 在第 10 行。 最后,再取两根跳线,将电位计的一个外部引脚(无论哪个)连接到面包板的电源轨,将电源轨连接到 Pico 的 3V3 引脚。 | + | 最常见的类型有一个小的、通常是塑料的,从顶部或前面伸出的旋钮来调节,这种电位计被称为旋转电位计。 |
- | 打开 Thonny 并开始一个新程序: | + | |
+ | {{ :potentiometer.jpg |}}<WRAP centeralign> 可调电位计 </WRAP> | ||
+ | |||
+ | 打开Thonny并开始一个新程序: | ||
<code python> | <code python> | ||
import machine | import machine | ||
行 32: | 行 44: | ||
</code> | </code> | ||
- | 与数字通用输入/输出 (GPIO) 引脚一样,模拟输入引脚由机器库处理——就像数字引脚一样,在使用之前需要设置它们。 继续你的程序: | + | 与数字通用输入/输出 ([[GPIO]]) 引脚一样,模拟输入引脚由machine库处理, 就像数字引脚一样,在使用之前需要设置它们。 继续我们的程序: |
<code python> | <code python> | ||
potentiometer = machine.ADC(26) | potentiometer = machine.ADC(26) | ||
</code> | </code> | ||
- | 这将引脚 GP26_ADC0 配置为模数转换器上的第一个通道 ADC0。 | + | 这将引脚GP26_ADC0配置为模数转换器上的第一个通道ADC0。 |
要从引脚读取,请设置一个循环: | 要从引脚读取,请设置一个循环: | ||
+ | |||
<code python> | <code python> | ||
while True: | while True: | ||
行 44: | 行 58: | ||
utime.sleep(2) | utime.sleep(2) | ||
</code> | </code> | ||
- | 在这个循环中,读取引脚的值并将其打印在一行上:这是将值读入变量然后打印变量的更紧凑的替代方法,但仅当您不想这样做时才有效 除了打印之外的任何阅读 - 这正是该程序目前所需要的。 | ||
- | 读取模拟输入几乎与读取数字输入相同,除了一件事:读取数字输入时使用 read(),但使用 read_u16() 读取该模拟输入。最后一部分 u16 只是警告您,您将收到一个 16 位无符号整数,即 0 到 65,535 之间的整数,而不是二进制 0 或 1 结果。 | ||
- | 单击运行图标并将您的程序保存为 Potentiometer.py。观看 Shell:您会看到您的程序打印出大量数字,可能超过 60,000。尝试将电位计一直朝一个方向旋转:根据您转动旋钮的方向和您在电路中使用的外腿,数字会上升或下降。反过来:该值将向相反的方向变化。 | ||
- | 但是,无论您朝哪个方向转动,它都不会接近 0。那是因为只有两条腿连接,电位计充当称为可变电阻器或变阻器的组件。压敏电阻是一个可以改变值的电阻器——在 10 kΩ 电位计的情况下,介于 0 Ω 和 10,000 Ω 之间。电阻越高,来自 3V3 引脚的电压到达您的模拟输入端的电压就越低——因此数字会下降。电阻越低,到达您的模拟输入的电压就越大——因此数字会增加。 | ||
- | 电位计的工作原理是在内部有一个导电条,连接到两个外部引脚,以及一个雨刷或刷子连接到内部引脚(图 8-2)。当您转动旋钮时,雨刷器会靠近条带的一端并远离另一端。雨刮器离您连接到 Pico 3V3 引脚的条带末端越远,电阻越高;离得越近,阻力越小。 | ||
- | 压敏电阻是非常有用的组件,但有一个缺点:您会注意到,无论您将旋钮向任一方向旋转多远,您都无法获得 0 值——或接近它的任何值。这是因为 10 kΩ 电阻器的强度不足以将 3V3 引脚的输出降至 0 V。您可以寻找具有更高最大电阻的更大电位器,或者您可以简单地将现有电位器连接起来作为分压器。 | ||
- | 作为分压器的电位器 | ||
- | 电位器上未使用的引脚不是用来展示的:在电路中添加到该引脚的连接完全改变了电位器的工作方式。单击停止图标以停止您的程序,并抓住两根公对公 (M2M) 跳线。如图 8-3 所示,使用一个将电位计未使用的引脚连接到面包板的接地轨。取另一个并将接地轨连接到 Pico 上的 GND 引脚。 | + | 在这个循环中,读取引脚的值并将其打印在一行上。 |
- | 单击运行图标以重新启动程序。 再次转动电位计旋钮,从一个方向一直旋转到另一个方向。 观察打印到 Shell 区域的值:与以前不同,它们现在从接近零变为接近完整的 65,535——但为什么呢? | + | 读取模拟输入几乎与读取数字输入相同,除了一件事:读取数字输入时使用read(),但使用read_u16()读取该模拟输入。最后一部分u16只是告诉我们将收到一个16位无符号的整数,即0到65,535之间的整数,而不是二进制0或1结果。 |
- | 将接地连接添加到电位计导电条的另一端创建了一个分压器:而在电位计之前只是充当 3V3 引脚和模拟输入引脚之间的电阻器,它现在将 3.3 V 输出之间的电压分压为 3V3 引脚和 GND 引脚的 0 V。 将旋钮完全旋转一个方向,您将获得 3.3V 的 100%; 完全反过来,0%。 | + | |
+ | 单击运行图标并将我们的程序保存为Potentiometer.py。 | ||
+ | |||
+ | 观看Shell部分:我们会看到程序打印出大量数字,可能超过60,000。尝试将电位计一直朝一个方向旋转:根据我们转动旋钮的方向和我们在电路中使用的外部引脚,数字会上升或下降;反过来:该值将向相反的方向变化。但是,无论我们朝哪个方向转动,它都不会接近0。这是因为只有两条腿连接,电位计充当称为可变电阻器或变阻器的器件。 | ||
+ | |||
+ | 压敏电阻是一个可以改变值的电阻器, 在10kΩ电位计的情况下,介于0Ω和10,000Ω之间。电阻越高,来自3V3引脚的电压到达我们的模拟输入端的电压就越低——因此数字会下降。电阻越低,到达我们的模拟输入的电压就越大,因此数字会增加。 | ||
+ | |||
+ | 电位计的工作原理是在内部有一个导电条,连接到两个外部引脚,以及一个雨刷或刷子连接到内部引脚。当我们转动旋钮时,雨刷器会靠近条带的一端而远离另一端。雨刮器离我们连接到Pico 3V3引脚的条带末端越远,电阻越高;离得越近,电阻越小。 | ||
+ | {{ :potentiometerinternal.jpg |}}<WRAP centeralign> 电位计内部的结构</WRAP> | ||
+ | |||
+ | 压敏电阻是非常有用的器件,但有一个缺点:无论我们将旋钮向任一方向旋转多远,都无法获得0值, 或接近它的任何值。这是因为10kΩ电阻器的强度不足以将3V3引脚的输出降至0V。我们可以寻找具有更高最大电阻的更大电位器,或者可以简单地将现有电位器连接起来作为分压器。 | ||
+ | |||
+ | ### 3. 作为分压器的电位器 | ||
+ | 电位器上未使用的引脚不是用来展示的:在电路中添加到该引脚的连接完全改变了电位器的工作方式。单击停止图标以停止您的程序,并抓住两根公对公 (M2M) 跳线。如图 8-3 所示,使用一个将电位计未使用的引脚连接到面包板的接地轨。取另一个并将接地轨连接到Pico上的GND引脚。 | ||
+ | |||
+ | 单击运行图标以重新启动程序。 再次转动电位计旋钮,从一个方向一直旋转到另一个方向。 观察打印到 Shell区域的值:与以前不同,它们现在从接近零变为接近完整的65,535——但为什么呢?将接地连接添加到电位计导电条的另一端创建了一个分压器:而在电位计之前只是充当3V3引脚和模拟输入引脚之间的电阻器,它现在将3.3 V输出之间的电压分压为3V3引脚和GND引脚的0V。 将旋钮完全旋转一个方向,您将获得3.3V的100%; 完全反过来,0%。 | ||
<WRAP center round tip 60%> | <WRAP center round tip 60%> | ||
**零是最难的数字** | **零是最难的数字** | ||
- | 如果您无法让 Pico 的模拟输入准确读取 0 或 65,535,请不要担心 - 您没有做错任何事情! 所有电子元件都带有公差,这意味着任何声称的价值都不会准确。 就电位器而言,它可能永远不会精确地达到其输入的 0% 或 100%——但它会让你非常接近! | + | 如果您无法让Pico的模拟输入准确读取0或65,535,请不要担心 - 您没有做错任何事情! 所有电子元件都带有公差,这意味着任何声称的值都不会准确。 就电位器而言,它可能永远不会精确地达到其输入的0%或100%——但它会让你非常接近! |
</WRAP> | </WRAP> | ||
- | 您在 Shell 上看到的数字是模数转换器原始输出的十进制表示——但这并不是最友好的查看方式,尤其是当您忘记 65,535 表示“全电压”时。 | + | 您在Shell上看到的数字是模数转换器原始输出的十进制表示——但这并不是最友好的查看方式,尤其是当您忘记65,535表示“全电压”时。不过,有一个简单的方法可以解决这个问题:一个简单的数学方程。 返回您的程序,并在循环上方添加以下内容: |
- | 不过,有一个简单的方法可以解决这个问题:一个简单的数学方程。 返回您的程序,并在循环上方添加以下内容: | + | |
<code python> | <code python> | ||
- | conversion_factor = 3.3 / (65535) | + | conversion_factor = 3.3/(65535) |
</code> | </code> | ||
- | 这建立了一种数学方法,可以将模数转换器提供给您的数字转换为它所代表的实际电压的近似值。 第一个数字是引脚可以预期的最大可能电压:3.3 V,来自 Pico 的 3V3 引脚; 第二个数字是模拟输入读数的最大值,65,535。 | + | 这建立了一种数学方法,可以将模数转换器提供给您的数字转换为它所代表的实际电压的近似值。 第一个数字是引脚可以预期的最大可能电压:3.3V,来自Pico的3V3引脚;第二个数字是模拟输入读数的最大值 - 65,535。 |
- | 总而言之,转换因子是由“3.3 除以 65,535”创建的数字 - 最大可能电压除以模数转换器报告的值范围,这反过来又是其分辨率的特征(以位为单位)。 | + | 总而言之,转换因子是由“3.3 除以65,535”创建的数字 - 最大可能电压除以模数转换器报告的值范围,这反过来又是其分辨率的特征(以位为单位)。 |
设置转换系数后,您只需在程序中使用它即可。 回到你的循环,编辑它以阅读: | 设置转换系数后,您只需在程序中使用它即可。 回到你的循环,编辑它以阅读: | ||
<code python> | <code python> | ||
行 79: | 行 100: | ||
</code> | </code> | ||
- | 循环内的第一行通过模拟输入引脚从电位计读取读数,并将其(* 符号)乘以您之前在程序中设置的转换因子,将结果存储为可变电压。 然后将该变量打印到 Shell,代替您之前使用的原始读数。 | + | 循环内的第一行通过模拟输入引脚从电位计读取读数,并将其(* 符号)乘以您之前在程序中设置的转换因子,将结果存储为可变电压。 然后将该变量打印到Shell,代替您之前使用的原始读数。 |
您完成的程序将如下所示: | 您完成的程序将如下所示: | ||
<code python> | <code python> | ||
行 85: | 行 106: | ||
import utime | import utime | ||
potentiometer = machine.ADC(26) | potentiometer = machine.ADC(26) | ||
- | conversion_factor = 3.3 / (65535) | + | conversion_factor = 3.3/(65535) |
while True: | while True: | ||
voltage = potentiometer.read_u16() * conversion_factor | voltage = potentiometer.read_u16() * conversion_factor | ||
行 95: | 行 116: | ||
**线性 VS 对数** | **线性 VS 对数** | ||
- | 如果您发现在一个极限和另一个极限之间缓慢转动电位计会使数字开始缓慢变化,然后开始更快地变化,或者反过来,您几乎可以肯定使用的是对数或对数电位计。 而线性电位器在 | + | 如果您发现在一个极限和另一个极限之间缓慢转动电位计会使数字开始缓慢变化,然后开始更快地变化,或者反过来,您几乎可以肯定使用的是对数或对数电位计。 而线性电位器在在它的整个范围内,对数电位计开始进行微小的变化,然后迅速提高变化的速度。 对数电位器通常用于放大器的音量控制,而线性电位器更常见于基于微控制器的设备,例如Pico。 |
- | 在它的整个范围内,对数电位计开始进行微小的变化,然后迅速提高变化的速度。 对数电位器通常用于放大器的音量控制,而线性电位器更常见于基于微控制器的设备,例如 Pico。 | + | |
</WRAP> | </WRAP> | ||
- | 单击运行图标。将电位计一直朝一个方向转动,然后再朝另一个方向转动。观察打印到 Shell 区域的数字:您会看到,当电位器一直处于单向位置时,数字非常接近于零;当完全相反时,它们非常接近 3.3。这些数字代表引脚读取的实际电压——当你转动电位器的旋钮时,你正在最小和最大之间平滑地划分电压,0 V 到 3.3 V。 | + | 单击运行图标。将电位计一直朝一个方向转动,然后再朝另一个方向转动。观察打印到Shell区域的数字:您会看到,当电位器一直处于单向位置时,数字非常接近于零;当完全相反时,它们非常接近3.3。这些数字代表引脚读取的实际电压——当你转动电位器的旋钮时,你正在最小和最大之间平滑地划分电压,0V到3.3V。 |
恭喜:您现在知道如何将电位计连接为压敏电阻和分压器,以及如何将模拟输入读取为原始值和电压! | 恭喜:您现在知道如何将电位计连接为压敏电阻和分压器,以及如何将模拟输入读取为原始值和电压! | ||
- | 测量温度 | + | |
- | Raspberry Pi Pico 的 RP2040 微控制器有一个内部温度传感器,可在第四个模数转换器通道上读取。与电位计一样,传感器的输出是可变电压:随着温度的变化,电压也会发生变化。 | + | ### 4. 测量温度 |
+ | Raspberry Pi Pico 的RP2040微控制器有一个内部温度传感器,可在第四个模数转换器通道上读取。与电位计一样,传感器的输出是可变电压:随着温度的变化,电压也会发生变化。 | ||
启动一个新程序,并导入 machine 和 utime 库: | 启动一个新程序,并导入 machine 和 utime 库: | ||
行 119: | 行 140: | ||
<code python> | <code python> | ||
- | conversion_factor = 3.3 / (65535) | + | conversion_factor = 3.3/(65535) |
</code> | </code> | ||
行 136: | 行 157: | ||
</code> | </code> | ||
- | 这是另一个数学方程,并且特定于 RP2040 中的温度传感器。 这些值取自称为数据表或数据手册的技术文件:所有电子元件都有数据表,通常应制造商的要求提供。 您可以在 rptl.io/rp2040-get-started 的 Pico 文档中查看 RP2040 的数据表——它包含了关于微控制器如何工作的完整信息,尽管它是针对工程师的,因此具有很强的技术性。 | + | 这是另一个数学方程,并且特定于RP2040中的温度传感器。这些值取自称为数据表或数据手册的技术文件:所有电子元件都有数据表,通常应制造商的要求提供。 您可以在 rptl.io/rp2040-get-started 的 Pico 文档中查看 RP2040 的数据表——它包含了关于微控制器如何工作的完整信息,尽管它是针对工程师的,因此具有很强的技术性。 |
最后,完成你的循环: | 最后,完成你的循环: | ||
<code python> | <code python> | ||
行 157: | 行 179: | ||
</code> | </code> | ||
- | 单击运行图标并将您的程序保存为 Temperature.py。 观察外壳区域:您会看到打印的数字代表传感器报告的温度(以摄氏度为单位)。 | + | 单击运行图标并将您的程序保存为Temperature.py。 观察外壳区域:您会看到打印的数字代表传感器报告的温度(以摄氏度为单位)。 |
<WRAP center round tip 60%> | <WRAP center round tip 60%> | ||
- | 热和 RP2040 | + | **发热和RP2040** |
- | 如果你有一个传统的温度计,你可能会看到你的 Pico 报告的数字要高一点:那是因为温度传感器位于 Pico 的 RP2040 芯片内部,它正在忙于运行你的程序。 当微控制器通电时,它会自行产生热量——而这些热量足以扭曲结果。 对于这样一个简单的程序,偏斜可能不会太高; 如果您的程序进行了大量复杂的计算,则偏斜可能会更高。 | + | 如果你有一个传统的[[temp_sensor|温度计]],你可能会看到你的Pico测量到的数字要高一点,那是因为我们用到的温度传感器是嵌在Pico的处理器[[RP2040]]内部的,它正在忙于运行我们给它编写好的程序。 当微控制器通电运行程序时,它就会自行产生热量,而这些热量足以让测量到的结果有偏差,对于这样一个简单的程序,偏斜可能不会太高; 如果您的程序进行了大量复杂的计算,则偏斜可能会更高。 |
</WRAP> | </WRAP> | ||
- | 尝试将指尖轻轻按在 Pico 中间最大的黑色芯片 RP2040 上,然后将其握在那里:手指的温暖应该会使芯片变暖,温度会升高。将手指从芯片上移开,温度会再次下降。 | + | 尝试将指尖轻轻按在Pico中间最大的黑色芯片RP2040上,保持一段时间,手指的温暖应该会使芯片变暖,温度会升高。将手指从芯片上移开,温度会再次下降。 |
- | 恭喜 - 您已经将 Pico 变成了温度计! | + | |
+ | 恭喜 - 我们已经将Pico变成了温度计! | ||
+ | |||
+ | ### 5. 用PWM使LED衰减 | ||
+ | [[rpi_pico|Pico]]中的[[adc|模数转换器]]仅以一种方式工作:它将模拟信号转换为微控制器可以理解的数字信号。如果我们想通过数字微控制器得到一个模拟量输出,我们通常需要一个[[dac|数模转换器(DAC)]], 但一般的微控制器中没有内置的DAC,不过有一种方法可以“伪造”模拟信号,使用一种叫做[[pwm|脉宽调制或PWM]]的技术。 | ||
+ | |||
+ | [[mcu|微控制器]]的数字输出只能是0或1,打开和关闭数字输出称为脉冲,通过改变引脚打开和关闭的速度,我们可以改变或调制这些输出的脉冲宽度, 因此称之为“脉宽调制”。 | ||
+ | |||
+ | Pico上的每个[[GPIO]]引脚都能够进行脉宽调制,但RP2040微控制器的脉宽调制块由八个切片(slice)组成,每个切片有两个输出。看图 8-4:你会看到每个引脚都有一个字母和一个数字。数字代表连接到该引脚的PWM片;字母表示使用切片的哪个输出。 | ||
+ | |||
+ | {{ :pico_pinout.png?700 |}} <WRAP centeralign>树莓派官方Pico模块的管脚定义 </WRAP> | ||
+ | |||
+ | {{ :rp2040_pwm.png |}} | ||
- | 用 PWM 使 LED 衰减 | ||
- | Pico 中的模数转换器仅以一种方式工作:它将模拟信号转换为微控制器可以理解的数字信号。如果你想走另一条路,让你的数字微控制器创建一个模拟输出,你通常需要一个数模转换器 (DAC)——但是有一种方法可以“伪造”模拟信号,使用一种叫做脉宽调制或PWM。 | ||
- | 微控制器的数字输出只能打开或关闭,0 或 1。打开和关闭数字输出称为脉冲,通过改变引脚打开和关闭的速度,您可以改变或调制这些输出的宽度脉冲——因此称为“脉宽调制”。 | ||
- | Pico 上的每个 GPIO 引脚都能够进行脉宽调制,但微控制器的脉宽调制块由八个切片组成,每个切片有两个输出。看图 8-4:你会看到每个引脚都有一个字母和一个数字。数字代表连接到该引脚的 PWM 片;字母表示使用切片的哪个输出。 | ||
<WRAP center round tip 60%> | <WRAP center round tip 60%> | ||
**PWM 冲突** | **PWM 冲突** | ||
- | 如果您不小心使用了两次相同的 PWM 输出,您就会知道,因为每次更改一个引脚上的 PWM 值时,它也会影响冲突的引脚。 如果发生这种情况,请查看图 8-4 中的引脚排列图和您的电路,并找到您没有的 PWM 输出还没用。 | + | 如果我们不小心使用了两次相同的PWM输出,每次更改一个引脚上的PWM值时,它也会影响冲突的引脚。 如果发生这种情况,请查看Pico管脚图中的引脚排列图和我们的电路,并找到我们还没有用的PWM输出。 |
</WRAP> | </WRAP> | ||
- | 如果这听起来令人困惑,请不要担心:这意味着您需要确保跟踪正在使用的 PWM 切片和输出,确保仅连接到带有字母和数字组合的引脚” t 已经使用。 如果您在 GP0 针脚上使用 PWM_A[0] 并在针脚 GP1 上使用 PWM_B[0],则一切正常,如果您在针脚 GP2 上添加 PWM_A[1],则将继续工作; 但是,如果您尝试在引脚 GP0 和引脚 GP16 上使用 PWM 通道,则会遇到问题,因为它们都连接到 PWM_A[0]。 | + | 是不是听起来很晕?不要担心:这意味着我们需要确保跟踪正在使用的PWM切片和输出,确保仅连接到带有字母和数字组合的引脚已经使用。如果我们在GP0针脚上使用PWM_A[0]并在针脚GP1上使用PWM_B[0],则一切正常,如果我们在管脚GP2上添加PWM_A[1],是没有问题的。但是,如果我们尝试在引脚GP0和引脚GP16上使用PWM通道,则会遇到问题,因为它们在芯片的内部都连接到PWM_A[0]。 |
- | 取一个 LED 和一个 330 Ω 的限流电阻,将它们放入面包板中,如图 8-5 所示。 将 LED 的较长脚(阳极)通过 330 Ω 电阻连接到 GP15 引脚,并将较短的脚连接到 Pico 的接地引脚。 | + | |
- | 单击 Thonny 工具栏下方的选项卡,返回您的第一个程序; 如果您已经关闭它,请单击“打开”图标并从您的 Pico 加载 Potentiometer.py。 在您将电位计设置为模数输入的位置下方,键入: | + | 单击Thonny工具栏下方的选项卡,返回我们的第一个程序; |
+ | |||
+ | 如果已经关闭它,请单击“打开”图标并从我们的Pico中加载Potentiometer.py。 | ||
+ | |||
+ | 将电位计设置为模数输入的位置下方,键入: | ||
<code python> | <code python> | ||
行 185: | 行 219: | ||
</code> | </code> | ||
- | 这会在引脚 GP15 上创建一个 LED 对象,但有一个区别:它激活引脚上的脉宽调制输出,通道 B[7]——第八个切片的第二个输出,从零开始计数。 | + | 这会在引脚GP15上创建一个LED对象,但有一个区别:它激活引脚上的脉宽调制输出,通道B[7]——第八个切片的第二个输出,从零开始计数。 |
- | 您还需要设置频率,这是您可以更改以控制或调制脉冲宽度的两个值之一。 在读数下方立即添加另一行: | + | |
+ | 我们还需要设置PWM的频率,是我们可以更改的,用以控制或调制脉冲宽度的两个值之一。 在读数下方立即添加另一行: | ||
<code python> | <code python> | ||
行 192: | 行 227: | ||
</code> | </code> | ||
- | 这将设置频率为 1000 赫兹 - 每秒一千个周期。 接下来,转到程序的底部并在添加以下内容之前删除 print(voltage) 和 utime.sleep(2) 行,记住将其缩进四个空格,使其成为循环中嵌套代码的一部分: | + | 这将设置频率为1000赫兹 - 每秒一千个周期。 接下来,转到程序的底部并在添加以下内容之前删除print(voltage)和utime.sleep(2)行,记住将其缩进4个空格,使其成为循环中嵌套代码的一部分: |
<code python> | <code python> | ||
行 198: | 行 233: | ||
</code> | </code> | ||
- | 这条线从连接到电位计的模拟输入中获取原始读数,然后将其用作脉宽调制的第二个方面:占空比。占空比控制引脚的输出:0% 的占空比使引脚在每秒 1000 个脉冲时关闭,并有效地关闭引脚; 100% 的占空比使引脚在每秒 1000 个脉冲时都处于开启状态,并且在功能上等同于仅将引脚作为固定数字输出开启;占空比为 50% 时,引脚打开一半脉冲,关闭一半脉冲。 | + | 这条线从连接到电位计的模拟输入中获取原始读数,然后将其用作脉宽调制的第二个参数:占空比。占空比控制引脚的输出:0%的占空比使引脚在每秒1000个脉冲时关闭,并有效地关闭引脚; 100%的占空比使引脚在每秒1000个脉冲时都处于开启状态,并且在功能上等同于仅将引脚作为固定数字输出开启;占空比为50%时,引脚打开一半脉冲,关闭一半脉冲。 |
- | 为了能够正确控制 LED 的亮度,您需要将模拟输入的值映射到 PWM 片可以理解的范围。执行此操作的最佳方法是告诉 MicroPython 您将占空比值作为无符号 16 位整数传递,与您从 Pico 的模拟输入引脚接收到的数字格式相同。这是通过使用 led.duty_u16 实现的。 | + | |
- | 您完成的程序将如下所示: | + | 为了能够正确控制[[LED]]的亮度,我们需要将模拟输入的值映射到PWM片可以理解的范围。执行此操作的最佳方法是告诉[[MicroPython]]我们将占空比值作为无符号16位整数传递,与我们从[[rpi_pico|Pico]]的模拟输入引脚接收到的数字格式相同。这是通过使用led.duty_u16实现的。 |
+ | |||
+ | 最后的程序将如下所示: | ||
<code python> | <code python> | ||
import machine | import machine | ||
import utime | import utime | ||
- | potentiometer = machine.ADC(26) | + | potentiometer = machine.ADC(28) |
- | led = machine.PWM(machine.Pin(15)) | + | led = machine.PWM(machine.Pin(25)) |
led.freq(1000) | led.freq(1000) | ||
while True: | while True: | ||
行 212: | 行 249: | ||
</code> | </code> | ||
- | 单击“运行”图标并尝试将电位计一直转动到一个方向,然后再转动到另一个方向。 观察 LED:这一次,除非您使用对数电位器,否则您会看到 LED 的亮度从电位器旋钮限制的一端完全关闭到另一端完全点亮。 | + | 单击“运行”图标并尝试将电位计一直转动到一个方向,然后再转动到另一个方向。 |
- | 恭喜:您不仅掌握了模拟输入,而且现在可以使用脉宽调制创建等效于模拟输出的内容! | + | |
+ | 观察LED:这一次,除非我们使用对数电位器,否则我们会看到LED的亮度从电位器旋钮限制的一端完全关闭到另一端完全点亮。 | ||
+ | |||
+ | 到此,我们不仅掌握了模拟输入,而且现在可以使用脉宽调制创建等效于模拟输出的内容! | ||
<WRAP center round tip 60%> | <WRAP center round tip 60%> | ||
**挑战:定制** | **挑战:定制** | ||
- | 您能否结合您的两个程序,并通过车载温度传感器的温度读数来控制 LED 的亮度? 您还记得您的 Pico 有多少个模拟输入吗? PWM输出呢? 尝试在 Pico 中添加另一个模拟传感器——比如光敏电阻器 (LDR)、气体传感器或气压计——并让你的程序读取它而不是电位计。 | + | 您能否结合您的两个程序,并通过车载温度传感器的温度读数来控制LED的亮度? 您还记得您的Pico有多少个模拟输入吗? PWM输出呢? 尝试在Pico中添加另一个模拟传感器——比如光敏电阻器(LDR)、气体传感器或气压计——并让你的程序读取它而不是电位计。 |
</WRAP> | </WRAP> | ||