Arduino筆記(46):使用I2C轉接板在LCD 1602顯示日期時間

在早期學習 Arduino時,有一篇筆記 Arduino筆記(4):在2x16 LCD上顯示 Hello World訊息,用到 2x16 LCD顯示模組時,需要接十幾條線,覺得有點麻煩。後來發現有一個模組 IIC/I2C/介面的 LCD1602轉接板,這個轉接板只佔用2個 IO ,如改接這個模組,只要 4條線就可以了。本實作就來看看如何連接這個轉接板,並將 RTC 時間顯示在 LCD上。可是筆記(4) 的作法是要先設定好時間,上傳程式,每次開機的日期、時間都一樣。想說再接兩個按鍵,加入時間設定,可以調整日期跟時間,比較方便。以下就看一下實作過程。

[安裝LiquidCrystal_I2C Library]

LiquidCrystal_I2C 程式庫提供顯示 LCD 1602 所需的功能。
在 Arduino 選單, [Sketch 草稿碼] →下拉選擇 [Include Library 匯入程式庫] → [Manage Libraries 管理程式庫] 。在搜尋的地方輸入 LiquidCrystal_I2C,選擇以下紅色框線的 Library,按下右方的 [Install],出現 [Installed] 表示安裝完成。

[安裝DS1302 Library]

DS1302 程式庫提供 RTC時鐘所需的功能。
在 Arduino 選單, [Sketch 草稿碼] →下拉選擇 [Include Library 匯入程式庫] → [Manage Libraries 管理程式庫] 。在搜尋的地方輸入 DS1302,選擇以下紅色框線的 Library,按下右方的 [Install],出現 [Installed] 表示安裝完成。


[材料]

  • Arduino Uno x 1
  • 1602 LCD模組 x 1
  • DS1302 RTC模組  x 1
  • IIC/I2C/介面 LCD1602轉接板 x 1
  • 10K 電阻 x 2
  • 按鍵 x 2
  • 連接線 x 12
  • 麵包板 x 1

[線路圖]

Arduino UNOI2C 1602轉接板RTC1302  按鍵  
5VVCCVCC-
GNDGND--
A4(SDA)SDA--
A5(SCL)SCL--
Pin2-RST-
Pin3-DAT-
Pin4-CLK-
Pin8--按鍵1
Pin9--按鍵2


按鍵1及2 一端VCC,另一端接 Arduino Pin8及Pin9 並連接電阻,電阻另一端接地。


[程式]

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <DS1302.h>

uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
// DS1302 初始化設定
DS1302 rtc(2, 3, 4);
Time t;

bool adjust = false; // 調整 clock 模式 yes/no
// 調整 hour, minute, day ... mode
bool ahour, aminute, aday, amonth, ayear, rfin = false; 
int stareb1, stareb2 = 0; // 按鍵狀態

// 變數 hour, minute, day, month, year 
int hh, mm, dd, mo, yy; 

const int button1 = 8; // 按鍵執行 設定/下一步/儲存
const int button2 = 9; // 按鍵調整時間日期/不儲存

// 設定 LCD 位址為 0x27,有 16 個字元 2 列
LiquidCrystal_I2C lcd(0x27,16,2);  

void setup()
{
// buttons 1 and 2 are set as inputs
 pinMode (button1, INPUT);
 pinMode (button2, INPUT);
  
  lcd.init();           // 初始化 lcd 
  lcd.backlight();
  lcd.print("Initialising...");
  lcd.createChar(2, clock);

  Wire.begin();

// 第一次設定寫入 DS1302 RTC時鐘,之後可以加上註解
//  rtc.setDOW(SUNDAY);      // 設定每週星期幾?
//  rtc.setTime(18, 39, 30);  // 設定24小時時間 20:16:30 
//  rtc.setDate(26, 7, 2019); // 設定日期(日, 月, 年)
 
}

