基于STM32的开源图书馆环境监测系统:温湿度光照粉尘采集与仿真
2026/9/18 3:07:31 网站建设 项目流程

图书馆这个地方看着安静,其实环境参数特别讲究。人一多,CO₂浓度上去了,闷得慌;梅雨季湿度大,书页发霉;北方的冬天又干得嘴唇起皮。我在学校做实验室助理那阵子,管理员三天两头问我:能不能搞个小玩意儿,实时看看阅览室的温湿度、光照和空气状况。市面上的成品监测仪要么贵得离谱,要么数据不开放,没法自己二次开发。后来我就动了心思,用STM32搭一套图书馆环境监测系统,把代码、原理图、仿真全部整理开源出来。这套东西能采集温湿度、光照强度、空气中的颗粒物浓度,本地OLED实时显示,超阈值蜂鸣器报警,还能通过串口把数据推给上位机记录。适合刚入门STM32的在校学生、想做课程设计的同学,以及想低成本部署多点监测的小型场馆管理员参考。整套方案主控成本控制在三十块以内,仿真工程不用买任何硬件就能跑通逻辑,非常适合拿来当练手项目。

1. 项目缘起与整体方案设计

1.1 图书馆场景到底需要监测哪些量

先说场景需求,不谈需求直接上代码的都是耍流氓。图书馆和普通家庭环境最大的区别在于:它是一个人员密集、静态陈列物品多、对防潮防霉有刚性要求的封闭空间。我蹲点观察了一周,把痛点归成四类。

第一类是温湿度。纸质书最怕的是高温高湿,温度长期超过28℃、相对湿度长期高于65%,霉菌孢子就开始活跃,书脊的胶装容易开胶。同时温度太高人也坐不住,阅览室的舒适区间大概在22℃到26℃、湿度40%到60%之间。

第二类是光照。书库长期被强光直射,纸张会发黄变脆,这就是所谓的"光老化"。靠窗的书架和过道尽头光照差异很大,管理员其实很想知道哪些区域需要加遮光帘。监测光照不是为了省电,是为了保护文献。

第三类是空气质量里的颗粒物。人流量大的时候,地面扬尘、衣物纤维都会飘起来,PM2.5和PM10浓度会明显上升,对过敏体质的读者很不友好。这个量不像温湿度那么直观,必须靠传感器量化。

第四类是可扩展项,比如CO₂浓度和噪声。CO₂是判断通风是否到位的好指标,人一多它就涨;噪声则直接关系阅览体验。这两项我在开源版本里预留了接口,但没有做成默认必装,原因后面在选型章节会讲清楚。

把这四类需求翻译成工程语言,就是:温度、湿度、光照强度、颗粒物浓度四个必测物理量,加两个可选量,再加一个报警输出和一个数据上传通道。

1.2 为什么选STM32而不是树莓派或Arduino

这是每个做环境监测的人都要问自己的第一个问题。我三种方案都实际做过,给你掰扯清楚取舍逻辑,你就能明白为什么这个项目落在STM32上。

树莓派是跑操作系统的。它的优势是算力强、能跑Python、联网方便,但缺点在图书馆这种场景里被放大了:启动慢、断电不友好、功耗高、长期运行有SD卡损坏风险。你要的是一个插上电就默默工作几个月不用管的小盒子,不是一台会死机的迷你电脑。而且树莓派成本摆在那里,要做多点部署,一个阅览室放三四个,预算立刻爆表。

Arduino Uno开发门槛最低,生态也成熟,问题是资源太紧。UNO只有2KB RAM、32KB Flash,你要同时跑DHT11时序、驱动OLED、做滤波算法、再挂个串口协议栈,很快就捉襟见肘。而且UNO的ADC是10位、参考电压固定,做颗粒物这种需要一定精度的采集有点勉强。

