学习资料来自Get started with MicroPython on Raspberry Pi Pico

目前我们已经使用了许多数字信号输入元件。数字信号只有两个状态,比如开关、被动式红外传感器。我们的Pico也接受另一种信号:模拟信号,模拟信号可以是一系列的值。模拟信号被广泛应用于音量控制、湿度和温度传感器中——它们通过模拟到数字信号转换器(analogue-to-digital converter, ADC)。

所需材料

  • Pico
  • 任意颜色的LED
  • 330Ω的电阻
  • 10kΩ的电位计
  • 公对公跳线若干

Analogue-to-digital converter

树莓派Pico的RP2040微处理器与其他主流微处理器一样,都是由成千上万的晶体管构成的,这种元件不是开就是关。也就是说,如果没有ADC等元件,我们的Pico就不能真正理解模拟信号。

我们无法用肉眼观察到ADC,它被内置到RP2040中了。许多微处理器和RP2040一样,都内置了ADC,对于没有内置ADC的,我们可以使用外接ADC。

ADC有两个核心功能:分辨率(以比特数(bits)计算)和频道(或者说可以一次性接受并转换多少模拟信号)。

测量温度

最常见的电位计是旋钮式电位计。

电路连接

读取电位计

导入所需库并定义模拟信号。

1
2
3
4
import machine
import utime

potentiometer = machine.ADC(26)

读取信息并输出:

1
2
3
while True:
print(potentiometer.read_u16())
utime.sleep(2)

读取模拟信号和数字信号几乎是相同的,除了我们读取数字信号时使用read(),而读取模拟信号时使用read_u16()

代码拆解

我们的PP2040处理器内置了一个温度传感器。

导入库并定义温度传感器:

1
2
3
4
import machine
import utime

sensor_temp = machine.ADC(4)

定义一个转换因子,用于将传感器的原始输出转换为电压值

1
conversion_factor = 3.3 / (65535)

开始循环

1
2
while True:
reading = sensor_temp.read_u16() * conversion_factor

我们当然不能直接输出电压值,再用一个方程将其转换为温度值

1
temperature = 27 - (reading - 0.706)/0.001721

这个方程是专用于RP2040的,它来自被乘坐data sheetdata book的技术文档。RP2040的技术文档在Raspberry Pi Documentation - Microcontrollers

最后结束循环

1
2
print(temperature)
utime.sleep(2)

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
import machine
import utime

sensor_temp = machine.ADC(4)

conversion_factor = 3.3 / (65535)

while True:
reading = sensor_temp.read_u16() * conversion_factor
temperature = 27 - (reading - 0.706)/0.001721
print(temperature)
utime.sleep(2)

使用LED

如果我们想要将模拟信号输出,我们通常需要digital-to-analogue converter (DAC),但我们也可以通过脉冲宽度调制(pulse-width modulation, PWM)。

电子信号只能输出0或1。开或关被称为脉冲(pulse)。通过改变针脚开关的速度,我们就可以改变或者说是调制信号。这种方法因此被称为脉冲宽度调制。

电路连接

代码拆解

定义LED:

1
led = machine.PWM(machine.Pin(15))

这行代码激活了PWM输出。

我们还需要设置频率为1000赫兹:

1
led.freq(1000)

在循环中添加:

1
led.duty_u16(potentiometer.read_u16())

完整代码

1
2
3
4
5
6
7
8
9
import machine
import utime

potentiometer = machine.ADC(26)
led = machine.PWM(machine.Pin(15))
led.freq(1000)

while True:
led.duty_u16(potentiometer.read_u16())