我们工作久了,久坐导致的毛病就显现出来了,腰酸背痛颈椎疼,最近看到利用番茄钟工作法挺好,工作25分钟,休息5分钟,既能调整工作节奏,避免精力过分消耗,也能避免久坐导致的身体问题。
我刚开始使用闹钟做提醒,后来尝试番茄钟软件,但是都要手动去 *** 作手机,拿起手机看到信息,然后就会去处理手机上的事情了,起不到作用…
直到有一天收拾东西看到了我大学期间基于51单片机做的一个电子设计,激起了我的灵感,开始了基于51单片机的自动番茄钟,久坐提醒神器的设计和制作。
整体方案硬件部分继承了大学时焊接的电路板,更换了传感器部分,软件部分重新编写了控制部分的代码。
之前的软硬件设计方案可以参考这篇文章《基于51单片机的上下限可调的数字温度控制系统》,本文重点阐述差异部分。
本设计要求能够识别到座位上有人,并开始计时,能够在LCD屏上显示工作状态和倒计时时间。当超过设置的久坐提醒时间(25分钟),进行蜂鸣器和LED灯报警,并在LCD屏上显示让你休息的提示。人离开后能够重置时间,LCD屏显示离开状态,直到你坐下后开始重新计时。另外如果有特殊情况无法按时休息,支持按复位键重新计时。
三、系统组成本系统由STC89C52单片机主控,通过晶振时钟模块、复位电路模块、按键模块、液晶显示模块、声光报警模块、传感器模块组成。
其中液晶显示模块采用LCD1602液晶显示屏,声光报警模块采用蜂鸣器和红黄绿三个LED灯,传感器模块开始采用的是E18-D80NK红外漫反射光电传感器。
传感器部分刚开始选用的是HC-SR501热释电红外传感器,但是调试过程中发现该人体红外传感器只能检测到移动的人体,无法检测到静止的人体。咱们工作的时候有时会很专注,静止在那里识别不到,传感器就认为没有人,导致功能失效。后来找了一下发现E18-D80NK红外漫反射光电传感器能够满足要求,于是选了这个传感器。
其中,传感器要换成红外漫反射光电传感器。
见附录
六、结果展示 1、正常工作状态 2、久坐提醒状态 3、离开休息状态 附录主控部分
main.c
#include#include #include "lcd1602.h" #define WORK_MAX_TIME (25 * 60) sbit beep = P1 ^ 3; //蜂鸣器 sbit pir = P2 ^ 0; //热释电红外传感器信号线 sbit reset = P3 ^ 2; //定义按键--复位键 sbit led0 = P2 ^ 2; //绿灯 sbit led1 = P2 ^ 3; //黄灯 sbit led2 = P2 ^ 4; //红灯 uint work_time = WORK_MAX_TIME; //工作坐着的秒数 //蜂鸣器 void di(uchar s) { beep = 0; delay1ms(s); beep = 1; } //按键音 void key() { di(100); } //报警音 void warn() { di(5000); } //点亮LED void lightLED(uchar c) { if (c == 'r') { // 红灯亮 led0 = 1; led1 = 1; led2 = 0; } else if (c == 'g') { // 绿灯亮 led0 = 0; led1 = 1; led2 = 1; } else if (c == 'y') { // 黄灯亮 led0 = 1; led1 = 0; led2 = 1; } else { led0 = 1; led1 = 1; led2 = 1; } } //液晶显示 void showLCD(char *_msg, uint _tm) { uchar tm[16] = {0}; uint min = _tm / 60; uint sec = _tm % 60; write_com(0x80); write_str(_msg); write_com(0x80 + 0x40); sprintf(tm, "time %02d:%02d", min, sec); write_str(tm); } //处理红外漫反射传感器信号 void processPIR() { // 人在座位上 if (pir == 0) { // led显示working和倒计时 if (work_time > 0) { showLCD("working ... ", work_time); // 绿灯亮 lightLED('g'); work_time--; } else { work_time = 0; showLCD("go go go !!! ", work_time); // 红灯亮 lightLED('r'); warn(); } } else if (pir == 1) { // led显示leaving和25:00 work_time = WORK_MAX_TIME; showLCD("leaving ... ", work_time); // 黄灯亮 lightLED('y'); } } void main() { EA = 1; //全局中断开关 IT0 = 1; //跳变沿触发方式 EX0 = 1; //开启外部中断0 led0 = 0; led1 = 0; led2 = 0; init_1602(); delay1ms(1000); while (1) { processPIR(); delay1ms(1000); } } //外部中断0函数 void int0(void) interrupt 0 { EX0 = 0; //关外部中断0 // 重置命令 if (reset == 0) { delay1ms(5); if (reset == 0) { while (!reset) ; key(); // 复位重新计时 work_time = WORK_MAX_TIME; } } EX0 = 1; //开启外部中断0 }
LCD1602部分
lcd1602.h
#ifndef _LCD1602_H_ #define _LCD1602_H_ #includetypedef unsigned char uchar; typedef unsigned int uint; //延时程序 void delay1ms(uint z); //写命令 *** 作 void write_com(uchar com); //写数据 *** 作 void write_data(uchar date); //写字符串 void write_str(uchar *str); //液晶初始化 void init_1602(); #endif //_LCD1602_H_
lcd1602.c
#include "lcd1602.h" sbit lcden = P3 ^ 7; //液晶使能端 sbit lcdrs = P3 ^ 4; //液晶数据命令选择端 sbit lcdrw = P3 ^ 6; //读写选择端 //延时程序 void delay1ms(uint z) { uint x, y; for (x = z; x > 0; x--) for (y = 114; y > 0; y--) ; } //写命令 *** 作 void write_com(uchar com) { lcdrs = 0; P0 = com; delay1ms(5); lcden = 1; delay1ms(5); lcden = 0; } //写数据 *** 作 void write_data(uchar date) { lcdrs = 1; P0 = date; delay1ms(5); lcden = 1; delay1ms(5); lcden = 0; } //写字符串 void write_str(uchar *str) { while (*str != '') //字符串未结束 { write_data(*str++); delay1ms(1); } } //液晶初始化 void init_1602() { uchar table[16] = {0}; uchar table1[16] = {0}; lcdrw = 0; lcden = 0; write_com(0x38); //设置16x2显示,5x7点阵,八位数据接口 write_com(0x0c); //设置开显示,不显示光标 write_com(0x06); //写一个字符后地址指针加1 write_com(0x01); //显示清0,数据指针清0 }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)