STM32F103系列是一个甜点。它基于ARM Cortex-M3内核,主频72MHz,Flash 64KB、RAM 20KB,资源对这个小项目来说绰绰有余。ADC是12位,有多路通道,可以同时接模拟和数字传感器。外设丰富,I2C、SPI、USART、定时器一应俱全。更关键的是价格,F103C8T6核心板加上最小系统,单板成本能压到十几块,批量部署毫无压力。低功耗模式也成熟,如果做电池供电的版本,待机电流能压到微安级。

一句话总结取舍:要联网算力选树莓派,要极简原型选Arduino,要性价比、稳定性和可量产性的平衡,STM32F103是最不容易翻车的选择。

1.3 系统整体架构与数据流

方案定了STM32,接下来把系统拆成三层:感知层、处理层、交互层。这个分层不是为了好看,是为了让每部分能独立调试、独立替换。

感知层就是各个传感器。温湿度用DHT11或者DHT22,光照用BH1750数字光照传感器,颗粒物用GP2Y1010AU0F这类光学粉尘传感器。它们的输出形式不同,有的走单总线,有的走I2C,有的直接出模拟电压,处理层要能全部兼容。

处理层是STM32主控。它的活儿分四步:第一步按各自的时序或协议把原始数据读进来;第二步做必要的换算和滤波,比如粉尘传感器的模拟电压要换算成浓度值,温湿度要做滑动平均去抖动;第三步做阈值判断,超限就触发报警;第四步把数据打包,一路送OLED显示,一路通过串口或ESP8266推给上位机。

交互层包括OLED显示、蜂鸣器报警和上位机。OLED用SSD1306,128x64分辨率,能把四个测量值加状态图标排得很清楚。蜂鸣器负责本地声光提示。上位机这部分我在开源版本里给的是Python串口接收脚本,收到数据后追加写CSV,方便后面做趋势分析。

整个数据流可以这样理解:传感器是"眼睛",STM32是"大脑",OLED是"脸",串口和上位机是"嘴"。眼睛看到什么,大脑判断一下,脸上显示出来,需要报告的时候就用嘴说出去。

提示:分层设计的好处是,当你发现某个传感器不合适想换型号时,只需要改感知层驱动和处理层的一小段换算代码,其他部分完全不用动。我在第一版里用的是模拟温度传感器,后来换成DHT11,改动量不到二十行。

2. 硬件选型与原理图设计拆解

2.1 主控最小系统的关键细节

很多新手拿到核心板就直接插杜邦线开工,结果跑着跑着程序莫名复位,查半天查不出问题。根源往往在最小系统上。STM32F103C8T6要稳定工作,最小系统必须包含几样东西:电源滤波、复位电路、时钟电路、启动模式配置和调试接口。

电源部分,核心板通常自带AMS1117-3.3V稳压,输入5V输出3.3V。但你要注意,AMS1117的静态电流和压差都不算优秀,如果整个系统峰值电流超过300mA,比如加上WiFi模块瞬间发射,建议单独给WiFi供电或者在3.3V上并一个大电容。我自己在板子上并了100μF电解电容加0.1μF陶瓷电容,专治上电瞬间的电压跌落。

复位电路一般是10kΩ上拉加100nF到地,核心板已经做了,不用重复。时钟电路是重点,F103外部晶振用8MHz,配合内部PLL倍频到72MHz。这里有个坑:晶振旁边的负载电容通常是20pF左右,如果你画PCB时走线太长,或者用了劣质晶振,可能出现起振慢甚至不起振。仿真里看不出来,实物上表现为程序跑飞或者串口乱码。

启动模式BOOT0和BOOT1要拉对。正常运行BOOT0接GND,从Flash启动;要串口下载就临时拉高BOOT0。我见过有同学把BOOT0悬空,结果偶尔启动到系统存储器模式,程序根本不跑,查了半天以为是代码问题。

