跳到主要内容

常用传感器

传感器是 Arduino 感知外部世界的"感官"。本章将介绍最常用传感器的原理和使用方法。

温湿度传感器 DHT11/DHT22

DHT 系列传感器是最常用的温湿度传感器,价格低廉,使用简单。

DHT11 vs DHT22

特性DHT11DHT22
温度范围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。

工作原理

  1. 触发引脚发送 10μs 高电平脉冲
  2. 模块发射 8 个 40kHz 超声波脉冲
  3. 接收引脚收到回波后输出高电平
  4. 高电平持续时间 = 声波往返时间
  5. 距离 = (时间 × 声速) / 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;
}

下一步

掌握了常用传感器后,我们将学习如何控制各种电机,包括直流电机、舵机和步进电机。