void loop()
{
 // 在位置0,0 顯示時間
 lcd.setCursor(0,0);
 lcd.print("Time:  ");
 lcd.print(rtc.getTimeStr());
 
 // 在位置0,1 顯示日期
 lcd.setCursor(0,1);
 lcd.print("Date: ");
 lcd.print(rtc.getDateStr());
  delay(1000);

  // 調整時間日期按鍵1
  stareb1 = digitalRead(button1);
  if (stareb1 == HIGH)
    {
      adjust = true; // 調整時間模式開啟
      t = rtc.getTime();
      hh = t.hour; mm = t.min; dd = t.date; 
      mo = t.mon; yy = t.year;
      int i = 1;   // 跳到設定子畫面
      delay(1000);
      lcd.clear();
      while (adjust)
       {
        
        // 調整小時      
        if (i == 1){  // 小時的子畫面為 1
          ahour = true;
          lcd.clear();
          while(ahour) {
           lcd.setCursor(0,0); 
           lcd.print(String("hour: ") + String(hh));
           stareb1 = digitalRead(button1);
           stareb2 = digitalRead(button2);

           // 按鍵 2 用來增加小時數,只到 23
           if (stareb2 == HIGH) {  
              hh++;
              if (hh == 24) hh = 0;
              delay (1000);
              lcd.clear();
              }
           // 按鍵 1被按下,跳到下一個子畫面
           if (stareb1 == HIGH) {  
              ahour = false;
              i++;
              delay (1000);
           }
           }
          }
          
        // 調整分鐘      
        if (i == 2){
          aminute = true;
          lcd.clear();
          while(aminute) {
           lcd.setCursor(0,0); 
           lcd.print(String("MIN: ") + String(mm));
           stareb1 = digitalRead(button1);
           stareb2 = digitalRead(button2);
           if (stareb2 == HIGH) {
              mm++;
              if (mm == 60) mm = 0;
              delay (1000);
              lcd.clear();
              }
           if (stareb1 == HIGH) {
              aminute = false;
              i++;
              delay (1000);
           }
           }
          }

        // 調整日期的天      
        if (i == 3){
          aday = true;
          lcd.clear();
          while(aday) {
           lcd.setCursor(0,1); 
           lcd.print(String("DATA: ") + String(dd));
           stareb1 = digitalRead(button1);
           stareb2 = digitalRead(button2);         
           if (stareb2 == HIGH) {
              dd++;
              if (dd == 32) dd = 1;
              delay (1000);
              lcd.clear();
              }
           if (stareb1 == HIGH) {
              aday = false;
              i++;
              delay (1000);
           }
           }
          }

        // 調整月份      
        if (i == 4){
          amonth = true;
          lcd.clear();
          while(amonth) {
           lcd.setCursor(0,1); 
           lcd.print(String("Month: ") + String(mo));
           stareb1 = digitalRead(button1);
           stareb2 = digitalRead(button2);           
           if (stareb2 == HIGH) {
              mo++;
              if (mo == 13) mo = 1;
              delay (1000);
              lcd.clear();
              }
           if (stareb1 == HIGH) {
              amonth = false;
              i++;
              delay (1000);
           }
           }
          } 
        // 調整年份     
        if (i == 5){
          ayear = true;
          lcd.clear();
          while(ayear) {
           lcd.setCursor(0,1); 
           lcd.print(String("Year: ") + String(yy));
           stareb1 = digitalRead(button1);
           stareb2 = digitalRead(button2);           
           if (stareb2 == HIGH) {
              yy++;
              // 只能設定到 2030 年,回到 2019繼續
              if (yy == 2030) yy = 2019;  
              delay (1000);
              }
           if (stareb1 == HIGH) {
              ayear = false;
              i++;
              delay (1000);
           }
           }
          } 
          
        // 調整結束,儲存設定值      
        if (i == 6){
          rfin = true;
          lcd.clear();
          while(rfin) {
           lcd.setCursor(0,0); 
           lcd.print("Save values?");
           lcd.setCursor(0,1); 
           // 左邊按鍵 1,右邊按鍵 2
           lcd.print(">>>> YES  NO <<<<"); 
           stareb1 = digitalRead(button1);
           stareb2 = digitalRead(button2); 

           // 按鍵 2 不修改,回到初始畫面                     
           if (stareb2 == HIGH) {  
              adjust = false;
              rfin = false;
              delay (1000);
              }
           // 按鍵 1 儲存改變值,回到初始畫面
           if (stareb1 == HIGH) {  
              adjust = false;
              rfin = false;
              rtc.setTime(hh, mm, 0);
              rtc.setDate(dd, mo, yy);
              lcd.clear(); 
              delay (1000);
           }
           }
          }                  
          
       }
     }

}

[實作結果]

實作前,IIC / I2C轉接板是跟 LCD 分開的,我先找了排針座銲在 LCD模組上,方便轉接板拆卸。

設定日期及時間的影片:

[參考資料]

2 留言

  1. 大大您好:
    調整時間的部分寫得很詳細,真正讚!
    可否請教:
    在我的電腦裡
    #include 要改成
    #include 要改成
    然後要ThreeWire myWire(6,5,7);
    再RtcDS1302 Rtc(myWire);
    Time t;這行出錯:
    'Time' does not name a type
    目前卡在這裡,有空請指導,謝謝!

    回覆刪除
    回覆
    1. 我覺得是不是沒有安裝正確的函數庫或是少了#include需要時間的函數庫?程式會用到跟時間有關的函數庫是DS1302.h,網路上有其他的DS1302函數庫,您留言的#include看不出來是哪個?您可以再檢查一下。

      刪除

張貼留言

較新的 較舊