数码管与DS18B20温度报警器设计

一、系统概述

设计使用DS18B20数字温度传感器采集环境温度,通过数码管实时显示温度值,并在温度超过设定阈值时触发声光报警。系统具有温度显示、阈值设置、超限报警等功能,适用于家庭、实验室、温室等场景的温度监测。

二、系统组成

1. 核心组件

组件 型号/参数 功能
主控制器 Arduino Uno/Nano 系统控制核心
温度传感器 DS18B20 (±0.5°C精度) 温度数据采集
显示模块 4位共阳数码管 温度值显示
报警模块 有源蜂鸣器+红色LED 超温声光报警
输入模块 3个按键 设置温度阈值
电源模块 5V DC电源适配器 系统供电

2. 电路连接图

+-------------------+          +-----------------+
|   Arduino Uno      |          |  4位共阳数码管  |
|                   |          |                 |
|   D2  ------------>|----------| DIO (数据)      |
|   D3  ------------>|----------| CLK (时钟)      |
|   D4  ------------>|----------| STB (锁存)      |
|                   |          +-----------------+
|   D5  <-----------|----------| 按键1 (设置+)   |
|   D6  <-----------|----------| 按键2 (设置-)   |
|   D7  <-----------|----------| 按键3 (确认)   |
|                   |          +-----------------+
|   D8  ------------>|----------| 蜂鸣器(+)      |
|   D9  ------------>|----------| LED(+)         |
|                   |          +-----------------+
|   D10 ------------>|----------| DS18B20 (数据)  |
|   GND ------------>|----------| GND            |
|   5V  ------------>|----------| VCC            |
+-------------------+          +-----------------+

三、硬件设计

1. DS18B20温度传感器

  • 单总线接口:仅需1根数据线
  • 防水封装:适合多种环境
  • 温度范围:-55°C ~ +125°C
  • 精度:±0.5°C (-10°C ~ +85°C)

2. 数码管驱动电路

  • 74HC595移位寄存器:减少IO占用
  • 共阳数码管:高电平驱动
  • 限流电阻:220Ω (每段)

3. 报警电路

  • 有源蜂鸣器:5V驱动,内置振荡电路
  • 红色LED:指示超温状态
  • 驱动三极管:S8050 (NPN型)

四、软件设计

1. 主程序流程图

graph TD A[系统初始化] --> B[读取DS18B20温度] B --> C[数码管显示温度] C --> D{温度 > 阈值?} D -- 是 --> E[触发声光报警] D -- 否 --> F[关闭报警] E --> G[检测按键输入] F --> G G --> H{按键按下?} H -- 是 --> I[进入设置模式] H -- 否 --> B I --> J[调整阈值] J --> K[保存设置] K --> B

2. Arduino代码实现

#include <OneWire.h>
#include <DallasTemperature.h>

// 引脚定义
#define ONE_WIRE_BUS 10
#define BUZZER_PIN 8
#define LED_PIN 9
#define KEY_SET 5
#define KEY_UP 6
#define KEY_DOWN 7
#define DIO 2
#define CLK 3
#define STB 4

// 全局变量
float currentTemp = 0.0;
float alarmThreshold = 30.0; // 默认报警阈值30°C
bool alarmActive = false;
unsigned long lastUpdate = 0;
const unsigned long updateInterval = 1000; // 1秒更新一次

// 数码管显示缓冲区
byte digitBuffer[4] = {0};
byte digitPos = 0;

