基于PIC16F877A的智能台灯设计。

该系统利用超声波传感器HCSR04进行测距,当人体靠近或环境光照过暗时,通过蜂鸣器和LED报警。用户可通过按键设置报警阈值,包括距离和光照强度。采用PIC单片机控制,集成学习时长报警功能,超过45分钟也会触发报警。
摘要由CSDN通过智能技术生成

        首先描述一下所实现的功能:本台灯可以对环境光照进行测量,当环境光强度太暗时,说明此时光线不适合学习,蜂鸣器就会报警。这里报警的光照阈值是可以通过按键进行设置的。另外,本台灯还有测距功能,当检测到人体距离台灯很近时,说明此时学习对眼睛不好,蜂鸣器也会进行报警。同样,报警的距离阈值也可以通过按键进行调整。还有学习时长报警,当学习时间超过45分钟时,就会进行报警,仿真时,时长用45S替代。需要说明的是,报警时,除蜂鸣器会鸣叫以外,LED灯也会亮。

        本次使用三个按键对两个值进行加减调整。实现思路如下:K3按下时,对flag++,当flag为奇数时,按下K1  K2是对光照阈值进行调节;当flag为偶数时,是对距离阈值进行调节!

整体仿真图如下所示:

        第一行左边显示的是 所测距离,右边是距离阈值。第二行左边是所测光照强度,右边是光照强度的阈值。

接下来进行详细讲解。

1.超声波传感器

        首先当然要重点介绍一下超声波传感器HCSR04了。

        超声波模块HCSR04是一种常用的测距传感器,利用超声波原理进行测距操作。它由发送模块和接收模块组成,能够实现非接触式的距离测量。

        HCSR04模块工作原理基于声学的传播速度和返回时间的测量。发送模块会发出一束超声波脉冲,然后接收模块接收到超声波反射回来的信号。通过测量超声波的发送时间和接收时间的差值,可以计算出物体与模块之间的距离。

        HCSR04模块具有以下特点:
        1. 高精度测距:可实现几厘米到几米的距离测量,精度达到毫米级别。
        2. 快速响应:测距速度较快,响应时间短。
        3. 非接触测距:无需物体与模块之间的接触,适用于避免接触传感器的应用场景。
        4. 安装方便:模块体积小巧,可方便地安装在各种设备和系统中。

        HCSR04模块广泛应用于机器人导航、智能无人车、避障装置等领域。通过测量物体与传感器的距离,可以实现避障、导航、精确定位等功能。同时,由于HCSR04模块成本低廉,容易获取,因此也被广泛应用于学习和实验项目中。

实物图如下:

工作时序图如下:

 

 

 

        超声波模块HCSR04利用超声波的传播速度和返回时间的差值来进行距离测量。它由发送模块和接收模块组成,工作过程如下:

        1. 发送超声波脉冲:发送模块向外发出一个超声波脉冲信号,该脉冲信号以一定频率发射,一般为40kHz。
        2. 接收超声波信号:接收模块开始等待接收反射回来的超声波信号。
        3. 接收到反射信号:超声波脉冲遇到物体后,会被物体反射回来,接收模块接收到这个反射信号。
        4. 计算距离:根据发送和接收的时间差,可以计算出物体与传感器的距离。

        测距原理如下:
        1. 发送模块发出超声波脉冲后,开始计时。
        2. 接收模块接收到反射信号后,停止计时。
        3. 通过测量发送和接收的时间差,可以得到超声波从传感器发射到物体反射回来所经过的时间。
        4. 根据声速传播的公式 v = d / t ,其中 v 为声速,d 为物体到传感器的距离,t 为时间差,可以求得物体与传感器的距离。

        需要注意的是,由于超声波在空气中的传播速度与温度、湿度等环境因素有关,测距过程中要根据环境条件对测量结果进行校正。另外,在测量中也需要注意避免信号的干扰和多次测量的稳定性。

        所以我们要做的就是,用PIC单片机触发超声波模块发送信号,然后记录接收到信号所经历的时间,有时间,有声音的速度,就能得到距离。

主代码如下:

// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#include <xc.h>
#include "ee302lcd.h"	// Include LCD header file
#include <stdio.h>	// Include Standard I/O header file
#include "I2C_EE302.h"

#define LED  RC0    // Define RC0 as LED
#define BEEP RC1     // Define RC1 as BEEP
#define trig	RB0
#define echo	RB1
#define KEY1 RB2		//label RB2 as key1
#define KEY2 RB3		//label RB3 as key2
#define KEY3 RB4		//label RB4 as key3

 unsigned char outString[5];	//character array for LCD string
 unsigned char outString2[5];	//存放光照阈值  用于显示
 
 int dis_limt=30;               //距离阈值
 int light_limt=150;            //关照强度阈值     光照强度范围:0-255
 int t=0;
 int i=0;
 int adc_value;
 char flag=0;               //用于标记模式选择




