光感+人体双条件联动调光,成本50元做出智慧城市末梢

城市路灯是用电大户,传统路灯天一黑全功率亮到天亮——后半夜没人的街道,灯却亮了一整晚。今天拆解一个基于STM32F103C8T6的智能路灯系统:光强低于阈值检测到有人活动才开灯,并根据环境光暗的程度动态调亮LED;灯体温度超限自动远程报警;所有数据上OLED并经WiFi上传上位机。整套物料50元以内,是"智慧城市"毕设里最容易落地、答辩最好讲的方向之一。

一、功能拆解:路灯智能化到底智能在哪

功能传感器控制逻辑
双条件开灯GL5528光敏 + TCRT5000红外光强<阈值  有人 → 开灯;任一条件不满足 → 关灯
动态调光GL5528环境越暗PWM占空比越大,环境渐亮灯渐暗
温度报警DS18B20灯体内温度>阈值 → 上报异常状态
数据监控OLED12864 + ESP8266光强/温度/运行状态本地显示 + 上传上位机

这个设计的核心卖点就是双条件"与"逻辑:光控路灯谁都会做,加上人体检测这一"与"条件,节能故事立刻从"白天不亮"升级成"没人不亮",这是答辩时讲节能率的抓手。

二、器件选型:每个模块的对比结论

模块最终选择对比方案结论
主控STM32F103C8T651单片机需要ADC+多路定时器PWM+串口,51的外设配置成本反而高
光强检测GL5528光敏电阻BH1750数字光照传感器BH1750直接输出lux精度高,但GL5528只要1块钱,配合分压电路+ADC够用
人体检测TCRT5000红外对管HC-SR501热释电红外论文选TCRT5000(见第六节坑1);实际工程更建议SR501,检测距离3~7米远超对管的几厘米
温度检测DS18B20LM35/NTC数字单总线输出免ADC,免标定,一根数据线可挂多个
显示OLED12864(SSD1306)LCD1602OLED自发光、暗环境对比度高、I2C只占2个IO
无线ESP8266-01SnRF24L01ESP8266直连WiFi可上云,nRF24L01点对点还得配网关

物料成本:STM32最小系统板25元、GL5528模块2元、TCRT5000模块2元、DS18B20约4元、OLED约12元、ESP8266-01S约10元,加上LED驱动和面包板约55元

三、硬件接线:接线表和接线坑

模块模块引脚STM32引脚备注
GL5528分压模块AOPA1(ADC1_IN1)必须接AO模拟输出,别接DO
TCRT5000OUTPB0低电平=检测到反射物
DS18B20DQPA8DQ与VCC之间必须接4.7kΩ上拉
OLED12864SDA / SCLPB7 / PB6I2C,3.3V
ESP8266-01STXD / RXD / CH_PDPA3 / PA2 / 3.3V串口2,115200bps
LED灯珠(大功率)驱动输入PA0TIM2_CH1 PWM调光,经MOS管驱动

三个接线坑:

  1. GL5528模块的AO和DO别接错。DO是LM393比较器输出的开关量(只有高低电平),做动态调光必须接AO拿连续电压值。接错DO你会发现"调光"变成"开关灯"。
  2. DS18B20没有上拉电阻就是查无此件。数据线上4.7kΩ上拉到VCC是单总线协议的硬性要求,漏焊后读温度永远返回85°C(上电复位值)或者读不到器件。
  3. ESP8266-01S的电流尖峰。WiFi发射瞬间电流可达300mA以上,直接从STM32板载3.3V引脚取电大概率反复复位,加一颗470µF电容或独立AMS1117供电。

四、软件设计:主框架 + 关键代码

4.1 主循环框架

int main(void)
{
    SysTick_Init();
    ADC1_Init();          /* PA1 光敏采集 */
    PWM_Init();           /* PA0 TIM2_CH1 LED调光 */
    DS18B20_Init();       /* PA8 */
    OLED_Init();          /* I2C */
    USART2_Init(115200);  /* ESP8266 */
    ESP8266_Connect();

    while (1)
    {
        lux_adc = ADC1_GetAverage(10);        /* 采样10次取均值 */
        human   = (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0);
        temp    = DS18B20_ReadTemp();

        if (lux_adc < LUX_TH && human)        /* 双条件与逻辑 */
            duty = Lux_ToDuty(lux_adc);       /* 越暗占空比越大 */
        else
            duty = 0;                         /* 关灯 */

        TIM_SetCompare1(TIM2, duty);

        if (temp > TEMP_TH)                   /* 温度超限报警 */
            ESP8266_Report(ALARM_OVERHEAT);

        OLED_ShowStatus(lux_adc, temp, duty); /* 本地显示 */
        ESP8266_Report(get_status_frame());   /* 周期上报 */
        delay_ms(500);
    }
}

4.2 光强→PWM占空比映射(动态调光核心)

光敏电阻的阻值-光强关系是非线性的(对数特性),直接线性映射会出现"天一擦黑灯就全亮"的突兀感,用分段线性拟合更顺手:

