• 售前

  • 售后

热门帖子
入门百科

基于51单片机和红外漫反射传感器的久坐提醒神器(番茄钟)的设计

[复制链接]
天下无敌522 显示全部楼层 发表于 2022-1-13 00:33:45 |阅读模式 打印 上一主题 下一主题
一、背景介绍

我们工作久了,久坐导致的毛病就显现出来了,腰酸背痛颈椎疼,最近看到利用番茄钟工作法挺好,工作25分钟,休息5分钟,既能调整工作节奏,避免精力过分消耗,也能避免久坐导致的身体问题。
我刚开始使用闹钟做提醒,后来尝试番茄钟软件,但是都要手动去操作手机,拿起手机看到信息,然后就会去处理手机上的事情了,起不到作用…
直到有一天收拾东西看到了我大学期间基于51单片机做的一个电子设计,激起了我的灵感,开始了基于51单片机的自动番茄钟,久坐提醒神器的设计和制作。
整体方案硬件部分继承了大学时焊接的电路板,更换了传感器部分,软件部分重新编写了控制部分的代码。
之前的软硬件设计方案可以参考这篇文章《基于51单片机的上下限可调的数字温度控制系统》,本文重点阐述差异部分。
二、功能描述

本设计要求能够识别到座位上有人,并开始计时,能够在LCD屏上显示工作状态和倒计时时间。当超过设置的久坐提醒时间(25分钟),进行蜂鸣器和LED灯报警,并在LCD屏上显示让你休息的提示。人离开后能够重置时间,LCD屏显示离开状态,直到你坐下后开始重新计时。另外如果有特殊情况无法按时休息,支持按复位键重新计时。
三、系统组成


本系统由STC89C52单片机主控,通过晶振时钟模块、复位电路模块、按键模块、液晶显示模块、声光报警模块、传感器模块组成。
其中液晶显示模块采用LCD1602液晶显示屏,声光报警模块采用蜂鸣器和红黄绿三个LED灯,传感器模块开始采用的是E18-D80NK红外漫反射光电传感器。
传感器部分刚开始选用的是HC-SR501热释电红外传感器,但是调试过程中发现该人体红外传感器只能检测到移动的人体,无法检测到静止的人体。咱们工作的时候有时会很专注,静止在那里识别不到,传感器就认为没有人,导致功能失效。后来找了一下发现E18-D80NK红外漫反射光电传感器能够满足要求,于是选了这个传感器。
四、硬件设计

1、总体电路图


其中,传感器要换成红外漫反射光电传感器。
2、传感器介绍


五、软件设计

1、流程图


2、源代码

见附录
六、结果展示

1、正常工作状态


2、久坐提醒状态


3、离开休息状态


附录