调试口SWD就两根线SWDIO和SWCLK,强烈建议硬件上留出排针。调试阶段你会感谢自己。用ST-Link下载和单步调试,比串口打印高效得多。

下面这张表把关键引脚分配列出来,方便你对着原理图接线。

功能模块引脚接口类型备注
DHT11温湿度PA0单总线需4.7kΩ上拉
BH1750光照PB6/PB7I2C1SCL/SDA,需上拉
OLED SSD1306PB8/PB9软件I2C独立于硬件I2C
粉尘传感器PA1ADC1_IN1模拟量输入
蜂鸣器PB5GPIO输出经三极管驱动
ESP8266PA9/PA10USART1TX/RX交叉

2.2 传感器选型背后的取舍

选传感器是这个项目最容易花冤枉钱的地方,我把每种的选择逻辑讲透。

温湿度这块,DHT11和DHT22是绕不开的两个选项。DHT11便宜,单只不到五块,但精度只有±2℃温度和±5%湿度,分辨率也低。DHT22贵一些,精度能到±0.5℃和±2%,量程也更宽。图书馆场景其实DHT11够用,因为你要看的是"有没有超出舒适区间",而不是精确到小数点后两位。我在开源版本里默认用DHT11,代码里留了宏定义,想换DHT22改一个参数就行,两者的时序协议几乎一样,只是数据位数和换算公式不同。

光照传感器我纠结过光敏电阻和BH1750。光敏电阻便宜到几毛钱,但它是模拟量,输出随温度漂移,而且要做标定才能得到勒克斯值,个体差异还大。BH1750是数字I2C输出,直接给你勒克斯lux值,精度高、免标定,虽然单价要五六块,但省下来的标定和调试时间远超这点成本。对图书馆这种要横向比较不同区域光照的场景,BH1750的绝对值输出很关键。

颗粒物传感器是个大坑,必须重点讲。市面上便宜的粉尘传感器大多是红外光学原理,靠颗粒物散射红外光来估算浓度,输出模拟电压。它的问题是:只能给相对趋势,不能给准确绝对值,而且受温湿度影响大。我选的是GP2Y1010AU0F这个经典型号,便宜、资料多,但它需要脉冲式驱动LED,采样时序有讲究,直接接ADC读出来是不准的。它的红外LED要按周期通断,在LED点亮的那一瞬间采样,才能避开环境光干扰。这个时序细节后面代码章节会展开。

CO₂和噪声我为什么没做成默认配置?CO₂传感器,无论NDIR还是电化学,价格都偏高,而且需要一个预热过程,不适合频繁断电的场景。噪声的话用驻极体麦克风加放大电路能做,但需要额外做FFT或者取包络,对初学者来说增加了理解成本。所以这两项做成预留接口,想扩展的人自己接,我不会把它们塞进主体流程里拖慢所有人。

传感器型号单价区间接口精度适用度
温湿度DHT113-5元单总线±2℃/±5%RH推荐
温湿度DHT2210-15元单总线±0.5℃/±2%RH进阶
光照BH17505-8元I2C1-65535lux推荐
光照光敏电阻0.5元ADC需标定不推荐
粉尘GP2Y101015-25元模拟+脉冲相对趋势推荐
粉尘PMS500340-60元UART较准进阶

2.3 电源与外围电路的避坑设计

电源这一块看着简单,实际是稳定性问题的重灾区。整个系统有三类负载:数字部分(STM32、OLED)、模拟部分(粉尘传感器)、无线部分(ESP8266)。它们的供电特性完全不同。

数字部分对电压波动不敏感,但对噪声敏感。OLED刷新时会有脉冲电流,如果和模拟部分共用一条细走线,噪声会串到ADC里,导致粉尘读数跳动。我的做法是模拟部分单独走一根电源线,并且在粉尘传感器的VCC和GND之间就近放0.1μF加10μF的滤波电容。

