基于STM32的空气质量监测系统:传感器选型、采集与校准实战
简介基于STM32F103 Mini开发板与MQ135传感器的空气质量监测系统面向物联网嵌入式初学者与开发者提供一套可编译运行的完整工程用于解决室内外空气质量实时采集与显示问题。工程基于Keil MDK组织共155个文件包含35个C源码与37个头文件覆盖ADC采集、LCD显示、定时器、Flash读写等模块同时附带uvprojx/uvoptx工程配置、axf/hex编译输出、bat辅助脚本及网页说明文档压缩包仅4.41MB目录结构清晰便于导入与二次开发。系统在STM32F103的高性能内核基础上通过MQ135测得的电阻变化经ADC采样及滤波处理最终在LCD或串口上呈现结果为理解气体传感器量化过程提供了完整示例。目前已有3400余人学习适用于课程设计、毕业设计或入门级环境监测项目读者可直接复用源码框架减少底层外设开发时间后续也可在现有代码上扩展无线通信、自动报警等高级功能。1. 基于STM32的空气质量监测系统到底在解决什么问题一个做嵌入式开发的同事装修完新房后买了几台不同价位的空气质量检测仪发现同一房间、同一时刻几台设备读数能差出两倍把检测仪从桌上挪到窗台数值立刻跳一下。他最后翻出一块吃灰的STM32开发板花了两个晚上搭了一套自己的空气质量监测系统把粉尘浓度、eCO2、TVOC、温湿度全部接到同一块主控上数据自己采、自己算、自己存。这套东西的价值不在于板子多高级而在于每一路数据从传感器到屏幕的链路都是自己可控的——读数异常时你知道该怀疑传感器还是怀疑电源。“基于STM32的空气质量监测系统”这类以 .zip 形式流传的项目通常包含完整的嵌入式源码、电路接线说明和显示逻辑适合三类人正在找毕业设计方向的学生、想给家里留一套可溯源空气质量记录的动手派以及准备做空气质量产品原型、需要先验证采集链路的开发者。STM32只负责按时点亮传感器、读取信号、换算浓度真正决定这套系统可不可用的是传感器选型、采样时序和电源隔离这三件事。这篇就把这三件事从头到尾拆开讲。2. 从传感器选型到接线搭建能长期运行的STM32数据采集底座拆开任何一个类似的监测系统核心都是“把几路传感器挂到MCU上”。STM32的代码框架大同小异真正拉开差距的是每路传感器的输出形式——是模拟电压、I2C数字还是单总线时序这决定了你后续要写的驱动代码复杂程度。先花半小时把链路定下来后面能省一整天的调试时间。2.1 传感器选型粉尘、气体、温湿度三条采集链路怎么定粉尘浓度是空气质量里最难采的一路。常见方案有两种一种是模拟电压输出的红外粉尘传感器典型型号GP2Y1010AU0F通过PWM脉冲驱动内部LED传感器把散射光转成电压MCU用ADC读取另一种是带UART数字输出的激光粉尘传感器数据直接就是浓度值但价格和体积都要高一个量级。在“基于STM32的空气质量监测系统”这个题目下红外模拟型更典型因为整个ADC采样、滤波、换算的数据链路都能在代码里看到项目价值更高。气体污染物这条路选型要点是拿到能直接参与判别的指标。SGP30是比较省事的选择I2C接口直接输出eCO2和TVOC两个值内部做了校准逻辑MCU这边只需要按时发读取命令。不建议新手用MQ系列气体传感器——需要加热功耗大输出受湿度和温度影响明显而且从模拟电压换算到ppm浓度往往要查datasheet里的对数曲线实测时极易翻车。温度湿度用SHT30。同样是I2C接口温湿度各16bit精度驱动代码比DHT11简单得多。DHT11虽然便宜但单总线时序对GPIO翻转时机非常敏感在带中断的系统里容易读取出错放在监测系统里会让整条链路变得不可控。三条链路的选型对比如下采集链路常见型号输出方式主要难点粉尘浓度GP2Y1010AU0F模拟电压 PWM脉冲驱动采样点必须与LED脉冲对齐气体指标SGP30I2C数字首次上电需等待基线稳定温湿度SHT30I2C数字注意CRC校验和地址区分2.2 STM32最小系统与供电设计让ADC采集值不漂选MCU不用纠结重点是外设够用且资料多。以STM32F103C8T6为例12位ADC、硬件I2C、多个定时器都具备Flash 64KB足够放下传感器驱动、滤波和显示逻辑如果想做低功耗版本可以换成STM32G0系列但代码结构基本不用改。选型时看三个指标ADC通道数不少于2个、I2C外设至少1个、Flash不小于64KB。供电是这套系统里最容易埋雷的地方。GP2Y1010内部的红外LED在脉冲点亮瞬间电流很大如果它和MCU共用同一条地线或同一条3.3V供电轨ADC采样点的地电位会被瞬间抬高采集到的电压值就会周期性跳动。常见做法是粉尘传感器用5V供电LED驱动和传感器供电都从5V取STM32、SGP30、SHT30和OLED用3.3V供电3.3V由低压差LDO从5V转换得到5V地线和3.3V地线在电源输入端单点相连。还有一个容易被忽略的点ADC的参考电压。在STM32F103这类封装里VDDA就是ADC参考电压它必须和VDD一样干净不能直接从开关电源的输出引脚取电。给VDDA加一个10uF钽电容加0.1uF陶瓷电容的组合能明显减少采集值的跳动。如果使用带独立VREF引脚的型号同样原则参考电压越稳采集值越可信。2.3 接线表与引脚分配动手前先对一遍给出一套经过验证的引脚分配方案F103和G0系列都可以参考。GP2Y1010有两个关键引脚LED驱动引脚接定时器PWM输出AOUT接ADC输入通道SGP30、SHT30和OLED挂在同一条I2C总线上。SGP30的7位地址是0x58SHT30是0x44OLED屏是0x3C地址不冲突可以共用总线。模块信号STM32引脚说明粉尘传感器LED驱动PB8TIM4_CH310ms周期0.32ms高电平粉尘传感器AOUT模拟输出PA0ADC1_IN0采样点对齐脉冲上升沿后0.28msSGP30SCL / SDAPB6 / PB7I2C1速率100kHzSHT30SCL / SDAPB6 / PB7与SGP30共用总线地址0x44OLEDSCL / SDAPB6 / PB7地址0x3C刷新频率1Hz为什么要用定时器PWM输出而不用GPIO翻转因为粉尘传感器的采样时序要求LED脉冲每隔10ms来一次脉宽0.32ms。GPIO翻转要挤在主循环里一旦被I2C通信或其他中断打断脉冲周期就飘了ADC采样点也跟着错。用PWM之后脉冲由硬件定时器独立产生CPU只负责在正确的时刻触发ADC转换时序稳得多。I2C总线上拉电阻用4.7k到3.3V如果总线走线超过10cm还要考虑把速率降到100kHz。3. 传感器采集代码把原始信号变成能看的浓度值接线完成后真正的调试从驱动代码开始。这一章给三段核心代码粉尘传感器的脉冲采样、SGP30的I2C读取、以及把ADC原始值换算成浓度的公式。三段代码都能直接抄进工程里但参数一定要根据你自己的硬件和传感器批次重新标定。3.1 粉尘传感器的PWM脉冲与ADC采样采样点错了读数全废GP2Y1010的工作时序是固定的每10ms产生一个0.32ms的LED驱动脉冲输出电压会在脉冲上升沿之后逐渐建立约0.28ms时达到与粉尘浓度对应的稳定值。如果ADC在这个时间点之前或之后采样得到的电压都不是真实浓度对应的值。最直接的实现方式是在主循环里控制GPIO和延时代码虽然简单但只适合用来验证传感器好坏不适合做正式系统。#define DUST_LED_PORT GPIOB #define DUST_LED_PIN GPIO_PIN_8 void dust_sample_once(uint16_t *raw) { HAL_GPIO_WritePin(DUST_LED_PORT, DUST_LED_PIN, GPIO_PIN_SET); delay_us(280); // 脉冲上升沿后0.28ms采样 HAL_ADC_Start(hadc); HAL_ADC_PollForConversion(hadc, 10); *raw HAL_ADC_GetValue(hadc); HAL_GPIO_WritePin(DUST_LED_PORT, DUST_LED_PIN, GPIO_PIN_RESET); delay_us(40); // 保证脉冲宽度接近0.32ms }上面的代码把LED引脚拉高后延时280us然后启动ADC转换最后拉低引脚。注意延时40us的意图让整个高电平时间接近320us符合数据手册的脉冲宽度要求。如果发现采样值“不是0就是4095”优先检查两件事一是ADC通道是否配置正确二是280us这个延时是否真的被编译优化掉了。在带优化等级的编译选项下空的delay_us函数可能被整个去掉建议用定时器或__NOP()循环实现。正式系统里推荐把LED脉冲交给定时器PWM硬件产生用另一个定时器在脉冲开始后280us触发ADC。这样CPU不需要阻塞在延时里采样节拍也不会被I2C通信打断。核心思路是PWM周期10ms、占空比3.2%对应320us高电平ADC触发时间点配置在PWM计数器的特定比较值上。不同定时器的比较值换算方式不同调试时用示波器同时看LED引脚和ADC采样完成标志确认采样点落在280us附近。3.2 I2C读SGP30起始命令、等待预热和字节拼装SGP30是标准的I2C从设备工作流程分两步先写初始化命令再周期性发测量命令读取数据。初始化命令是0x2003测量命令是0x2005返回6字节数据前两字节是eCO2单位ppm中间两字节是TVOC单位ppb最后两字节是前两字节的CRC校验。首次上电后传感器需要一段时间建立基线前几分钟读到的数据会明显偏高或偏低不要在开机后立刻把数据写进历史记录。static uint8_t sgp30_cmd_init[2] {0x20, 0x03}; static uint8_t sgp30_cmd_meas[2] {0x20, 0x05}; static uint8_t sgp30_buf[6]; void sgp30_init(I2C_HandleTypeDef *hi2c) { HAL_I2C_Master_Transmit(hi2c, 0x58 1, sgp30_cmd_init, 2, 100); HAL_Delay(50); // 等待初始化命令生效 } uint16_t sgp30_read_eco2(I2C_HandleTypeDef *hi2c) { HAL_I2C_Master_Transmit(hi2c, 0x58 1, sgp30_cmd_meas, 2, 100); HAL_Delay(20); // 测量命令后至少等待12ms HAL_I2C_Master_Receive(hi2c, 0x58 1, sgp30_buf, 6, 100); return (sgp30_buf[0] 8) | sgp30_buf[1]; // eCO2值 }两个参数需要说明。地址0x58左移一位变成0xB0是HAL库要求的8位I2C地址格式7位地址本身不需要改。测量后的延时20ms是参考SGP30数据手册中“测量时长典型值12ms”留出的余量如果延时太短读回来的可能是上一帧数据或者全0xFF。CRC校验在调试阶段可以先不写但等到数据频繁异常时一定要把CRC检查加上它能区分是传感器输出错误还是总线错误。3.3 浓度换算公式为什么不能用别人代码里的系数GP2Y1010的模拟输出电压与粉尘浓度近似线性关系但不同批次传感器的零点电压和灵敏度差异很大。数据手册给出的典型关系是无尘环境下输出电压约0.9V灵敏度约0.005V/(ug/m3)。换算公式为浓度 (Vout - 零点电压) / 灵敏度。直接把网上的系数抄进代码换一颗传感器后数据就会系统性偏大或偏小。float dust_voltage_to_ugm3(uint16_t adc_raw, float vref, uint32_t adc_max) { float vout (float)adc_raw * vref / (float)adc_max; float offset 0.90f; // 零点电压单位V需要实测标定 float sens 0.005f; // 灵敏度单位V/(ug/m3) float conc (vout - offset) / sens; return (conc 0.0f) ? conc : 0.0f; }这里的offset和sens不是从某个神秘压缩包里抄来的魔法数字而是必须用实际传感器标定出来的参数。标定方法不复杂在干净的室内环境最好用标准仪器同步测量记录ADC原始值反算出零点电压再把传感器放到已知浓度环境里测一次反算灵敏度。没有标准仪器时也可以在室外空气质量优良的时段采集一组数据作为零点参考至少能消除大部分个体差异。把这两个参数放到一个配置文件里换传感器时只改配置不用动业务代码。4. 数据处理与显示报警从“有读数”到“能看懂空气”采集到原始浓度只是第一步。直接把这个值显示到屏幕上你会发现数字一直在跳——不是传感器坏了而是颗粒物本身就是离散的加上传感器本身的噪声单次采样值没有统计意义。这一章解决三个问题怎么让数据稳定、怎么判断空气质量等级、怎么让显示不干扰采集。4.1 滑动平均去毛刺单次采集值不能直接上屏粉尘传感器输出的是短时间内颗粒物散射光的积分值单个颗粒物飘过检测区域时输出电压会瞬间拉高再回落。如果直接显示屏幕上的数字会像心跳一样来回跳。SGP30的读数虽然相对平稳但在空气流动较大时也有波动。常见的做法是滑动窗口平均窗口大小决定了显示数据的平滑程度和响应速度。#define WINDOW_SIZE 10 static uint16_t adc_buf[WINDOW_SIZE]; static uint8_t buf_idx 0; uint16_t adc_filtered(uint16_t new_sample) { uint32_t sum 0; adc_buf[buf_idx] new_sample; buf_idx (buf_idx 1) % WINDOW_SIZE; for (uint8_t i 0; i WINDOW_SIZE; i) { sum adc_buf[i]; } return (uint16_t)(sum / WINDOW_SIZE); }窗口大小选择有讲究。10个采样点按1秒采一次算对应10秒的平滑窗口能压住大部分毛刺同时对开窗通风这类变化能在几十秒内反映出来。窗口太小去不掉毛刺窗口太大则会掩盖真实趋势——比如你打开空气净化器要等很久屏幕数值才开始降会让人误以为设备没效果。如果还想更激进一点可以先去掉窗口里的最大值和最小值再做平均对脉冲型干扰的抑制效果更好。4.2 分级阈值与报警防抖不要用一个点触发报警有了稳定浓度值之后下一步是告诉用户“当前空气到底行不行”。eCO2和粉尘浓度各有不同的分级标准不同国家标准差异很大做监测系统时不需要纠结遵循哪个标准只要在系统里明确定义一套分级阈值并写清楚依据即可。建议用四级优、良、轻度污染、重度污染分别对应不同颜色和报警策略。指标优良轻度污染重度污染eCO2ppm 600600 ~ 10001000 ~ 1800 1800粉尘浓度ug/m3 3535 ~ 7575 ~ 150 150报警逻辑最容易犯的错是“超过阈值立刻报警”。颗粒物浓度瞬时波动可能持续几秒钟比如有人从旁边走过带起灰尘系统不该因为这个就响蜂鸣器。正确做法是加入防抖逻辑连续N次超过阈值才触发报警N次采样之间间隔1秒相当于要求污染状态持续N秒以上才动作。这样既不会漏报也不会误报。static uint8_t over_count 0; #define ALARM_TRIGGER_COUNT 3 void check_alarm(float current_conc, float alarm_threshold) { if (current_conc alarm_threshold) { over_count; if (over_count ALARM_TRIGGER_COUNT) { HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_SET); } } else { over_count 0; HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET); } }注意ALARM_TRIGGER_COUNT的取值。3对应“连续3秒超标”适合粉尘这类波动较大的指标eCO2变化比较慢可以提高到5甚至10避免人在传感器旁边呼一口气就触发报警。这个参数同样应该放进配置文件不要写死在业务逻辑里。4.3 OLED刷新策略别让显示拖慢采集节拍OLED屏幕通过I2C刷新一帧画面需要传输约1KB数据。在400kHz的I2C速率下刷新一次屏幕要花几十毫秒如果每次采样完立即刷屏粉尘传感器的采样周期会被拉长而且不稳定。更麻烦的是刷屏期间I2C总线一直被占用SGP30和SHT30的读取只能排队等待。常见的解决方案是把采集和显示拆成两个节奏采集用定时器固定节拍触发显示在主循环里按需刷新。volatile uint8_t sample_flag 0; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM2) { sample_flag 1; // 采集节拍标志 } } int main(void) { while (1) { if (sample_flag) { sample_flag 0; uint16_t raw 0; dust_sample_once(raw); // 每周期采集 uint16_t eco2 sgp30_read_eco2(hi2c1); /* 滤波、报警判断、数据保存 */ if (display_due()) { // 每1秒刷新一次屏 update_display(); } } } }display_due()的作用是控制屏幕刷新频率比如用一个计数器每10个采集周期刷一次屏对应每秒刷新一次。这样既保证采样节拍稳定又不会让屏幕看起来卡顿。如果后续要升级成带WiFi上传的版本同样的调度框架可以继续用只需要把“刷新屏幕”替换成“打包发送数据”采样和通信互不干扰。5. 常见问题排查让采集值翻车的四个坑代码照着写完之后真正的挑战才开始。以下四个问题是我在类似项目里反复踩过的坑按“现象 → 原因 → 解决”的方式列出来遇到类似情况可以直接对照排查。5.1 粉尘传感器读数恒为0或一直是满量程现象OLED上显示的粉尘浓度要么是0要么始终是最大值怎么调整传感器位置都不变。原因ADC采样点和LED脉冲没有对齐。一种情况是采样发生在脉冲到来之前读到的是无光时的输出电压另一种情况是脉冲宽度不够输出电压还没建立起来。解决用示波器同时测量LED驱动引脚和传感器AOUT引脚确认AOUT的峰值出现在LED脉冲上升沿后的0.28ms附近然后把ADC采样时机对准这个位置。如果手边没有示波器可以在代码里把280us延时从0开始每次加50us打印换算后的浓度值找到读数跳变最大的那个延时点那里就是正确的采样位置。5.2 电池供电时读数漂移插上充电器后恢复现象用USB供电时数据稳定换成电池供电后粉尘浓度整体偏高且数值随机跳动。原因ADC参考电压不稳定。电池电压随着放电逐渐下降如果3.3V是直接从电池经LDO转换的VDDA同样会波动实测中传感器输出电压没变但ADC用变化的参考电压去量化它结果自然跟着漂。解决给VDDA单独加LC滤波或者把3.3V改用低 dropout 的LDO供电确保在电池电压下降到截止电压之前3.3V输出保持稳定。还有一种软件补偿办法读取MCU内部参考电压VREFINT根据它的实测值反推当前参考电压再参与浓度换算但这是补救手段不如把供电做好来得干净。5.3 SGP30读取超时偶尔读到0xFFFF现象I2C读取时返回HAL_TIMEOUT或者eCO2值偶尔变成65535。原因I2C总线电气参数不达标。最常见的是SCL和SDA缺少上拉电阻、总线走线过长、或者I2C速率设在400kHz但上拉电阻选的太大导致信号上升沿过缓。解决在SCL和SDA上各接一个4.7k电阻到3.3V检查SGP30和SHT30是否弄反了地址把I2C时钟从400kHz降为100kHz。这三个措施按顺序做大多数超时问题都能解决。如果仍然偶发就要在读取函数里加返回值判断超时后丢弃本次数据不更新显示值。5.4 数值正常但OLED刷新瞬间数据跳一下现象屏幕刷新那一刻粉尘浓度会出现一个明显的尖峰刷新结束后恢复。原因OLED刷屏占用了I2C总线而总线上同时挂着SGP30和SHT30刷屏时的总线电平变化干扰了传感器读取时序。或者更隐蔽的原因OLED的I2C通信和粉尘传感器的ADC采样共用了中断优先级刷屏中断打断了ADC采样。解决调整调度顺序先把所有传感器数据读取完并保存到局部变量再执行OLED刷新将ADC采样中断优先级设置高于I2C事件中断如果还不行就把OLED换到另一组软件I2C引脚上让它物理上不干扰传感器总线。6. 进阶让监测系统留下可追溯的数据系统能稳定显示数据之后值得花半小时做三件事给传感器做个体校准、把数据以带时间戳的格式输出、考虑低功耗运行的改造方式。这三件事决定了这套系统是“能亮的demo”还是“能长期跑的工具”。6.1 本地校准两点法修正传感器个体差异每个传感器出厂一致性有限尤其是GP2Y1010这类模拟输出器件零点电压随温度变化明显。两点校准法最实用第一次在干净空气中记录输出零点第二次在已知污染环境下记录第二个点然后计算斜率和截距。把这两个参数放在一个结构体里存到Flash系统启动时加载typedef struct { float offset; // 零点电压 float slope; // 灵敏度 } CalibParam; CalibParam g_dust_calib {0.90f, 0.005f};换传感器时只需要重新标定并更新这两个字段浓度换算代码一行都不用改。我习惯把标定参数和报警阈值统一放在一个配置结构体里通过串口命令在线修改——因为现场安装位置和传感器个体差异这些参数总要在实际环境里微调。6.2 串口输出带时间戳的CSV上电后每秒输出一行CSV格式为“时间戳,粉尘,PM2.5,TVOC,CO2,温度,湿度”。时间戳用MCU启动后的秒数即可需要真实时间时再接RTC模块。数据写入串口后从USB转串口工具保存成文件就能直接导入电子表格分析通风效果或在空气净化器开启前后对比曲线。6.3 低功耗改造思路需要电池供电时把采集周期拉长到30秒或1分钟采集完立即进入停机模式用RTC定时唤醒。SGP30在长时间停机后重新读取需要重新建立基线前几分钟数据不可靠所以低功耗方案里要么保持传感器常供电、要么接受开机后一段时间的无效数据。OLED只在查看时点亮平时关闭功耗能降一个量级。最后说一个个人习惯每次调完传感器我都会把标定参数、接线图和采样时序记录在同一个文档里下次再搭类似的系统不用重新趟一遍坑。这套基于STM32的空气质量监测系统最难的部分从来不是代码而是摸清每个传感器的脾气。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Python闭包与装饰器:函数对象、作用域链与运行时机制深度解析

