Arduino温度计Proteus仿真实现

 项目简介

        用Arduino开发板在Proteus仿真软件中搭建DHT22温湿度计,实现用ws2812灯带颜色区分温度计工作状态。所用软件版本为Arduino IDE1.8.19,Proteus8.11。

一、设计方案

1.1功能介绍

1.1.1 DHT22温湿度传感器(A0引脚)

        DHT22温湿度计测量范围(0——100°),用于读取环境中的实际温度和实际湿度,第一行显示实际湿度(%),第二行显示实际温度(°C)。

66d126ca387544bba3a5ebe8d437d804.png

1.1.2 WS2812灯带(8位)(13号引脚)

        用于区分环境实际温度相对于设置的阈值温度的大小,当实际温度高于阈值温度,WS2812灯带显示红色;当实际温度等于阈值温度,WS2812灯带显示绿色;当实际温度低于阈值温度,WS2812灯带显示蓝色。

214f5607b63a4246a7b5431700945681.png

6317acbf7cf64c2783cee191fc24fdc6.png

3964f0cee0904c829a1387ad8f314215.png

1.1.3 工作状态区分灯带(12号引脚)

        正常工作时灯带颜色是彩虹色,表示温度计处于正常工作状态。

551dd625fe294763a08463f464766916.png

1.1.4 超过阈值温度报警器(11号引脚)

        当实际温度超过设置的阈值温度时,报警器响铃。

                b193e1a5654a42309160bebcb000c27d.png                                        e72bf1cb83fc467483cc8997c3be56a7.png

      实际温度未超过阈值温度(报警器未响起)                            实际温度超过阈值温度(报警器响起)

1.1.5 LCD显示屏(A4、A5引脚)

        第一行Temp代表实际温度(℃),第二行THR代表设置的阈值温度(℃)(阈值温度默认为27°C),第三行humidity代表环境的湿度值(%),第四行前五列作为阈值温度输入模式时的输入温度显示。

72e425e5334f4222a2071d2ed3cefb87.png

1.1.6 串口模块(0、1号引脚)

        温度/湿度值通过虚拟串口发送,串口将一些数据通过串口发送。波特率设置为9600。

                     d520925a5f134091979bba40fa7eb3be.png                                     c7dcc89d994545a392842eb9f0714537.png

1.1.7 阈值温度输入模式开关(9号引脚)

        接高电平打开阈值输入模式,程序进入中断;输入完成阈值温度后,将阈值温度输入模式开关接地,关闭阈值输入模式。

                   2d0d49b4ea0e4c229f9abfb9f2456e53.png                                         2b58f0ce19964169830f6d07d93bec29.png

                        阈值输入模式打开                                                       阈值输入模式关闭

1.1.8 阈值温度输入模式指示灯(10号引脚)

        打开阈值输入模式开关时亮起,指示灯亮的时候表示可以进行阈值温度的设置,关闭阈值输入模式时熄灭。

         f2e1aded99cd436d89a4563b39e5b413.png                                            974195f2972349a8b9f45062a1e702de.png

                 阈值输入模式关闭                                                               阈值输入模式打开

1.1.9 4*3矩阵输入键盘(2、3、4、5、6、7、8引脚)

        用于打开阈值温度输入模式后进行阈值温度的设置输入,阈值温度默认设置为27°C,阈值温度输入格式"xx.xx + Enter"。

7c446ec2d1df4b308c1ebccbc0adf4a8.png

实现功能:

        温度测量模式:用DHT22温湿度传感器采集环境的实际温度和实际湿度,当实际温度高于阈值温度(默认27°C)时,ws2812显示红色,报警器报警响铃;当实际温度等于阈值温度时,ws2812显示绿色;当实际温度低于阈值温度时,ws2812显示蓝色。

      阈值温度输入模式:打开阈值温度输入模式可以进行阈值温度的输入,输入格式为xx.xx+Enter。输入完成之后要关闭阈值温度输入模式开关,可以实现阈值温度的更改。

1.2所用库名

1.2.1 Adafruit_NeoPixel.h库

        Adafruit_NeoPixel是一个开源的Arduino库,用于控制基WS2812等LED驱动芯片的RGB LED像素串。

