1. 项目概述:一个为树莓派量身定制的多功能扩展板
手头有一块树莓派 3B+,总想让它干点更“实在”的活儿,比如实时监控书房的环境温湿度,或者用一个统一的遥控中心来管理空调、电视这些老式红外设备。市面上现成的HAT(Hardware Attached on Top)扩展板功能要么太单一,要么价格不菲,对于喜欢折腾的玩家来说,自己动手设计制作一块专属的扩展板,无疑是更具成就感和灵活性的选择。这个项目,就是基于这个想法诞生的:利用一块自制的单面PCB,将高精度的Si7020温湿度传感器和一个大功率红外发射管集成到树莓派上,并额外增加一个静音风扇接口用于主动散热,最终形成一个集环境感知与设备控制于一体的小型家庭自动化节点。
整个流程走下来,你会发现它不仅仅是一个简单的焊接作业,而是一次完整的嵌入式硬件开发实践。从在EasyEDA上绘制第一根原理图连线,到用廉价的3018 CNC雕刻机将设计转化为实体电路板,再到挑战手工焊接微小的SMD(表面贴装)元件,最后用Python脚本让一切“活”起来。这个过程会涉及到I2C通信协议的底层调用、PCB设计中的抗干扰与走线技巧、CNC雕刻的参数“玄学”,以及SMD焊接的“手感”艺术。无论你是想深入学习树莓派GPIO应用的软件开发者,还是渴望踏入PCB自制领域的硬件新手,这个项目都能提供一条清晰的路径。最终,你将得到一块独一无二、完全符合你个人需求的树莓派“帽子”,并且掌握从电路设计到成品调试的全套技能。
2. 核心硬件选型与电路设计解析
2.1 主控与核心传感器:为什么是树莓派与Si7020?
选择树莓派 3B+作为主控平台,主要基于其极佳的生态与性能平衡。它提供了完整的Linux环境,使得用Python编写控制脚本变得异常简单,远超传统的单片机开发体验。其标准的40针GPIO排针,特别是内置的硬件I2C接口,为连接传感器提供了“即插即用”的便利。相比之下,Si7020温湿度传感器是一个经过市场检验的可靠选择。它采用I2C通信,仅需两根线(SDA和SCL)即可完成数据读写,极大简化了硬件连接。其测量精度(温度±0.4°C,湿度±3% RH)对于家庭环境监控绰绰有余,并且内部集成了信号处理电路,输出即为校准后的数字值,省去了复杂的模拟信号调理步骤。
在电路连接上,Si7020的供电(VDD)直接连接到树莓派的3.3V引脚(物理引脚1或17)。这里有一个关键细节:必须使用3.3V,而非5V。因为树莓派的GPIO逻辑电平是3.3V,Si7020的工作电压也是3.3V,使用5V会直接烧毁传感器。其I2C数据线(SDA)和时钟线(SCL)分别连接到树莓派的物理引脚3(GPIO2/SDA)和5(GPIO3/SCL)。这两个引脚是树莓派默认启用的I2C-1接口,在系统中已有上拉电阻,一般情况下无需外接。Si7020的地址引脚(ADDR)在本设计中接地,将其I2C设备地址设置为0x40,这是该芯片的默认地址。
2.2 红外发射电路:驱动能力与波形质量
红外遥控的核心是重现设备能识别的特定载波脉冲信号。常见的红外载波频率是38kHz。我们虽然可以用树莓派的GPIO引脚直接模拟这个方波,但驱动能力非常弱,发射距离可能只有几厘米。因此,需要一个简单的晶体管放大电路来驱动大功率红外发射管(IRED)。
本设计使用了一个经典的NPN晶体管(BC846B)作为开关。其工作原理是:当树莓派GPIO(例如物理引脚12,GPIO18)输出高电平(3.3V)时,电流通过一个4.7kΩ的基极电阻注入晶体管,使其饱和导通,此时红外发射管的阴极相当于接地,电流从3.3V电源经一个限流电阻(63Ω)和发射管流通,使其发出红外光。当GPIO输出低电平时,晶体管截止,电路断开。
注意:限流电阻的计算至关重要。假设红外发射管的正向压降(Vf)约为1.2V,电源电压为3.3V,期望的工作电流(If)为100mA(具体需查阅你的发射管数据手册)。根据欧姆定律:R = (Vcc - Vf) / If = (3.3V - 1.2V) / 0.1A = 21Ω。原设计使用的63Ω电阻会将电流限制在约33mA,这可能是为了保守起见,防止电流过大损坏GPIO或晶体管,但会牺牲一些发射距离。你可以根据手头元件的实际参数进行调整。晶体管BC846B的集电极电流(Ic)最大可达100mA,足以胜任。
2.3 风扇接口与电源保护
扩展板上设计了一个标准的2针风扇接口(连接物理引脚4,5V和6,GND),用于连接一个25x25mm的微型风扇,为树莓派主动散热。这是一个非常实用的附加功能,尤其是在CPU持续工作时。电路上并联了一个100nF(0.1uF)的陶瓷电容,作用是为风扇电机这个感性负载提供去耦,吸收电机启停或换向时产生的电压尖峰,防止干扰树莓派或其他敏感电路的电源稳定性。
此外,在5V输入路径上串联了一个1N4148二极管。它的作用是防止电源反接。如果意外将电源极性接反,二极管会处于反向截止状态,阻断电流,从而保护树莓派和扩展板上的所有元件不被烧毁。这是一个成本极低但非常有效的保护措施,在自制硬件中强烈推荐加入。
3. 从设计到实体:PCB制作全流程实操
3.1 使用EasyEDA进行PCB布局设计
对于初学者,EasyEDA是在线PCB设计工具的绝佳选择。首先根据前面的原理图,在编辑器中放置所有元件并完成电气连接。之后进入关键的PCB布局环节。对于这种简单的单面板,布局的核心原则是:优先摆放位置固定的连接器(如树莓派排针),然后围绕核心器件(Si7020)和功率路径(红外驱动部分)进行布局,尽量使走线简短直接。
由于我们使用CNC雕刻而非化学腐蚀,走线设计需要特别考虑雕刻刀的物理限制。原作者的策略非常实用:将所有焊盘和走线的最小宽度设置为0.6mm。这是因为他使用的0.1mm尖端的30度V型刀,在雕刻小于0.6mm的间隙时,很容易因为刀具磨损或机床精度问题导致过度切割,使相邻走线短路或断开。将走线宽度和间距都放宽,能极大提高雕刻成功率和后期焊接的便利性。在布线时,尽量使用45度角或圆弧拐角,避免90度直角,后者在高频电路中容易产生辐射干扰,在雕刻中也更容易残留铜屑。
3.2 CNC雕刻参数设置与“踩坑”经验
将设计好的PCB导出为Gerber文件后,需要使用FlatCam这类软件将矢量图形转换为CNC机床能识别的G代码。这个过程参数设置是成败的关键。
1. 走线雕刻(Isolation Milling):
- 刀具直径:这里填的不是刀的物理直径,而是“有效切割直径”。对于30度V型刀,尖端宽度几乎为0。这个值(如0.13mm)决定了软件计算路径时的偏移量,略大于实际切出的线宽,可以确保走线间的铜被完全清除。需要经过几次测试来确定最佳值。
- 切割深度(Cut Z):设置为-0.06mm。这个值需要非常谨慎。它意味着刀尖只会切入覆铜板铜层大约0.06毫米。铜箔厚度通常只有0.035mm左右,这个深度足以刮掉铜,但又不会过深损伤下面的玻纤基板。设置过深会直接导致断刀或基板损坏。
- 多层切割(Multi-Depth):启用并设置为0.03mm。这是一个非常重要的技巧!它会让机床分两次雕刻:第一次下切-0.03mm,第二次走到-0.06mm。这样既能保证彻底清除铜箔,又能减少单次切削力,保护脆弱的V型刀尖,��时获得更光滑的侧壁。
2. 钻孔与轮廓切割:
- 钻孔:换用0.7mm或0.8mm的直柄钻头。切割深度(Cut Z)需设置为覆铜板厚度的负值(如-1.5mm),确保钻透。
- 轮廓切割:使用1mm的直柄铣刀将小板从大板上切下来。切割深度同样要大于板厚,通常采用“多次铣削”的方式,比如每次下切0.5mm,分3次切透,这样边缘更整齐,不易崩边。
3. 在bCNC中运行与调平:在发送G代码到CNC机床前,必须执行“自动调平”(Autolevel)。因为你的覆铜板表面很可能不是绝对水平的,如果不调平,雕刻深度就会不一致,有的地方铜没刮干净,有的地方却刻穿了。在bCNC的调平设置中,将X-Y方向的探测步进(Probing Step)设置为最大值3mm。这意味着探针每移动3mm测量一次高度,生成一个高度网格图(Height Map)。机床在雕刻时会根据这个网格图动态调整Z轴高度,保证刀尖在整个板面上的切割深度恒定。这是获得高质量雕刻PCB的最关键一步。
3.3 SMD元件的手工焊接技巧
面对0603或1206封装的SMD电阻电容,没有热风枪怎么办?原作者提供了一个巧妙的“拖焊+热风枪”组合技法,但纯手工烙铁同样可以完成。
准备工作:一把尖头烙铁(温度设定在320°C-350°C为宜),细焊锡丝(0.3mm-0.5mm),优质助焊剂(膏状或液体),镊子,以及放大镜或台灯。
焊接步骤:
- 对位与固定:用镊子将元件大致放到焊盘上。先在一个焊盘上堆上少量焊锡,然后用烙铁加热这个焊盘,同时用镊子将元件一端推过去,使焊锡浸润元件电极并冷却固定。这时元件可能歪斜,但已被固定住一端。
- 焊接另一端:去焊接元件的另一个电极。焊锡丝接触焊盘和元件电极的交界处,烙铁头同时加热两者,待焊锡熔化并自然流铺开后移开烙铁。
- 修正与补焊:现在再回去加热第一个焊点,用镊子轻微调整元件至完全摆正,然后移开烙铁冷却。检查两个焊点,应呈光滑的圆锥形,饱满地包裹住元件电极。如果焊锡过多形成球状,可以用吸锡带吸走多余部分;如果焊锡少或虚焊,补一点锡即可。
- Si7020的焊接:这是一个有多个引脚的小芯片。同样采用“固定一角,再焊其他”的策略。先在PCB上一个焊盘上上锡,用镊子夹住芯片对准所有引脚,用烙铁熔化那个焊盘的锡并轻轻推入芯片一角使其固定。然后,从对角的引脚开始,逐一焊接。关键技巧:使用足够的助焊剂!在引脚排上涂一点助焊膏,然后用烙铁头带上少量焊锡,轻轻从引脚排的一端拖到另一端,焊锡会在助焊剂的作用下自动流向每个引脚并形成完美焊点,这就是“拖焊”。最后检查是否有桥接(短路),如有,在桥接处加助焊剂,用干净的烙铁头轻轻划过即可吸走多余焊锡。
实操心得:焊接SMD时,“助焊剂是你的朋友”。它能清除氧化层,降低焊锡表面张力,让焊点更光亮、焊接更牢固。焊接完成后,建议用洗板水或无水酒精配合硬毛刷清洗板子,去除残留的助焊剂,既美观又能防止日后吸潮腐蚀。
4. 软件配置与Python数据采集脚本
4.1 启用I2C接口与检测设备
硬件连接好后,首先需要确保树莓派的I2C接口已启用。在终端中运行sudo raspi-config,选择Interface Options->I2C,启用它并重启。随后,安装必要的工具:
sudo apt update sudo apt install i2c-tools python3-smbus重启后,运行sudo i2cdetect -y 1来扫描I2C总线上的设备。如果一切正常,你应该能看到地址0x40处显示为40,这证实了Si7020已被正确识别并连接。
4.2 编写Python脚本读取温湿度
与Si7020通信需要遵循其特定的命令序列。下面是一个增强版的Python脚本,包含了错误处理和简单的数据校准:
#!/usr/bin/env python3 import smbus2 import time class Si7020: def __init__(self, bus=1, address=0x40): self.bus = smbus2.SMBus(bus) self.address = address def _read_temperature(self): """发送温度测量命令并读取结果""" try: # 发送测量命令(不保持主设备) self.bus.write_byte(self.address, 0xF3) time.sleep(0.1) # 等待测量完成,数据手册建议最大12ms # 读取2字节数据 data = self.bus.read_i2c_block_data(self.address, 0, 2) if len(data) < 2: raise IOError("I2C read failed") # 将两个字节组合成一个16位整数 raw_temp = (data[0] << 8) | data[1] # 根据数据手册公式转换:((175.72 * raw) / 65536) - 46.85 celsius = (175.72 * raw_temp / 65536.0) - 46.85 return celsius except Exception as e: print(f"Error reading temperature: {e}") return None def _read_humidity(self): """发送湿度测量命令并读取结果""" try: self.bus.write_byte(self.address, 0xF5) time.sleep(0.1) data = self.bus.read_i2c_block_data(self.address, 0, 2) if len(data) < 2: raise IOError("I2C read failed") raw_humi = (data[0] << 8) | data[1] # 公式:((125 * raw) / 65536) - 6 humidity = (125.0 * raw_humi / 65536.0) - 6.0 # 将湿度限制在0-100%的合理范围内 humidity = max(0.0, min(100.0, humidity)) return humidity except Exception as e: print(f"Error reading humidity: {e}") return None def read_all(self, temp_offset=0.0): """读取温度和湿度,并可选择对温度进行偏移校准""" temp = self._read_temperature() humi = self._read_humidity() if temp is not None: temp += temp_offset # 应用校准偏移 return temp, humi if __name__ == "__main__": sensor = Si7020() # 尝试读取传感器序列号进行验证(可选) try: self.bus.write_byte(self.address, 0xFA) self.bus.write_byte(self.address, 0x0F) snb = self.bus.read_i2c_block_data(self.address, 0, 8) print(f"Sensor SN: {bytes(snb).hex()}") except: print("Could not read sensor SN, but continuing...") while True: temperature, humidity = sensor.read_all(temp_offset=-7.0) # 应用经验偏移 if temperature is not None and humidity is not None: print(f"Temperature: {temperature:.2f} °C, Humidity: {humidity:.2f} %RH") else: print("Sensor read error!") time.sleep(2)脚本解析与校准说明:
- 通信流程:脚本遵循Si7020数据手册的流程:先向设备地址发送一个测量命令(0xF3为温度,0xF5为湿度),等待一小段时间让传感器完成测量,然后读取两个字节的结果数据进行转换。
- 温度偏移(
temp_offset=-7.0):这是原作者发现的一个重要经验值。Si7020传感器安装在树莓派CPU上方,会受到CPU发热的直接影响,导致读数偏高。这个-7°C的偏移量是一个经验性校准值,用于补偿这种局部热源的影响。你的��际偏移量可能不同,需要通过对比一个远离热源的、准确的温度计读数来确定。 - 错误处理:脚本中添加了基本的
try-except块,当I2C通信失败时(如线缆松动),会打印错误信息而不是直接崩溃,提高了鲁棒性。
4.3 配置LIRC实现红外控制
控制红外发射管需要生成标准的38kHz载波。树莓派上最常用的工具是LIRC(Linux Infrared Remote Control)。
安装与配置:
sudo apt install lirc编辑/etc/lirc/lirc_options.conf,修改以下关键行:
driver = default device = /dev/lirc0编辑/boot/config.txt,在末尾添加一行,指定使用GPIO18作为红外输出引脚(根据你的实际连接修改gpio_out_pin):
dtoverlay=gpio-ir-tx,gpio_pin=18重启树莓派。
录制与发送红外信号:
- 录制:使用
irrecord -d /dev/lirc0 ~/lircd.conf命令,按照提示对准你的原始遥控器并按下按键,LIRC会学习并生成一个配置文件。 - 发送:将生成的
~/lircd.conf文件复制到/etc/lirc/lircd.conf.d/目录下,并重启LIRC服务:sudo systemctl restart lircd。之后,就可以使用irsend SEND_ONCE MY_REMOTE KEY_POWER这样的命令来发送红外信号了,其中MY_REMOTE是你在配置文件中定义的遥控器名称,KEY_POWER是按键名。
5. 系统集成、调试与问题排查
5.1 整合与自动化运行
将温湿度监测和红外控制结合起来,就能构建一些自动化场景。例如,创建一个Python脚本,当温度超过28°C时,自动发送红外信号打开空调。
import subprocess import time from si7020_sensor import Si7020 # 假设之前的传感器类保存为此文件 sensor = Si7020() AC_REMOTE = "my_ac_remote" AC_ON_CMD = "KEY_POWER" AC_TEMP_UP = "KEY_TEMP_UP" TEMP_THRESHOLD_HIGH = 28.0 TEMP_THRESHOLD_LOW = 25.0 ac_is_on = False while True: temp, humi = sensor.read_all(temp_offset=-7.0) if temp is None: time.sleep(10) continue print(f"Current temp: {temp:.1f}C, AC state: {'ON' if ac_is_on else 'OFF'}") if temp > TEMP_THRESHOLD_HIGH and not ac_is_on: print("Too hot! Turning AC ON.") subprocess.run(["irsend", "SEND_ONCE", AC_REMOTE, AC_ON_CMD]) time.sleep(2) # 等待空调启动 # 假设需要按几下升温键达到目标温度 for _ in range(5): subprocess.run(["irsend", "SEND_ONCE", AC_REMOTE, AC_TEMP_UP]) time.sleep(0.5) ac_is_on = True elif temp < TEMP_THRESHOLD_LOW and ac_is_on: print("Cool enough. Turning AC OFF.") subprocess.run(["irsend", "SEND_ONCE", AC_REMOTE, AC_ON_CMD]) ac_is_on = False time.sleep(60) # 每分钟检查一次5.2 常见问题与排查速查表
在制作和调试过程中,你可能会遇到以下问题。这里提供一个快速排查指南:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
I2C设备检测不到 (i2cdetect无显示) | 1. I2C未启用。 2. 物理连接错误(SDA/SCL接反、虚焊)。 3. 电源问题(传感器未供电或电压不对)。 4. 上拉电阻缺失(某些传感器模块需要)。 | 1. 运行sudo raspi-config确认I2C已启用。2. 用万用表检查树莓派引脚3/5到传感器对应引脚的连通性,确认焊接牢固。 3. 测量传感器VCC引脚电压是否为稳定的3.3V。 4. 尝试在SDA和SCL线上各接一个4.7kΩ电阻上拉到3.3V。 |
| 温度读数明显偏高且不稳定 | 1. 传感器受树莓派CPU发热影响(主要因素)。 2. I2C总线受到干扰。 | 1.物理隔离:尝试用杜邦线将传感器移开主板一段距离。 2.软件校准:对比已知准确温度计,计算并应用固定的偏移量(如本项目的-7°C)。 3.降低采样率:延长两次读取之间的间隔,减少传感器自身发热。 |
| 红外控制无效或距离极短 | 1. LIRC配置错误或未启动。 2. 红外发射管极性接反。 3. 驱动电路限流电阻过大,电流不足。 4. 发射管本身功率太小或损坏。 | 1. 运行systemctl status lircd检查服务状态。用irsend LIST MY_REMOTE ""测试命令是否有效。2. 用手机摄像头对准发射管,按下遥控时观察是否发出微弱紫光(红外光对摄像头可见)。 3. 根据发射管参数重新计算并更换更小的限流电阻,增大工作电流。 4. 更换一个已知良好的大功率红外发射管。 |
| CNC雕刻走线粘连或断裂 | 1. 切割深度(Cut Z)设置不当。 2. 刀具磨损或装夹不牢。 3. 未进行自动调平(Autolevel)。 4. 走线设计太细(小于刀具有效切割宽度)。 | 1. 先用废板进行深度测试,找到刚好刮净铜层又不伤基板的深度。 2. 检查并更换锋利刀具,确保刀具在夹头中不晃动。 3.务必执行自动调平,并设置合理的探测网格密度。 4. 在PCB设计软件中,将最小线宽/间距规则设置为0.6mm或以上。 |
| 焊接后芯片不工作或发热 | 1. 焊点桥接(短路)。 2. 芯片极性或方向焊反。 3. 静电击穿或烙铁温度过高损坏。 | 1. 在放大镜下仔细检查所有引脚间有无细小的锡桥。使用助焊剂和吸锡带清理。 2. 对照数据手册和PCB丝印,确认芯片方向(通常有圆点或缺口标记对应PCB上的标记)。 3. 焊接时佩戴防静电手环,控制烙铁温度在350°C以下,接触时间尽可能短。 |
完成所有调试后,你可以为你的Python脚本创建系统服务,让其开机自启动,这样你的树莓派扩展板就成为一个24小时不间断工作的智能环境监测与控制终端。这个项目最大的收获不在于最终的那块小板,而在于整个从设计、制造到编程、调试的完整闭环体验。它让你对硬件如何与软件对话有了最直观的理解,下一次当你再看到任何智能设备,你大概都能在心里勾勒出它从电路图到成品的大致路径了。