// 初始化OneWire和DallasTemperature
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup() {
  // 初始化串口
  Serial.begin(9600);
  
  // 设置引脚模式
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(KEY_SET, INPUT_PULLUP);
  pinMode(KEY_UP, INPUT_PULLUP);
  pinMode(KEY_DOWN, INPUT_PULLUP);
  pinMode(DIO, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(STB, OUTPUT);
  
  // 初始化DS18B20
  sensors.begin();
  sensors.setResolution(12); // 12位分辨率
  
  // 初始化数码管
  clearDisplay();
  displayNumber(8888); // 测试显示
  delay(1000);
  clearDisplay();
  
  // 从EEPROM加载阈值
  // alarmThreshold = EEPROM.read(0) + (EEPROM.read(1) << 8) / 100.0;
}

void loop() {
  // 每秒更新一次温度
  if (millis() - lastUpdate >= updateInterval) {
    readTemperature();
    lastUpdate = millis();
  }
  
  // 显示温度
  displayTemperature(currentTemp);
  
  // 检查温度是否超限
  if (currentTemp > alarmThreshold) {
    triggerAlarm();
  } else {
    stopAlarm();
  }
  
  // 检查按键输入
  checkKeys();
  
  // 短暂延时
  delay(10);
}

// 读取温度
void readTemperature() {
  sensors.requestTemperatures();
  currentTemp = sensors.getTempCByIndex(0);
  
  // 错误处理
  if (currentTemp == DEVICE_DISCONNECTED_C) {
    Serial.println("Error: Could not read temperature data");
    currentTemp = 0.0;
  }
  
  Serial.print("Current Temperature: ");
  Serial.print(currentTemp);
  Serial.println(" °C");
}

// 数码管显示温度
void displayTemperature(float temp) {
  // 将温度转换为整数显示(保留两位小数)
  int integerPart = (int)temp;
  int decimalPart = (int)((temp - integerPart) * 10);
  
  // 设置显示缓冲区
  digitBuffer[0] = integerPart / 10;   // 十位
  digitBuffer[1] = integerPart % 10;   // 个位
  digitBuffer[2] = decimalPart;         // 小数位
  digitBuffer[3] = 12;                 // 显示'C'符号
  
  // 更新数码管显示
  updateDisplay();
}

// 触发报警
void triggerAlarm() {
  if (!alarmActive) {
    digitalWrite(BUZZER_PIN, HIGH);
    digitalWrite(LED_PIN, HIGH);
    alarmActive = true;
    Serial.println("ALARM! Temperature exceeds threshold!");
  }
}

// 停止报警
void stopAlarm() {
  if (alarmActive) {
    digitalWrite(BUZZER_PIN, LOW);
    digitalWrite(LED_PIN, LOW);
    alarmActive = false;
  }
}

// 检查按键输入
void checkKeys() {
  static bool settingMode = false;
  static unsigned long lastPressTime = 0;
  const unsigned long debounceTime = 200;
  
  if (millis() - lastPressTime < debounceTime) return;
  
  if (digitalRead(KEY_SET) == LOW) {
    settingMode = !settingMode;
    lastPressTime = millis();
    
    if (settingMode) {
      // 进入设置模式,显示当前阈值
      int threshInt = (int)alarmThreshold;
      int threshDec = (int)((alarmThreshold - threshInt) * 10);
      digitBuffer[0] = threshInt / 10;
      digitBuffer[1] = threshInt % 10;
      digitBuffer[2] = threshDec;
      digitBuffer[3] = 13; // 显示'H'表示阈值
      updateDisplay();
    } else {
      // 保存设置
      // EEPROM.write(0, (int)alarmThreshold);
      // EEPROM.write(1, (int)(alarmThreshold * 100) % 100);
    }
  }
  
  if (settingMode) {
    if (digitalRead(KEY_UP) == LOW) {
      alarmThreshold += 0.5;
      if (alarmThreshold > 50.0) alarmThreshold = 50.0;
      lastPressTime = millis();
    }
    
    if (digitalRead(KEY_DOWN) == LOW) {
      alarmThreshold -= 0.5;
      if (alarmThreshold < 0.0) alarmThreshold = 0.0;
      lastPressTime = millis();
    }
  }
}

// 数码管显示函数
void updateDisplay() {
  // 数码管段码表 (0-9, C, H, 灭)
  byte digitCode[14] = {
    B00111111, // 0
    B00000110, // 1
    B01011011, // 2
    B01001111, // 3
    B01100110, // 4
    B01101101, // 5
    B01111101, // 6
    B00000111, // 7
    B01111111, // 8
    B01101111, // 9
    B00111001, // C
    B01110110, // H
    B00000000  // 灭
  };
  
  // 关闭显示
  digitalWrite(STB, HIGH);
  shiftOut(DIO, CLK, MSBFIRST, 0xFF);
  digitalWrite(STB, LOW);
  
  // 选择要更新的数码管位置
  digitalWrite(STB, HIGH);
  shiftOut(DIO, CLK, MSBFIRST, 1 << digitPos);
  digitalWrite(STB, LOW);
  
  // 发送段码
  byte code = digitCode[digitBuffer[digitPos]];
  if (digitPos == 2) { // 小数位显示小数点
    code |= B10000000;
  }
  shiftOut(DIO, CLK, MSBFIRST, code);
  digitalWrite(STB, HIGH);
  
  // 移动到下一个位置
  digitPos = (digitPos + 1) % 4;
}

// 清除显示
void clearDisplay() {
  for (int i = 0; i < 4; i++) {
    digitBuffer[i] = 12; // 灭
  }
  digitPos = 0;
  updateDisplay();
}

// 显示数字
void displayNumber(int number) {
  digitBuffer[0] = (number / 1000) % 10;
  digitBuffer[1] = (number / 100) % 10;
  digitBuffer[2] = (number / 10) % 10;
  digitBuffer[3] = number % 10;
  updateDisplay();
}

参考代码 用数码管与DS18B20设计温度报警器 www.youwenfan.com/contentcnt/135565.html

五、系统功能

1. 基本功能

  • 温度采集:DS18B20实时测量环境温度
  • 温度显示:4位数码管显示当前温度(XX.X°C)
  • 超温报警:温度超过设定阈值时触发声光报警
  • 阈值设置:通过按键设置报警温度阈值

2. 高级功能

  • 温度单位切换:支持°C/°F显示(需修改代码)
  • 报警记忆:记录超温发生时间和温度
  • 低功耗模式:空闲时进入睡眠状态
  • 数据记录:通过串口输出温度数据

六、PCB设计

1. PCB布局

+-----------------------------------+
|  [DS18B20]  [数码管]  [蜂鸣器+LED]  |
|                                   |
|  [Arduino Nano]                   |
|  +-------------------------------+ |
|  | 74HC595  | 按键  | 电源接口   | |
|  +-------------------------------+ |
|                                   |
|  [电源指示灯]  [复位按钮]          |
+-----------------------------------+

七、制作与调试

1. 制作步骤

  1. 焊接电路板:按照原理图焊接所有元件
  2. 烧录程序:使用Arduino IDE将代码上传到开发板
  3. 组装外壳:3D打印或定制塑料外壳
  4. 校准温度:使用标准温度计校准DS18B20
  5. 测试功能:验证温度显示、报警、设置功能

2. 常见问题解决

问题 解决方法
数码管显示不全 检查段码表,确认接线正确
温度读数不稳定 增加软件滤波(如移动平均)
报警不触发 检查阈值设置,确认蜂鸣器/LED正常工作
DS18B20无法通信 检查上拉电阻(4.7kΩ),确认接线正确
按键响应不灵敏 增加软件消抖,检查按键接触

八、扩展功能

1. 无线传输

  • 添加蓝牙模块(HC-05)实现手机APP监控
  • 使用ESP8266 WiFi模块上传数据到云平台

2. 多区域监测

  • 增加多个DS18B20传感器
  • 使用LCD屏显示各点温度

3. 自动控制

  • 连接继电器控制空调/加热器
  • 实现恒温控制功能

九、材料清单

序号 名称 规格/型号 数量 单价(元) 备注
1 Arduino Nano ATmega328P 1 25.00 主控板
2 DS18B20 防水型 1 8.00 温度传感器
3 4位共阳数码管 0.56英寸 1 12.00 温度显示
4 74HC595 移位寄存器 1 1.50 数码管驱动
5 有源蜂鸣器 5V 1 2.00 声音报警
6 LED 5mm红色 1 0.20 视觉报警
7 轻触按键 6×6×5mm 3 0.30 设置按键
8 电阻 220Ω 8 0.10 限流保护
9 电阻 4.7kΩ 1 0.10 DS18B20上拉
10 三极管 S8050 1 0.30 蜂鸣器驱动
11 洞洞板 5×7cm 1 5.00 电路载体
12 电源适配器 5V/1A 1 15.00 系统供电
总计 约70元
posted @ 2026-04-15 13:33  w199899899  阅读(67)  评论(0)    收藏  举报