1.2.2 LiquidCrystal_I2C.h库

        LCD1604是一种16列4行的字符液晶显示模块,常用于Arduino等嵌入式系统的用户接口。为了简化连接和编程,我们将使用I2C接口,这只需要Arduino的两个模拟输入引脚,需要安装用于I2C通信的arduino库LiquidCrystal_I2C。

1.2.3 Keypad.h库

        Keypad.h库是一个用于Arduino的库,用于处理键盘输入。它可以用于连接和读取矩阵式键盘或按钮阵列。通过使用Keypad.h库,可以轻松地检测按下的按钮,并执行相应的操作。

二、电路图

2.1 设计proteus仿真电路图如下图所示

7e812312814c490898220a455f469e84.png

三、程序流程图

3.1  arduino程序中的loop循环运行逻辑流程图如下图所示:

5b876cb259104608a9d993d1289e9e25.png

四、设计实现结果

        当实际温度为27°C等于阈值温度(默认27°C)时,ws2812灯带显示绿色。

a5d586c6a7884059aedfb4ed7ff08249.png

        当实际温度为27.1°C大于阈值温度(默认27°C)时,ws2812灯带显示红色,超过阈值温度报警器响起。

23ee6aaff108420cb7d97d61d6b13e67.png

        当实际温度为26.9°C小于阈值温度(默认27°C)时,ws2812灯带显示蓝色。

5f62751915b747568cf4a88e7e5a21ef.png

同时,串口发送环境的实际温度和环境的实际湿度。

17eefe5be3e44be4902bc92207df9b36.png

        打开阈值温度输入模式开关,进行阈值温度重新设定输入,可以看到阈值温度输入模式指示灯亮起。

5c27246a79a14f228e7f6c2dbc25bed4.png

        重新设置阈值温度为15.04°C,可以看到LCD屏幕第四行前五列显示输入的阈值温度,输入完成后点击Enter键确定,然后关闭阈值温度输入模式开关。

5dc4d142d20a41ceb01f1b0d1959b589.png

        等待2s后可以在LCD显示屏上看到阈值温度THR变成了15.04°C,实际温度26.9°C大于重新设置的阈值温度,ws2812灯带显示红色,超过阈值温度报警器响起。

cf07182fc36f4e0ca02783b87658487f.png

五、Arduino代码

#include<Adafruit_NeoPixel.h>   //ws2812灯带
#include<LiquidCrystal_I2C.h>   //LCD显示屏
#include<Keypad.h>              //导入矩阵键盘模块

#define WS2812_Pin1 13        //ws2812灯带1接引脚13
#define WS2812_Pin2 12        //ws2812灯带2接引脚12
#define NUM_LEDS1 8           //灯带一有8个灯
#define NUM_LEDS2 16          //灯带二有16个灯
#define switch_key 9          //阈值温度输入模式开关接引脚9
#define LED 10                //阈值温度输入模式指示灯接引脚10
#define sounder 11            //温度阈值报警器接引脚11
#define data A0   //DHT22的Data引脚接到Arduino开发板的A0引脚

Adafruit_NeoPixel strip1(NUM_LEDS1, WS2812_Pin1, NEO_GRB + NEO_KHZ800);//ws2812灯带1
Adafruit_NeoPixel strip2(NUM_LEDS2, WS2812_Pin2, NEO_GRB + NEO_KHZ800);//ws2812灯带2
LiquidCrystal_I2C lcd(0x27, 16, 4); //16*4 LCD显示屏

unsigned char i;  //无符号8位整型变量
float RH,T;       //单精度浮点数(32位长度)
byte RH_H,RH_L,T_H,T_L,sum,check;  //字节变量,二进制数
float Threshold_temperature = 27.0;   //阈值温度(默认27.00°C)
int j = 0;            //对输入显示位置计数
const byte ROWS = 4;           //矩阵键盘行数
const byte COLS = 3;           //矩阵键盘列数
char keys[ROWS][COLS] = {  // 定义键盘矩阵数组
  {'1','2','3'},          // 1   2   3
  {'4','5','6'},          // 4   5   6
  {'7','8','9'},          // 7   8   9
  {'.','0','A'},          // .   0   A
};

byte rowPins[ROWS] = {2, 3, 4, 5};//行的针脚连接的接口,第一行连2脚,第二行连3脚,第三行连4脚,第四行连5脚
byte colPins[COLS] = {6, 7, 8};   //列的针脚连接的接口,第一列连6脚,第二列连7脚,第三列连8脚

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); //4*3键盘
String inputString = ""; // 保存输入数据的字符串