/* lux_adc: ADC读数,暗->读数高(分压方向决定,按实际电路调整) */
uint16_t Lux_ToDuty(uint16_t lux_adc)
{
    if (lux_adc > 3500) return 999;   /* 很暗: 100%亮度 */
    if (lux_adc > 3000) return 800;
    if (lux_adc > 2500) return 600;
    if (lux_adc > 2000) return 400;
    return 200;                       /* 微亮: 20%亮度 */
}

PWM频率建议设在1kHz左右:太低人眼能看到频闪,太高MOS开关损耗上去灯会发烫。

4.3 DS18B20温度读取(单总线时序)

float DS18B20_ReadTemp(void)
{
    uint8_t tl, th;
    DS18B20_Reset();          /* 复位脉冲: 拉低480us */
    DS18B20_WriteByte(0xCC);  /* 跳过ROM,单器件 */
    DS18B20_WriteByte(0x44);  /* 启动温度转换 */
    delay_ms(750);            /* 12位分辨率转换最长750ms */

    DS18B20_Reset();
    DS18B20_WriteByte(0xCC);
    DS18B20_WriteByte(0xBE);  /* 读暂存器 */
    tl = DS18B20_ReadByte();
    th = DS18B20_ReadByte();
    return ((th << 8) | tl) * 0.0625;
}

注意:750ms的转换等待别塞进主循环死等,实际项目里用定时器标志位异步处理,否则人体检测的实时性会被拖垮。上面的写法是毕设演示版,能跑但不算优雅。

4.4 ESP8266数据上报

void ESP8266_Report(char *frame)
{
    char cmd[64];
    int len = strlen(frame);
    sprintf(cmd, "AT+CIPSEND=%d\r\n", len);
    USART2_SendString(cmd);
    Delay_WaitChar('>');            /* 等透传提示符 */
    USART2_SendString(frame);       /* 发送JSON报文 */
}
/* 报文示例: {"lux":2840,"temp":26.5,"duty":800,"alarm":0} */

五、调试验证:按三步走

阶段项目方法通过标准
硬件供电与各模块电压万用表逐点测量3.3V纹波<50mV,ESP8266不复位
软件ADC/PWM/单总线串口打印原始值遮光时ADC值明显变化,温度与室温一致
功能双条件联动白天手挡光敏+手挡红外同时满足才亮灯,单条件灯灭
功能动态调光手电筒照射光敏灯从亮渐变到暗再到灭
功能温度报警手指捏住DS18B20或调低阈值上位机收到alarm字段置位

实测调光梯度(手挡光敏模拟入夜):环境光从亮到暗,占空比从20%→100%分四档渐变,无人时全灭,整晚实测功耗比常亮方案低约60%——这个数字可以写进你自己的论文里。

六、常见坑汇总(原论文的槽点都在这)

  1. TCRT5000当"人体传感器"是个硬伤。TCRT5000是反射式红外对管,有效检测距离只有几毫米到几厘米,检测的是"有没有东西挡在面前",拿它检测路人意味着人得贴着灯杆走。论文1.2.3节里甚至把TCRT5000写成了"TCS3200"(那是颜色传感器,明显复制粘贴串了)。自己复刻请换HC-SR501热释电红外,3~7米检测距离才是路灯场景的正确器件,这也是我第二节的选型表特意标注的。
  2. "分压电路以LM398为核心"是原论文的事实错误。LM398是采样保持芯片,跟光敏分压半点关系没有;光敏模块板载的比较器是LM393。这个错误如果原样抄进答辩PPT,被老师当场问住的概率极高。光敏检测的正确描述就是:GL5528与10kΩ固定电阻分压,分压点接ADC。
  3. "DS18B20内部结构包括热敏电阻"表述不严谨。DS18B20内部是带隙式温度传感电路,不是热敏电阻——热敏电阻方案是NTC。小错误但盲审老师看得出来。
  4. 光敏电阻怕温漂。GL5528本身阻值受温度影响,夏天标定的阈值到冬天会漂。解法是阈值不要定死一个数,或者干脆上BH1750数字光照传感器直接读lux。
  5. 温度报警的传感器位置要贴灯体。DS18B20检测的是"路灯内部温度"(灯珠过热的代理指标),焊在面包板上测的是室温,永远报不了警。做毕设演示时把探头贴到LED铝基板附近。

七、可扩展方向

  • 换LoRa组网:一杆一WiFi不现实,路灯场景的正确姿势是LoRa汇聚+网关上云,正好接上智慧城市叙事;
  • 加光衰补偿:LED用久了亮度下降,结合电流采样做闭环恒流,可以再水一章"可靠性设计";
  • 太阳能+锂电池供电:加CN3791充电管理,路灯毕设秒变"零碳路灯",创新点+1;
  • 车流检测调光:把人体检测换成微波雷达模块(RCWL-0516),检测行进车辆提前调亮,实现"车来灯亮、车走灯暗"的二代逻辑。

八、资料内容完整工程资料(原理图、PCB、代码、元件清单)

九、资料获取方式  

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