常用传感器
传感器是 Arduino 感知外部世界的"感官"。本章将介绍最常用传感器的原理和使用方法。
温湿度传感器 DHT11/DHT22
DHT 系列传感器是最常用的温湿度传感器,价格低廉,使用简单。
DHT11 vs DHT22
| 特性 | DHT11 | DHT22 |
|---|---|---|
| 温度范围 | 0-50°C | -40-80°C |
| 温度精度 | ±2°C | ±0.5°C |
| 湿度范围 | 20-80% | 0-100% |
| 湿度精度 | ±5% | ±2-5% |
| 采样间隔 | 1秒 | 2秒 |
| 价格 | 便宜 | 稍贵 |
硬件连接
DHT 引脚 1 (VCC) ── 5V
DHT 引脚 2 (DATA) ── D2(数据引脚)
DHT 引脚 3 (NC) ── 悬空
DHT 引脚 4 (GND) ── GND
DHT 引脚 2 和 5V 之间连接 10kΩ 上拉电阻(部分模块已集成)
代码示例
首先需要安装 DHT 库:项目 → 加载库 → 管理库 → 搜索 "DHT sensor library"
#include <DHT.h>
#define DHT_PIN 2
#define DHT_TYPE DHT22 // 或 DHT11
DHT dht(DHT_PIN, DHT_TYPE);
void setup() {
Serial.begin(9600);
dht.begin();
Serial.println("DHT 传感器测试");
}
void loop() {
// 读取温湿度
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
// 检查读取是否成功
if (isnan(humidity) || isnan(temperature)) {
Serial.println("读取失败!");
return;
}
// 计算体感温度
float heatIndex = dht.computeHeatIndex(temperature, humidity, false);
Serial.print("湿度: ");
Serial.print(humidity);
Serial.print("% | 温度: ");
Serial.print(temperature);
Serial.print("°C | 体感: ");
Serial.print(heatIndex);
Serial.println("°C");
delay(2000); // DHT22 需要 2 秒采样间隔
}
超声波测距传感器 HC-SR04
HC-SR04 通过发射超声波并接收回波来测量距离,范围 2cm-400cm。
工作原理
- 触发引脚发送 10μs 高电平脉冲
- 模块发射 8 个 40kHz 超声波脉冲
- 接收引脚收到回波后输出高电平
- 高电平持续时间 = 声波往返时间
- 距离 = (时间 × 声速) / 2
硬件连接
HC-SR04 VCC ── 5V
HC-SR04 GND ── GND
HC-SR04 Trig ── D9(触发)
HC-SR04 Echo ── D10(接收)
代码示例
const int TRIG_PIN = 9;
const int ECHO_PIN = 10;
void setup() {
Serial.begin(9600);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
}
void loop() {
float distance = measureDistance();
Serial.print("距离: ");
Serial.print(distance);
Serial.println(" cm");
delay(500);
}
float measureDistance() {
// 发送触发信号
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// 读取回波时间(微秒)
long duration = pulseIn(ECHO_PIN, HIGH);
// 计算距离(声速 343m/s = 0.0343cm/μs)
float distance = duration * 0.0343 / 2;
return distance;
}
改进版本(带滤波)
const int TRIG_PIN = 9;
const int ECHO_PIN = 10;
const int NUM_SAMPLES = 5;
void setup() {
Serial.begin(9600);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
}
void loop() {
float distance = getFilteredDistance();
if (distance > 0) {
Serial.print("距离: ");
Serial.print(distance);
Serial.println(" cm");
} else {
Serial.println("测量失败");
}
delay(200);
}
float getFilteredDistance() {
float sum = 0;
int validSamples = 0;
for (int i = 0; i < NUM_SAMPLES; i++) {
float d = measureDistance();
if (d > 2 && d < 400) { // 过滤无效值
sum += d;
validSamples++;
}
delay(20);
}
return validSamples > 0 ? sum / validSamples : -1;
}
float measureDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000); // 30ms 超时
return duration * 0.0343 / 2;
}
人体红外传感器 HC-SR501
HC-SR501 是一种热释电红外传感器,用于检测人体移动。
硬件连接
HC-SR501 VCC ── 5V
HC-SR501 GND ── GND
HC-SR501 OUT ── D2
调节说明
- 时间延迟调节:检测触发后持续高电平的时间(0.3秒-5分钟)
- 灵敏度调节:检测距离(3-7米)
- 触发模式选择:
- H(可重复触发):持续检测期间保持高电平
- L(不可重复触发):检测后进入锁定状态
代码示例
const int PIR_PIN = 2;
const int LED_PIN = 13;
void setup() {
Serial.begin(9600);
pinMode(PIR_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
Serial.println("等待传感器稳定...");
delay(10000); // PIR 需要 10-60 秒稳定
Serial.println("系统就绪");
}
void loop() {
int motionDetected = digitalRead(PIR_PIN);
if (motionDetected == HIGH) {
digitalWrite(LED_PIN, HIGH);
Serial.println("检测到人体移动!");
} else {
digitalWrite(LED_PIN, LOW);
}
delay(100);
}
光线传感器
光敏电阻(LDR)
最简单的光线传感器,阻值随光照强度变化。
硬件连接:
5V ── LDR ── A0 ── 10kΩ 电阻 ── GND
代码:
const int LDR_PIN = A0;
void setup() {
Serial.begin(9600);
}
void loop() {
int lightValue = analogRead(LDR_PIN);
// 映射为百分比(根据实际校准)
int brightness = map(lightValue, 0, 1023, 100, 0);
Serial.print("光线强度: ");
Serial.print(brightness);
Serial.println("%");
delay(500);
}
BH1750 数字光强传感器
I2C 接口的数字光强传感器,精度更高。
硬件连接:
BH1750 VCC ── 5V
BH1750 GND ── GND
BH1750 SCL ── A5(Uno)
BH1750 SDA ── A4(Uno)
BH1750 ADDR ── GND(设置地址 0x23)
代码:需要安装 BH1750 库
#include <Wire.h>
#include <BH1750.h>
BH1750 lightMeter;
void setup() {
Serial.begin(9600);
Wire.begin();
lightMeter.begin();
Serial.println("BH1750 测试");
}
void loop() {
float lux = lightMeter.readLightLevel();
Serial.print("光照强度: ");
Serial.print(lux);
Serial.println(" lx");
delay(1000);
}
烟雾/气体传感器 MQ-2
MQ-2 可检测烟雾、液化气、丁烷、丙烷、甲烷、酒精、氢气等。
硬件连接
MQ-2 VCC ── 5V
MQ-2 GND ── GND
MQ-2 A0 ── A0(模拟输出)
MQ-2 D0 ── D2(数字输出,可选)
代码示例
const int MQ_PIN = A0;
const int LED_PIN = 13;
const int BUZZER_PIN = 8;
// 报警阈值(根据实际校准)
const int SMOKE_THRESHOLD = 300;
void setup() {
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
Serial.println("MQ-2 传感器预热中...");
delay(20000); // 预热 20 秒
Serial.println("系统就绪");
}
void loop() {
int smokeValue = analogRead(MQ_PIN);
Serial.print("烟雾值: ");
Serial.println(smokeValue);
if (smokeValue > SMOKE_THRESHOLD) {
// 触发报警
digitalWrite(LED_PIN, HIGH);
tone(BUZZER_PIN, 1000, 200);
Serial.println("警告:检测到烟雾!");
} else {
digitalWrite(LED_PIN, LOW);
noTone(BUZZER_PIN);
}
delay(500);
}
土壤湿度传感器
用于检测土壤湿度,常用于自动浇花系统。
硬件连接
传感器 VCC ── 5V
传感器 GND ── GND
传感器 A0 ── A0
代码示例
const int SOIL_PIN = A0;
const int PUMP_PIN = 8;
// 阈值(需根据实际校准)
const int DRY_THRESHOLD = 800; // 干燥阈值
const int WET_THRESHOLD = 400; // 湿润阈值
void setup() {
Serial.begin(9600);
pinMode(PUMP_PIN, OUTPUT);
}
void loop() {
int soilValue = analogRead(SOIL_PIN);
// 映射为湿度百分比(值越小越湿)
int moisture = map(soilValue, 1023, 0, 0, 100);
moisture = constrain(moisture, 0, 100);
Serial.print("土壤湿度: ");
Serial.print(moisture);
Serial.println("%");
// 自动浇水逻辑
if (soilValue > DRY_THRESHOLD) {
Serial.println("土壤干燥,开始浇水");
digitalWrite(PUMP_PIN, HIGH);
delay(3000); // 浇水 3 秒
digitalWrite(PUMP_PIN, LOW);
}
delay(5000); // 每 5 秒检测一次
}
声音传感器
声音检测模块
简单的声音检测,输出高低电平。
const int SOUND_PIN = 2;
const int LED_PIN = 13;
void setup() {
Serial.begin(9600);
pinMode(SOUND_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
int soundDetected = digitalRead(SOUND_PIN);
if (soundDetected == LOW) { // 通常低电平有效
digitalWrite(LED_PIN, HIGH);
Serial.println("检测到声音!");
delay(200); // 消抖
} else {
digitalWrite(LED_PIN, LOW);
}
}
麦克风模块(模拟输出)
const int MIC_PIN = A0;
void setup() {
Serial.begin(9600);
}
void loop() {
int soundLevel = analogRead(MIC_PIN);
Serial.print("声音强度: ");
Serial.println(soundLevel);
delay(50);
}
综合示例:环境监测站
整合多个传感器的环境监测系统:
#include <DHT.h>
#define DHT_PIN 2
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
const int LDR_PIN = A0;
const int SOIL_PIN = A1;
const int MQ_PIN = A2;
const int TRIG_PIN = 9;
const int ECHO_PIN = 10;
void setup() {
Serial.begin(9600);
dht.begin();
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
Serial.println("=== 环境监测站 ===");
}
void loop() {
// 读取温湿度
float temp = dht.readTemperature();
float humidity = dht.readHumidity();
// 读取光线
int light = analogRead(LDR_PIN);
// 读取土壤湿度
int soil = analogRead(SOIL_PIN);
// 读取空气质量
int airQuality = analogRead(MQ_PIN);
// 读取距离
float distance = measureDistance();
// 输出报告
Serial.println("\n----- 环境报告 -----");
Serial.print("温度: "); Serial.print(temp); Serial.println("°C");
Serial.print("湿度: "); Serial.print(humidity); Serial.println("%");
Serial.print("光线: "); Serial.println(light);
Serial.print("土壤: "); Serial.println(soil);
Serial.print("空气质量: "); Serial.println(airQuality);
Serial.print("距离: "); Serial.print(distance); Serial.println("cm");
Serial.println("-------------------");
delay(3000);
}
float measureDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000);
return duration * 0.0343 / 2;
}
传感器使用技巧
1. 电源去耦
在传感器电源引脚附近添加 0.1μF 电容,减少电源噪声:
传感器 VCC ──┬── 5V
└── 0.1μF ── GND
2. 数据滤波
传感器读数常有噪声,使用移动平均滤波:
int getSmoothedValue(int pin, int samples = 10) {
long sum = 0;
for (int i = 0; i < samples; i++) {
sum += analogRead(pin);
delayMicroseconds(100);
}
return sum / samples;
}
3. 校准
传感器需要校准才能获得准确读数:
// 在 setup 中进行校准
int baseline;
void setup() {
// 采集 100 个样本求平均作为基准值
long sum = 0;
for (int i = 0; i < 100; i++) {
sum += analogRead(A0);
delay(10);
}
baseline = sum / 100;
}
下一步
掌握了常用传感器后,我们将学习如何控制各种电机,包括直流电机、舵机和步进电机。