模拟信号处理ADC采集、DAC输出与温湿度光照传感器数据读取(嵌入式开发入门)

在嵌入式系统开发中,模拟信号处理是连接物理世界与数字系统的核心技术,其中ADC(模数转换)、DAC(数模转换)和传感器数据读取是最基础也最常用的技能组合。

一、模拟信号处理基础:ADC与DAC核心原理

1.1 ADC(模数转换器):把模拟信号变成数字信号

ADC的核心作用是将连续变化的模拟信号(如传感器输出的电压、电流)转换为离散的数字信号,供单片机或处理器处理。比如温度传感器检测到25℃时输出1.25V电压,ADC会将这个电压值转换为对应的数字代码,让控制器能识别和计算。

关键工作流程

  • 采样:按固定时间间隔捕捉模拟信号的瞬时值(需满足奈奎斯特定理,采样频率≥2倍信号最高频率,避免信号失真);
  • 量化:将采样得到的模拟值映射到有限的数字等级(比如10位ADC可分成1024个等级);
  • 编码:将量化后的等级转换为二进制数字(如10位ADC对应0~1023的数值范围)。

核心性能参数

  • 分辨率:常见8位(0255)、10位(01023)、12位(0~4095),位数越高精度越高;
  • 采样率:每秒采样次数(单位kHz/MHz),速率越高越能捕捉快速变化的信号;
  • 输入范围:可接收的电压区间(通常由开发板供电电压或参考电压决定,如3.3V或5V)。

1.2 DAC(数模转换器):把数字信号还原为模拟信号

DAC与ADC功能相反,负责将处理器输出的数字信号转换为连续的模拟信号,驱动外部模拟设备工作。比如将数字指令转换为电压信号,控制LED亮度、电机转速或扬声器发声。

关键工作流程

  • 解码:接收处理器输出的数字值,解读为对应的电压/电流等级;
  • 重建:通过电阻网络(如R-2R梯形网络)生成模拟信号;
  • 平滑:通过低通滤波器消除阶梯波形的高频噪声,输出连续信号。

核心性能参数

  • 分辨率:与ADC一致,决定输出模拟信号的精度(如12位DAC可输出4096种不同电压);
  • 输出范围:可输出的电压/电流区间(通常与参考电压相关);
  • 建立时间:输出信号稳定到目标值的时间,影响动态信号的响应速度。

1.3 传感器与模拟信号的关联

温度、湿度、光照等传感器是模拟信号的主要来源,其输出信号类型分为两种:

  • 模拟输出型:直接输出05V电压或420mA电流(如部分温度传感器),需通过ADC转换后读取;
  • 数字输出型:内置ADC模块,直接输出数字信号(如I2C协议的BH1750光照传感器),无需额外转换但需按协议读取。

选择传感器时需根据场景匹配:工业长距离传输优先420mA电流型(抗干扰强),家庭/办公场景选数字型(部署便捷),传统工控系统可选05V电压型(兼容性好)。

二、实操:ADC采集完整步骤(以Arduino/ESP32为例)

ADC采集是传感器数据读取的基础,以下以“采集模拟电压信号”为例,讲解硬件接线、软件配置和代码实现。

2.1 硬件准备

  • 主控板:Arduino UNO或ESP32开发板;
  • 模拟信号源:电位器(或传感器模拟输出端);
  • 辅助器材:杜邦线3根、5V电源(可选)。

2.2 硬件接线

  • 电位器VCC引脚 → 开发板5V引脚;
  • 电位器GND引脚 → 开发板GND引脚;
  • 电位器信号引脚 → 开发板ADC输入引脚(Arduino选A0A5,ESP32选GPIO36GPIO39等ADC引脚)。

2.3 软件配置与代码实现

核心配置要点:

  • 参考电压设置:默认使用开发板供电电压(Arduino UNO为5V,ESP32为3.3V),也可通过analogReference()函数设置内部或外部参考电压;
  • 采样速度优化:Arduino默认ADC时钟为125kHz,可通过调整预分频器平衡速度与精度(推荐分频64,时钟250kHz);
  • 噪声抑制:在输入引脚并联0.1µF电容到GND,或采样时短暂关闭中断。

完整代码(含注释):

void setup() {
  Serial.begin(9600); // 初始化串口通信(用于数据打印)
  // ADC配置:设置参考电压为默认5V,优化采样时钟
  analogReference(DEFAULT); 
  ADCSRA &= ~(bit(ADPS0) | bit(ADPS1) | bit(ADPS2)); // 清除预分频位
  ADCSRA |= bit(ADPS1) | bit(ADPS2); // 分频64,ADC时钟250kHz(平衡速度与精度)
}

void loop() {
  noInterrupts(); // 关闭中断,减少采样噪声
  int adcRaw = analogRead(A0); // 读取A0引脚ADC原始值(0~1023)
  interrupts(); // 恢复中断
  
  // 电压转换:ADC原始值 → 实际电压(5V参考电压)
  float voltage = adcRaw * (5.0 / 1023.0); 
  
  // 串口打印结果
  Serial.print("ADC原始值:");
  Serial.print(adcRaw);
  Serial.print(" | 实际电压:");
  Serial.print(voltage);
  Serial.println("V");
  
  delay(100); // 采样间隔(可根据需求调整)
}

2.4 数据验证与优化

  • 打开串口监视器(波特率9600),旋转电位器可看到数值随电压变化;
  • 若数据波动大:增加采样间隔、添加硬件滤波电容,或采用多次采样取平均值(如连续读取5次取中间值);
  • 若精度不足:更换12位ADC的开发板(如ESP32),或使用外部高精度ADC模块(如ADS1115)。

三、实操:DAC输出完整步骤(生成模拟波形)

DAC输出常用于驱动模拟设备,以下以“生成正弦波”为例,结合Arduino/ESP32讲解实操流程。

3.1 硬件准备

  • 主控板:ESP32(内置DAC功能,Arduino UNO需外接DAC模块如MCP4725);
  • 输出设备:示波器(用于观察波形)、LED(用于简单验证);
  • 辅助器材:杜邦线2根、面包板1块。

3.2 硬件接线

  • ESP32 DAC输出引脚(GPIO25或GPIO26) → 示波器输入通道;
  • 若接LED:需串联220Ω电阻(DAC输出引脚→电阻→LED→GND)。

3.3 软件配置与代码实现

核心配置要点:

  • ESP32内置12位DAC,输出电压范围0~3.3V;
  • 波形生成:预计算正弦波采样点,通过循环输出实现连续波形;
  • 频率控制:通过调整采样间隔控制波形频率(采样点越多波形越平滑)。

完整代码(生成1kHz正弦波):

#include <math.h>

const int dacPin = 25; // ESP32 DAC输出引脚
const float freq = 1000; // 目标波形频率(1kHz)
const int samplesPerCycle = 255; // 每个周期采样点数(平滑度控制)
uint16_t sineTable[samplesPerCycle]; // 正弦波采样表

void setup() {
  Serial.begin(115200);
  // 预计算正弦波采样值(映射-1~1到0~4095,适配12位DAC)
  for (int i = 0; i < samplesPerCycle; i++) {
    float angle = 2 * PI * i / samplesPerCycle;
    uint16_t val = 2048 + 2047 * sin(angle); // 中点2048,振幅2047
    sineTable[i] = constrain(val, 0, 4095); // 防止溢出
  }
  Serial.println("DAC正弦波输出开始...");
}

void loop() {
  static unsigned long lastTime = 0;
  static int index = 0;
  // 计算采样间隔(控制波形频率)
  unsigned long interval = 1000000 / (freq * samplesPerCycle); 
  
  if (micros() - lastTime >= interval) {
    dacWrite(dacPin, sineTable[index]); // DAC输出正弦波采样值
    index = (index + 1) % samplesPerCycle; // 循环采样表
    lastTime = micros();
  }
}

3.4 效果验证

  • 用示波器连接DAC输出引脚,可观察到稳定的正弦波;
  • 调整freq参数可改变波形频率,增加samplesPerCycle可提升波形平滑度;
  • 若使用Arduino UNO:需外接MCP4725 DAC模块(I2C通信),通过adafruit_mcp4725库实现输出。

四、实操:温湿度/光照传感器数据读取

传感器数据读取是模拟信号处理的典型应用,以下选择3种常用传感器,讲解接线、协议配置和代码实现。

4.1 温度湿度传感器:DHT11(数字型,含内置ADC)

硬件准备:

  • 传感器:DHT11(3针/4针版本);
  • 接线:VCC→5V,GND→GND,DATA→Arduino D4引脚(需串联10kΩ上拉电阻)。

代码实现(需安装DHT库):

#include <DHT.h>

#define DHTPIN 4       // 数据引脚
#define DHTTYPE DHT11  // 传感器类型
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  dht.begin(); // 初始化传感器
  delay(1000); // 传感器启动延时
}

void loop() {
  // 读取温湿度(DHT11采样间隔≥1秒)
  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature();
  
  // 数据校验(避免读取错误)
  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("传感器数据读取失败,请检查接线!");
    delay(1000);
    return;
  }
  
  // 打印结果
  Serial.print("湿度:");
  Serial.print(humidity);
  Serial.print("% | 温度:");
  Serial.print(temperature);
  Serial.println("℃");
  
  delay(2000); // 采样间隔2秒
}

4.2 光照传感器:BH1750(I2C数字型)

硬件准备:

  • 传感器:BH1750;
  • 接线:VCC→5V,GND→GND,SCL→Arduino A5,SDA→Arduino A4(I2C引脚)。

代码实现(需安装BH1750库):

#include <Wire.h>
#include <BH1750.h>

BH1750 lightSensor; // 初始化传感器
uint16_t lightIntensity; // 光照强度(单位lx)

void setup() {
  Serial.begin(9600);
  Wire.begin();
  // 初始化传感器(1lx分辨率,采样时间120ms)
  if (!lightSensor.begin(BH1750::ONE_TIME_HIGH_RES_MODE)) {
    Serial.println("光照传感器初始化失败!");
    while (1); // 初始化失败则暂停
  }
}

void loop() {
  if (lightSensor.measurementReady()) {
    lightIntensity = lightSensor.readLightLevel(); // 读取光照强度
    Serial.print("光照强度:");
    Serial.print(lightIntensity);
    Serial.println(" lx");
  }
  
  // 重新启动测量(连续模式)
  lightSensor.startMeasurement(BH1750::CONTINUOUS_HIGH_RES_MODE);
  delay(200);
}

4.3 传感器数据校准与优化

  • 温湿度校准:DHT11默认误差±2℃/±5%RH,可通过实际测量值修正(如temperature = temperature + 0.5);
  • 光照传感器:BH1750可切换分辨率模式(高分辨率适合弱光环境,低分辨率适合强光);
  • 抗干扰措施:工业环境中使用屏蔽线,远离电机、变频器等强电磁干扰源,或采用RS485总线组网。

五、综合项目案例:环境光控系统(ADC+DAC+传感器)

5.1 项目功能

通过BH1750读取光照强度,ADC采集传感器数据,DAC输出模拟电压控制LED亮度(光照越暗LED越亮,反之越暗)。

5.2 物料清单

  • 主控板:ESP32;
  • 传感器:BH1750光照传感器;
  • 执行器:LED、220Ω电阻;
  • 辅助器材:杜邦线、面包板。

5.3 硬件接线

  • BH1750:VCC→5V,GND→GND,SCL→GPIO22,SDA→GPIO21;
  • LED:ESP32 DAC引脚(GPIO25)→220Ω电阻→LED→GND。

5.4 完整代码

#include <Wire.h>
#include <BH1750.h>

BH1750 lightSensor;
const int dacPin = 25; // DAC输出引脚(控制LED)
uint16_t lightVal;
uint16_t dacVal;

void setup() {
  Serial.begin(115200);
  Wire.begin();
  lightSensor.begin(BH1750::CONTINUOUS_HIGH_RES_MODE);
  pinMode(dacPin, OUTPUT);
}