Python闭包与装饰器:函数对象、作用域链与运行时机制深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 19:50:57 阅读更多 →
设备树of函数详解:从节点查找到属性读取的驱动实战指南

设备树of函数详解:从节点查找到属性读取的驱动实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 19:50:57 阅读更多 →
Seata 1.2 接入 Spring Cloud Alibaba:分布式事务与 AT 模式落地实战

Seata 1.2 接入 Spring Cloud Alibaba:分布式事务与 AT 模式落地实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 19:50:57 阅读更多 →

最新新闻

AI逆向工程实战:31.2K Star开源项目如何用大模型辅助二进制分析

AI逆向工程实战:31.2K Star开源项目如何用大模型辅助二进制分析

1. 当AI把目光投向二进制:逆向工程的门槛正在被重新定义第一次看到“AI开始搞逆向工程”这个说法,我的反应是:终于有人把这件事摆到台面上了。逆向工程这个领域,长期以来都是少数人的游戏——你得懂汇编,得熟悉PE/ELF文…

2026/10/14 23:16:08 阅读更多 →
ARM架构CentOS 7.6网口bond配置实战与优化指南

ARM架构CentOS 7.6网口bond配置实战与优化指南

1. 项目背景与需求拆解1.1 为什么要在ARM架构的CentOS 7.6上做网口bond在ARM服务器上跑CentOS 7.6,这个组合本身就有点意思。ARM架构的服务器这几年在数据中心里越来越常见,尤其是那些对功耗敏感、需要高密度部署的场景。但ARM平台跟传统的x86平台在硬件…

