IoT-For-Beginners 第 3 课:用传感器与执行器与物理世界交互——从模拟/数字信号原理到智能夜灯实战
【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners
导读
本篇文章对应 IoT-For-Beginners 课程体系中《入门》模块的第 3 课,核心主题是 IoT 设备如何与物理世界交互:**传感器(sensors)**负责把物理世界的温度、光照、运动等信息转换为电信号交给设备,执行器(actuators)则把设备发出的电信号转换成发光、发声、转动等物理动作。文章会先讲清传感器与执行器的分类与底层电学原理(模拟/数字、ADC/DAC、PWM),随后带你走完一个完整实战:给设备接入光线传感器和 LED,构建一个根据环境光照自动亮灭的智能夜灯。读完本文,你将理解传感器/执行器的电气工作方式,并能在 Wio Terminal、Raspberry Pi 和虚拟设备三种硬件路径上完成可运行的夜灯程序。
本文主体内容来自 translations/cs/1-getting-started/lessons/3-sensors-and-actuators/README.md,并辅以该课目录下的硬件操作指南与示例代码(
code-sensor/、code-actuator/)进行深化说明。
什么是传感器?
传感器(sensor)是感知物理世界的硬件设备——它测量周围环境的一项或多项属性,并把信息发送给 IoT 设备。由于可测量的对象极多(从空气温度这类自然属性,到运动这类物理交互),传感器的种类非常庞大。
常见传感器包括:
| 传感器 | 作用 |
|---|---|
| 温度传感器 | 测量空气或所处环境的温度;面向爱好者和开发者的型号常把气压、湿度集成在同一个传感器里 |
| 按钮 | 检测是否被按下 |
| 光线传感器 | 检测光照水平,可针对特定颜色、紫外线(UV)、红外线(IR)或普通可见光 |
| 摄像头 | 通过拍照或视频流捕捉世界的视觉呈现 |
| 加速度计 | 检测多个方向的运动 |
| 麦克风 | 感知声音,可以是总体音量水平,也可以是定向声音 |
所有传感器的共同点是:把感知到的物理量转换为能被 IoT 设备解释的电信号。这个电信号如何被解释,取决于传感器本身,也取决于它与 IoT 设备通信所用的通信协议(本课程后续会介绍 I²C、SPI、UART 等协议)。
实战:把传感器接入设备
本课提供了三条硬件路径的接入指南,你可以按自己的设备选择:
- Arduino 平台(Wio Terminal):wio-terminal-sensor.md
- 单板计算机(Raspberry Pi):pi-sensor.md
- 单板计算机(虚拟设备 CounterFit):virtual-device-sensor.md
三条路径使用的都是光线传感器:物理硬件上它是一个基于 [photodiode](光电二极管)的模拟传感器,输出一个 0~1023 的整数值来表示相对光照量(不映射到 lux 等标准单位)。三条路径的核心代码完全一致,只是导入的库不同(真实 Grove 库 vs CounterFit shim 库),下面会逐一展开。
传感器类型:模拟 vs 数字
传感器分为**模拟(analog)和数字(digital)**两大类。
模拟传感器
最基础的传感器大多是模拟传感器:IoT 设备向传感器送入一个电压,传感器内部元件调整这个电压,然后测量传感器返回的电压来得到传感器数值。
**背景知识:电压(Voltage)**是衡量"推动"电荷从一处移到另一处(如从电池正极到负极)的力的大小。标准 AA 电池为 1.5V(V 是伏特的符号)。不同电气元件需要不同电压:LED 在 2~3V 即可点亮,而 100W 白炽灯泡需要 240V。
**电位器(potentiometer)**是一个典型例子:它是一个可以在两个位置之间旋转的旋钮,传感器测量旋转角度。
IoT 设备向电位器发送一个电压信号,例如 5V。当电位器被调节时,它改变另一侧输出的电压。想象一个从 0 到 11 的旋钮(类似放大器上的音量旋钮):当电位器处于完全关闭位置(0)时,输出 0V;处于完全打开位置(11)时,输出 5V。返回的电压被 IoT 设备读取后,设备即可据此作出响应。
取决于传感器类型,输出电压可能是任意值,也可能映射到标准单位。例如基于**热敏电阻(thermistor)**的模拟温度传感器,其电阻随温度变化,输出端电压可以在代码里通过计算转换为开尔文(Kelvin),再换算成 °C 或 °F。
⚠️思考题:如果传感器返回的电压比发送的电压更高(例如来自外部电源),会发生什么?⛔️ 切勿实际测试!
模拟到数字的转换(ADC)
IoT 设备本质上是数字设备——只能处理 0 和 1,无法直接处理模拟值。因此,模拟传感器的数值必须先转换为数字信号才能被处理。许多 IoT 设备内置模数转换器(ADC,analog-to-digital converter);传感器也可以通过**连接板(connector board)**上的 ADC 工作。例如在 Seeed Grove 生态系统中,Raspberry Pi 上的模拟传感器连接到安装在 Pi 上方、与 GPIO 引脚相连的"hat"板上的特定端口,该 hat 内置 ADC,把电压转换为可从 Pi 的 GPIO 引脚输出的数字信号。
具体换算过程举例:假设你有一个连接到 3.3V 设备的模拟光线传感器,它返回 1V。这个 1V 在数字世界没有意义,需要转换。电压会根据设备和传感器按一定刻度换算为模拟值。以 Seeed Grove 光线传感器为例,它输出 0~1023 的值;在 3.3V 供电下,1V 输出对应数值300。IoT 设备无法把 300 当作模拟值处理,因此该值会被 Grove hat 转换为0000000100101100(300 的二进制表示),再交给 IoT 设备处理。
从编程角度看,这类转换通常由传感器附带的库完成,你无需自己处理:Grove 光线传感器在 Python 里调用light属性,在 Arduino 里调用analogRead,就能直接拿到 300 这个数值。
数字传感器
数字传感器和模拟传感器一样,通过电压变化感知周围世界,区别在于它们输出数字信号:要么只测量两种状态,要么内置 ADC 自行完成转换。数字传感器越来越普及,正是为了省去在连接板或 IoT 设备上使用 ADC 的需求。
最简单的数字传感器是按钮/开关——一个只有开、关两种状态的传感器。
IoT 设备上的 GPIO 引脚可以直接把这种信号读成 0 或 1:如果返回电压与发送电压相同,读到的值是 1,否则是 0。信号无需转换,它只能是 0 或 1:
- 3.3V 进入按钮,按钮断开 → 输出 0V → 读到值 0
- 3.3V 进入按钮,按钮闭合 → 输出 3.3V → 读到值 1
💁关于电压容差:电压永远不会完全精确,因为传感器内部元件存在电阻,所以通常有容差范围。例如 Raspberry Pi 的 GPIO 引脚工作在 3.3V,把高于 1.8V 的返回信号读为 1,低于 1.8V 读为 0。
更高级的数字传感器会读取模拟值,再用板载 ADC转换为数字信号。例如数字温度传感器同样使用热电偶、同样测量当前温度下热电偶电阻引起的电压变化,但它不返回模拟值、也不依赖设备或连接板做转换,而是由传感器内置的 ADC 完成转换,并以一串 0 和 1 发送给 IoT 设备——发送方式与按钮的数字信号完全一致(1 表示满电压,0 表示 0V)。
发送数字数据还让传感器可以做更复杂的事:发送更详细的数据,甚至为安全传感器发送加密数据。摄像头就是一个例子——它捕捉图像并作为包含该图像的数字数据(通常是 JPEG 等压缩格式)发送给 IoT 设备,甚至可以逐帧发送完整图像或压缩视频流,实现视频流传输。
什么是执行器?
执行器(actuator)是传感器的"反义词"——它们把 IoT 设备的电信号转换为与物理世界的交互,例如发光、发声或驱动电机转动。
常见执行器包括:
| 执行器 | 作用 |
|---|---|
| LED | 通电时发光 |
| 扬声器 | 根据收到的信号发声,从简单的蜂鸣器到能播放音乐的音频扬声器 |
| 步进电机 | 把信号转换为定义好的旋转量,例如把旋钮旋转 90° |
| 继电器 | 用电信号控制开/关的开关;允许 IoT 设备的小电压去控制更大的电压 |
| 屏幕 | 更复杂的执行器,在多段显示屏上展示信息;从简单 LED 显示屏到高分辨率视频监视器 |
实战:用执行器构建智能夜灯
这一步要做的是:用光线传感器收集光照水平,用执行器(LED)在检测到光照过低时发光,组装成一个 IoT 夜灯。逻辑用伪代码表示为:
检查光照水平。 如果光照小于 300 打开 LED 否则 关闭 LED按以下指南接入执行器:
- Arduino(Wio Terminal):wio-terminal-actuator.md
- 单板计算机(Raspberry Pi):pi-actuator.md
- 单板计算机(虚拟设备 CounterFit):virtual-device-actuator.md
执行器类型:模拟 vs 数字
与传感器一样,执行器也分为模拟与数字两大类。
模拟执行器
模拟执行器接收模拟信号并将其转换为某种交互,交互强度随供给电压变化。典型例子是可调光灯泡——供给灯泡的电压大小决定亮度。
和传感器的情况一样,真正的 IoT 设备工作在数字信号上。要发送模拟信号,IoT 设备需要数模转换器(DAC,digital-to-analog converter)——可以内置在设备上,也可以在连接板上。DAC 把 IoT 设备的 0 和 1 转换为执行器可用的模拟电压。
⚠️思考题:如果 IoT 设备发送的执行器电压超过其承受能力,会发生什么?⛔️ 切勿实际测试!
脉冲宽度调制(PWM)
另一种把 IoT 设备数字信号转换为模拟信号的方法是脉冲宽度调制(PWM,pulse-width modulation):发送大量短促的数字脉冲,使其表现得像模拟信号。以用 PWM 控制电机转速为例:
假设用 5V 电源控制一个电机:向电机发送一个短脉冲,把电压切换到高电平(5V)并保持 0.02 秒,这段时间内电机可旋转十分之一圈(36°);然后暂停 0.02 秒,发送低电平(0V)。每个"开+关"周期持续 0.04s,随后循环重复。
这意味着每秒有 25 个 0.02s 的 5V 脉冲驱动电机旋转,每个脉冲后跟 0.02s 的 0V 暂停。每个脉冲让电机转十分之一圈,因此电机每秒完成 2.5 圈——你用一个数字信号就让电机以每秒 2.5 圈、即 **150 转/分(rpm)**的速度旋转:
25 pulses per second x 0.1 rotations per pulse = 2.5 rotations per second 2.5 rotations per second x 60 seconds in a minute = 150rpm🎓 当 PWM 信号一半时间开启、一半时间关闭时,称为50% 占空比(duty cycle)。占空比以信号处于开启状态的时间百分比来衡量。
改变脉冲宽度即可改变电机转速:保持同样的 0.04s 周期,把开启脉冲缩短一半(0.01s),关闭脉冲延长到 0.03s。每秒脉冲数(25)不变,但每个开启脉冲只有原来一半长,每次只转二十分之一圈,于是电机每秒完成 1.25 圈,即75 rpm——通过改变数字信号的脉冲宽度,你把模拟电机的速度降为一半:
25 pulses per second x 0.05 rotations per pulse = 1.25 rotations per second 1.25 rotations per second x 60 seconds in a minute = 75rpm✅思考题:尤其在低速时,如何让电机转动保持平滑?是用少量长脉冲配长暂停,还是用大量极短脉冲配极短暂停?
💁 补充:一些传感器也会用 PWM 把模拟信号转换为数字信号。
数字执行器
数字执行器与数字传感器类似:要么只有两个状态(由高/低电压控制),要么内置 DAC,能把数字信号转换为模拟信号。
最简单的数字执行器就是 LED:设备发送数字信号 1 时输出高电压点亮 LED,发送数字信号 0 时电压降到 0V、LED 熄灭。
✅思考题:还能想到哪些简单的两状态执行器?例如螺线管(solenoid)——一种电磁体,通电后可以移动门闩实现门的上锁/开锁。
更高级的数字执行器(如屏幕)要求数字数据按特定格式发送,通常附带库来简化发送正确控制数据的过程。
三平台夜灯完整代码实现
下面给出三条硬件路径的完整夜灯代码(结合光线传感器阈值 300 与 LED 控制),全部来自仓库code-sensor/与code-actuator/目录。
Wio Terminal(Arduino / PlatformIO)
Wio Terminal 的光线传感器内置在设备背面、透过透明塑料窗可见,直接使用引脚WIO_LIGHT即可。在setup中把WIO_LIGHT配置为INPUT,把右侧 Grove 插座对应的数字引脚D0配置为OUTPUT(右侧 Grove 插座支持模拟和数字传感器/执行器;左侧插座仅用于 I²C 与数字设备):
#include <Arduino.h> void setup() { Serial.begin(9600); while (!Serial) ; // Wait for Serial to be ready delay(1000); pinMode(WIO_LIGHT, INPUT); pinMode(D0, OUTPUT); } void loop() { int light = analogRead(WIO_LIGHT); Serial.print("Light value: "); Serial.println(light); if (light < 300) { digitalWrite(D0, HIGH); } else { digitalWrite(D0, LOW); } delay(1000); }代码要点:
analogRead(WIO_LIGHT)从板载光线传感器读取 0~1023 的模拟值;- 光照小于 300 时,
digitalWrite(D0, HIGH)向D0写高电平(值为 1)点亮 LED;光照 ≥ 300 时写LOW(值为 0)熄灭 LED; - 向执行器发送数字值时,
LOW是 0V,HIGH是设备最大电压——Wio Terminal 的高电平为3.3V; delay(1000)让程序每秒采样一次,光照无需连续检查,降低功耗。
完整源码位于 code-actuator/wio-terminal/nightlight/src/main.cpp,对应传感器版在 code-sensor/wio-terminal/nightlight/src/main.cpp。PlatformIO 工程配置见 platformio.ini:使用atmelsam平台、seeed_wio_terminal板卡与arduino框架。串口监视器(9600 波特率)会输出类似下面的光照读数,用手遮挡/移开传感器时数值随之变化:
--- Miniterm on /dev/cu.usbmodem101 9600,8,N,1 --- Light value: 4 Light value: 5 Light value: 4 Light value: 158 Light value: 343 Light value: 348 Light value: 344Raspberry Pi(Grove Base hat + Python)
Grove 光线传感器通过 Grove 线缆连接到 Grove Base hat 的模拟插座 A0(GPIO 引脚旁一排插座中右数第二个);Grove LED 模块连接到数字插座 D5。注意 LED 是二极管,电流只能单向导通,安装时较平的一侧为负极,应连接到模块靠中间一侧的孔位,圆侧引脚接标有+的孔位。
import time from grove.grove_light_sensor_v1_2 import GroveLightSensor from grove.grove_led import GroveLed light_sensor = GroveLightSensor(0) led = GroveLed(5) while True: light = light_sensor.light print('Light level:', light) if light < 300: led.on() else: led.off() time.sleep(1)代码要点:
GroveLightSensor(0)连接模拟引脚A0;GroveLed(5)连接数字引脚D5;- 该 hat 上所有插座都有唯一引脚号:引脚 0、2、4、6 是模拟引脚,引脚 5、16、18、22、24、26 是数字引脚;
light属性在 0~1023 刻度上读取当前光照;led.on()/led.off()分别发送数字值 1/0;- Raspberry Pi 的数字高电平(1 值)同样是3.3V;
- 用
python3 app.py运行后控制台输出示例:Light level: 634→Light level: 230→Light level: 104……遮住传感器时 LED 应点亮(若 LED 不亮,检查是否插反、亮度旋钮是否旋到最大)。
完整源码见 code-actuator/pi/nightlight/app.py,传感器版见 code-sensor/pi/nightlight/app.py。
虚拟设备(CounterFit)
没有实体硬件时,可在 CounterFit 应用中模拟同样的夜灯:在Sensors面板创建类型为Light、引脚为0的传感器;在Actuators面板创建类型为LED、引脚为5的执行器(可用颜色选择器修改 LED 颜色)。代码与 Raspberry Pi 版几乎一致,只是把库换成 CounterFit shim:
import time from counterfit_connection import CounterFitConnection from counterfit_shims_grove.grove_light_sensor_v1_2 import GroveLightSensor from counterfit_shims_grove.grove_led import GroveLed CounterFitConnection.init('127.0.0.1', 5000) light_sensor = GroveLightSensor(0) led = GroveLed(5) while True: light = light_sensor.light print('Light level:', light) if light < 300: led.on() else: led.off() time.sleep(1)运行后在 CounterFit 中修改光照值(直接在Value输入数字后点Set,或勾选Random并设置Min/Max让传感器每次返回随机数),就能让 LED 在 300 阈值上下翻转。完整源码见 code-actuator/virtual-device/nightlight/app.py 与 code-sensor/virtual-device/nightlight/app.py。
挑战与课后作业
挑战:前两课要求你尽可能多地列出家中、学校或工作场所里的 IoT 设备,并判断它们是围绕微控制器(microcontroller)、单板计算机(single-board computer)还是两者混合构建的。现在请进一步思考:每个设备上连接了哪些传感器和执行器?每个传感器与执行器的用途是什么?
课后作业:深入研究传感器与执行器,详见 assignment.md。
小结
- 传感器把物理量转换为电信号,分为模拟与数字两类;模拟信号需要经 ADC(设备内置或连接板承载)转为 0/1 才能被 IoT 设备处理,数字传感器则直接输出两状态信号或通过板载 ADC 输出数字数据。
- 执行器把电信号转换为物理动作,同样分模拟与数字两类;模拟执行器需要 DAC 或PWM来由数字信号驱动,PWM 通过调整脉冲宽度(占空比)可以连续地控制电机转速等模拟量。
- 三条硬件路径(Wio Terminal、Raspberry Pi、CounterFit 虚拟设备)共享同一套夜灯逻辑:读取光照 → 与阈值 300 比较 → 控制 LED 开关,示例代码均可直接在仓库 code-sensor 与 code-actuator 目录中找到。
理解这些基础后,后续课程将在此基础上继续深入:连接互联网、搭建更完整的物联网应用(可继续浏览 2-farm、3-transport 等模块的实战项目)。
【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考