void loop() {
  // 读取光照强度
  if (lightSensor.measurementReady()) {
    lightVal = lightSensor.readLightLevel();
    
    // 光照强度映射为DAC值(光照越强,DAC值越小,LED越暗)
    dacVal = map(lightVal, 0, 1000, 4095, 500); // 0~1000lx对应500~4095DAC值
    dacVal = constrain(dacVal, 500, 4095); // 限制最小亮度(避免LED熄灭)
    
    dacWrite(dacPin, dacVal); // DAC输出控制LED
    
    // 打印状态
    Serial.print("光照:");
    Serial.print(lightVal);
    Serial.print("lx | DAC值:");
    Serial.print(dacVal);
    Serial.println(" | LED亮度:" + String(map(dacVal, 500, 4095, 10, 100)) + "%");
  }
  
  delay(300);
}

5.5 效果说明

  • 打开串口监视器可查看光照强度、DAC值和LED亮度百分比;
  • 用手遮挡传感器,光照强度降低,LED亮度自动增加;
  • 移开遮挡物,光照强度升高,LED亮度自动减弱。

六、常见问题排查与进阶建议

6.1 常见问题解决

  1. 传感器读不到数据:检查电源电压(如DHT11需3.3~6V)、接线是否松动、通信协议是否匹配(如I2C引脚是否接对);
  2. ADC采集数据波动大:增加采样间隔、添加硬件滤波电容、采用多次采样取平均值,或远离干扰源;
  3. DAC输出波形失真:减少采样间隔、增加采样点数、添加低通滤波器,或降低波形频率;
  4. 数据精度不足:更换更高分辨率的ADC/DAC模块、校准参考电压、优化传感器安装位置(如温度传感器远离热源)。

6.2 进阶学习方向

  1. 高精度采集:使用ADS1115(16位ADC)、MCP4725(12位DAC)等专用模块,提升数据精度;
  2. 抗干扰设计:工业场景采用差分信号传输、屏蔽线缆,或使用4~20mA电流型传感器;
  3. 多传感器组网:通过RS485或WiFi实现多个温湿度/光照传感器数据采集,构建分布式监测系统;
  4. 信号滤波算法:在软件中实现卡尔曼滤波、滑动平均滤波,进一步降低数据噪声。

模拟信号处理是嵌入式开发的核心技能,掌握ADC/DAC操作和传感器数据读取后,可拓展到音频处理、电机控制、工业自动化等更多场景。建议多动手实操,结合示波器、万用表等工具观察信号变化,加深对原理的理解。

要不要我帮你整理一份模拟信号处理常用模块选型清单,包含ADC/DAC模块、温湿度/光照传感器的型号、参数、适用场景和采购建议?# 模拟信号处理完整教程:ADC采集、DAC输出与温湿度光照传感器数据读取(嵌入式开发入门)
在嵌入式系统开发中,模拟信号处理是连接物理世界与数字系统的核心技术,其中ADC(模数转换)、DAC(数模转换)和传感器数据读取是最基础也最常用的技能组合。本教程从原理到实操,结合Arduino/ESP32开发板,手把手教你掌握模拟信号处理全流程,内容兼顾入门友好性与工程实用性,适合电子爱好者、嵌入式入门开发者参考。

一、模拟信号处理基础:ADC与DAC核心原理

1.1 ADC(模数转换器):把模拟信号变成数字信号

ADC的核心作用是将连续变化的模拟信号(如传感器输出的电压、电流)转换为离散的数字信号,供单片机或处理器处理。比如温度传感器检测到25℃时输出1.25V电压,ADC会将这个电压值转换为对应的数字代码,让控制器能识别和计算。

关键工作流程

  • 采样:按固定时间间隔捕捉模拟信号的瞬时值(需满足奈奎斯特定理,采样频率≥2倍信号最高频率,避免信号失真);
  • 量化:将采样得到的模拟值映射到有限的数字等级(比如10位ADC可分成1024个等级);
  • 编码:将量化后的等级转换为二进制数字(如10位ADC对应0~1023的数值范围)。

核心性能参数

  • 分辨率:常见8位(0255)、10位(01023)、12位(0~4095),位数越高精度越高;
  • 采样率:每秒采样次数(单位kHz/MHz),速率越高越能捕捉快速变化的信号;
  • 输入范围:可接收的电压区间(通常由开发板供电电压或参考电压决定,如3.3V或5V)。

1.2 DAC(数模转换器):把数字信号还原为模拟信号

DAC与ADC功能相反,负责将处理器输出的数字信号转换为连续的模拟信号,驱动外部模拟设备工作。比如将数字指令转换为电压信号,控制LED亮度、电机转速或扬声器发声。

关键工作流程

  • 解码:接收处理器输出的数字值,解读为对应的电压/电流等级;
  • 重建:通过电阻网络(如R-2R梯形网络)生成模拟信号;
  • 平滑:通过低通滤波器消除阶梯波形的高频噪声,输出连续信号。

核心性能参数

  • 分辨率:与ADC一致,决定输出模拟信号的精度(如12位DAC可输出4096种不同电压);
  • 输出范围:可输出的电压/电流区间(通常与参考电压相关);
  • 建立时间:输出信号稳定到目标值的时间,影响动态信号的响应速度。

1.3 传感器与模拟信号的关联

温度、湿度、光照等传感器是模拟信号的主要来源,其输出信号类型分为两种:

  • 模拟输出型:直接输出05V电压或420mA电流(如部分温度传感器),需通过ADC转换后读取;
  • 数字输出型:内置ADC模块,直接输出数字信号(如I2C协议的BH1750光照传感器),无需额外转换但需按协议读取。

选择传感器时需根据场景匹配:工业长距离传输优先420mA电流型(抗干扰强),家庭/办公场景选数字型(部署便捷),传统工控系统可选05V电压型(兼容性好)。

二、实操:ADC采集完整步骤(以Arduino/ESP32为例)

ADC采集是传感器数据读取的基础,以下以“采集模拟电压信号”为例,讲解硬件接线、软件配置和代码实现。

2.1 硬件准备

  • 主控板:Arduino UNO或ESP32开发板;
  • 模拟信号源:电位器(或传感器模拟输出端);
  • 辅助器材:杜邦线3根、5V电源(可选)。

2.2 硬件接线

  • 电位器VCC引脚 → 开发板5V引脚;
  • 电位器GND引脚 → 开发板GND引脚;
  • 电位器信号引脚 → 开发板ADC输入引脚(Arduino选A0A5,ESP32选GPIO36GPIO39等ADC引脚)。

2.3 软件配置与代码实现

核心配置要点:

  • 参考电压设置:默认使用开发板供电电压(Arduino UNO为5V,ESP32为3.3V),也可通过analogReference()函数设置内部或外部参考电压;
  • 采样速度优化:Arduino默认ADC时钟为125kHz,可通过调整预分频器平衡速度与精度(推荐分频64,时钟250kHz);
  • 噪声抑制:在输入引脚并联0.1µF电容到GND,或采样时短暂关闭中断。

完整代码(含注释):

void setup() {
  Serial.begin(9600); // 初始化串口通信(用于数据打印)
  // ADC配置:设置参考电压为默认5V,优化采样时钟
  analogReference(DEFAULT); 
  ADCSRA &= ~(bit(ADPS0) | bit(ADPS1) | bit(ADPS2)); // 清除预分频位
  ADCSRA |= bit(ADPS1) | bit(ADPS2); // 分频64,ADC时钟250kHz(平衡速度与精度)
}

void loop() {
  noInterrupts(); // 关闭中断,减少采样噪声
  int adcRaw = analogRead(A0); // 读取A0引脚ADC原始值(0~1023)
  interrupts(); // 恢复中断
  
  // 电压转换:ADC原始值 → 实际电压(5V参考电压)
  float voltage = adcRaw * (5.0 / 1023.0); 
  
  // 串口打印结果
  Serial.print("ADC原始值:");
  Serial.print(adcRaw);
  Serial.print(" | 实际电压:");
  Serial.print(voltage);
  Serial.println("V");
  
  delay(100); // 采样间隔(可根据需求调整)
}

