Arduino “学生寝室”门禁管理(红外遥控+舵机+无源蜂鸣器+DHT11温湿度传感器+LCD1602+LED灯)

一、项目要求描述

通过红外接收模块接收指令,将红外接收的引脚模式设置为输入,通过红外遥控器的按键“1~5”向其输入指令。编写代码,使得Arduino UNO控制板及相关传感器实现“学生寝室”门禁管理。


二、控制电路连接

本电路所包含的电子元件:Arduino UNO板,红外接收传感器、DHT11温湿度传感器、LED灯、舵机、蜂鸣器(无源)、LCD1602显示屏。

硬件接线
红外接收器OUT2
DHT11温湿度传感器OUT4
LED灯I/O5
舵机PWM6
无源蜂鸣器I/O12
LCD1602SDA、SCLSDA、SCL

三、功能分析

在硬件通电情况下,LCD屏上显示“This is chamber:113”(这是113寝室)。

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(receivePin,INPUT); //红外VOUT端口模式,输入
pinMode(servoPin,OUTPUT); //舵机端口模式,输出
pinMode(ledPin,OUTPUT);//led灯端口模式,输出
pinMode(fmqPin,OUTPUT);//蜂鸣器端口模式,输出
lcd.init(); //初始化LCD
lcd.backlight(); //打开背光
lcd.print("This is chamber:"); //在LCD上打印信息
lcd.setCursor(0,1); //跳转新的一行
lcd.print("113"); //在LCD上打印信息
sensorIR.enableIRIn();
}

1、功能一:开门

将开门按键设置为“1”,使用1的键值。通过遥控器按下“1”时,舵机旋转120度,灯光闪烁5次,提示有人到来,LCD屏上显示“Door is open.”(门已开启)。

 if(results.value==0xFF30CF){  //设置开门按键为1,使用1的键值
   servopluse(6,120);           //实现开门功能(舵机旋转120°)
    lcd.clear();                //LCD屏上打印“门已开启”
    lcd.setCursor(0,0);
    lcd.print("Door is open.");
    
    for(int i=0;i<5;i++){        //灯光闪烁5次
    analogWrite(ledPin,HIGH);
    delay(500);
    analogWrite(ledPin,LOW);
    delay(500);
   }
}

2、功能二:关门

将开门按键设置为“2”,使用2的键值。通过遥控器按下“2”时,舵机旋转回原始位置,LCD屏上显示“See you!”(再见)。

if(results.value==0xFF18E7){ //设置关门按键为2,使用2的键值
    servopluse(6,0);           //实现关门功能(舵机旋转至原始位置)
    lcd.clear();               //LCD屏上打印“再见”
    lcd.setCursor(0,0);
    lcd.print("See you!");
    digitalWrite(ledPin,LOW);  //灯光熄灭
  } 

3、功能三:欢迎

将开门按键设置为“3”,使用3的键值。通过遥控器按下“3”时,无源蜂鸣器播放《两只老虎》,LCD屏上显示“Welcome!”(欢迎)。

if(results.value==0xFF7A85){ //设置关门按键为3,使用3的键值
   lcd.clear();                //LCD屏上打印“欢迎”,蜂鸣器播放歌曲《两只老虎》
   lcd.setCursor(0,0);
   lcd.print("Welcome!");
   
   int frequency[] = {262,294,330,262,262,294,330,262,330,349,392,330,349,392,
      392,440,392,349,330,262,392,440,392,349,330,262,294,221,262,294,221,262}; // 音频频率数组

   float duration[]={0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,1,0.5,0.5,1,
   0.25,0.25,0.25,0.25,0.5,0.5,0.25,0.25,0.25,0.25,0.5,0.5,0.5,0.5,1,0.5,0.5,1};//持续时间数组

   for (int i = 0; i < 32; i++) { // 循环遍历音符
   tone(fmqPin, frequency[i], 500); // 发出声音
   delay(600*duration[i]); // 延时 600 毫秒,以便听到声音
}
}

4、功能四:勿扰

将开门按键设置为“4”,使用4的键值。通过遥控器按下“4”时,LCD屏上滚动显示勿扰信息。

if(results.value==0xFF10EF){  //设置关门按键为4,使用4的键值
   lcd.clear();  LCD屏上打印字符串(勿扰信息)
   f="Sorry,I am busy now!Can you wait a minute?I will open the door for you soon!";
   lcdprint();
  }

5、功能五:天气

将开门按键设置为“5”,使用5的键值。通过遥控器按下“5”时,LCD屏上显示实时的温湿度。

if(results.value==0xFF38C7){  //设置关门按键为5,使用5的键值
        sensor_Dht11.read(Dht11_Pin);
        hum=float(sensor_Dht11.humidity),0;
        tem=float(sensor_Dht11.temperature),0; //温湿度传感器采集环境温湿度信息
        lcd.clear();  //LCD屏上打印温湿度信息
        lcd.setCursor(0,0);
        lcd.print("Humidity:");
        lcd.setCursor(10,0);
        lcd.print(hum);
        lcd.setCursor(13,0);
        lcd.print("^C");
        lcd.setCursor(0,1);
        lcd.print("Temper:");
        lcd.setCursor(10,1);
        lcd.print(tem);
        lcd.setCursor(13,1);
        lcd.print("%");
  }

四、定义函数

1、调用各类传感器需要用到的库函数,给出接口及相关函数定义

#include<Wire.h>
#include<LiquidCrystal_I2C.h>
#include <dht11.h>
#include <IRremote.h>
#define receivePin 2
#define fmqPin 12
#define Dht11_Pin 4
#define ledPin 5
#define servoPin 6 //库函数及接口定义
dht11 sensor_Dht11;
int myangle;
int pulsewidth;
int hum,tem;
int e=0;
String f; //函数定义
LiquidCrystal_I2C lcd(0x20,16,2);
IRrecv sensorIR(receivePin);
decode_results results;

2、定义舵机脉冲函数

void servopluse(int servopin,int myangle){ //舵机脉冲函数 
  pulsewidth=(myangle*11)+500;
  digitalWrite(servopin,HIGH);
  delayMicroseconds(pulsewidth);
  digitalWrite(servopin,LOW);
  delay(20-pulsewidth/1000);
}

3、定义LCD字符串滚动函数

void lcdprint() //LCD屏显示已知字符串
{
  char fe[(f.length()+1)];
  f.toCharArray(fe,f.length()+1);
  int k=0;
  int ur=0;
  delay(100);
  lcd.clear();
  lcd.write(fe[ur]);
  e=1;
  while (fe[ur]){
    e++;
    ur++;
    if (e>16&&e<=31)
    {
      if(k==0)
      {
        lcd.setCursor(0,1);
        k=1;
        }
        lcd.write(fe[ur]);
      }
      else if(e>31)
      {
        lcd.write(fe[ur]);
        k=0;
        e=0;
        delay(2000);
        lcd.clear();
        }
        else
        {
          lcd.write(fe[ur]);
          }
    }
  e=0;
  lcd.clear();
  lcd.print("This is chamber:"); //在LCD上打印信息
  lcd.setCursor(0,1); //跳转新的一行
  lcd.print("113"); //在LCD上打印信息
}

五、相关问题

1、解决红外遥控与舵机模块均为pwm输出的问题

解决舵机库和pwm输出冲突:直接通过延时函数来给舵机脉冲,达到控制的效果,因为Arduino里延时函数delay()用的是定时器Timer0,所以就不会影响彼此的功能了。

bc867f7f035f425b848d3c79dae38b60.png

 因此,不要调用舵机库,使用不调库的写法。


2、解决IRrecv类库函数(红外遥控)与tone()函数(蜂鸣器音调)共用定时器Timer2的问题

  1. UNO板定时器较少,只有三个,可以通过修改库文件使用Timer1e2cbfc431caf43a588e3305c62b3c91b.png

    Arduino定时器相关介绍

  2. 此处将tone()函数的默认计时器Timer2修改为Timer1,修改Arduino里Core核心函数里的Tone.c文件(UNO板将118和120行的2改为1),然后再将其添加到项目的文件夹里,点击编译

    #else
    
    #define AVAILABLE_TONE_PINS 1
    #define USE_TIMER1
    
    // Leave timer 0 to last.
    const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 1 /*, 1, 0 */ };
    static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ };
    

    6a78da727946451da3a4a7a817c7cdd8.png

    定时器冲突实践解决方法

  3. 由于舵机模块并没有调用库servo.h,因此Timer1并没有被占用,实现了红外按键同时遥控舵机、蜂鸣器的功能


    六、整体代码

#include<Wire.h>
#include<LiquidCrystal_I2C.h>
#include <dht11.h>
#include <IRremote.h>
#define receivePin 2
#define fmqPin 12
#define Dht11_Pin 4
#define ledPin 5
#define servoPin 6 //库函数及接口定义
dht11 sensor_Dht11;
int myangle;
int pulsewidth;
int hum,tem;
int e=0;
String f; //函数定义
LiquidCrystal_I2C lcd(0x20,16,2);
IRrecv sensorIR(receivePin);
decode_results results;

void servopluse(int servopin,int myangle){ //舵机脉冲函数 
  pulsewidth=(myangle*11)+500;
  digitalWrite(servopin,HIGH);
  delayMicroseconds(pulsewidth);
  digitalWrite(servopin,LOW);
  delay(20-pulsewidth/1000);
}

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(receivePin,INPUT); //红外VOUT端口模式,输入
pinMode(servoPin,OUTPUT); //舵机端口模式,输出
pinMode(ledPin,OUTPUT);//led灯端口模式,输出
pinMode(fmqPin,OUTPUT);//蜂鸣器端口模式,输出
lcd.init(); //初始化LCD
lcd.backlight(); //打开背光
lcd.print("This is chamber:"); //在LCD上打印信息
lcd.setCursor(0,1); //跳转新的一行
lcd.print("113"); //在LCD上打印信息
sensorIR.enableIRIn();
}

void loop() {
  // put your main code here, to run repeatedly:
if (sensorIR.decode(&results)){
  
   if(results.value==0xFF30CF){  //设置开门按键为1,使用1的键值
   servopluse(6,120);           //实现开门功能(舵机旋转120°)
    lcd.clear();                //LCD屏上打印“门已开启”
    lcd.setCursor(0,0);
    lcd.print("Door is open.");
    
    for(int i=0;i<5;i++){        //灯光闪烁5次
    analogWrite(ledPin,HIGH);
    delay(500);
    analogWrite(ledPin,LOW);
    delay(500);
   }
}
  
 if(results.value==0xFF18E7){ //设置关门按键为2,使用2的键值
    servopluse(6,0);           //实现关门功能(舵机旋转至原始位置)
    lcd.clear();               //LCD屏上打印“再见”
    lcd.setCursor(0,0);
    lcd.print("See you!");
    digitalWrite(ledPin,LOW);  //灯光熄灭
  } 

  if(results.value==0xFF7A85){ //设置关门按键为3,使用3的键值
   lcd.clear();                //LCD屏上打印“欢迎”,蜂鸣器播放歌曲《两只老虎》
   lcd.setCursor(0,0);
   lcd.print("Welcome!");
   
   int frequency[] = {262,294,330,262,262,294,330,262,330,349,392,330,349,392,
      392,440,392,349,330,262,392,440,392,349,330,262,294,221,262,294,221,262}; // 音频频率数组

   float duration[]={0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,1,0.5,0.5,1,
   0.25,0.25,0.25,0.25,0.5,0.5,0.25,0.25,0.25,0.25,0.5,0.5,0.5,0.5,1,0.5,0.5,1};//持续时间数组

   for (int i = 0; i < 32; i++) { // 循环遍历音符
   tone(fmqPin, frequency[i], 500); // 发出声音
   delay(600*duration[i]); // 延时 600 毫秒,以便听到声音
}
}

  if(results.value==0xFF10EF){  //设置关门按键为4,使用4的键值
   lcd.clear();  LCD屏上打印字符串(勿扰信息)
   f="Sorry,I am busy now!Can you wait a minute?I will open the door for you soon!";
   lcdprint();
  }

  if(results.value==0xFF38C7){  //设置关门按键为5,使用5的键值
        sensor_Dht11.read(Dht11_Pin);
        hum=float(sensor_Dht11.humidity),0;
        tem=float(sensor_Dht11.temperature),0; //温湿度传感器采集环境温湿度信息
        lcd.clear();  //LCD屏上打印温湿度信息
        lcd.setCursor(0,0);
        lcd.print("Humidity:");
        lcd.setCursor(10,0);
        lcd.print(hum);
        lcd.setCursor(13,0);
        lcd.print("^C");
        lcd.setCursor(0,1);
        lcd.print("Temper:");
        lcd.setCursor(10,1);
        lcd.print(tem);
        lcd.setCursor(13,1);
        lcd.print("%");
  }
  
  sensorIR.resume(); //等待下一次红外接收指令
}
delay(100);
}

void lcdprint() //LCD屏显示已知字符串
{
  char fe[(f.length()+1)];
  f.toCharArray(fe,f.length()+1);
  int k=0;
  int ur=0;
  delay(100);
  lcd.clear();
  lcd.write(fe[ur]);
  e=1;
  while (fe[ur]){
    e++;
    ur++;
    if (e>16&&e<=31)
    {
      if(k==0)
      {
        lcd.setCursor(0,1);
        k=1;
        }
        lcd.write(fe[ur]);
      }
      else if(e>31)
      {
        lcd.write(fe[ur]);
        k=0;
        e=0;
        delay(2000);
        lcd.clear();
        }
        else
        {
          lcd.write(fe[ur]);
          }
    }
  e=0;
  lcd.clear();
  lcd.print("This is chamber:"); //在LCD上打印信息
  lcd.setCursor(0,1); //跳转新的一行
  lcd.print("113"); //在LCD上打印信息
}

  • 8
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 28
    评论
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小朱在长旅

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

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

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

打赏作者

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

抵扣说明:

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

余额充值