主控部分
main.c
  1. #include <reg52.h>
  2. #include <stdio.h>
  3. #include "lcd1602.h"
  4. #define WORK_MAX_TIME (25 * 60)
  5. sbit beep = P1 ^ 3;   //蜂鸣器
  6. sbit pir = P2 ^ 0;    //热释电红外传感器信号线
  7. sbit reset = P3 ^ 2;  //定义按键--复位键
  8. sbit led0 = P2 ^ 2;  //绿灯
  9. sbit led1 = P2 ^ 3;  //黄灯
  10. sbit led2 = P2 ^ 4;  //红灯
  11. uint work_time = WORK_MAX_TIME;  //工作坐着的秒数
  12. //蜂鸣器
  13. void di(uchar s) {
  14.     beep = 0;
  15.     delay1ms(s);
  16.     beep = 1;
  17. }
  18. //按键音
  19. void key() {
  20.     di(100);
  21. }
  22. //报警音
  23. void warn() {
  24.     di(5000);
  25. }
  26. //点亮LED
  27. void lightLED(uchar c) {
  28.     if (c == 'r') {  // 红灯亮
  29.         led0 = 1;
  30.         led1 = 1;
  31.         led2 = 0;
  32.     } else if (c == 'g') {  // 绿灯亮
  33.         led0 = 0;
  34.         led1 = 1;
  35.         led2 = 1;
  36.     } else if (c == 'y') {  // 黄灯亮
  37.         led0 = 1;
  38.         led1 = 0;
  39.         led2 = 1;
  40.     } else {
  41.         led0 = 1;
  42.         led1 = 1;
  43.         led2 = 1;
  44.     }
  45. }
  46. //液晶显示
  47. void showLCD(char *_msg, uint _tm) {
  48.     uchar tm[16] = {0};
  49.     uint min = _tm / 60;
  50.     uint sec = _tm % 60;
  51.     write_com(0x80);
  52.     write_str(_msg);
  53.     write_com(0x80 + 0x40);
  54.     sprintf(tm, "time %02d:%02d", min, sec);
  55.     write_str(tm);
  56. }
  57. //处理红外漫反射传感器信号
  58. void processPIR() {
  59.     // 人在座位上
  60.     if (pir == 0) {
  61.         // led显示working和倒计时
  62.         if (work_time > 0) {
  63.             showLCD("working ...     ", work_time);
  64.             // 绿灯亮
  65.             lightLED('g');
  66.             work_time--;
  67.         } else {
  68.             work_time = 0;
  69.             showLCD("go go go !!!    ", work_time);
  70.             // 红灯亮
  71.             lightLED('r');
  72.             warn();
  73.         }
  74.     } else if (pir == 1) {
  75.         // led显示leaving和25:00
  76.         work_time = WORK_MAX_TIME;
  77.         showLCD("leaving ...     ", work_time);
  78.         // 黄灯亮
  79.         lightLED('y');
  80.     }
  81. }
  82. void main() {
  83.     EA = 1;   //全局中断开关
  84.     IT0 = 1;  //跳变沿触发方式
  85.     EX0 = 1;  //开启外部中断0
  86.     led0 = 0;
  87.     led1 = 0;
  88.     led2 = 0;
  89.     init_1602();
  90.     delay1ms(1000);
  91.     while (1) {
  92.         processPIR();
  93.         delay1ms(1000);
  94.     }
  95. }
  96. //外部中断0函数
  97. void int0(void) interrupt 0 {
  98.     EX0 = 0;  //关外部中断0
  99.     // 重置命令
  100.     if (reset == 0) {
  101.         delay1ms(5);
  102.         if (reset == 0) {
  103.             while (!reset)
  104.                 ;
  105.             key();
  106.             // 复位重新计时
  107.             work_time = WORK_MAX_TIME;
  108.         }
  109.     }
  110.     EX0 = 1;  //开启外部中断0
  111. }
复制代码
LCD1602部分
lcd1602.h
  1. #ifndef _LCD1602_H_
  2. #define _LCD1602_H_
  3. #include <reg52.h>
  4. typedef unsigned char uchar;
  5. typedef unsigned int uint;
  6. //延时程序
  7. void delay1ms(uint z);
  8. //写命令操作
  9. void write_com(uchar com);
  10. //写数据操作
  11. void write_data(uchar date);
  12. //写字符串
  13. void write_str(uchar *str);
  14. //液晶初始化
  15. void init_1602();
  16. #endif  //_LCD1602_H_
复制代码
lcd1602.c
  1. #include "lcd1602.h"
  2. sbit lcden = P3 ^ 7;  //液晶使能端
  3. sbit lcdrs = P3 ^ 4;  //液晶数据命令选择端
  4. sbit lcdrw = P3 ^ 6;  //读写选择端
  5. //延时程序
  6. void delay1ms(uint z) {
  7.         uint x, y;
  8.         for (x = z; x > 0; x--)
  9.                 for (y = 114; y > 0; y--)
  10.                         ;
  11. }
  12. //写命令操作
  13. void write_com(uchar com) {
  14.         lcdrs = 0;
  15.         P0 = com;
  16.         delay1ms(5);
  17.         lcden = 1;
  18.         delay1ms(5);
  19.         lcden = 0;
  20. }
  21. //写数据操作
  22. void write_data(uchar date) {
  23.         lcdrs = 1;
  24.         P0 = date;
  25.         delay1ms(5);
  26.         lcden = 1;
  27.         delay1ms(5);
  28.         lcden = 0;
  29. }
  30. //写字符串
  31. void write_str(uchar *str) {
  32.         while (*str != '\0')  //字符串未结束
  33.         {
  34.                 write_data(*str++);
  35.                 delay1ms(1);
  36.         }
  37. }
  38. //液晶初始化
  39. void init_1602() {
  40.         uchar table[16] = {0};
  41.         uchar table1[16] = {0};
  42.         lcdrw = 0;
  43.         lcden = 0;
  44.         write_com(0x38);  //设置16x2显示,5x7点阵,八位数据接口
  45.         write_com(0x0c);  //设置开显示,不显示光标
  46.         write_com(0x06);  //写一个字符后地址指针加1
  47.         write_com(0x01);  //显示清0,数据指针清0
  48. }
复制代码
来源:https://blog.caogenba.net/fddnihao/article/details/122437475
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作