采集光敏模块的AD数值

Tutorial: 卓越工程师 Category: 嵌入式 Published: 2026-10-23 11:05:29 Views: 1 Likes: 0 Comments: 0

313.8、采集光敏模块的 AD 数值

void setup() {                     // 定义初始化函数;Arduino Uno 上电或复位后执行一次
  pinMode(A0, INPUT);              // 将 A0 明确设为高阻输入;保留视频最终上传代码中的写法
  Serial.begin(115200);            // 以 115200 bit/s 初始化串口,串口监视器必须选择相同波特率
}                                  // setup() 初始化结束

void loop() {                      // 定义主循环;本函数结束后会从开头继续执行
  int adc = analogRead(A0);        // 对 A0 上的模拟电压进行一次 ADC 转换,并把 0~1023 的结果保存到 adc
  Serial.println(adc);             // 以十进制打印本次 ADC 结果,并在末尾发送换行符
  delay(1500);                     // 阻塞等待 1500 ms,因此下一次采样约在 1.5 秒后进行
}                                  // 本轮采样结束,随后再次进入 loop()

一、光敏电阻的使用

本节先用一只光敏电阻模块完成最小采样实验:模块的模拟输出 AO 接入 Arduino Uno 的 A0,程序每隔约 1.5 秒读取一次 ADC 转换结果并发送到串口监视器。视频实测表明,遮住光敏电阻后数值升高,用外部光源近距离照射后数值明显降低。

视频前端圆片状、带蛇形感光图案和两根引脚的器件才是光敏电阻本体。它是无正负极的两端无源电阻;蓝色电路板则是完整的光敏模块,在光敏电阻之外还集成了分压电阻、LM393 比较器、电位器和指示灯,因此模块排针具有 4 个引脚,并且 VCC、GND 不能接反。不要把“光敏电阻本体的两脚”和“模块的四针接口”混为一谈。

页首源码来自视频中最终编译、上传并实际运行的草图。课件预置代码曾写成 analogRead(right),但本节并没有定义 right;教师在 Arduino IDE 中实际输入和上传的是 analogRead(A0),因此不能把课件中的占位名称当成本节最终源码。

需要先区分两个外形很相近的名称:

  • AO 中最后一个字符是字母 O,表示模块的 Analog Output(模拟输出)。
  • A0 中最后一个字符是数字 0,表示 Arduino Uno 的第 0 路模拟输入。
  • 信号路径是 光照 → 光敏电阻阻值 → AO 电压 → A0 → Uno 内部 ADC → 0~1023 的数字结果。AO 端本身不会把模拟量转换成数字量,真正完成转换的是 Uno 内部 ADC。

1.1 代码编写

1.1.1 初始化部分

pinMode(A0, INPUT) 把 A0 明确设置为高阻输入。视频把 Uno 上的引脚模式概括为输入、输出和上拉输入;对本节使用的 AVR Uno 而言,对应常量是 INPUT、OUTPUT 和 INPUT_PULLUP。

不过,analogRead(A0) 并不依赖这句显式配置才能工作:Uno 复位后引脚默认为输入,Arduino 官方的 Analog Read Serial 示例也直接调用 analogRead(A0)。本节仍按视频原样保留 pinMode(A0, INPUT),它能表达“这一路只用于采样”的意图。不要改成 INPUT_PULLUP,否则内部上拉电阻会参与传感器分压并改变读数。

Serial.begin(115200) 设置串口传输速率。这里的 115200 是每秒传输的比特数(bit/s),串口监视器右下角也必须选择 115200 baud。原始笔记中的 125200 是识别错误,视频代码和监视器画面均为 115200。

1.1.2 循环采样与打印

程序在每一轮 loop() 中依次完成三件事:

  1. analogRead(A0) 启动一次模数转换,返回 A0 当前电压对应的 ADC 码。
  2. 局部变量 adc 保存结果;Uno 上的 int 足以容纳 0~1023。
  3. Serial.println(adc) 打印十进制数并换行,随后 delay(1500) 等待 1500 ms。

因此,串口监视器会逐行显示一个新数值。采样周期是“ADC 转换、串口发送等执行时间 + 1500 ms”,所以严格来说会略大于 1.5 秒,而不是精确的 1.500 秒。delay() 期间处理器不会继续执行本草图的其他循环业务;本节只有单路观察任务,这种阻塞写法足够演示,不能据此提前补写后续四路追光逻辑。

