实验三:温湿度传感器
实验目的
- 初步了解 LCD 电子屏幕的使用;
- 使用温湿度传感器将温湿度参数显示在电子屏幕上。
实验展示
实验代码
#include <LiquidCrystal_I2C.h>
#include <DFRobot_DHT11.h>
LiquidCrystal_I2C lcd(0x20,16,2);//设置LCD的地址,2行,每行16字符
DFRobot_DHT11 DHT;
#define DHT11_PIN 4
void setup() {
// put your setup code here, to run once:
lcd.init();// LCD初始化设置
lcd.backlight();// 打开 LCD背光
Serial.begin(9600);//设置串口波特率9600
Serial.print("Type, status, Humidity(%), Temperature(C)\n");//串口输出”Type, status, Humidity(%), Temperature(C)”
lcd.setCursor(0,0);
lcd.print("Humidity(%):");//LCD屏显示” Humidity(%):”
lcd.setCursor(0,1);//光标移到第2行,第一个字符
lcd.print("Temp(C):");//LCD屏显示”Temp(C):”
}
void loop() {
// put your main code here, to run repeatedly:
Serial.print("DHT11, \t");w
//读取 DHT11传感器的数据
DHT.read(DHT11_PIN);
//串口显示温湿度值
Serial.print(DHT.humidity,1);
Serial.print(",\t");
Serial.println(DHT.temperature,1);
//LCD显示温湿度值
lcd.setCursor(12,0);//LCD屏的光标移动到第1行某个位置
lcd.print(DHT.humidity,1);//LCD屏打印湿度值
lcd.setCursor(8,1);//LCD屏的光标移动到第2行某个位置
lcd.print(DHT.temperature,1);//LCD屏打印温度值
delay(1000);
}
实验四:电子闹钟
实验目的
- 模拟时间的流逝过程,实现时钟的正常运行;
- 实现电子闹钟的修改模式;
- 实现闹钟模式,保存闹钟时间并在指定时间使蜂鸣器发出声音。
实验展示
正常模式及修改模式
闹钟模式
实验代码
#include <IRremote.h>
#include <LiquidCrystal_I2C.h>
#define IR_RECEIVE_PIN 4
#define ALARM_PIN 8
IRrecv irrecv(IR_RECEIVE_PIN);
decode_results results;
inline int Isyearp(int x){
if(x%400==0)return 1;
if(x%100 && x%4==0)return 1;
return 0;
}
LiquidCrystal_I2C lcd(0x20,16,2);
int Y1,Y2,Y3,Y4;
int M1,M2;
int D1,D2;
int H1,H2;
int MI1,MI2;
int S1,S2;
int Date;
//定义全局闹铃时间变量--月 日 时 分
int Alarm_M1,Alarm_M2;//定义月份的两位,从高到低
int Alarm_D1,Alarm_D2;//定义日期的两位,从高到低
int Alarm_H1,Alarm_H2;//定义小时的两位,从高到低
int Alarm_MI1,Alarm_MI2;//定义分钟的两位,从高到低
int Alarm_S1,Alarm_S2;//定义秒数的两位,从高到低
//定义临时变量存储时间
int temp_Y1,temp_Y2,temp_Y3,temp_Y4;//定义年份的四位,从高到低
int temp_M1,temp_M2;//定义月份的两位,从高到低
int temp_D1,temp_D2;//定义日期的两位,从高到低
int temp_H1,temp_H2;//定义小时的两位,从高到低
int temp_MI1,temp_MI2;//定义分钟的两位,从高到低
int temp_Date;//定义星期
int temp_S1,temp_S2;//定义秒数的两位,从高到低
int pos[]={3,4,5,6,8,9,11,12,
13,14,16,17,19,20,22};
bool modify_flag,light_flag,alarm_flag,buzzer_flag;
int modifyindex,x,y;
char Datename[7][5]={"Mon","Tue","Wed","Thu","Fri","Sat","Sun"};
inline void xblink(){//实现光标闪烁
lcd.setCursor(x,y);
lcd.blink();
}
inline void xNoblink(){//取消光标闪烁
lcd.noBlink();
}
int Dayofmonth[13][2]={
0,0,
31,31,
28,29,
31,31,
30,30,
31,31,
30,30,
31,31,
31,31,
30,30,
31,31,
30,30,
31,31
};
void calendarShow(){
lcd.setCursor(3,0);
lcd.print(Y1);lcd.print(Y2);lcd.print(Y3);lcd.print(Y4);
lcd.print("/");
lcd.print(M1);lcd.print(M2);
lcd.print("/");
lcd.print(D1);lcd.print(D2);
lcd.setCursor(1,1);
lcd.print(H1);lcd.print(H2);
lcd.print(":");
lcd.print(MI1);lcd.print(MI2);
lcd.print(":");
lcd.print(S1);lcd.print(S2);
//Date
lcd.setCursor(10,1);
if(Date==0)lcd.print("Mon");
else if(Date==1)lcd.print("Tue");
else if(Date==2)lcd.print("Wes");
else if(Date==3)lcd.print("Thu");
else if(Date==4)lcd.print("Fri");
else if(Date==5)lcd.print("Sat");
else if(Date==6)lcd.print("Sun");
else lcd.print("Error!");
return ;
}
void date(){
Date++;Date%=7;
D2++;
if(D2==10){
D2=0;D1++;
}
int day=D1*10+D2,month=M1*10+M2,year=Y1*1000+Y2*100+Y3*10+Y4;
int type=Isyearp(year);
if(day>Dayofmonth[month][type]){
D1=0;D2=1;
M2++;
if(M2==10)M2=0,M1++;
if(M1*10+M2>12){
Y4++;
if(Y4==10)Y4=0,Y3++;
if(Y3==10)Y3=0,Y2++;
if(Y2==10)Y2=0,Y1++;
}
}
}
void tita(){
S2++;
if(S2==10)S2=0,S1++;
if(S1==6)S1=0,MI2++;
if(MI2==10)MI2=0,MI1++;
if(MI1==6)MI1=0,H2++;
if(H2==4 && H1==2){
H1=H2=0;
date();
}
else if(H2==10){
H2=0;
H1++;
}
if(Alarm_S1==S1 && Alarm_S2==S2 && Alarm_MI2 == MI2 && Alarm_MI1 == MI1 && Alarm_H2 == H2 && Alarm_H1 == H1 && Alarm_D2 == D2 && Alarm_D1 == D1 && Alarm_M2 == M2 && Alarm_M1 == M1){
Serial.print(Alarm_H1);
Serial.print(Alarm_H2);
Serial.print(":");
Serial.print(Alarm_MI1);
Serial.print(Alarm_MI2);
Serial.print(":");
Serial.print(Alarm_S1);
Serial.print(Alarm_S2);
buzzer_flag=true;//启动蜂鸣器
}
if(S2==((Alarm_S2+3)%10)){//响铃3S,自动关闭闹钟
buzzer_flag=false;//关闭蜂鸣器
}
return ;
}
void addTime(){
int days,a,b;
if(y==0){
switch(x){
case 8://M1
if(M2<3)M1++,M1%=2;
else M1=0;
lcd.print(M1);
break;
case 9://M2
if(M1==0){
M2++;
if(M2==10)M2=1;
}
else M2++,M2%=3;
lcd.print(M2);
break;
case 11://D1
int month=M1*10+M2,year=Y1*1000+Y2*100+Y3*10+Y4;
int type=Isyearp(year);
if(month==2){
if(type){//isp
D1++;D1%=3;
}
else {
if(D2==9)D1++,D2%=2;
else D1++,D1%=3;
}
}
else {//month!=2
if(D2==0)D1++,D1%=4;
else if(D2==1){
int days=Dayofmonth[month][type];
if(days==31)D1++,D1%=4;
else if(days==30)D1++,D1%=3;
}
else D1++,D1%=3;
}
lcd.print(D1);
break;
case 12://D2
month=M1*10+M2,year=Y1*1000+Y2*100+Y3*10+Y4;
type=Isyearp(year);
if(month==2){
if(D1==2){
if(type)D2++,D2%=10;
else D2++,D2%=9;
}
else D2++,D2%=10;
}
else {
int days=Dayofmonth[month][type];
if(D1==3){
if(days==31)D2++,D2%=2;
else D2=0;
}
else D2++,D2%=10;
}
lcd.print(D2);
break;
case 3://Y1
Y1++;Y1%=10;
lcd.print(Y1);
break;
case 4:
Y2++;Y2%=10;
lcd.print(Y2);
break;
case 5:
Y3++;Y3%=10;
lcd.print(Y3);
break;
case 6:
Y4++;Y4%=10;
lcd.print(Y4);
break;
default:break;
}
}
else {//y=1
switch(x){
case 1://H1
if(H2<4)H1++,H1%=3;
else H1++,H1%=2;
lcd.print(H1);
break;
case 2://H2
if(H1==2)H2++,H2%=4;
else H2++,H2%=10;
lcd.print(H2);
break;
case 4:
MI1++;MI1%=6;
lcd.print(MI1);
break;
case 5:
MI2++;MI2%=10;
lcd.print(MI2);
break;
case 7:
S1++;S1%=6;
lcd.print(S1);
break;
case 8:
S2++;S2%=10;
lcd.print(S2);
break;
case 10:
Date++;Date%=7;
lcd.print(Datename[Date]);
break;
}
}
lcd.setCursor(x,y);
}
void setAlarm(){
Alarm_M1=M1;Alarm_M2=M2;
Alarm_D1=D1;Alarm_D2=D2;
Alarm_H1=H1;Alarm_H2=H2;
Alarm_MI1=MI1;Alarm_MI2=MI2;
Alarm_S1=S1;Alarm_S2=S2;
}
void setup() {
// put your setup code here, to run once:
//setup time
Y1=2;Y2=0;Y3=2;Y4=3;
M1=M2=1;
D1=2;D2=1;
Date=1;
H1=0;H2=8;
MI1=4;MI2=1;
//Tuesday 2023/11/21 8:41
x=3;y=0;
modifyindex=0;
modify_flag=alarm_flag=buzzer_flag=false;
//IR_remote
pinMode(ALARM_PIN,OUTPUT);
irrecv.enableIRIn();
//lcd
lcd.init();
lcd.backlight();
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
if(irrecv.decode()){
Serial.println(irrecv.decodedIRData.decodedRawData,HEX);
if(irrecv.decodedIRData.decodedRawData == 0xFF00BF00){//电源键
light_flag^=1;
if(light_flag)lcd.backlight();
else lcd.noBacklight();
}
else if(irrecv.decodedIRData.decodedRawData == 0xEF10BF00){//1
modifyindex=0;
modify_flag^=1;
if(modify_flag){
xblink();
Serial.println("接受到1信号,进入修改时间模式");
}
else{
xNoblink();
modifyindex=0;
//光标逻辑位置数组的索引初始化
}
}
else if(irrecv.decodedIRData.decodedRawData == 0xEE11BF00){//2
modifyindex=0;
if(alarm_flag){
xNoblink();
modify_flag=false;
alarm_flag^=1;
setAlarm();
Y1=temp_Y1;Y2=temp_Y2;Y3=temp_Y3;Y4=temp_Y4;
M1=temp_M1;M2=temp_M2;D1=temp_D1;D2=temp_D2;
H1=temp_H1;H2=temp_H2;MI1=temp_MI1;MI2=temp_MI2;
S1=temp_S1;S2=temp_S2;
Date=temp_Date;
}
else{
temp_Y1=Y1;temp_Y2=Y2;temp_Y3=Y3;temp_Y4=Y4;
temp_M1=M1;temp_M2=M2;temp_D1=D1;temp_D2=D2;
temp_H1=H1;temp_H2=H2;temp_MI1=MI1;temp_MI2=MI2;
temp_Date=Date;
temp_S1=S1;temp_S2=S2;
modify_flag=true;
buzzer_flag=false;
alarm_flag=true;
x=1,y=1;modifyindex=8;
xblink();
}
}
else if(irrecv.decodedIRData.decodedRawData == 0xFB04BF00){//左快进
if(modify_flag){
xNoblink();
(modifyindex+=14)%=15;
x=pos[modifyindex];
if(x>12){
x-=12;y=1;
}
else y=0;
xblink();
}
}
else if(irrecv.decodedIRData.decodedRawData == 0xF906BF00){//右快进
if(modify_flag){
xNoblink();
(modifyindex+=1)%=15;
x=pos[modifyindex];
if(x>12){
x-=12;y=1;
}
else y=0;
xblink();
}
}
else if(irrecv.decodedIRData.decodedRawData == 0xFE01BF00){//vol+
if(modify_flag)addTime();
}
irrecv.resume();
}
if(!modify_flag && !alarm_flag){
tita();
calendarShow();
delay(1000);
}
if(buzzer_flag){
digitalWrite(ALARM_PIN,HIGH);
}
else{
digitalWrite(ALARM_PIN,LOW);
}
}