用51单片机和红外传感器DIY一个超市/图书馆人数统计器(附Keil5源码)
2026/6/11 23:26:54 网站建设 项目流程

用51单片机和红外传感器DIY智能客流统计系统

每次走进常去的自习室,总会遇到"人满为患却不知具体人数"的尴尬。作为电子爱好者,我决定用最基础的51单片机和红外传感器打造一个低成本客流统计器,解决这个小烦恼。这个项目不仅能用于小型商铺、图书馆,还能改装成家庭入口的访客记录仪,核心在于如何用两个传感器准确判断进出方向。

1. 硬件选型与电路设计

选择STC89C52作为主控芯片,主要看中其稳定性和丰富的IO口资源。红外传感器选用E18-D80NK,这款光电开关有效探测距离3-80cm可调,自带灵敏度调节旋钮,能有效避免误触发。显示模块采用经典的LCD1602液晶屏,性价比高且驱动简单。

提示:E18-D80NK的工作电压为5V,与51单片机完全兼容,无需额外电平转换电路

传感器安装位置直接影响计数准确性。我的实测方案是:

  • 入口传感器:距地面15cm,倾斜15度朝向外侧
  • 出口传感器:与入口对称安装,倾斜方向相反
  • 间距要求:两个传感器中心距≥25cm,防止同时遮挡

电路连接关键点:

模块连接引脚备注
LCD1602P0口需接10K上拉电阻
红外传感器AP3.2(INT0)入口检测,下降沿触发
红外传感器BP3.3(INT1)出口检测,下降沿触发
蜂鸣器P2.0接NPN三极管驱动
// 硬件初始化代码片段 void hardware_init() { P0 = 0xFF; // LCD数据口置高 P2 = 0xFE; // 蜂鸣器初始关闭 IT0 = 1; // 设置INT0边沿触发 IT1 = 1; // 设置INT1边沿触发 EX0 = 1; // 使能INT0中断 EX1 = 1; // 使能INT1中断 EA = 1; // 全局中断使能 }

2. 方向判断逻辑实现

核心难点在于区分进出方向。通过实验发现,人体经过两个传感器时会形成特定的触发序列:

  • 进入触发序列:传感器A→传感器B(间隔300-800ms)
  • 离开触发序列:传感器B→传感器A(间隔300-800ms)
volatile bit flag_A = 0, flag_B = 0; volatile unsigned int timestamp_A = 0, timestamp_B = 0; // INT0中断服务函数(传感器A) void SensorA_ISR() interrupt 0 { flag_A = 1; timestamp_A = sys_ticks; // 获取系统时间戳 if(flag_B && (timestamp_A - timestamp_B < 1000)) { person_enter++; // 进入计数 flag_A = flag_B = 0; } } // INT1中断服务函数(传感器B) void SensorB_ISR() interrupt 2 { flag_B = 1; timestamp_B = sys_ticks; if(flag_A && (timestamp_B - timestamp_A < 1000)) { person_exit++; // 离开计数 flag_A = flag_B = 0; } }

实际调试中发现三个常见问题及解决方案:

  1. 误触发问题:调整传感器灵敏度旋钮至中间档位,并在代码中添加去抖动延时
  2. 同时遮挡:优化安装位置,确保无法同时遮挡两个传感器
  3. 快速通过:在中断函数中添加时间窗口判断(300-1000ms)

3. 报警功能与交互设计

系统设置人数上限报警功能,当实时人数达到预设值时触发声光报警。采用三个按键实现设置交互:

  • SET键:进入/退出设置模式
  • UP键:上限值增加/计数清零(长按3秒)
  • DOWN键:上限值减少
void check_alarm() { if(current_count >= limit_count) { buzzer_on(); // 蜂鸣器鸣响 lcd_set_cursor(1, 0); lcd_write_string("ALERT! OVERFLOW "); } else { buzzer_off(); } } // 按键处理代码片段 void key_handle() { if(SET_pressed()) { setting_mode = !setting_mode; if(!setting_mode) save_limit_to_eeprom(); } if(setting_mode && UP_pressed()) { limit_count++; if(limit_count > 9999) limit_count = 0; } if(UP_long_pressed()) { // 长按清零 current_count = 0; person_enter = person_exit = 0; } }

LCD显示界面设计为两行:

人数:023 上限:050 进入:015 离开:012

4. 系统优化与扩展

基础功能实现后,我做了以下优化提升实用性:

  1. 数据持久化:添加AT24C02 EEPROM存储上限设置值,断电不丢失
  2. 抗干扰设计
    • 所有IO口添加104瓷片电容滤波
    • 传感器信号线使用双绞线
    • 电源输入端加入470μF电解电容
  3. 低功耗模式:当5分钟无人员进出时,关闭LCD背光(按任意键唤醒)
// 低功耗处理代码 void power_manage() { static unsigned int idle_counter = 0; if(last_count != current_count) { idle_counter = 0; lcd_backlight(ON); } else if(++idle_counter > 30000) { // 约5分钟 lcd_backlight(OFF); } last_count = current_count; }

进阶改进方向:

  • 增加WiFi模块上传数据到云端
  • 改用OLED显示屏提升可视角度
  • 添加温度传感器实现环境监测
  • 开发手机APP实时查看数据

5. 常见问题排查指南

在面包板搭建阶段遇到几个典型问题:

  1. LCD显示乱码

    • 检查对比度调节电位器(通常10KΩ)
    • 确认初始化时序满足说明书要求
    • 测试电源电压稳定在5V±0.2V
  2. 传感器响应不稳定

    # 用示波器检测信号波形时应观察到 # 无遮挡时:稳定的3.3V高电平 # 遮挡时:清晰的低电平脉冲(>100ms)
  3. 蜂鸣器不发声

    • 测量驱动三极管基极电压(应有0.7V左右)
    • 检查蜂鸣器极性(有源蜂鸣器分正负)
    • 测试单独供电时能否发声

调试小技巧:

  • 使用LED指示灯辅助调试(每个传感器配一个状态灯)
  • 在关键代码处添加调试输出
  • 分段测试:先验证传感器单独工作,再测试联动逻辑

这个项目最让我惊喜的是用基础元件就能实现实用的日常解决方案。记得第一次成功区分进出方向时,那种成就感远超预期。建议初学者先从面包板搭建开始,逐步优化,最后再设计PCB做成完整设备。

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

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

立即咨询