void setup() {
  // put your setup code here, to run once:
  
  Serial.begin(9600);          //设置串口通信波特率9600
  
  lcd.init();                  //LCD初始化
  lcd.backlight();  
  lcd.setCursor(0,0);          //lcd第1行显示温度
  lcd.print("Temp:        C");
  lcd.setCursor(12,0);
  lcd.print((char)223); //显示o符号
  lcd.setCursor(0,1);          //lcd第2行显示阈值温度
  lcd.print("THR:         C");
  lcd.setCursor(12,1);
  lcd.print((char)223); //显示o符号
  lcd.setCursor(7,1);
  lcd.print(Threshold_temperature);   //LCD阈值温度显示
  lcd.setCursor(-4,2);         //lcd第三行显示湿度
  lcd.print("humidity:     %");
  
  strip1.begin();              //设置灯带开始
  strip1.setBrightness(250);   //设置灯带亮度(0,255)
  strip1.show();               // 初始化
  strip2.begin();              //设置灯带开始
  strip2.setBrightness(250);   //设置灯带亮度(0,255)
  strip2.show();               // 初始化
  
  pinMode(LED,OUTPUT);          // LED引脚输出模式
  digitalWrite(LED,LOW);        // 低电平输出
  pinMode(sounder,OUTPUT);      // 报警器引脚输出模式
  digitalWrite(sounder,LOW);    // 低电平输出
  pinMode(switch_key, INPUT);  // 设置引脚10为输入模式
}

void loop() {
  // put your main code here, to run repeatedly:
  
  if(digitalRead(switch_key) == HIGH){  // 如果开关被按下,进入阈值温度输入模式
  digitalWrite(LED,HIGH);               // 点亮led表示可以进行阈值温度输入
  char key = keypad.waitForKey();       // 存贮输入的字符
  delay(200);                           // 延迟 200ms
  
  if(key != 'A'){
  lcd.setCursor(-4+j,3);
  lcd.print(key);
  j++;
  }
  
  inputString += key;
  Serial.print(key);
  Serial.print("\n");
  Serial.print("Current inputString:");
  Serial.print(inputString);
  theaterChaseRainbow(0); // 彩虹灯带亮
  }
  else{
  digitalWrite(LED,LOW);        //led低电平
  theaterChaseRainbow(3);
  }
  
  if (inputString.endsWith("A")) {
    inputString = inputString.substring(0, inputString.length() - 1); // 移除结束标志‘A’
    float temperature = inputString.toFloat(); // 将字符串转换成浮点数xx.xx
    if(temperature >= 0 && temperature <= 100){   //判读输入温度是否合理
      Threshold_temperature = temperature;      //设置阈值温度大小
    }
    inputString = "";                         //清空字符串
    Serial.print("\n");
    Serial.print(Threshold_temperature);      //串口发送显示阈值温度大小
    lcd.setCursor(7,1);                 
    lcd.print(Threshold_temperature);   //LCD阈值温度显示
    digitalWrite(LED,LOW);              //led低电平关闭
    i = 0;
    delay(3000);                        //延长3秒,用于灯带用户取消阈值输入模式
  }
  
  digitalWrite(LED,LOW);
  DHT22();        //获取温湿度数据
  Serial.print("Humidity:");  //向串口打印 Humidity:
  Serial.print(RH);           //向串口打印湿度数据
  Serial.print("%");
  Serial.print("  Temperature:");
  Serial.print(T);            //向串口打印温度数据
  Serial.println("C");
  
  lcd.setCursor(7,0);
  lcd.print(T);               //LCD温度显示
  lcd.setCursor(5,2);
  lcd.print(RH);              //LCD湿度显示
  lcd.setCursor(7,1);
  lcd.print(Threshold_temperature);   //LCD阈值温度显示
  
  if(T < Threshold_temperature){
    colorWipe(strip1.Color(  0,   0, 255), 30); // 蓝
    digitalWrite(sounder,LOW);
  }
  else if(T > Threshold_temperature){
    colorWipe(strip1.Color(255,   0,   0), 30); // 红
    digitalWrite(sounder,HIGH);
  }
  else{
    colorWipe(strip1.Color(  0, 255,   0), 30); // 绿
    digitalWrite(sounder,LOW);
  }
  
}