void do_adc(void)
{
    __delay_us(30);					//Acqusition time delay set to 30us (>19.7us)
    GO_nDONE=1;						//Start ADC conversion
	while(GO_nDONE)continue;		//Wait until conversion finishes
    adc_value = ADRESH;					//Pass ADRESH value to adc_value variable
    sprintf(outString2,"%d  %d  %d",ADRESH,light_limt,t);	 //显示光照强度  光照阈值  运行时间
    Lcd8_Set_Cursor(2,0);	
    Lcd8_Write_String(outString2);
    
    
}

//设置阈值   
void set_threshold(void)
{   
    if(KEY3==0)
    {   
        __delay_ms(100);	
        if(KEY3==0)             //flag为偶数时   是对距离阈值的调整   奇数  是对光照阈值的调整
            flag++;             
    }
    if(KEY1==0)
    {   
        __delay_ms(100);	
        if(KEY1==0)
        {
            if(flag%2==0)
                dis_limt++;
            else
                light_limt+=10;
        }
    }
    if(KEY2==0)
    {   
        __delay_ms(100);	
        if(KEY2==0)
        {
            if(flag%2==0)
                dis_limt--;
            else
                 light_limt-=10;
        }
    }
   
}



int get_srf04(void)
{
	TMR1H = 0xff;						// prepare timer for 10uS pulse
	TMR1L = 0xf0;
	T1CON = 0x11;						// enables timer1, sets it to internal clock, sets prescaler to x2 
	TMR1IF = 0;	
	trig = 1;							// start trigger pulse
	while(!TMR1IF);					// wait 10uS
	trig = 0;							// end trigger pulse
	TMR1ON = 0;							// stop timer
		
	TMR1H = 0;							// prepare timer to measure echo pulse
	TMR1L = 0;
	T1CON = 0x10;						// 1:2 prescale but not running yet
	TMR1IF = 0;
	while(!echo && !TMR1IF);		// wait for echo pulse to start (go high)
	TMR1ON = 1;							// start timer to measure pulse
	while(echo && !TMR1IF);			// wait for echo pulse to stop (go low)
	TMR1ON = 0;							// stop timer
	return (TMR1H<<8)+TMR1L;		// 
}

void main(void) 
{
    int dis=0;          //distance from HCSR04
    i2c_init();			//do i2c intialisation, TRISC modified here
    Lcd8_Init();				// Required initialisation of LCD to 8-bit mode
    TRISC=0x00;                 // Ensure LEDs are set as outputs RC0, RC1
    
    TRISB=0x1E;					// Set PORTB bit  2  3 4 as input for switch   1 input for echo 0 output for trig
    PORTB=0X1E;                 //enable internal pull up
    OPTION_REG=0X00;            //turn on pull up in port B
    
    //iic
    TRISC 	|= 0x18;		// RC6 and RC7 must be configured as inputs to enable the UART
						// RC4 and RC3 high from I2C_init 
    
    TRISA=0x04;					// Set PORTA bit 3 as input for AN2
    ADCON0 = 0b01010001;		// ADCS1:ADCS0 set to 0:1 for Tosc x8 (Fosc/8)
								// Channel 2
								// ADC On
    ADCON1 = 0b00000010;		// Left justified result
                                // ADCS2 = 0 for Tosc x8 (Fosc/8)
								// RA2/AN2 selected as analog input
								// Vref+ : Vdd   Vref- : Vss
								// AN7, AN6 and AN5 selected for Digital I/O for LCD
    
    //USART
    TRISC 	|= 0xC0;		// RC6 and RC7 must be configured as inputs to enable the UART 
	TXSTA 	= 0x24;		// Set TXEN and BRGH
	RCSTA 	= 0x80;		// Enable serial port by setting SPEN bit
	SPBRG	= 0x19;		// Select 9600 baud rate.
    
    //TIMER0  							
    OPTION_REG=0x07;             //TMR0----256分频
    INTCON = 0xC0;				//enables global interrupts and peripherial interrupts
    TMR0IE = 1;
	TMR0IF = 0;
    TMR0=0x00;               //定时器初值
    
   
    while(1)
    {   
        dis=(get_srf04()*34.0)/1000.0+1;            //covert to cm
        sprintf(outString,"%dcm  %dcm",dis,dis_limt);	
        Lcd8_Clear();							//clear LCD
        Lcd8_Write_String(outString);
        do_adc();
        set_threshold();                    //设置阈值
        if(adc_value<light_limt || dis>dis_limt || t>45)        //如果光照过暗  距离太近  时间太久  就报警
        {
            BEEP=1;
            LED=1;
        }
        else
        {
            BEEP=0;
            LED=0;
        }
         __delay_ms(10);
    }
}


void __interrupt() 
isr() {                         //interrupt service routine


if (TMR0IF == 1)				//Check if Timer0 Interrupt?
	{
		TMR0IF=0;				//resets timer0 interrupt flag
        
        i++;
        if(i==15)
        {
            i=0;
            t++;
        }
			
	TMR0=0x00;        //设置定时器初值							
		

	}

}

        本代码用定时器0进行时间的记录,超过45S还在学习就会报警。另外,采用定时器1,进行超声波模块的触发和时间的记录,从而得到距离。其他的输入输出部分的原理可以看我其他的PIC文章。

        完整的代码和仿真文件,稍后会在评论区给出!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式小李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值