恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Arduino入门实战:温湿度报警、光控窗帘、自动浇花项目全记录
首页
资讯中心
/
Arduino入门实战:温湿度报警、光控窗帘、自动浇花项目全记录
Arduino入门实战:温湿度报警、光控窗帘、自动浇花项目全记录
发布时间:2026/10/15 20:26:43
Arduino玩了大半年回头翻翻自己的笔记和代码发现已经攒了好几个能跑的小项目。这篇文章算是我入门阶段的真实记录不是那种三步教你学会某某的速成教程更像是一个过来人把弯路和惊喜都摊开给你看。内容主要围绕几个问题展开怎么选板子、怎么写第一段能动手的代码以及我做过的几个小东西——一个能显示温湿度、超阈值会响的报警小站一个天黑自动合上的窗帘控制器还有一个阳台自动浇花的小装置。如果你刚拿到一块Arduino板子不知道从哪下手这篇应该能帮你省掉不少弯路如果你已经做过几个项目可以直接翻到最后的问题排查部分说不定能对号入座。我尽量把为什么这么做讲清楚再给出可以直接抄的接线和代码。文章比较长按入门顺序排开先认识Arduino本身然后是环境与编程基础接着逐个项目拆解最后是常见问题与排查技巧。代码和接线表都贴出来了照着做就能跑起来但要真正变成自己的东西还是建议每个模块都亲手改一改、调一调。1. 入门第一件事想清楚Arduino是什么以及怎么选板子1.1 为什么入门选Arduino而不是其他板子先说说我自己的理解。Arduino本质是一块单片机开发板加上一整套好用的开发工具和库。它最大的价值不是某颗神乎其神的芯片而是把读传感器、控制电机、处理逻辑这件事的门槛压得很低。比如你要让一个灯每隔一秒闪烁用裸单片机得看数据手册、翻寄存器、配时钟用Arduino只需要在setup和loop里写几行代码。我更愿意把它理解成硬件世界里的乐高引脚就相当于插孔传感器模块是现成的积木块代码则是连接它们的卡扣。不需要懂复杂的电路原理也能在半小时内让一个LED按你的心意亮灭。等玩明白了再往深处钻那时再看寄存器、看原理图反而容易多了。不少人会把Arduino和树莓派放在一起比较。树莓派是一台完整的迷你电脑能跑操作系统、能跑各种大程序但它的强项不在实时控制上开机要几十秒系统更新的问题也多一个引脚坏了整个板子都受影响。Arduino上电瞬间就开始跑程序某个引脚坏了可以换一个脚重新定义这对硬件折腾来说非常友好。对入门者来说Arduino还有个隐形优势——生态资料极其丰富你踩到的坑基本都有人踩过搜一搜就能找到填坑记录。1.2 板子怎么选Uno、Nano还是ESP32我的第一块板子是Uno R3后来才慢慢接触Nano和ESP8266。给新手的建议是先买Uno。不是因为性能多好而是因为它的引脚全部排开和面包板配合很方便而且绝大多数教程都默认用Uno遇到问题好查。等做出来的东西想缩小体积或者想装进小盒子里可以换Nano代码几乎不用改。如果确定要联网直接上ESP8266或ESP32。它们自带WiFi性能也更强但要留意绝大多数型号只有3.3V逻辑电平而很多传感器模块是5V供电的不能直接把3.3V引脚接到5V传感器上得做电平匹配。另外ESP系列的库和传统Arduino有些差异模拟输入脚的定义、串口数量等都不一样代码移植时容易踩坑。板卡逻辑电平典型用途入门友好度Uno R35V通用学习、原型验证最高Nano5V缩小体积、小项目高ESP82663.3V联网数据采集中ESP323.3V联网复杂控制中如果是纯入门不用纠结直接Uno R3等有具体需求了再换。1.3 入门必备的配件清单我踩过的一个弯路是买了一整套豪华配件包里面塞了大量用不到的模块真正有用的反而被挤在角落里。其实入门阶段的核心配件不算多Arduino板子、面包板、杜邦线公对公为主、母对母备用、几颗按键、电阻包尤其10k和220Ω、LED、蜂鸣器、光敏电阻、DHT11温湿度模块、SG90舵机、0.96寸OLED屏、土壤湿度模块、继电器模块、小水泵。如果后面想做小车再买电机驱动板完全不用一开始就囤货。杜邦线的质量非常影响体验。那种一拔一插就松垮的线真的会让人崩溃到想砸板子。排查到最后经常发现只是线接触不良。强烈建议买触点上带小弹片、插拔有阻尼感的线虽然贵一点点但能省下大量排查时间。注意面包板用久了弹片会氧化变松同一个孔位插几次就开始接触不良。遇到诡异故障先用另一根线换一个孔位试试往往问题立消。2. 环境搭建与编程基础这些东西先弄明白再动手2.1 IDE、驱动和板卡管理器Arduino IDE直接到官网下载新版2.x的体验已经不错了。装完IDE之后第一项工作是装驱动很多高仿Uno板用的是CH340芯片需要手动装CH340驱动否则电脑识别不到COM口。如果插上板子后设备管理器里出现黄色感叹号不要急着重装IDE先去把对应驱动补上。识别不到串口时也先别怀疑板子坏了USB线本身也可能只供电不传数据——我手头就有一根只能充电不能通信的线坑过我好几次。装非官方板卡支持比如ESP时需要在首选项里添加开发板管理器网址再从管理器里搜索安装。这一步看起来简单但很多人失败在网址填错或者下载到一半中断。解决办法是换一个源或者找离线包这属于环境问题不用太纠结。2.2 代码结构setup和loop是怎么配合的Arduino程序没有传统的main函数入口就是setup()和loop()。setup只运行一次用来做初始化设定引脚模式、开启串口、启动传感器库。loop则是无限循环持续执行主逻辑。第一次写代码不建议直接抄整个项目先写一个最简单的LED闪烁把pinMode、digitalWrite、delay这三个函数吃透。模拟输入输出是真正常用到的概念。analogRead读到的范围一般是0到1023对应0到5V电压analogWrite输出的是PWM波范围0到255可以让LED亮度渐变也能让舵机转到特定角度。这里容易有个误解所谓模拟输出并不是真正的连续电压而是快速切换高低电平靠惯性让人眼看起来像模拟量。理解这一点后面遇到LED亮度不均匀、舵机在某角度抖动等问题时就能想到是不是PWM频率或者占空比精度的问题。延时方面非敏感场景用delay是最方便的但一旦涉及多任务——比如同时读传感器和驱动蜂鸣器——delay会把整个程序卡住传感器刷新不了按键也响应不了。替代方案是用millis()记录时间差非阻塞地执行任务。入门阶段可以先靠delay把功能跑通但我建议尽早习惯millis()否则项目稍微复杂一点改起来会非常痛苦。2.3 按键输入为什么非要上拉电阻按键是入门第一个容易翻车的地方。数字输入引脚如果悬空会接收到各种电磁干扰读数忽高忽低按键按下与否完全不可靠。解决办法是给引脚接一个上拉电阻到电源这样没按键时引脚读到高电平按下按键时读到低电平。Arduino内部已经内置了上拉电阻在pinMode里使能INPUT_PULLUP就行比外接电阻省事很多。用一个简单类比引脚就像一只怕吵的耳朵上拉电阻相当于给它塞了耳塞没有信号时它听到的是安静。如果不上拉引脚听到的全是环境噪音输出自然不稳定。2.4 动手前先做引脚规划这个习惯能省一半时间接线前画一张引脚分配表几乎是我最想安利给新手的习惯。看清哪些引脚带PWM比如Uno上是3、5、6、9、10、11哪些是I2C引脚A4/A5哪些是串口引脚0/1避免传感器抢脚。我就犯过一次把OLED插在I2C引脚上、结果程序里却按普通数字脚初始化的错误屏幕死活不出字排查了半天才发现线序插错位了。画表的时候顺便把电平也标清楚哪些模块要5V供电哪些是3.3V逻辑电源脚和地脚有没有跟别人共用。多花五分钟做这件事后面能少折腾几个小时。3. 我的几个小项目从功能拆解到完整实现3.1 小项目一温湿度报警小站这个项目的需求很简单房间里的温湿度要能实时显示超过设定阈值就报警。硬件只有三样DHT11温湿度模块、0.96寸I2C OLED屏、有源蜂鸣器。接线表DHT11引脚Arduino引脚VCC5VGNDGNDDATAD2OLED引脚Arduino引脚VCC5VGNDGNDSDAA4SCLA5蜂鸣器引脚Arduino引脚正极D8负极GND代码#include DHT.h #include U8g2lib.h #define DHTPIN 2 #define DHTTYPE DHT11 #define BUZZER_PIN 8 DHT dht(DHTPIN, DHTTYPE); U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0); float tempLimit 30.0; float humiLimit 70.0; void setup() { Serial.begin(9600); dht.begin(); pinMode(BUZZER_PIN, OUTPUT); u8g2.begin(); } void loop() { float temp dht.readTemperature(); float humi dht.readHumidity(); if (isnan(temp) || isnan(humi)) { Serial.println(DHT11 read error); return; } u8g2.clearBuffer(); u8g2.setFont(u8g2_font_6x10_tr); u8g2.setCursor(0, 12); u8g2.print(Temp: ); u8g2.print(temp); u8g2.print( C); u8g2.setCursor(0, 24); u8g2.print(Humi: ); u8g2.print(humi); u8g2.print( %); u8g2.sendBuffer(); if (temp tempLimit || humi humiLimit) { digitalWrite(BUZZER_PIN, HIGH); } else { digitalWrite(BUZZER_PIN, LOW); } delay(2000); }这是可以直接运行的完整代码用库管理器搜索安装DHT sensor library和U8g2两个库就行。DHT11的读取间隔必须大于1秒所以delay用了2000毫秒读太快会返回NAN。项目本身简单但有个很典型的坑DHT11插上电立刻读返回的往往是NAN。解决方法是上电后等1秒以上或者先读一次直接丢弃。另外DHT11本来就是低精度传感器温湿度波动在1℃和5%左右都算正常别把它当精密仪器用。真需要精确测量后面可以换DHT22或者SHT30代码结构基本不用大改。这个项目还能扩展阈值改成按键可调、数据通过串口发给上位机、加一个继电器控制加湿器。我当时把报警逻辑改成晚上才响、白天不烦人其实就是在loop里加一个时间段判断非常简单但做完特别有成就感。3.2 小项目二光控窗帘这个项目的需求是白天自动把窗帘拉开天黑自动合上。核心就是光敏电阻检测环境亮度舵机旋钮带动帘绳。硬件用了光敏电阻加一个10k电阻组成分压电路。光敏电阻的阻值随光照变化光照越强阻值越小模拟输入读到电压越高。我把光敏电阻一端接5V另一端接A0同时从这个点串联10k电阻到GND这就把电阻变化转换成了电压变化。接线表元件Arduino引脚光敏电阻一端5V光敏电阻另一端A0同时经10k电阻到GNDSG90舵机信号线D9PWMSG90电源线5V建议外部供电SG90地线GND必须共地代码#include Servo.h #define LIGHT_PIN A0 #define SERVO_PIN 9 Servo myServo; int openAngle 0; int closeAngle 150; int lightValue 0; bool isOpen true; void setup() { Serial.begin(9600); myServo.attach(SERVO_PIN); myServo.write(openAngle); } void loop() { lightValue analogRead(LIGHT_PIN); Serial.print(light: ); Serial.println(lightValue); if (lightValue 300 isOpen) { myServo.write(closeAngle); isOpen false; } else if (lightValue 500 !isOpen) { myServo.write(openAngle); isOpen true; } delay(500); }调试的时候有几个点要认真对待。舵机第一次上电往往会抖一下这是它在自动校准初始角度不是程序问题但如果在极限角度上电舵机可能会使劲顶着结构造成堵转发热。每次上电前先用手抓住舵盘转一转确认它没有顶着东西再固定安装。光敏电阻的阈值不是一成不变的阴天和晴天的读数差别很大房间灯光也会有影响。我先把Serial输出打开观察一整天的实际读数变化再确定阈值。代码里特意留了滞回区间低于300才关窗帘高于500才开窗帘中间不动。没有滞回区间的话窗帘会在临界光照下反复抽搐这是我实际调试时亲眼见到的场面非常滑稽。舵机供电要特别注意。SG90标称电流不大但快速动作或堵转瞬间电流很高细杜邦线、劣质面包板都会导致电压跌落舵机表现成没力、抖动。更稳妥的方案是外部5V电源单独给舵机供电Arduino板子和舵机之间只共用GND信号线照常接。共地的原因很简单两个电源必须有公共参考点信号才能被正确识别——不共地信号回不来。3.3 小项目三阳台自动浇花装置这个项目解决的是出门几天、阳台花没人浇的问题。用土壤湿度模块检测土壤含水量太干就启动水泵浇水浇够了自动停。硬件列表土壤湿度模块、继电器模块、小水泵。土壤湿度模块有两根探针插进土里电阻变化转为电压我用A1读取模拟值。模块上通常还有一个小电位器用来调灵敏度。接线表元件Arduino引脚土壤湿度模块VCC5V土壤湿度模块GNDGND土壤湿度模块A0A1继电器模块IND6继电器模块供电5V和GND看模块类型水泵继电器常开端接电源正极公共端接电源负极这里有一个非常关键的坑很多继电器模块其实是低电平触发IN引脚为低电平时继电器才吸合。如果代码里写反就会变成土壤很湿的时候反而一直在浇水。买模块时先看清楚丝印说明或者最开始用一个LED接在继电器输出端做测试确认触发逻辑再连水泵。水泵的控制逻辑不复杂但一定要加一个最大浇水时长保护。防止土壤湿度探头松动、读数一直很干水泵无限工作把花淹了。我在代码里限制每次浇水最多10秒之后至少等30分钟才能再次浇水。#define SOIL_PIN A1 #define RELAY_PIN 6 #define MAX_WATER_SEC 10 #define CHECK_INTERVAL_MIN 30 unsigned long lastCheckTime 0; unsigned long waterStartTime 0; bool isWatering false; void setup() { Serial.begin(9600); pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, HIGH); // 取决于继电器是低电平触发还是高电平触发 } void loop() { unsigned long now millis(); if (now - lastCheckTime CHECK_INTERVAL_MIN * 60000UL) { return; } lastCheckTime now; int soilValue analogRead(SOIL_PIN); Serial.print(soil: ); Serial.println(soilValue); if (isWatering) { if (now - waterStartTime MAX_WATER_SEC * 1000UL) { digitalWrite(RELAY_PIN, HIGH); isWatering false; Serial.println(stop watering); } return; } if (soilValue 600) { digitalWrite(RELAY_PIN, LOW); waterStartTime now; isWatering true; Serial.println(start watering); } }注意不同模块的数值含义可能相反有的模块读数越大表示越干有的反之。接线后务必先打印裸读数用手摸一下探头——湿手和干手分别看读数变化——确定判断方向再写逻辑。继电器模块也分两种一种自带光耦隔离一种是普通继电器。做水泵这种带感性负载的控制我更推荐带光耦的模块可以避免水泵启动或停止瞬间的反电动势干扰单片机。水泵本身是直流电机堵转会发热水管如果被折住了很容易烧水泵。这个经验我一定要记在这里小水泵最怕的不是电路问题而是管路问题。装机前把水管理顺确保水位高于进水口比调什么代码都重要。3.4 几个项目的共性和扩展思路这三个项目放在一起能组出不少新东西。温湿度报警加上联网模块就变成远程温湿度监测光控窗帘把光敏电阻换成环境光传感器可以联动室内灯光亮度自动浇花把定时逻辑改成根据天气接口调整就更聪明了。如果想实现数据传到手机可以先不用一上来就学复杂的ESP32开发。更平滑的路径是用一块ESP8266模块通过串口和Arduino通信Arduino负责采集传感器数据ESP8266负责WiFi收发串口协议自己定。这个方案的优点是把采集和通信分离调试起来可以一件事一件事地处理出问题容易定位。4. 常见问题与排查技巧实录4.1 编译报错锁定第一行别被海量报错吓到编译期最常见的问题是库冲突和重复定义。一个项目里同时装了两个功能重叠的库容易出现xx was not declared或redefinition的错误。解决办法优先用官方库管理器安装库少用手动下载Zip同一个项目不要引入两个功能类似的库。遇到报错看第一行错误信息它往往会直接指向文件和函数名后面几百行往往只是连锁反应。另一类是选错开发板类型。写了AVR板的代码跑到ESP板模拟引脚号定义不同自然报错。出现这类问题先检查Tools菜单里的Board选择是否正确再看端口配置。4.2 上传失败按顺序排查不信邪上传失败的原因很多COM口选错、板子没有进入bootloader、驱动没装好。正确顺序是先看设备管理器有没有对应COM口IDE里是否选对端口再换一根USB线试试有些线只能供电不能通信最后在上传前按一下板子上的复位键时机要卡在IDE提示上传中出现之前。如果还是不行把手边能换的都换一遍——USB口、电脑、甚至换一块板子——逐个变量排除。程序一旦启动就死机或者串口监视器里不断打印垃圾信息大概率是波特率不对。Serial.begin(9600)和串口监视器右下角的波特率必须一致否则出来就是乱码。4.3 传感器读数不稳定先查电源、再查共地、最后怀疑传感器传感器读数乱跳我的排查顺序是固定的先用万用表测模块VCC端的实际电压很多5V模块在高负载下实际只有4.6V稳压不足读数自然飘再检查共地仔细看所有模块的GND是否都连到了同一个公共点然后检查杜邦线是否松动。都没问题才考虑传感器本身坏了。DHT11这类传感器容易踩的坑更特殊读取太快、上电立刻读、数据引脚离电源线太近被干扰。以前我以为是模块坏了后来发现是数据线太长、旁边又有电机在工作信号被干扰了。把线缩短、远离电机线问题就消失了。现象排查顺序常见原因读数乱跳电压→共地→接线→传感器供电不足、线松、干扰读数恒为某值换引脚→换模块引脚烧坏、模块损坏读数总是NAN读取间隔→上电时间→接线顺序DHT11读太快、上电即读4.4 一个排查实例蜂鸣器一直响我在做温湿度报警时遇到过一个问题蜂鸣器一上电就响程序逻辑明明没有触发报警条件。排查过程供参考先用一段最简代码强制digitalWrite(D8, LOW)把蜂鸣器关闭。如果关闭不了说明不是代码逻辑问题而是硬件问题。然后用万用表量蜂鸣器两端电压发现D8引脚输出正常但蜂鸣器仍然响。最后拆下蜂鸣器一看正负极接反了——有源蜂鸣器正极本来应该接D8负极接GND我把它插反了结果变成了正极接GND、负极接D8工业逻辑下一样能响但控制信号就反了。这个案例想说明的排查思路是用最简单的代码隔离软件问题用万用表验证硬件问题最后才怀疑板子本身。从软件到硬件逐层排除大部分故障都能定位不要一开始就认为是板子坏了。5. 写在最后回到Arduino入门这件事入门Arduino最难的不是背语法而是建立一种硬件回路思维每个模块都有电源脚、地脚、信号脚信号要么是高电平、低电平要么是模拟量程序要做的事情就是把这些信号读进来、算一算、再输出控制。一旦想通了这一点换什么传感器心里都有底因为底层逻辑都是相通的。我的建议是别做那种复制教程代码进去、灯亮了就完事的项目一定要给自己加需求。我做完温湿度报警之后给自己加了一个晚上自动静音的规则就逼着自己去学怎么判断时间、怎么处理用户按键。项目不一定要大但要有变化、要有坑。坑踩多了自然就会了。后面我打算把几个小项目整合成一个阳台管家光照控制遮阳帘土壤湿度控制浇水温湿度控制通风。控制器从Uno换成ESP32数据想办法推到手机里。硬件这条路入门之后才算真正开始。