2.4 数据验证与优化

  • 打开串口监视器(波特率9600),旋转电位器可看到数值随电压变化;
  • 若数据波动大:增加采样间隔、添加硬件滤波电容,或采用多次采样取平均值(如连续读取5次取中间值);
  • 若精度不足:更换12位ADC的开发板(如ESP32),或使用外部高精度ADC模块(如ADS1115)。

三、实操:DAC输出完整步骤(生成模拟波形)

DAC输出常用于驱动模拟设备,以下以“生成正弦波”为例,结合Arduino/ESP32讲解实操流程。

3.1 硬件准备

  • 主控板:ESP32(内置DAC功能,Arduino UNO需外接DAC模块如MCP4725);
  • 输出设备:示波器(用于观察波形)、LED(用于简单验证);
  • 辅助器材:杜邦线2根、面包板1块。

3.2 硬件接线

  • ESP32 DAC输出引脚(GPIO25或GPIO26) → 示波器输入通道;
  • 若接LED:需串联220Ω电阻(DAC输出引脚→电阻→LED→GND)。

3.3 软件配置与代码实现

核心配置要点:

  • ESP32内置12位DAC,输出电压范围0~3.3V;
  • 波形生成:预计算正弦波采样点,通过循环输出实现连续波形;
  • 频率控制:通过调整采样间隔控制波形频率(采样点越多波形越平滑)。

完整代码(生成1kHz正弦波):

#include <math.h>

const int dacPin = 25; // ESP32 DAC输出引脚
const float freq = 1000; // 目标波形频率(1kHz)
const int samplesPerCycle = 255; // 每个周期采样点数(平滑度控制)
uint16_t sineTable[samplesPerCycle]; // 正弦波采样表

void setup() {
  Serial.begin(115200);
  // 预计算正弦波采样值(映射-1~1到0~4095,适配12位DAC)
  for (int i = 0; i < samplesPerCycle; i++) {
    float angle = 2 * PI * i / samplesPerCycle;
    uint16_t val = 2048 + 2047 * sin(angle); // 中点2048,振幅2047
    sineTable[i] = constrain(val, 0, 4095); // 防止溢出
  }
  Serial.println("DAC正弦波输出开始...");
}

void loop() {
  static unsigned long lastTime = 0;
  static int index = 0;
  // 计算采样间隔(控制波形频率)
  unsigned long interval = 1000000 / (freq * samplesPerCycle); 
  
  if (micros() - lastTime >= interval) {
    dacWrite(dacPin, sineTable[index]); // DAC输出正弦波采样值
    index = (index + 1) % samplesPerCycle; // 循环采样表
    lastTime = micros();
  }
}

3.4 效果验证

  • 用示波器连接DAC输出引脚,可观察到稳定的正弦波;
  • 调整freq参数可改变波形频率,增加samplesPerCycle可提升波形平滑度;
  • 若使用Arduino UNO:需外接MCP4725 DAC模块(I2C通信),通过adafruit_mcp4725库实现输出。

四、实操:温湿度/光照传感器数据读取

传感器数据读取是模拟信号处理的典型应用,以下选择3种常用传感器,讲解接线、协议配置和代码实现。

4.1 温度湿度传感器:DHT11(数字型,含内置ADC)

硬件准备:

  • 传感器:DHT11(3针/4针版本);
  • 接线:VCC→5V,GND→GND,DATA→Arduino D4引脚(需串联10kΩ上拉电阻)。

代码实现(需安装DHT库):

#include <DHT.h>

#define DHTPIN 4       // 数据引脚
#define DHTTYPE DHT11  // 传感器类型
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  dht.begin(); // 初始化传感器
  delay(1000); // 传感器启动延时
}

void loop() {
  // 读取温湿度(DHT11采样间隔≥1秒)
  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature();
  
  // 数据校验(避免读取错误)
  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("传感器数据读取失败,请检查接线!");
    delay(1000);
    return;
  }
  
  // 打印结果
  Serial.print("湿度:");
  Serial.print(humidity);
  Serial.print("% | 温度:");
  Serial.print(temperature);
  Serial.println("℃");
  
  delay(2000); // 采样间隔2秒
}