//用一种颜色一个接一个地填充条形像素。带材未先清除;原有像素都将被逐个覆盖。
void colorWipe(uint32_t color, int wait) {
  
  for(int i=0; i<strip1.numPixels(); i++) { //每次循环处理一个像素
    strip1.setPixelColor(i, color);         //  设置像素值 (在RAM里)
    strip1.show(); 
    delay(wait);                                            
  }
  
}

// 彩虹函数,在帧之间传递延迟时间(毫秒)
void theaterChaseRainbow(int wait) {
  int firstPixelHue = 0;     // 第一个像素以红色开始(色调0)
  
  for(int a=0; a<30; a++) {  // 重复30次...
    
    for(int b=0; b<3; b++) { //  'b'从0到2…
      strip2.clear();         //   将RAM中的所有像素设置为0(关闭)
      // “c”从“b”开始计数,以3为增量到条带的末尾…
      
      for(int c=b; c<strip2.numPixels(); c += 3) {
        // 像素“c”的色相被偏移了一定的量,使其饱满
        // 色轮(范围65536)沿长度的转数
        // (strip. numpixels()步骤):
        int      hue   = firstPixelHue + c * 65536L / strip2.numPixels();
        uint32_t color = strip2.gamma32(strip2.ColorHSV(hue)); // hue -> RGB
        strip2.setPixelColor(c, color); // 设置像素c的值为color
      }
      
      strip2.show();                    // 用新内容更新条带
      delay(wait);                     // 等待
      firstPixelHue += 65536 / 90;     // 一个周期的色轮超过90帧
    }
  }
}
void DHT22(void)
{
  RH_H=0,RH_L=0,T_H=0,T_L=0,sum=0,check=0;
  
  pinMode(data,OUTPUT);   //设置IO口为输出模式
  digitalWrite(data,1);   //设置IO口输出高电平
  delay(10);              //延时10毫秒
  digitalWrite(data,0);   //设置IO口输出低电平
  delay(25);              //延时25毫秒
  digitalWrite(data,1);   //设置IO口输出高电平
  pinMode(data,INPUT);    //设置IO口为输入模式
  delayMicroseconds(30);  //延时30微秒
  
  if(!digitalRead(data))  //判断IO口输入电平是否低电平
  {
    
    while(!digitalRead(data));  //一直循环至输入为高电平
    while(digitalRead(data));   //一直循环至输入为低电平
    
    for(i=0;i<8;i++)            //循环执行8次
    {   
      while(!digitalRead(data));//一直循环至输入为高电平   
      delayMicroseconds(28);    //延时28微秒
      if(digitalRead(data)){    //判断IO口输入电平是否高电平
        bitWrite(RH_H, 7-i, 1); //在二进制变量RH_H的第7-i位(从右数起)写入1     
        while(digitalRead(data));
      }
    }
    
    for(i=0;i<8;i++)
    {
      while(!digitalRead(data));
      delayMicroseconds(28);
      if(digitalRead(data)){
        bitWrite(RH_L, 7-i, 1);
        while(digitalRead(data));
      }
    }
    
    for(i=0;i<8;i++)
    {
      while(!digitalRead(data));
      delayMicroseconds(28);
      if(digitalRead(data)){      
        bitWrite(T_H, 7-i, 1);
        while(digitalRead(data));
      }
    }
    
    for(i=0;i<8;i++)
    {
      while(!digitalRead(data));
      delayMicroseconds(28);
      if(digitalRead(data)){      
        bitWrite(T_L, 7-i, 1);
        while(digitalRead(data));
      }
    }
    
    for(i=0;i<8;i++)
    {
      while(!digitalRead(data));
      delayMicroseconds(28);
      if(digitalRead(data)){      
        bitWrite(check, 7-i, 1);
        while(digitalRead(data));
      }
    }
    
   }
  sum=RH_H + RH_L + T_H + T_L;
  byte sum_temp=0;
  //读取sum的末8位写入sum_temp
  
  for(i=0;i<8;i++){
    bitWrite(sum_temp,i,bitRead(sum,i)); 
  }
  
  if(check==sum_temp){
    if(bitRead(RH_H,7)==1){ //判断温度是否零下
      T=-(float(T_H<<8)+float(T_L))/10;
    }else{
      T=(float(T_H<<8)+float(T_L))/10;
    }
    RH=(float(RH_H<<8)+float(RH_L))/10;
  }  
  
}

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值