ESP8266是最大的害群之马,它发送数据时瞬时电流能到200mA以上,很多人的系统一联网就复位,就是因为它把3.3V拉下去了。解决办法要么给它单独供电,要么在它的电源脚旁边放一个470μF的电解电容做能量缓冲。我用的是后者,实测联网瞬间电压跌落从0.4V降到0.1V以内,复位问题消失。

蜂鸣器虽然电流不大,但它是感性负载,关断瞬间会产生反向电动势。直连GPIO不仅可能烧IO口,还会干扰附近的信号。标准做法是用一个NPN三极管(比如S8050)做开关,GPIO接基极串1kΩ电阻,蜂鸣器接在集电极和VCC之间,并联一个反向的续流二极管。这个二极管很多新手会漏掉,加上之后蜂鸣器"咔咔"的杂音都会小很多。

PCB布局上,晶振要尽量靠近主控,下面不要走线,最好挖空或者敷铜隔离。I2C的两根线走线不要太长,超过20厘米就考虑降低速率或者加缓冲。这些都是仿真里体现不出来、必须靠经验积累的细节。

3. 固件代码实现与关键驱动

3.1 开发环境搭建和工程骨架

工欲善其事,环境先搭好。我推荐用Keil MDK或者STM32CubeIDE,前者资料多、寄存器级操作直观,后者免费、HAL库封装好、跨平台。开源工程我提供了CubeIDE版本的完整配置,用Keil的同学可以参考着改。

CubeIDE里第一步是用CubeMX配置外设,这一步千万别偷懒手写寄存器。配置清单大致是:RCC里开启外部晶振HSE,时钟树把SYSCLK配到72MHz;GPIO里把用到的引脚配好模式和上下拉;ADC1开启通道1并设置采样时间;USART1配成115200波特率;I2C1配成标准模式100kHz。配置完生成代码,工程骨架就有了。

这里有个小经验:CubeMX生成的中断优先级和DMA配置容易让新手迷惑。这个项目其实不需要DMA,数据量很小,直接轮询读就行。中断只用到了滴答定时器做延时,外加一个串口接收中断。保持简单是这个项目的一个设计原则,能用轮询就不上中断,能不上DMA就不上DMA,减少出错面。

工程目录我分成几个文件夹:Core放主逻辑,Drivers放CubeMX生成的库,User放自己写的传感器驱动,比如dht11.c、bh1750.c、oled.c、dust.c。每个驱动只对外暴露两三个函数,读写和初始化,这样主逻辑里调用起来清爽,换传感器也只需替换对应文件。

3.2 温湿度与光照驱动实现

DHT11的难点在时序,它用的是单总线协议,通信全靠拉高拉低的时间长短来编码,没有独立时钟线。主机先拉低至少18毫秒作为起始信号,然后释放,DHT11响应后再连续送40位数据:8位湿度整数、8位湿度小数、8位温度整数、8位温度小数、8位校验和。

关键点是每一位数据的"0"和"1"靠高电平持续时间区分,0是26到28微秒,1是70微秒左右。所以读的时候要先用while等电平变化,再延时大约30微秒后采样,判断这时是高还是低。这个延时精度要求高,不能被打断。我实现的时候是先关总中断,读完再开,避免其它中断打乱时序。

// dht11.c 关键读取函数(简化示意) uint8_t DHT11_ReadByte(void) { uint8_t i, byte = 0; for (i = 0; i < 8; i++) { while (DHT11_PIN == 0); // 等待50us低电平结束 Delay_us(40); // 延后40us判断电平 byte <<= 1; if (DHT11_PIN == 1) byte |= 1; while (DHT11_PIN == 1); // 等待本位高电平结束 } return byte; }

注意:Delay_us这类微秒延时函数千万别用系统滴答定时器实现,因为SysTick默认1毫秒中断,精度不够。要么用空循环掐时间,要么用定时器做精确计数。我用的是空循环加编译优化等级固定的方式,简单可靠。

BH1750就舒服多了,纯I2C通信,命令很简单:上电后发送0x01开电源,发0x10进入连续高分辨率模式,之后直接读两个字节,拼起来除以1.2就是lux值。这里要提醒一句,BH1750的测量范围大,但在强光下高分辨率模式会饱和,如果需要测很亮的环境要切到低分辨率模式。

// bh1750.c 读取函数 float BH1750_ReadLux(void) { uint8_t buf[2]; I2C_ReadBytes(BH1750_ADDR, buf, 2); uint16_t raw = (buf[0] << 8) | buf[1]; return raw / 1.2f; }

代码里我加了一级滑动平均滤波,连续采5次取平均再上报。别小看这一步,DHT11和BH1750在真实环境下读数都会有小幅跳变,不滤波的话OLED上的数字一直闪,看着就像坏了。

3.3 颗粒物传感器的脉冲采样技巧

这是整个项目里最容易被做错的地方,我单独拿出来说。GP2Y1010AU0F的引脚里有一根LED驱动脚,它要求你按周期给一个短脉冲去点亮内部的红外LED,然后在点亮后的大约0.28毫秒时刻去读模拟输出脚,这时候读到的是有LED照射时的散射光强度,减去LED熄灭时的本底值,才是真正的粉尘信号。

如果你不按这个时序,直接把输出脚接ADC一直读,读到的其实是环境光加电路噪声,数值随光照变化,完全没有意义。很多网上抄来的代码就是这么干的,能跑但数据不可信。

正确的做法是用一个定时器或者软件延时产生周期为10毫秒、宽度约0.32毫秒的脉冲。点亮后延时0.28毫秒采样,熄灭后再采一次作为本底。可以这样写:

// dust.c 采样一次 float Dust_ReadOnce(void) { float v_on, v_off, voltage; LED_PIN_HIGH(); // 点亮红外LED Delay_us(280); // 等待稳定 v_on = ADC_Read(DUST_CH); LED_PIN_LOW(); // 熄灭 Delay_us(40); v_off = ADC_Read(DUST_CH); voltage = v_on - v_off; // 去除本底 // 电压转浓度,经验公式,需按传感器单独标定 return (voltage - 0.6f) / 0.005f; }

换算公式里的系数不是固定值,不同批次传感器有差异,我用的是公开资料里常见的经验系数。想要更准,得上标准粉尘环境标定,普通项目用相对趋势就够了。这里我给的建议是:多做几次采样,取中位数而不是平均值,因为偶尔会有异常大的跳变,平均值会被带偏,中位数抗干扰更强。

3.4 显示、报警与数据上报逻辑

OLED走的是SSD1306驱动,我用的是软件I2C,原因是硬件I2C已经被BH1750占了,而且软件I2C的引脚可以随便换,调试方便。显示内容我排成两列,左边温度湿度,右边光照粉尘,顶上留一行显示状态和是否报警。刷新频率不用太高,每500毫秒刷一次就够,刷太快占CPU还伤屏。

报警逻辑是核心业务。我给每个量都设了上下限,比如温度低于18℃或高于28℃报警,湿度低于35%或高于65%报警,光照超过某个lux值报警,粉尘超标报警。报警时蜂鸣器按"响两秒停一秒"的节奏间歇鸣叫,而不是一直响,这样既不吵人又能引起注意。OLED上对应的数值会闪烁或者前面加个感叹号。

数据上报我用的是USART1,直接接USB转TTL就能在电脑上看,如果想无线可以用ESP8266做透传。协议设计得很简单,一行一个数据包,用逗号分隔:T=24.5,H=55.2,L=320,D=12.3,S=OK。这样上位机解析起来毫无难度,用Python的split就能拆开。

# 上位机接收脚本片段 import serial ser = serial.Serial('COM3', 115200, timeout=1) with open('env_log.csv', 'a') as f: while True: line = ser.readline().decode('utf-8', errors='ignore').strip() if line.startswith('T='): f.write(line.replace('=', ',').replace(',', ',') + '\n')