2026/10/14 23:16:08 阅读更多 →
两级式光伏MMC并网系统故障穿越Simulink仿真模型解析

两级式光伏MMC并网系统故障穿越Simulink仿真模型解析

1. 项目概述与问题背景做光伏并网研究的同学,对"故障穿越"这四个字应该都不陌生。无论你研究的是组串式逆变器、集中式逆变器,还是近几年大热的MMC拓扑,只要涉及并网,就绕不开电网故障时"能不能撑住、撑多久、怎么…

2026/10/14 23:16:08 阅读更多 →
AI Agent实操:五个新工具让AI学会用鼠标干活

AI Agent实操:五个新工具让AI学会用鼠标干活

1. 这次AI的进化方向,是先学会用鼠标Copilot能“直接操作”电脑这个事,让我琢磨了好几天。以前我们聊AI,聊的都是大模型能读多少token、能写多长的代码、能生成多像样的图。但那个层面的能力再强,它也是关在对话框里的——你问它答…

2026/10/14 23:16:08 阅读更多 →
OpenCV特征提取与匹配实战:SIFT、ORB、AKAZE选型与调参指南

OpenCV特征提取与匹配实战:SIFT、ORB、AKAZE选型与调参指南

1. 从一张拍歪的照片说起:为什么特征提取值得花时间搞懂很多人第一次接触OpenCV,都是从读图、灰度化、边缘检测这条线走下来的,觉得图像处理不过如此。直到某天需要把两张不同角度拍的同一场景对齐,或者想让程序在一堆商品图里找出…

2026/10/14 23:16:08 阅读更多 →
用Hermes Agent打造AI数字员工:企业自动化实战全解析

用Hermes Agent打造AI数字员工:企业自动化实战全解析

先交代一下背景,这个教程源自我在某企业内部做的一次 AI 自动化试点总结。当时团队的任务很直接,把重复性高、规则清晰但又需要人肉判断的活儿,逐步交给一套能听指挥、能调用工具、能自己干活的系统。市面上轮子很多,最终敲定用 H…

2026/10/14 23:14:55 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →