项目设想

因为我住的宿舍楼光线较差,尤其是一到晚上,楼道里漆黑一片,虽然楼道内装了声控灯,但总觉得发出声音有些不好意思,因此晚上总是摸黑前行。于是有一次我十分尴尬的走错了寝室,这让我下定决心给我们的宿舍门做一些装饰:光感应灯。

我打算用3个LED(红、黄、绿各一个)结合Pico和光感应模块将门牌“511”照亮。

参考资料

材料清单及成本

  • 树莓派Pico(以下简称:Pico)

    https://3.cn/24w1Y-gh ¥16.8

  • 2节5号电池盒

    https://m.tb.cn/h.gMC3Lv3?tk=n7Lh3gOjHF2 ¥3.52/5 = ¥0.704

  • 光感应模块

    https://m.tb.cn/h.golCN8X?tk=5p9M3gOlumG ¥2.95

  • 2节5号碱性电池

    https://3.cn/24w3-aLa ¥8.8/5 = ¥1.76

  • 3个LED

    成本忽略不计

  • 小电线

    成本忽略不计

电路连接

Pico引脚分布图

Pico GPIO Layout.png

将LED与Pico连接

按照上面的引脚分布图,将红、黄、绿的LED分别与GP2GP12GP15连接。

连接光传感器

  • 传感器模块的VCC脚接树莓派Pico的3V3
  • 传感器模块的GND脚接树莓派Pic 的GND
  • 传感器模块的AO脚接树莓派Pico的GP28
  • 传感器模块的 DO 脚接树莓派Pico的GP27

代码实现

导入所需库并定义LED

1
2
3
4
5
6
import machine
import utime

ledG = machine.Pin(15, machine.Pin.OUT)
ledY = machine.Pin(12, machine.Pin.OUT)
ledR = machine.Pin(2, machine.Pin.OUT)

定义开灯/关灯函数

1
2
3
4
5
6
7
8
9
def lightOn():
ledG.on()
ledY.on()
ledR.on()

def lightOff():
ledG.off()
ledY.off()
ledR.off()

定义光传感器(模拟信号、数字信号)

1
2
sensor_analog = machine.ADC(28)
sensor_digital = machine.Pin(27, machine.Pin.IN)

先编写如下程序进行测试:

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

sensor_analog = machine.ADC(28)
sensor_digital = machine.Pin(27, machine.Pin.IN)

while True:
print('Analog value: %d, Digital value: %d.' % (65535 - sensor_analog.read_u16(), 1 - sensor_digital.value()))
utime.sleep(0.5)

如下是开启我桌上台灯前后的输出结果。

1
2
3
4
5
6
7
8
9
Analog value: 41786, Digital value: 1.
Analog value: 41930, Digital value: 1.
Analog value: 41674, Digital value: 1.
Analog value: 41706, Digital value: 1.
Analog value: 47035, Digital value: 1.
Analog value: 57454, Digital value: 1.
Analog value: 57422, Digital value: 1.
Analog value: 57454, Digital value: 1.
Analog value: 57358, Digital value: 1.

定义阈值并编写测量函数

如上所示,将测试用阈值暂定为50000,即模拟信号值大于50000时,开启LED;反之,则不开启。

1
2
3
4
5
6
7
8
9
10
11
12
# 定义阈值
threshold = 50000

def testing(threshold):
# 定义光传感器
sensor_analog = machine.ADC(28)
sensor_digital = machine.Pin(27, machine.Pin.IN)
print('Analog value: %d, Digital value: %d.' % (65535 - sensor_analog.read_u16(), 1 - sensor_digital.value()))
if 65535 - sensor_analog.read_u16() >= threshold:
return True
else:
return False

开/关灯逻辑实现

1
2
3
4
5
6
while True:
utime.sleep(0.1)
if testing(threshold):
lightOff()
else:
lightOn()

实地测量获取数据

如上的阈值是用于桌上判断台灯开启与否的,与实际需求(见“项目设想”)必然存在一定差异,因此我们必须再做更多实地测量获取可用的阈值。

但把电脑搬到外面去似乎不太合适(主要也是不方便),于是我们需要自动启动程序并将测量值记录下来。

编写测量程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import machine
import utime

sensor_analog = machine.ADC(28)
sensor_digital = machine.Pin(27, machine.Pin.IN)


# 为每次启动分行
with open('dataLogger.txt', 'a') as f:
f.write('\n')

while True:
with open('dataLogger.txt', 'a') as f:
f.write('Analog value: %d, Digital value: %d.\n' % (65535 - sensor_analog.read_u16(), 1 - sensor_digital.value()))

utime.sleep(0.5)

Pico自动运行程序

将如上程序保存为main.py。按下CTRL+D,这样Thonny就能将Pico激活。

这样,就可以带上充电宝(和USB A2B数据线),来到宿舍门外试验啦!

测量日志:

2024/9/4 14:35(这时天很亮,楼道里也能勉强看清)宿舍门前的声控灯开启与否的阈值约为30000

2024/9/4 21:21 阈值约为18000

综上,我决定采用18000作为最终阈值。

附:记录日志

14:35

23:21

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import machine
import utime

# 定义LED
portG = 15
portY = 12
portR = 2
ledG = machine.Pin(portG, machine.Pin.OUT)
ledY = machine.Pin(portY, machine.Pin.OUT)
ledR = machine.Pin(portR, machine.Pin.OUT)

# 定义阈值
threshold = 18000

def lightOn():
ledG.on()
ledY.on()
ledR.on()

def lightOff():
ledG.off()
ledY.off()
ledR.off()


def testing(threshold):
# 定义光传感器
sensor_analog = machine.ADC(28)
sensor_digital = machine.Pin(27, machine.Pin.IN)
print('Analog value: %d, Digital value: %d.' % (65535 - sensor_analog.read_u16(), 1 - sensor_digital.value()))
if 65535 - sensor_analog.read_u16() >= threshold:
return True
else:
return False


while True:
utime.sleep(0.1)
if testing(threshold):
lightOff()
else:
lightOn()

记得将上述代码保存为main.py

使用电池供电

目前为止,我们都是采用Pico上的micro USB接口为其供电。但我们不可能专门为这个光感应灯配备一个充电宝,这样成本太高了,因此最佳方案是使用干电池为其供电。(当然也可以选用带micro USB口的电池盒,但这个方案被pass掉的原因同样是成本较高)

根据树莓派官网的信息,Pico的安全供电电压介于1.8V5.5V之间,因此我们选用2节干电池,提供3V的工作电压。

将电池盒的正、负极分别接在Pico的VSYS口、GND口。

形成产品

为了能让我们的光感应灯长久的贴于寝室门上,我们需要一个外壳。我手头刚好有一个惠普鼠标的纸壳,便用它作为产品外壳。

首先大致测量数字5 1 1之间的长度,以确定LED的位置,随后,用小刀之类的工具在其上钻三个孔用于将灯泡置于壳外。

接着,在纸壳的下部,钻一个方形的孔,用于放置光感应模块。

实物图:

实物图2.jpg
实物图1.jpg