上位机这边我特意做成追加写CSV,不覆盖,方便长期记录。你甚至可以挂个脚本每周生成一张趋势图,这些扩展空间都留给使用者。这里有个小提醒:CSV文件长时间写要记得定时flush,或者用with语句保证关闭时落盘,不然断电会丢最后一段数据。

4. 仿真验证与联调过程

4.1 为什么这个项目一定要跑仿真

有人觉得做STM32项目直接上实物就行,仿真多余。我以前也这么想,直到有一次接错了电源脚,一口气烧了两块板子加一个传感器,才知道仿真省钱有多重要。

仿真的价值有三个。第一是验证逻辑,不接硬件就能确认代码流程走不走得通、状态机对不对、阈值判断准不准。第二是验证原理图,仿真软件里可以把元件拖进来连线,很多接线错误在画图阶段就暴露了。第三是方便教学和分享,你把仿真工程发出去,别人不用买任何东西就能跑起来看效果,特别适合开源项目传递。

我在开源包里提供的仿真工程,包含了主控、传感器模拟源、OLED显示和串口终端。传感器数据用软件方式注入,可以手动拖动滑块调节温湿度光照值,实时看系统怎么响应。这个对理解阈值逻辑特别直观。

4.2 仿真工程的搭建步骤

搭建顺序建议是先放主控最小系统,再逐个挂外设,每挂一个就测一次,不要一次性全连完再调,那样出问题你根本不知道是哪一步的错。

第一步加载STM32F103C8的模型,把时钟和电源接好。仿真软件里晶振和复位可以省略,但电源和地一定要接。第二步挂OLED,先跑一个最简单的"Hello World"显示,确认I2C时序没问题。第三步挂DHT11的模拟模型,设置初始温湿度,看主程序能不能读出正确值。第四步挂BH1750和粉尘传感器模型,这里粉尘用的是模拟电压源加脉冲响应,需要把采样时序在仿真里也模拟出来。

仿真里最麻烦的是时序模拟。真实DHT11的微秒级延时,仿真软件跑起来时钟频率不一样,可能会有偏差。我的经验是把仿真时钟调慢一点,或者把延时参数按比例放大,先验证逻辑正确性,时序精度的最终确认还是要在实物上做。

仿真阶段挂载模块验证目标常见失败现象
第一阶段主控+电源能下载能跑空程序无时钟、无响应
第二阶段OLED能显示字符花屏、全亮、无显示
第三阶段DHT11能读温湿度读数全0或全1
第四阶段BH1750+粉尘能读光照浓度数值恒定不变
第五阶段串口能输出数据包乱码、收不到

4.3 仿真跑通之后怎么过渡到实物

仿真跑通不代表实物就顺。我总结仿真和实物之间有三个典型差异必须提前知道。

第一个差异是电源噪声。仿真里电源是理想3.3V,实物上有纹波、有压降。凡是仿真里正常、实物里复位或者ADC跳动的,先查电源。用示波器看3.3V的纹波,超过100mV就要处理。

第二个差异是时序精度。仿真里延时函数按指令周期跑,实物上受中断、编译优化影响,实际延时可能差几十个微秒。DHT11这类对时序敏感的器件,实物上要重新校准延时参数。我的办法是先在实物上用示波器量一下GPIO翻转的实际时间,再修正循环次数。

第三个差异是传感器个体差异。仿真里粉尘传感器的换算系数是理想的,实物上每只传感器都要标定。我第一次拿实物测,读数比仿真里偏高30%,就是系数没标定导致的。

提示:过渡阶段最有效的方法是"分模块替换"。先只把OLED从仿真换成实物,其它还留在仿真里,确认没问题再换下一个。这样任何异常都能立刻定位到刚替换的那个模块。

