尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Arduino UNO+HC-05蓝牙串口控制四路继电器智能家居

Arduino UNO+HC-05蓝牙串口控制四路继电器智能家居 简介这是一份面向物联网入门者、电子爱好者及毕业设计学生的Arduino智能家居控制系统设计文档以PDF形式呈现围绕Arduino UNO核心板、EDR蓝牙协议与易安卓E4A开发的Android客户端展开解决传统家电需手动接触式控制的痛点。压缩包共1个PDF文件约1.9MB内容为完整的毕业设计论文式文档含中英文摘要、目录、引言、系统总体设计方案等章节。文档系统梳理了系统架构与工作原理包括控制中心、无线通信与客户端应用三层结构模块化设计思路下的智能开关、灯光提示、场景模式、设备监控与安全防护五类功能并对比总结高效传输、操作简单、可靠性强、易于扩展等优势。读者可据此了解Arduino与蓝牙模块的对接方式、Android端软件设计流程、模块划分与集成测试方法以及环境参数监测和烟雾、门窗传感器报警的实现思路。目前已有1108人学习适合需要搭建课程设计、毕业设计或自学智能家居原型的读者参考借鉴。1. 从一块 UNO 和四个继电器说起很多人第一次把 Arduino 和智能家居摆在一起想到的是动辄上千元的整套方案。这套以 Arduino UNO 为核心的毕业设计给出了另一种答案一块 UNO、一个 HC-05 蓝牙串口模块、一块四路光耦继电器板加一个用易安卓E4A拖出来的 Android 界面就能把家里四路电器的通断搬到手机上。它的链路短得几乎没有中间层——手机和 UNO 之间走的是 EDR 蓝牙串口协议没有云、没有网关、不需要配网断电重启后重新配对一次就能继续用。代价也很明确控制距离被限制在蓝牙覆盖范围内同一时刻只允许一个主设备连接。对刚接触嵌入式的人这是把「指令下发—无线传输—执行动作」三层打通成本最低的题目对做过 STM32 或 ESP32 方案的人它能反过来提醒你模块化划分和帧协议设计这两个基本功比堆外设更值得花时间。下面按硬件接线、固件实现、上位机客户端、调试进阶四段拆开讲。2. 硬件层拆解Arduino UNO、HC-05 与四路光耦继电器接线2.1 为什么选 EDR 蓝牙而不是 WiFi 模块四路开关这个需求数据量小到可以忽略每次控制只发 7 个字节一天点一百次也才 700 字节。WiFi 的吞吐、组网、远程访问优势在这里完全用不上反而额外引入路由器配网、IP 分配、云端依赖三件事。蓝牙串口协议的做法是手机和模块之间建立一条串口仿真通道MCU 侧就把它当普通串口读写代码和有线串口调试几乎一样。HC-05 采用 CSR 的 BC417 芯片工作频段 2.4GHz ISM调制方式 GFSK模块极限发射功率 4dBm接收灵敏度约 -85dBm板载 PCB 天线标称覆盖距离 10 米尺寸 27mm×13mm×2mm邮票孔封装支持 AT 指令改参数板上有 LED 指示连接状态。这些数字落到实际使用里大概是这样的同一房间内基本不丢帧隔一堵承重墙会出现偶发延迟隔两堵墙就要考虑把模块挪到走廊或换位置。另一个必须提前知道的限制是EDR 属于经典蓝牙和 BLE 是两套不同的 Android API。用 BLE 的扫描接口去找 HC-05结果永远是空的——这是新手卡得最久的一个坑。2.2 引脚分配与交叉接线接线本身不复杂但两根数据线必须交叉这是第一个容易接反的地方。UNO 引脚接到说明5VHC-05 VCC、继电器模块 VCCHC-05 板载 LDOVCC 接 5VGNDHC-05 GND、继电器 GND必须共地否则串口收到乱码D2HC-05 TXD软串口接收脚D3HC-05 RXD软串口发送脚3.3V 逻辑D4继电器模块 1 的 IN低电平触发D5继电器模块 2 的 IN低电平触发D6继电器模块 3 的 IN低电平触发D7继电器模块 4 的 IN低电平触发注意UNO 上的软件串口接收脚固定用 D2 才有实际可用的引脚变化中断支持换成别的脚会出现「能发不能收」的现象。HC-05 的 RXD 是 3.3V 逻辑常见做法是在 D3 和 HC-05 RXD 之间串一个 1kΩ 电阻、再对地接一个 2kΩ 电阻做分压长期跑更安心。软串口占掉 D2、D3 之后D0/D1 仍然留给 USB 下载口这样上传代码时不用拔线调试体验好很多。2.3 四路光耦继电器的电气参数与负载边界选型时先看参数表再决定要不要用它去控制大功率电器。参数5V 版本典型值工作电压5V静态电流约 19mA单路触发电流2~4mA触发电平低电平 0V 触发高电平 5V 释放触点容量AC250V/10A、DC30V/10A隔离方式光耦隔离2.3.1 光耦隔离到底隔离了什么继电器线圈吸合瞬间会产生反向电动势如果线圈回路和单片机 IO 直接连通这个尖峰容易顺着电源线回灌造成 MCU 复位或死机。光耦把控制侧和线圈侧的电气连接彻底断开只保留光信号传递同时模块自带的续流二极管把线圈的反向电压钳位掉。这也是为什么一块四路光耦板只要 2~4mA 就能驱动一路比直接用三极管驱动省心。2.3.2 10A 触点容量不等于能带 10A 的空调AC250V/10A 指的是纯阻性负载下的触点能力。电机、压缩机这类感性负载启动瞬间电流是额定值的 3~7 倍直接用它去切空调或大功率水泵触点会在几个月内烧蚀粘连。合格做法是灯光、风扇、加湿器这类小功率负载直接切空调、热水器只在继电器前级做信号控制主回路交给接触器。接好线之后先用一段固定延时程序把四路逐一跑一遍确认每一路都能听到清晰的吸合声const uint8_t RELAY_PIN[4] {4, 5, 6, 7}; // 四路继电器控制脚 void setup() { for (uint8_t i 0; i 4; i) { digitalWrite(RELAY_PIN[i], HIGH); // 先写高电平避免设成输出的瞬间吸合 pinMode(RELAY_PIN[i], OUTPUT); } } void loop() { for (uint8_t i 0; i 4; i) { digitalWrite(RELAY_PIN[i], LOW); // 低电平触发吸合 delay(500); digitalWrite(RELAY_PIN[i], HIGH); // 释放 delay(200); } }这里的顺序不能颠倒。digitalWrite写在pinMode之前是为了让引脚在切换成输出模式的那一刻就是高电平反过来写的话引脚会先落到默认低电平四路继电器会同时「啪」一声吸合——上电瞬间的全部灯闪一下就是这个原因。3. 固件层实现软串口收帧、继电器寻址与状态回传3.1 软串口初始化与缓冲区处理固件要干三件事从软串口收字节、按协议把字节拼成完整指令、驱动对应引脚。前两件事的关键在于「怎么判断一帧结束了」。蓝牙串口没有包边界字节是一个一个来的必须自己定义分隔符。代码里用\n作为帧结束符收到就交给解析函数然后清空缓冲区。缓冲区大小给 16 字节够放一条完整指令和几个干扰字符每收一个字节都要检查下标有没有越界否则蓝牙断连时残留的脏数据会直接把数组写穿表现是「用着用着就死机」。3.2 帧协议设计rly-序号-动作帧格式定得越简单越好记格式如下字段取值说明固定头rly-4 字节用来丢弃无效数据通道号1~4对应继电器 1 到 4分隔符-固定第 6 个字符动作1吸合 /0释放固定第 7 个字符一条完整指令就是rly-2-1\n含义是「第 2 路继电器吸合」。这个设计放弃了 JSON、放弃了校验和换来的是手机端拼字符串、单片机端按下标取值两边都不需要任何解析库。代价是抗干扰能力弱所以固件里必须先把帧头比对一遍再往下走。3.3 上电抖动抑制与低电平触发的连锁坑低电平触发的继电器逻辑是反的引脚输出 LOW 时吸合HIGH 时释放。这意味着如果代码里习惯性写成「开 高电平」四路电器会全部反过来——按钮点「开」实际关点「关」实际开。写代码时把注释和变量名统一成RELAY_ON LOW比事后一处处翻代码划算得多。另一个坑是 UNO 复位。手机端发指令的过程中如果按下 UNO 的复位键或者 USB 供电波动导致复位引脚会回到输入态继电器状态丢失。常见做法是在setup()里把四路全部置为释放态并且把当前状态通过蓝牙回传给手机让 APP 的按钮显示与实际硬件重新对齐。3.4 完整固件与回传逻辑把上面几点合起来就是可以直接烧录的版本#include SoftwareSerial.h SoftwareSerial BT(2, 3); // RX2 接 HC-05 TXD, TX3 接 HC-05 RXD const uint8_t RELAY_PIN[4] {4, 5, 6, 7}; // 四路继电器低电平吸合 const uint8_t RELAY_ON LOW; // 低电平使能 const uint8_t RELAY_OFF HIGH; char buf[16]; uint8_t idx 0; void setup() { for (uint8_t i 0; i 4; i) { digitalWrite(RELAY_PIN[i], RELAY_OFF); // 先写电平再切输出避免上电全吸合 pinMode(RELAY_PIN[i], OUTPUT); } Serial.begin(9600); // USB 串口用于本地调试 BT.begin(9600); // 与 HC-05 默认波特率一致 } void loop() { while (BT.available() 0) { char c BT.read(); if (c \n || c \r) { // 收到结束符认为一帧收完 if (idx 7) handleFrame(buf); idx 0; memset(buf, 0, sizeof(buf)); // 清空缓冲区防止脏数据残留 } else if (idx sizeof(buf) - 1) { buf[idx] c; } } } void handleFrame(char *s) { if (strncmp(s, rly-, 4) ! 0) return; // 帧头不对直接丢弃 uint8_t ch s[4] - 0; if (ch 1 || ch 4) return; // 通道号越界 if (s[5] ! -) return; // 分隔符位置不对 uint8_t pin RELAY_PIN[ch - 1]; if (s[6] 1) digitalWrite(pin, RELAY_ON); else if (s[6] 0) digitalWrite(pin, RELAY_OFF); else return; BT.print(ok-); // 回传实际状态APP 据此刷新按钮 BT.print(ch); BT.print(-); BT.println(s[6] 1 ? 1 : 0); }handleFrame里每个return都是一道闸门帧头、通道范围、分隔符位置、动作值。任何一项不满足就直接返回不做任何动作。这种「宁可漏执行不可错执行」的写法在控制真实电器时是必须的——把rly-9-1这种越界指令放行轻则数组越界重则误开不该开的电器。BT.print那三行回传不能省。手机端发完指令就改按钮颜色看起来响应快但硬件实际有没有吸合是不知道的等固件回传ok-2-1再刷新才能保证界面和硬件一致。本地调试时把BT换成Serial再打印一遍用串口监视器就能看到每一条进出的帧。3.5 自测不接手机也能验完固件上传代码后把波特率设成 9600在串口监视器里把行尾设成「换行符」直接敲rly-1-1回车对应的继电器应该吸合同时串口回显ok-1-1。四路都测一遍再故意敲rly-8-1和abc确认没有任何一路动作。这一步过了才说明固件侧的协议解析是可靠的后面连不上手机时就只需要排查蓝牙和 APP。4. 上位机侧E4A 可视化界面与蓝牙配对、重连逻辑4.1 易安卓的事件驱动模型E4A 全称 easy for android2013 年发布是一套全中文的 Android 开发平台。它的写法和 Eclipse 时代的手写 Activity 完全不同从左侧组件区把按钮、标签、蓝牙客户端组件拖到可视化界面上然后在属性区设名称、标题、可用状态在事件列表里双击某个事件就往里面填逻辑。这套模型对硬件背景的人特别友好——不需要理解 Activity 生命周期只需要理解「什么事件触发什么动作」。代价是复杂逻辑不好维护所以界面上的按钮命名要规范比如按钮_继电器1、标签_状态后面事件块一多才不会乱。4.2 SPP 连接流程与配对失败分支整个客户端的状态机只有四步搜索设备、找到目标设备、连接、连接成功后解锁控制按钮。用 E4A 的事件块写出来大致是这样 蓝牙1 为蓝牙客户端组件仅作事件逻辑示意组件名以实际工程为准 事件 按钮_搜索.被单击() 蓝牙1.搜索设备() 结束 事件 事件 蓝牙1.发现设备(名称 为 文本型, 地址 为 文本型) 如果 名称 SmartHome 则 与 HC-05 的 ATNAME 保持一致 蓝牙1.连接设备(地址) 结束 如果 结束 事件 事件 蓝牙1.连接状态改变(状态 为 整数型) 如果 状态 2 则 已连接 标签_状态.标题 配对成功 按钮_继电器1.可用 真 按钮_继电器2.可用 真 按钮_继电器3.可用 真 按钮_继电器4.可用 真 否则 标签_状态.标题 配对失败请重新配对 按钮_继电器1.可用 假 结束 如果 结束 事件 事件 按钮_继电器1.被单击() 如果 继电器1状态 假 则 蓝牙1.发送数据(rly-1-1 字符(10)) 继电器1状态 真 否则 蓝牙1.发送数据(rly-1-0 字符(10)) 继电器1状态 假 结束 如果 结束 事件两个细节决定成败。第一搜索时按名称过滤SmartHome这个名字必须和 HC-05 里ATNAME设的值完全一致大小写都不能错否则扫描列表刷出一堆设备却永远匹配不上。第二发送数据结尾的字符(10)就是换行符对应固件里的\n。漏掉它单片机侧会一直等不到帧结束符表现是「手机显示已发送继电器毫无反应」——这是排查时间最长的一类问题。另外Android 6.0 以后扫描经典蓝牙设备需要位置权限只申请蓝牙权限是扫不到任何东西的。E4A 的蓝牙组件在部分版本里会自己弹权限申请如果没有弹就要在工程配置里手动勾上定位权限。4.3 界面状态与固件回传的对齐只靠本地变量继电器1状态来记状态会遇到一个典型场景手机连着的时候手动按了继电器板上的按键或者 UNO 被复位过此时 APP 显示「开」硬件其实是「关」。解决方式是在客户端加一个接收事件解析固件回传的ok-通道-状态用它去覆盖本地变量并刷新按钮。更省事的做法是每次成功连接后主动让固件把四路当前状态全量回传一次。这样无论中间发生过什么连接建立的那一刻界面和硬件就自动对齐了不需要用户手动点一遍确认。四个按钮的初始颜色统一设成灰色收到回传再变成高亮视觉上也能一眼看出哪几路是通的。5. 调试与进阶AT 指令改参、供电与误触发排查HC-05 出厂默认名称五花八门波特率也可能是 38400 而不是 9600所以第一件事是进 AT 模式把它改成自己要的样子。AT 模式必须在上电之前把 EN/KEY 脚接到高电平上电后再接是进不去的。进入后波特率固定为 38400常用指令如下指令作用典型返回AT连通性测试OKATNAMESmartHome改设备名APP 按这个名字过滤OKATPSWD1234改配对码OKATUART9600,0,0改串口波特率为 9600OKATROLE0设为从机模式等待手机连接OKATCMODE1允许任意地址连接OK改动波特率后固件里的BT.begin(9600)必须同步改两边不一致的表现是收到一堆乱码或者干脆一个字都没有。改完记得断电把 EN/KEY 脚松开再上电模块才会以正常数据模式工作。供电是最容易忽略的一环。HC-05 工作电流约 40mA四路继电器同时吸合的电流接近 300mA全部从 UNO 的 5V 脚取电会让板载稳压芯片明显发热严重时触发欠压复位表现是「按了开关手机断连了」。稳妥做法是继电器模块单独用一个 5V 电源供电只把 GND 和 UNO 共起来D4~D7 的信号线照常接。判断是否踩到这个坑的方法很简单用万用表量一下四路全开时 UNO 的 5V 脚电压掉到 4.5V 以下就说明供电不足。最后是误触发。如果发现某个继电器偶尔自己吸合一下先看是不是 D4~D7 的走线和电源线捆在一起——继电器的线圈是感性负载走线并行时容易把尖峰耦合到信号线上。分开走线、信号线尽量短必要时在继电器模块的 VCC 和 GND 之间并一个 100μF 电解电容问题基本就消失了。本文还有配套的精品资源点击获取
返回列表