在额济纳支教这一年,给孩子们上了很多Arduino开发的课,也带他们完成了几个Arduino综合项目,下面陆续把这些小项目放上来,欢迎围观~~~非科班出身,C语言学的不好,望各路大神批评指点。
功能介绍
本项目主要是实现基本的闹钟功能:
- LCD屏幕实时显示当前时间(年、月、日、星期、时、分、秒)以及闹钟的开关;
- 通过4*4键盘可以设置初始时间及闹钟时间;
- 通过键盘,还可以查看当前设置的闹钟时间;
- 当闹钟时间到了,蜂鸣器便会响起,同时LED亮起,可以通过键盘关闭闹钟。
准备材料
- Arduino UNO *1
- LCD 1602A *1
- LCD1602液晶屏转接板(PCF8574AT) *1
- 4*4 矩阵键盘 *1
- RTC I2C时钟模块(DS1307)
- 蜂鸣器 *1
- LED灯 *1
- 面包板 *1
- 跳线若干
- 电烙铁、松香、焊锡等
就不给出购买链接了,这些材料在某宝上随便一搜就有~
模块接线
-
键盘与Arduino
R1-C4 -> 2-9
键盘与Arduino接线示意图 -
LCD 1602与转接板
如下图把转接板与LCD1602焊接在一起就行了,或者也可以插在面包板上。
LCD 1602与转接板焊接图
-
转接板与Arduino
PCF8574T | Arduino | |
---|---|---|
GND | -> | GND |
VCC | -> | 5V |
SDA | -> | A4 |
SCL | -> | A5 |
-
DS1307时钟模块与Arduino
DS1307 | Arduino | |
---|---|---|
GND | -> | GND |
VCC | -> | 5V |
SDA | -> | AREF上一个口 |
SCL | -> | AREF上两个口 |
-
蜂鸣器、LED灯与Arduino
蜂鸣器、LED灯 | Arduino | |
---|---|---|
负极 | -> | GND |
正极 | -> | 10 |
第三方库
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"
#include <Keypad.h>
#include <SCoop.h>
下载地址:
-
SCoop.h
->https://github.com/fabriceo/SCoop -
RTClib.h
->https://github.com/adafruit/RTClib -
Keypad.h
-> http://playground.arduino.cc/uploads/Code/keypad.zip -
LiquidCrystal_I2C.h
->https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
源程序
/*-----( Import needed libraries )-----*/
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"
#include <Keypad.h>
#include <SCoop.h>
void formatPrint( int hour, int minute, int second);
String show_s(int a,int b,int c,int d);
void menu();
char set_time();
char input_show(int x);
char set_time_year();
char set_time_month();
char set_time_day();
char set_time_hour();
char set_time_minute();
char set_time_second();
char set_clock();
char set_clock_hour();
char set_clock_minute();
char set_clock_second();
LiquidCrystal_I2C lcd(0x3F,2,1,0,4,5,6,7); // 0x27 is the I2C bus address for an unmodified backpack
char y[4]; //存储year的数值
int i=0;//循环计数
/**初始时间**/
int py; //year
int pmo; //month
int pd; //day
int ph; //hour
int pmi; //minute
int ps; //second
/**闹钟时间**/
//int cy = 2015; //year
//int cmo = 5; //month
//int cd = 21; //day
int ch = 00; //hour
int cmi = 00; //minute
int cs = 00; //second
char daysOfTheWeek[7][12] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
int menu_flag = 0;
int show_flag = 1; //1是显示,-1是不显示
int switch_flag = 1; //1是开,-1是关
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
{'0','1','2','3'},
{'4','5','6','7'},
{'8','9','A','B'},
{'C','D','E','F'}
};
byte rowPins[ROWS] = {2, 3, 4, 5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 7, 8, 9}; //connect to the column pinouts of the keypad
//initializes an instance of the Keypad class
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
/*-----( Declare objects )-----*/
RTC_DS1307 rtc; // Create a RealTimeClock object
defineTask(Task1)
void Task1::setup() {
Serial.begin(9600);
pinMode(10,OUTPUT);
}
void Task1::loop() {
char key = keypad.getKey();
if (key == 'F'){
show_flag = -show_flag;
menu();
show_flag = 1;
}else if(key == 'C'){
switch_flag = -switch_flag;
noTone(10);
}else if(key == 'D'){
show_flag = -show_flag;
lcd.clear();
lcd.noBlink();
lcd.setCursor(3,0);
lcd.print("Alarm Clock");
formatPrint(ch, cmi, cs);
if(keypad.waitForKey())
show_flag = -show_flag;
}
DateTime nowClock = rtc.now(); // Read data from the RTC Chip
if(nowClock.hour() == ch && nowClock.minute() == cmi && nowClock.second() == cs && switch_flag == 1)
{
tone(10, 31);
key = keypad.getKey();
if(key == 'C'){
switch_flag = -switch_flag;
noTone(10);
}
}
}
void setup() /****** SETUP: RUNS ONCE ******/
{
Serial.begin(9600); // Set up for Serial Monitor to be able to see this work
/*----( These lines allow code to work also on Arduino DUE )----- */
// Put these "//" in front of the line you do NOT want to use
// following line sets the RTC to the date & time this sketch was compiled
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// May 21, 2015 at 6pm you would call: (use 24 hour time)
#ifdef AVR
Wire.begin();
#else
Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
rtc.begin(); // Start the RTC library code
rtc.adjust(DateTime(2015, 5, 21, 18, 0, 0));
lcd.begin (16,2); // for 16 x 2 LCD module
lcd.setBacklightPin(3,POSITIVE);
lcd.setBacklight(HIGH);
mySCoop.start();
}
void loop() /****** LOOP: RUNS CONSTANTLY ******/
{
switch(show_flag){
case 1:{
DateTime now = rtc.now(); // Read data from the RTC Chip
//lcd.home (); // set cursor to 0,0
lcd.noBlink();
lcd.setCursor(1,0);
lcd.print(show_s(now.year(),now.month(),now.day(),1)+' ' +daysOfTheWeek[now.dayOfTheWeek()]);
lcd.setCursor (4,1); // go to start of 2nd line
if(switch_flag == 1)
lcd.print(String(show_s(now.hour(),now.minute(),now.second(),0)+" o"));
else
lcd.print(String(show_s(now.hour(),now.minute(),now.second(),0)+" x"));
break;
}
case -1:{
break;
}
}
yield(); //本函数必须放在主线的loop循环体中
}//--(end main loop )---
//显示日期和时间的字符拼合及补零函数
String show_s(int a,int b,int c,int d){
String s1,s2,s3;
if(a<10)
s1 = String('0'+String(a));
else
s1 = String(a);
if(b<10)
s2 = String('0'+String(b));
else
s2 = String(b);
if(c<10)
s3 = String('0'+String(c));
else
s3 = String(c);
if(d==1)
return String(s1+'/'+s2+'/'+s3);
else
return String(s1+':'+s2+':'+s3);
}
//菜单函数
void menu(){
rmenu:
char m1,m2;
lcd.clear();
lcd.noBlink();
lcd.setCursor(0,0);
lcd.print("1.Set_Time");
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("2.Set_Clock");
int f = keypad.waitForKey();
switch(f){
case '1':lcd.clear();
lcd.home();
lcd.print("<<<<Set_Time>>>>");
m1 = set_time();
if(m1 == '#')
goto rmenu;
break;
case '2':lcd.clear();
lcd.home();
lcd.print("<<<<Set_Clock>>>>");
m2 = set_clock();
if(m2 == '#')
goto rmenu;
break;
default: show_flag = -show_flag;
break;
}
lcd.clear();
}
/**---设置初始时间---**/
char set_time(){
char t1,t2,t3,t4,t5,t6;
styear:
t1 = set_time_year();
if(t1 == '#')
return '#';
Serial.println(py);
stmonth:
t2 = set_time_month();
if(t2 == '#')
goto styear;
Serial.println(pmo);
stday:
t3 = set_time_day();
if(t3 == '#')
goto stmonth;
Serial.println(pd);
sthour:
t4 = set_time_hour();
if(t4 == '#')
goto stday;
Serial.println(ph);
stminute:
t5 = set_time_minute();
if(t5 == '#')
goto sthour;
Serial.println(pmi);
t6 = set_time_second();
if(t6 == '#')
goto stminute;
Serial.println(ps);
rtc.adjust(DateTime(py, pmo, pd, ph, pmi, ps));
lcd.clear();
lcd.setCursor (1,0);
lcd.print("Press any key!");
lcd.setCursor (3,1);
lcd.print("Success!");
keypad.waitForKey();
show_flag = -show_flag;
}
char set_time_year(){
char k1;
lcd.clear();
lcd.home();
lcd.print("<<<<Set_Time>>>>");
lcd.setCursor (2,1);
lcd.blink();
lcd.print("Year:");
for(i=0;i<4;i++){
tYear:
y[i] = input_show(i+7);
Serial.println(y[i]);
if(y[i]=='*')
i = i-2;
else if(y[i]=='#')
return '#';
if(i == 3)
while(1){
k1 = keypad.waitForKey();
if( k1 == 'B'){ //确定
py = (int(y[0])-48)*1000+(int(y[1])-48)*100+(int(y[2])-48)*10+(int(y[3])-48);
break;
}else if( k1 == 'A'){//取消
lcd.setCursor(i+7,1);
lcd.print(" ");
lcd.setCursor(i+7,1);
goto tYear;
}
}
}
}
char set_time_month(){
char k1;
lcd.clear();
lcd.home();
lcd.print("<<<<Set_Time>>>>");
lcd.setCursor (1,1);
lcd.blink();
lcd.print("Month:");
for(i=0;i<2;i++){
tMonth:
y[i] = input_show(i+7);
if(y[i]=='*')
i = i-2;
else if(y[i]=='#')
return '#';
if(i == 1){
while(1){
k1 = keypad.waitForKey();
if( k1 == 'B'){ //确定
pmo = (int(y[0])-48)*10+(int(y[1])-48);
break;
}else if( k1 == 'A'){//取消
lcd.setCursor(i+7,1);
lcd.print(" ");
lcd.setCursor(i+7,1);
goto tMonth;
}
}
}
}
if(pmo > 12 || pmo < 1){
Serial.print("error");
lcd.clear();
lcd.setCursor (5,1);
lcd.print("ERROR!");
keypad.waitForKey();
set_time_month();
}
}
char set_time_day(){
char k1;
lcd.clear();
lcd.home();
lcd.print("<<<<Set_Time>>>>");
lcd.setCursor (3,1);
lcd.blink();
lcd.print("Day:");
for(i=0;i<2;i++){
tDay:
y[i] = input_show(i+7);
if(y[i]=='*')
i = i-2;
else if(y[i]=='#')
return '#';
if(i == 1){
while(1){
k1 = keypad.waitForKey();
if( k1 == 'B'){ //确定
pd = (int(y[0])-48)*10+(int(y[1])-48);
break;
}else if( k1 == 'A'){//取消
lcd.setCursor(i+7,1);
lcd.print(" ");
lcd.setCursor(i+7,1);
goto tDay;
}
}
}
}
if(pd > 31 || pd < 1){
Serial.print("error");
lcd.clear();
lcd.setCursor (5,1);
lcd.print("ERROR!");
keypad.waitForKey();
set_time_day();
}
}
char set_time_hour(){
char k1;
lcd.clear();
lcd.home();
lcd.print("<<<<Set_Time>>>>");
lcd.setCursor (2,1);
lcd.blink();
lcd.print("Hour:");
for(i=0;i<2;i++){
tHour:
y[i] = input_show(i+7);
if(y[i]=='*')
i = i-2;
else if(y[i]=='#')
return '#';
if(i == 1){
while(1){
k1 = keypad.waitForKey();
if( k1 == 'B'){ //确定
ph = (int(y[0])-48)*10+(int(y[1])-48);
break;
}else if( k1 == 'A'){//取消
lcd.setCursor(i+7,1);
lcd.print(" ");
lcd.setCursor(i+7,1);
goto tHour;
}
}
}
}
if(ph > 24 || ph < 0){
Serial.print("error");
lcd.clear();
lcd.setCursor (5,1);
lcd.print("ERROR!");
keypad.waitForKey();
set_time_hour();
}
}
char set_time_minute(){
char k1;
lcd.clear();
lcd.home();
lcd.print("<<<<Set_Time>>>>");
lcd.setCursor (0,1);
lcd.blink();
lcd.print("Minute:");
for(i=0;i<2;i++){
tMinute:
y[i] = input_show(i+7);
if(y[i]=='*')
i = i-2;
else if(y[i]=='#')
return '#';
if(i == 1){
while(1){
k1 = keypad.waitForKey();
if( k1 == 'B'){ //确定
pmi = (int(y[0])-48)*10+(int(y[1])-48);
break;
}else if( k1 == 'A'){//取消
lcd.setCursor(i+7,1);
lcd.print(" ");
lcd.setCursor(i+7,1);
goto tMinute;
}
}
}
}
if(pmi > 60 || pmi < 0){
Serial.print("error");
lcd.clear();
lcd.setCursor (5,1);
lcd.print("ERROR!");
keypad.waitForKey();
set_time_minute();
}
}
char set_time_second(){
char k1;
lcd.clear();
lcd.home();
lcd.print("<<<<Set_Time>>>>");
lcd.setCursor (0,1);
lcd.blink();
lcd.print("Second:");
for(i=0;i<2;i++){
tSecond:
y[i] = input_show(i+7);
if(y[i]=='*')
i = i-2;
else if(y[i]=='#')
return '#';
if(i == 1){
while(1){
k1 = keypad.waitForKey();
if( k1 == 'B'){ //确定
ps = (int(y[0])-48)*10+(int(y[1])-48);
break;
}else if( k1 == 'A'){//取消
lcd.setCursor(i+7,1);
lcd.print(" ");
lcd.setCursor(i+7,1);
goto tSecond;
}
}
}
}
if(ps > 60 || ps < 0){
Serial.print("error");
lcd.clear();
lcd.setCursor (5,1);
lcd.print("ERROR!");
keypad.waitForKey();
set_time_second();
}
}
/**---设置初始时间结束---**/
/**---设置闹钟时间---**/
char set_clock(){
char c1,c2,c3;
schour:
c1 = set_clock_hour();
if(c1 == '#')
return '#';
Serial.println(ch);
scminute:
c2 = set_clock_minute();
if(c2 == '#')
goto schour;
Serial.println(cmi);
c3 = set_clock_second();
if(c3 == '#')
goto scminute;
Serial.println(cs);
lcd.clear();
lcd.setCursor (1,0);
lcd.print("Press any key!");
lcd.setCursor (3,1);
lcd.print("Success!");
keypad.waitForKey();
show_flag = -show_flag;
}
char set_clock_hour(){
char k1;
lcd.clear();
lcd.home();
lcd.print("<<<<Set_Clock>>>");
lcd.setCursor (2,1);
lcd.blink();
lcd.print("Hour:");
for(i=0;i<2;i++){
cHour:
y[i] = input_show(i+7);
if(y[i]=='*')
i = i-2;
else if(y[i]=='#')
return '#';
if(i == 1){
while(1){
k1 = keypad.waitForKey();
if( k1 == 'B'){ //确定
ch = (int(y[0])-48)*10+(int(y[1])-48);
break;
}else if( k1 == 'A'){//取消
lcd.setCursor(i+7,1);
lcd.print(" ");
lcd.setCursor(i+7,1);
goto cHour;
}
}
}
}
if(ch > 24 || ch < 0){
Serial.print("error");
lcd.clear();
lcd.setCursor (5,1);
lcd.print("ERROR!");
keypad.waitForKey();
set_clock_hour();
}
}
char set_clock_minute(){
char k1;
lcd.clear();
lcd.home();
lcd.print("<<<<Set_Clock>>>");
lcd.setCursor (0,1);
lcd.blink();
lcd.print("Minute:");
for(i=0;i<2;i++){
cMinute:
y[i] = input_show(i+7);
if(y[i]=='*')
i = i-2;
else if(y[i]=='#')
return '#';
if(i == 1){
while(1){
k1 = keypad.waitForKey();
if( k1 == 'B'){ //确定
cmi = (int(y[0])-48)*10+(int(y[1])-48);
break;
}else if( k1 == 'A'){//取消
lcd.setCursor(i+7,1);
lcd.print(" ");
lcd.setCursor(i+7,1);
goto cMinute;
}
}
}
}
if(cmi > 60 || cmi < 0){
Serial.print("error");
lcd.clear();
lcd.setCursor (5,1);
lcd.print("ERROR!");
keypad.waitForKey();
set_clock_minute();
}
}
char set_clock_second(){
char k1;
lcd.clear();
lcd.home();
lcd.print("<<<<Set_Clock>>>");
lcd.setCursor (0,1);
lcd.blink();
lcd.print("Second:");
for(i=0;i<2;i++){
cSecond:
y[i] = input_show(i+7);
if(y[i]=='*')
i = i-2;
else if(y[i]=='#')
return '#';
if(i == 1){
while(1){
k1 = keypad.waitForKey();
if( k1 == 'B'){ //确定
cs = (int(y[0])-48)*10+(int(y[1])-48);
break;
}else if( k1 == 'A'){//取消
lcd.setCursor(i+7,1);
lcd.print(" ");
lcd.setCursor(i+7,1);
goto cSecond;
}
}
}
}
if(cs > 60 || cs < 0){
Serial.print("error");
lcd.clear();
lcd.setCursor (5,1);
lcd.print("ERROR!");
keypad.waitForKey();
set_clock_second();
}
}
/**---设置闹钟时间结束---**/
char input_show(int x){
char k = keypad.waitForKey();
if(k == 'A'){ //"取消"
if(x-1>6){
lcd.setCursor(x-1,1);
lcd.print(" ");
lcd.setCursor(x-1,1);
return '*';
}else{
return '#';
}
}else if( k >= '0' && k <= '9'){
lcd.setCursor(x,1);
lcd.print(k);
Serial.println(i);
return k;
}else{
i = i-1;
Serial.println(i);
}
}
void formatPrint( int hour, int minute, int second){
lcd.noBlink();
lcd.setCursor (4,1); // go to start of 2nd line
if(hour<10){
lcd.print(0);
lcd.setCursor (5,1); // go to start of 2nd line
lcd.print(hour);
}else
lcd.print(hour);
lcd.setCursor(6,1);
lcd.print(":");
lcd.setCursor(7,1);
if(minute<10){
lcd.print(0);
lcd.setCursor (8,1); // go to start of 2nd line
lcd.print(minute);
}else
lcd.print(minute);
lcd.setCursor(9,1);
lcd.print(":");
lcd.setCursor(10,1);
if(second<10){
lcd.print(0);
lcd.setCursor(11,1); // go to start of 2nd line
lcd.print(second);
}else
lcd.print(second);
}
源程序下载地址
:https://github.com/wwwxmu/ArduinoClock/tree/master
演示视频
http://v.qq.com/page/h/l/2/h0310pa7xl2.html
写在最后
- 每个模块不不清楚怎么用的可以参考我之前写的基础教程;
- LCD的I2C地址要先确定好(见http://www.jianshu.com/p/eee98fb5e68f)
- 实在是想不出其他办法了,才在程序里用了goto语句,接受各路大神批评指正!
网友评论
并按之组装、烧写程序后发现LED显示屏上并没有文字,只有背景光。我已经把程序中DS1307的总线地址改成了我自己的,但是LCD1602与转接板之间我没有焊接,以及DS1307我也没有焊接排针,只是简单的用杜邦线连接了起来。请问是由于接触不良导致的没有文字显示吗?以及在LCD1602转接板PCF8574AT上的蓝色小方块是用来调整液晶屏亮度的吗?麻烦您了,谢谢。