【Arduino综合项目】小闹钟

作者: 繁著 | 来源:发表于2016-06-30 11:32 被阅读3995次
    小闹钟项目

    在额济纳支教这一年,给孩子们上了很多Arduino开发的课,也带他们完成了几个Arduino综合项目,下面陆续把这些小项目放上来,欢迎围观~~~非科班出身,C语言学的不好,望各路大神批评指点。

    功能介绍

    本项目主要是实现基本的闹钟功能:

    1. LCD屏幕实时显示当前时间(年、月、日、星期、时、分、秒)以及闹钟的开关;
    2. 通过4*4键盘可以设置初始时间及闹钟时间;
    3. 通过键盘,还可以查看当前设置的闹钟时间;
    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上两个口
    DS1307时钟模块与Arduino接线示意图
    • 蜂鸣器、LED灯与Arduino

    蜂鸣器、LED灯 Arduino
    负极 -> GND
    正极 -> 10

    第三方库

    #include <LiquidCrystal_I2C.h> 
    #include "RTClib.h"
    #include <Keypad.h>
    #include <SCoop.h>
    

    下载地址:

    源程序

    /*-----( 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

    写在最后

    1. 每个模块不不清楚怎么用的可以参考我之前写的基础教程;
    2. LCD的I2C地址要先确定好(见http://www.jianshu.com/p/eee98fb5e68f
    3. 实在是想不出其他办法了,才在程序里用了goto语句,接受各路大神批评指正!

    相关文章

      网友评论

      • 非法参数:您好,很抱歉这么晚了还来打扰您。我在网络上找到了您的教程【Arduino综合项目】小闹钟
        并按之组装、烧写程序后发现LED显示屏上并没有文字,只有背景光。我已经把程序中DS1307的总线地址改成了我自己的,但是LCD1602与转接板之间我没有焊接,以及DS1307我也没有焊接排针,只是简单的用杜邦线连接了起来。请问是由于接触不良导致的没有文字显示吗?以及在LCD1602转接板PCF8574AT上的蓝色小方块是用来调整液晶屏亮度的吗?麻烦您了,谢谢。
      • Luat物联网通信模块:可以关注下Luat开源项目,基于Air200 GPRS模块(价格才12块多),基于Lua开发应用软件,超级容易上手。 而且开发点阵LCD 的UI 非常方便,有丰富的底层库,支持中文很方便。
      • bb3df733dd5c:谢谢分享

      本文标题:【Arduino综合项目】小闹钟

      本文链接:https://www.haomeiwen.com/subject/bzetjttx.html