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)
|