5. 常见问题与排查技巧实录

5.1 传感器读数异常怎么查

温湿度读数为零或者固定不变,先去查上拉电阻。DHT11是开漏输出,没有上拉电阻就永远是低电平,读出来全是0。标准是用4.7kΩ上拉到3.3V,不能用10kΩ,太大了上升沿变慢,时序会出错。

光照值一直不变,八成是I2C没通。用万用表量SCL和SDA在空闲时应该是高电平,如果一直低,就是被拉死了,常见原因是传感器供电没接或者地址写错。BH1750的地址是0x23或者0x5C,取决于ADDR脚接高还是接低,接错就读不到。

粉尘值乱跳,回到上一章讲的脉冲时序。先确认LED驱动脚有没有在正确翻转,用示波器看那根脚的波形,正常应该是10毫秒周期、几百微秒宽度的脉冲。如果一直是高或者一直是低,那就不是算法问题,是引脚配置问题。

现象可能原因排查动作
温度恒为0上拉电阻缺失补4.7kΩ上拉
光照不变I2C地址错核对ADDR脚接法
粉尘大跳变未做本底扣除检查v_on-v_off
数据全乱码波特率不匹配核对115200
莫名复位电源跌落并大电容、查WiFi供电

5.2 代码层面的高频坑

第一个坑是Delay_us不准。前面说过,别用SysTick做微秒延时。还有编译优化等级,Keil里O0和O3下空循环延时差好几倍,要么把延时函数放在固定的优化文件里,要么用定时器实现。

第二个坑是I2C卡死。软件I2C如果没做超时处理,某次通信失败后一直等应答,整个程序就卡住了。我的做法是每个等待加一个最大循环次数,超了就返回错误,让主循环继续跑。这个防御性编程习惯能救命。

第三个坑是浮点运算。F103没有硬件浮点单元,所有float运算都是软件模拟,慢且占空间。显示和滤波里能不用浮点就不用,温度可以用0.1℃为单位的整数存储,需要显示时再转。这个优化能让程序跑得更顺。

第四个坑是中断里做耗时操作。有同学把OLED刷新或者传感器读取放进定时器中断里,结果中断执行时间过长,其它中断被延迟,系统时序就乱了。记住一个原则:中断里只做标记和搬运,重活留给主循环。

5.3 实测经验与长期运行建议

这套系统我在阅览室连续挂了一个学期,积累了几条书上不会写的经验。

外壳一定要开散热孔。我第一版用密封塑料盒装,夏天盒内温度比环境高了五六度,测出来的温度完全失真。后来在前后面板各开了几排小孔,读数立刻对齐了。传感器本身也会轻微发热,探头不能紧贴主控芯片。

长期运行要加看门狗。STM32自带独立看门狗,我配了4秒超时,主循环里定时喂狗。有一次因为静电干扰程序跑飞,看门狗把它拉回来了,数据只丢了十几秒,没人察觉。如果没这个机制,可能就得手动去重启。

数据记录建议存到SD卡或者定时上传,别只放内存里。RAM掉电就没了,攒一周的数据一次断电全丢。我在上位机脚本里加了每分钟落盘一次,配合CSV追加写,即使电脑断电,最多丢一分钟的数据。

最后分享一个校准小技巧。温湿度传感器久了会有漂移,每隔几个月拿一个靠谱的参考仪表放在旁边,两个读数对比,如果偏差超过阈值就在代码里加一个补偿常量。这个常量写成宏定义,方便以后调整。光照和粉尘同理,定期用标准环境对比一次,心里就有底了。

这套图书馆环境监测系统从选型到跑通,我的体会是:真正花时间的从来不是写代码,而是搞清楚每个数据背后的物理含义、把硬件时序抠准、以及处理真实环境里的各种意外。代码和原理图都是死的,把"为什么这么做"想明白,你换成任何场景都能重新搭一套出来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询