1.1.3 Uno 的模拟输入与 10 位 ADC

Arduino Uno R3 引出的模拟输入是 A0~A5,共 6 路,不是视频口述的“五路”。后续项目需要四只光敏模块,可以占用其中四路;本节只连接和读取 A0。

Uno 所用 ATmega328P 的 ADC 分辨率为 10 位,因此共有:

$ 2^{10}=1024\text{ 个量化码} $

这些码从 0 开始编号,所以 analogRead() 的返回范围是:

$ 0\sim 1023 $

“1024 个可能值”不等于“最大值为 1024”。原视频课件和口述中的“0~1024”以及后段误说的“$2^{14}$”都应修正:本板是 10 位 ADC、1024 个码、最大码 1023。

默认参考电压下,Uno 把接近 0 V 的输入转换为接近 0,把接近参考电压的输入转换为接近 1023。若以标称 5 V 为参考,一位最低有效位对应的理想电压步长约为:

$ \Delta V=\frac{V_{REF}}{1024}=\frac{5\text{ V}}{1024}\approx4.88\text{ mV} $

这只是 ADC 输入电压的量化结果,不是光照的 lux 值,也不是光敏电阻的欧姆值。供电与参考电压偏差、模块个体差异、安装角度和环境杂散光都会影响读数;追光项目更关心四个方向之间的相对差值。

1.1.4 AO、DO 和蓝色电位器

视频中的四针模块具有 VCC、GND、DO、AO:

引脚信号类型本节是否连接作用
VCC电源是,接 5V给分压电路、比较器和指示灯供电
GND电源参考是,接 GND为电源和 AO 信号提供共同的零电位参考
AO连续模拟电压是,接 A0随光敏分压变化,由 Uno 的 ADC 采样
DO数字比较结果否只表示 AO 位于可调阈值的哪一侧,结果为高/低电平

蓝色电位器主要用于产生 LM393 比较器的参考电压,从而调节 DO 的翻转阈值,也就是“多亮时数字输出才改变”。它不会改变光敏电阻本身,也不是本节 AO → A0 采样链路的增益旋钮。换句话说,转动它通常会改变 DO 和状态指示灯在何时翻转,却不会按比例放大或缩小 analogRead(A0) 的连续数值。

模块上通常有两只指示灯:

  • 电源指示灯在 VCC、GND 正确供电后保持点亮。
  • 比较器状态灯跟随 DO 的状态。视频所用模块在环境较亮时状态灯亮,遮挡光敏电阻后熄灭;其翻转点受电位器位置影响。其他版型若比较器输入或 LED 接法不同,亮灭极性也可能不同,应以对应原理图或实测为准。

1.2 接线教学

1.2.1 本节实际接线

本节只需三根线,DO 保持不接:

光敏电阻模块                         Arduino Uno
┌────────────┐
│ VCC        ├───────────────────── 5V
│ GND        ├───────────────────── GND
│ AO         ├───────────────────── A0
│ DO         ├──── 本节悬空,不接
└────────────┘

建议断电后按照模块丝印逐根核对,不要只凭杜邦线颜色判断。GND 不只是“负极线”,还是 AO 与 A0 共同的电压参考;没有共地,A0 读数就不可靠。AO 只能接到允许的输入电压范围内,本实验由同一 5 V 系统供电,不要再把外部高于 5 V 或负电压直接送入 A0。

视频使用的是课程方加焊了多组 5V、GND 的 Uno 扩展排针。它们只是把同一电源网络复制到多个插口,便于后续连接四只模块,并不会生成彼此隔离的新电源,也不会提高 USB 或开发板能够提供的总电流。

1.2.2 为什么亮时数值反而更小

光敏电阻(LDR)通常表现为光越强、阻值越小;光越弱、阻值越大。结合本模块接法和视频实测,AO 所在的分压链路可简化为:

5V ── 固定电阻 ──┬── AO ──> Arduino A0
                  │
               光敏电阻
                  │
                 GND

设固定电阻为 $R_F$、光敏电阻为 $R_{LDR}$,则:

$ V_{AO}=V_{CC}\times\frac{R_{LDR}}{R_F+R_{LDR}} $

由公式可直接得到本节观察到的关系:

环境变化$R_{LDR}$$V_{AO}$analogRead(A0)
光线增强变小下降数值减小
光线减弱或被遮挡变大上升数值增大

这个方向来自本节模块的实际分压接法,并不是“所有光敏模块都必然亮时数值小”。如果另一款模块把光敏电阻和固定电阻上下互换,AO 的变化方向就会反过来;换模块后应先做遮挡和照射实验再编写判断逻辑。

1.2.3 上传与串口监视器

视频中的完整操作顺序为:

  1. 把模块 AO、GND、VCC 分别接到 Uno 的 A0、GND、5V。
  2. 用 USB 数据线连接电脑,在 Arduino IDE 中选择本机实际出现的 Uno 串口。
  3. 编译并上传页首草图。
  4. 打开串口监视器,把波特率设为 115200 baud。
  5. 先记录正常环境光读数,再遮住光敏电阻,最后用外部光源近距离照射,比较三种状态。

如果监视器出现乱码,应先检查监视器与 Serial.begin(115200) 是否一致;如果始终没有新行,应检查端口、上传状态和串口监视器连接;如果数值固定为 0 或 1023,则应检查 AO 是否误接 GND/5V、三根线是否插错,以及模块与 Uno 是否共地。

1.2.4 视频实测结果

视频画面可读到的代表性数据如下;这些是演示样机的现场读数,不是所有模块都必须达到的标准值:

测试状态视频中的代表性 ADC 读数现象
普通环境光320、298、293、304,随后约 312~331AO 处于中间电压区间
用手遮挡566、553、547、558光线变弱,读数升高;状态灯熄灭
外部光源逐渐靠近290、296、193、37、26光线增强,读数显著降低

数值变化只能说明该模块在当前供电和安装条件下的相对明暗变化。它没有经过照度标定,不能把“26”直接写成 26 lux,也不能把“558”理解为光敏电阻是 558 Ω。

1.2.5 面向后续四路追光的注意点
  • 本节只验证一路 A0;四路传感器的引脚定义、差值比较和舵机动作会在后续课程中编写,不能补入本节页首源码。
  • 安装前应依次遮挡或照射每只模块,在串口中确认实际接线对应的上、下、左、右,不能只相信线色或标签。
  • 四只模块存在个体偏差。即使受到相同光照,读数也可能不同;后续阈值应结合实物测试,而不是把本节的 300、500 或 26 当作固定标准。
  • 做相对追光时,传感器之间应尽量采用相同供电、相近安装角度和一致遮光结构,否则比较结果会混入结构误差。
  • 状态灯是否点亮来自 DO 比较结果;本项目后续比较的是四路 AO 的 ADC 数值,两者不能混为一条控制信号。

核对依据

  • 本地 videos/313.8、采集光敏模块的AD数值.mp4:逐帧核对最终上传代码、A0/5V/GND 三线连接、115200 baud 串口设置、1.5 秒延时,以及环境光、遮挡和外部强光下的实际 ADC 数值与状态灯变化。
  • 本地 transcripts/313.8、采集光敏模块的AD数值.txt 与 .srt:核对讲解顺序、四路传感器的项目用途和现场操作;结合视频画面纠正“五路”“0~1024”“$2^{14}$”“125200”等转录或口述错误。
  • 本地配套 太阳能追光路灯.pptx、接线图.jpg 与最终 6.ino:只用于交叉核对模块四针定义、项目实际使用 AO 以及后续四路接口;本节源码仍严格以本节视频最终上传版本为准,没有提前补入追光程序。
  • Arduino Uno R3 官方页面:核对 Uno R3 具有 6 路模拟输入。
  • Arduino 官方 Analog Read Serial 示例:核对 analogRead(A0) 的用法、0~1023 返回范围、默认 0~5 V 输入关系,以及官方示例无需先调用 pinMode(A0, INPUT)。
  • Microchip ATmega328P 官方资料:核对 Uno 主控 ADC 的 10 位分辨率。
  • TI LM393 官方资料:核对模块所用比较器的开集电极输出性质;电位器、DO 与状态灯的具体连接仍以课程模块电路及本节实测为准。