标题:
Arduino电子闹钟源码
[打印本页]
作者:
luyunwei123
时间:
2018-6-6 18:31
标题:
Arduino电子闹钟源码
Arduino的电子闹钟,可以设置时间,蜂鸣器报警,播放葫芦娃,使用超声波模块,当手与超声波一定距离的时候关掉闹钟。
代码复制到IDE下载即可。
Arduino单片机源程序如下:
#include <EEPROM.h>
#include <SR04.h>
//葫芦娃对应的乐谱
#define NOTE_D0 -1
#define NOTE_D1 262
#define NOTE_D2 293
#define NOTE_D3 329
#define NOTE_D4 349
#define NOTE_D5 392
#define NOTE_D6 440
#define NOTE_D7 494
#define NOTE_DL1 147
#define NOTE_DL2 165
#define NOTE_DL3 175
#define NOTE_DL4 196
#define NOTE_DL5 221
#define NOTE_DL6 248
#define NOTE_DL7 278
#define NOTE_DH1 523
#define NOTE_DH2 586
#define NOTE_DH3 658
#define NOTE_DH4 697
#define NOTE_DH5 783
#define NOTE_DH6 879
#define NOTE_DH7 987
//以上部分是定义是把每个音符和频率值对应起来,其实不用打这么多,但是都打上了,后面可以随意编写D调的各种歌,我这里用NOTE_D+数字表示音符,NOTE_DH+数字表示上面有点的那种音符,NOTE_DL+数字表示下面有点的那种音符。这样后面写起来比较好识别。
#define WHOLE 1
#define HALF 0.5
#define QUARTER 0.25
#define EIGHTH 0.25
#define SIXTEENTH 0.625
//这部分是用英文对应了拍子,这样后面也比较好看
int tune[] =
{
NOTE_DH1,NOTE_D6,NOTE_D5,NOTE_D6,NOTE_D0,
NOTE_DH1,NOTE_D6,NOTE_D5,NOTE_DH1,NOTE_D6,NOTE_D0,NOTE_D6,
NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D6,NOTE_D0,NOTE_D6,
NOTE_DH1,NOTE_D6,NOTE_D5,NOTE_DH1,NOTE_D6,NOTE_D0,
NOTE_D1,NOTE_D1,NOTE_D3,
NOTE_D1,NOTE_D1,NOTE_D3,NOTE_D0,
NOTE_D6,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D6,
NOTE_D5,NOTE_D1,NOTE_D3,NOTE_D0,
NOTE_DH1,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D6,
NOTE_D5,NOTE_D1,NOTE_D2,NOTE_D0,
NOTE_D7,NOTE_D7,NOTE_D5,NOTE_D3,
NOTE_D5,
NOTE_DH1,NOTE_D0,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D5,NOTE_D6,NOTE_D6,
NOTE_D0,NOTE_D5,NOTE_D1,NOTE_D3,NOTE_D0,
NOTE_DH1,NOTE_D0,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D5,NOTE_D6,NOTE_D6,
NOTE_D0,NOTE_D5,NOTE_D1,NOTE_D2,NOTE_D0,
NOTE_D3,NOTE_D3,NOTE_D1,NOTE_DL6,
NOTE_D1,
NOTE_D3,NOTE_D5,NOTE_D6,NOTE_D6,
NOTE_D3,NOTE_D5,NOTE_D6,NOTE_D6,
NOTE_DH1,NOTE_D0,NOTE_D7,NOTE_D5,
NOTE_D6,
};//这部分就是整首曲子的音符部分,用了一个序列定义为tune,整数
float duration[]=
{
1,1,0.5,0.5,1,
0.5,0.5,0.5,0.5,1,0.5,0.5,
0.5,1,0.5,1,0.5,0.5,
0.5,0.5,0.5,0.5,1,1,
1,1,1+1,
0.5,1,1+0.5,1,
1,1,0.5,0.5,1,
0.5,1,1+0.5,1,
0.5,0.5,0.5,0.5,1+1,
0.5,1,1+0.5,1,
1+1,0.5,0.5,1,
1+1+1+1,
0.5,0.5,0.5+0.25,0.25,0.5+0.25,0.25,0.5+0.25,0.25,
0.5,1,0.5,1,1,
0.5,0.5,0.5+0.25,0.25,0.5+0.25,0.25,0.5+0.25,0.25,
0.5,1,0.5,1,1,
1+1,0.5,0.5,1,
1+1+1+1,
0.5,1,0.5,1+1,
0.5,1,0.5,1+1,
1+1,0.5,0.5,1,
1+1+1+1
};//这部分是整首曲子的接拍部分,也定义个序列duration,浮点(数组的个数和前面音符的个数是一样的,一一对应么)
//LCD初始化
#include <LiquidCrystal.h>
LiquidCrystal lcd=LiquidCrystal(2,3,4,5,6,7,8);
// 初始 化按键
int ring=A3;
int set=A0; //选择端口
int add=A1; //加
int minus=A2; //减
//设置参数
int jy=0,jmonth=0,jd=0,jh=0,jm=0,js=0;// 进位
int year=0,month=0,day=0,hour=0,minute=0,second=0;// 当前时间
int YEAR=2018,MONTH=4,DAY=12,HOUR=18,MINUTE=10,SECOND=00;// 初始设定时间
int moving=0,ring_moving=0;// 设置时间的移动
int ring_hour=0,ring_minute=0,jr=0;//闹钟时间
unsigned long seconds=0;//读取程序运行时间
unsigned long b=1,secondcomp=0,exsecond=0;
//蜂鸣器模块定义
int length;//这里定义一个变量,后面用来表示共有多少个音符
int tonePin=9;//蜂鸣器的pin
int a=0;
//超声波模块管脚参数
int echo=13;
int trig=12;
SR04 target=SR04(echo,trig);
long distance=0;
//共同体设置,把 无符号长整 分4个字节存入 EEPROM
union data
{
float renewtime;
byte difference[4];
};
data col;
void Time_Lcd(int rol,int raw,int number)// 标准格式 在lcd 显示时间
{
lcd.setCursor(rol,raw);
if(number<10)// 如果小于 10,输出 为 0X
{
lcd.print(0);
}
lcd.print(number);
}
//显示具体的时间
void time()
{
if(SECOND<=0) SECOND=0;
second=(secondcomp+seconds+SECOND+exsecond)%60;
Time_Lcd(6,1,second);
jm=(seconds+SECOND)/60;
if(MINUTE<=0) MINUTE=0;
minute=(jm+MINUTE)%60;
Time_Lcd(3,1,minute);
jh=(jm+MINUTE)/60;
if(HOUR<=0) HOUR=0;
hour=(jh+HOUR)%24;
Time_Lcd(0,1,hour);
lcd.setCursor(2,1);
lcd.print(":");
lcd.setCursor(5,1);
lcd.print(":");
lcd.setCursor(8,1);
lcd.print(" ");
lcd.setCursor(4,0);
lcd.print("-");
lcd.setCursor(7,0);
lcd.print("-");
}
//算出当月一共多少个月
int DAYS(int year,int month)
{
if(year%4==0&&year%100!=0||year%400==0)
{
switch(month){
case 1:case 3:case 5:case 7:case 8:case 10:case 12: return 31;break;
case 2:return 29;break;
case 4:case 6:case 9:case 11: return 30;break;}
}
else
{
switch(month){
case 1:case 3:case 5:case 7:case 8:case 10:case 12: return 31;break;
case 2:return 28;break;
case 4:case 6:case 9:case 11: return 30;break;}
}
}
//设置后的天数,考虑进一个月或者天数为 0,退一个月的情况
void Day()
{
if(DAY<=0) DAY=0;
int day=0;
int exdays=0;
int days=DAYS(year,month);
if(month==1) exdays=DAYS(year-1,12);
else exdays=(year,month-1);
jd=(HOUR+jh)/24;
day=(jd+DAY)%(days+1);
if((jd+DAY)==0)
{
jmonth--;
DAY=exdays;
}
if((jd+DAY)==(days+1))
{
jmonth++;
DAY=DAY-days;
}
Time_Lcd(8,0,day);
}
//设置后的月数,考虑 0月退一年的情况
void Month()
{
if(MONTH<=0) MONTH=0;
month=(MONTH+jmonth)%12;
if(month==0&&(MONTH+jmonth)!=0) month=12;
jy=(jmonth+MONTH-1)/12;
if((MONTH+jmonth)==0)
{
month=12;
jy--;
}
Time_Lcd(5,0,month);
}
//设置 年
void Year()
{
if(YEAR<=0) YEAR=0;
year=(jy+YEAR)%10000;
lcd.setCursor(0,0);
if(year<1000)
{
lcd.print("0");
}
if(year<100)
{
lcd.print("00");
}
if(year<10)
{
lcd.print("000");
}
lcd.print(year);
}
// 显示时间汇总
//设置闹钟,移动光标到对应的时间位置
void Set_Clock() //按键选择
{
if(digitalRead(set)==LOW)
{
lcd.setCursor(9, 1); lcd.print("SetTime");
while(1)
{
if(digitalRead(set)==LOW)
{
delay(10);
if(digitalRead(set)==LOW)
moving++;
}
seconds = millis()/1000;
Show_Time();
if(moving == 1)
Set_Time(0, 1, HOUR); //设置小时
if(moving == 2)
Set_Time(3, 1, MINUTE); //分钟
if(moving == 3)
Set_Time(6, 1, SECOND); //秒
if(moving== 4)
Set_Time(8, 0, DAY); //天
if(moving== 5)
Set_Time(5, 0, MONTH); // 月
if(moving== 6)
Set_Time(2, 0, YEAR); // 年
if(moving >= 7)
{
moving = 0;
lcd.setCursor(9,1);
lcd.print(" ");
break;
}
}
delay(50);
}
}
//光标闪烁,显示正在设置哪一位
void Cursor_Blink(int col,int raw)
{
lcd.setCursor(col,raw);
lcd.cursor();
delay(100);
lcd.noCursor();
delay(100);
}
//更改初始时间
void Set_Time(int col, int row, int &TIME) //通过按键设置时间
{
Cursor_Blink(col, row);
if(digitalRead(add) == LOW)
{
delay(10);
if(digitalRead(add) == LOW)
TIME ++;
Show_Time();
}
if(digitalRead(minus) == LOW)
{
delay(10);
if(digitalRead(minus) == LOW)
TIME --;
Show_Time();
}
}
//光标闪烁,显示正在设置哪一位
//更改初始时间
void Show_Time()
{
time();
Day();
Month();
Year();
}
//设置闹铃时间,原理同上
void Set_Ring()
{
if(digitalRead(ring)==LOW)
{
lcd.setCursor(0,0); lcd.print(" set RINGTime ");
lcd.setCursor(0,1);
lcd.print(" ");
Time_Lcd(2,1,ring_hour);
lcd.print(":");
Time_Lcd(5,1,ring_minute);
lcd.print(" ");
while(1)
{
if(digitalRead(ring)==LOW)
{
delay(10);
if(digitalRead(ring)==LOW)
ring_moving++;
}
if(ring_moving == 1)
Set_RingHour(); //SetHour
if(ring_moving == 2)
Set_RingMinute(); //SetMinute
if(ring_moving >= 3)
{
ring_moving = 0;
lcd.setCursor(10,0);
lcd.print(" ");
break;
}
}
delay(100);
}
}
void Set_RingHour() //通过按键设置时间
{
Cursor_Blink(2,1);
if(digitalRead(add) == LOW)
{
delay(10);
if(digitalRead(add) == LOW)
ring_hour++;
ring_hour=ring_hour%24;
Time_Lcd(2,1,ring_hour);
Time_Lcd(5,1,ring_minute);
}
if(digitalRead(minus) == LOW)
{
delay(10);
if(digitalRead(minus) == LOW)
ring_hour--;
Time_Lcd(2,1,ring_hour);
Time_Lcd(5,1,ring_minute);
}
}
void Set_RingMinute() //通过按键设置时间
{
Cursor_Blink(5,1);
if(digitalRead(add) == LOW)
{
delay(10);
if(digitalRead(add) == LOW)
{
ring_minute++;
ring_minute=ring_minute%60;
if(ring_minute==0) ring_hour++;
ring_hour=ring_hour%24;
}
Time_Lcd(2,1,ring_hour);
Time_Lcd(5,1,ring_minute);
}
if(digitalRead(minus) == LOW)
{
delay(10);
if(digitalRead(minus) == LOW)
ring_minute--;
ring_minute=ring_minute%60;
Time_Lcd(2,1,ring_hour);
Time_Lcd(5,1,ring_minute);
}
}
void showdistance() //超声波测量距离
{
distance=target.Distance();
}
void music()//控制蜂鸣器
{
length = sizeof(tune)/sizeof(tune[0]);//这里用了一个sizeof函数,可以查出tone序列里有多少个音符
for(int x=0;x<length;x++)
{
distance=target.Distance();
if(distance<10)
{
break;
}
tone(tonePin,tune[x]);//此函数依次播放tune序列里的数组,即每个音符
delay(200*duration[x]);//每个音符持续的时间,即节拍duration,400是调整时间的越大,曲子速度越慢,越小曲子速度越快,自己掌握吧
noTone(tonePin);//停止当前音符,进入下一音符
}
}
void Ring()//闹铃
{
if(hour==ring_hour&&minute==ring_minute&&second==0)
music();
}
void setup() {
// put your setup code here, to run once:
lcd.begin(16,2);
digitalWrite(add, HIGH);
digitalWrite(minus, HIGH);
digitalWrite(set, HIGH);
digitalWrite(ring,HIGH);
pinMode(tonePin,OUTPUT);//设置蜂鸣器的pin为输出模式
for(int i=0;i<4;i++)
col.difference[i]=EEPROM.read(i);
exsecond=col.renewtime;
}
void loop() {
// put your main code here, to run repeatedly:
seconds=millis()/1000;
if(seconds==900*b+(b-1)) {secondcomp++;b++;}//补偿误差
Show_Time();
Set_Clock();
Set_Ring();
Ring();
col.renewtime=seconds;
for(int i=0;i<4;i++)
EEPROM.write(i, col.difference[i]);
}
复制代码
所有资料51hei提供下载:
电子闹钟.docx
(16.28 KB, 下载次数: 55)
2018-6-6 18:31 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
Z的男人
时间:
2020-11-28 14:38
这个实物怎么接线呀
作者:
ziba108
时间:
2023-7-30 12:28
这个实物怎么接线呀,同问
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1