4.2 光照传感器:BH1750(I2C数字型)

硬件准备:

  • 传感器:BH1750;
  • 接线:VCC→5V,GND→GND,SCL→Arduino A5,SDA→Arduino A4(I2C引脚)。

代码实现(需安装BH1750库):

#include <Wire.h>
#include <BH1750.h>

BH1750 lightSensor; // 初始化传感器
uint16_t lightIntensity; // 光照强度(单位lx)

void setup() {
  Serial.begin(9600);
  Wire.begin();
  // 初始化传感器(1lx分辨率,采样时间120ms)
  if (!lightSensor.begin(BH1750::ONE_TIME_HIGH_RES_MODE)) {
    Serial.println("光照传感器初始化失败!");
    while (1); // 初始化失败则暂停
  }
}

void loop() {
  if (lightSensor.measurementReady()) {
    lightIntensity = lightSensor.readLightLevel(); // 读取光照强度
    Serial.print("光照强度:");
    Serial.print(lightIntensity);
    Serial.println(" lx");
  }
  
  // 重新启动测量(连续模式)
  lightSensor.startMeasurement(BH1750::CONTINUOUS_HIGH_RES_MODE);
  delay(200);
}

4.3 传感器数据校准与优化

  • 温湿度校准:DHT11默认误差±2℃/±5%RH,可通过实际测量值修正(如temperature = temperature + 0.5);
  • 光照传感器:BH1750可切换分辨率模式(高分辨率适合弱光环境,低分辨率适合强光);
  • 抗干扰措施:工业环境中使用屏蔽线,远离电机、变频器等强电磁干扰源,或采用RS485总线组网。

五、综合项目案例:环境光控系统(ADC+DAC+传感器)

5.1 项目功能

通过BH1750读取光照强度,ADC采集传感器数据,DAC输出模拟电压控制LED亮度(光照越暗LED越亮,反之越暗)。

5.2 物料清单

  • 主控板:ESP32;
  • 传感器:BH1750光照传感器;
  • 执行器:LED、220Ω电阻;
  • 辅助器材:杜邦线、面包板。

5.3 硬件接线

  • BH1750:VCC→5V,GND→GND,SCL→GPIO22,SDA→GPIO21;
  • LED:ESP32 DAC引脚(GPIO25)→220Ω电阻→LED→GND。

5.4 完整代码

#include <Wire.h>
#include <BH1750.h>

BH1750 lightSensor;
const int dacPin = 25; // DAC输出引脚(控制LED)
uint16_t lightVal;
uint16_t dacVal;

void setup() {
  Serial.begin(115200);
  Wire.begin();
  lightSensor.begin(BH1750::CONTINUOUS_HIGH_RES_MODE);
  pinMode(dacPin, OUTPUT);
}

void loop() {
  // 读取光照强度
  if (lightSensor.measurementReady()) {
    lightVal = lightSensor.readLightLevel();
    
    // 光照强度映射为DAC值(光照越强,DAC值越小,LED越暗)
    dacVal = map(lightVal, 0, 1000, 4095, 500); // 0~1000lx对应500~4095DAC值
    dacVal = constrain(dacVal, 500, 4095); // 限制最小亮度(避免LED熄灭)
    
    dacWrite(dacPin, dacVal); // DAC输出控制LED
    
    // 打印状态
    Serial.print("光照:");
    Serial.print(lightVal);
    Serial.print("lx | DAC值:");
    Serial.print(dacVal);
    Serial.println(" | LED亮度:" + String(map(dacVal, 500, 4095, 10, 100)) + "%");
  }
  
  delay(300);
}

5.5 效果说明

  • 打开串口监视器可查看光照强度、DAC值和LED亮度百分比;
  • 用手遮挡传感器,光照强度降低,LED亮度自动增加;
  • 移开遮挡物,光照强度升高,LED亮度自动减弱。
posted @ 2025-12-28 21:40  好汉技术  阅读(395)  评论(0)    收藏  举报