---
# System prepended metadata

title: HW5_Arduino_數位式時鐘設計
tags: [Arduino]

---

# HW5_Arduino_數位式時鐘設計

>撰寫人[name=AmiYaku1049] [首頁--天空路1049號](https://skys-kid-lai.github.io/1004/)
>>最後編輯[time=Sun, May 1, 2022 11:26 PM]
___
## 實驗目的

透過指撥開關及七段顯示器，配合Arduino UNO 開發版，做出計時以及調整時間之用途

## 實驗原理

透過設計程式碼並使用Tinkercad 網頁版模擬器及Arduino UNO 開發版，透過指撥開關及七段顯示器，做出計時以及調整時間之用途

## 實驗材料

**◆透過Tinkercad網頁模擬器線上實作◆**

◎七段顯示器 x4
◎Arduino UNO 開發版 x1
◎歐姆版 x1
◎PMOSFET x4
◎電阻 100Ω x7
◎電阻 2.2kΩ x5
◎電阻 10kΩ x4
◎按鈕 x4
◎指撥開關 x1

◎跟你默契好的可愛電腦 x1

◎安靜的LED小夥伴 x1  --> 用以方便讀秒

## 實驗步驟

1.在Tinkercad網頁模擬器連接電路
2.在程式編譯區進行程式碼編譯（程式碼在下方↓）
3.確定程式碼無誤，按左上方即可開始模擬
4.紀錄輸出

### 電路連接完整圖
![](https://i.imgur.com/ClJM3v9.png =70%x)

#### 電路部分放大
▽右下
![](https://i.imgur.com/oi98uW7.png =70%x)

▽中
![](https://i.imgur.com/iBGxFvf.png =70%x)


▽上
![](https://i.imgur.com/gKTVYMs.png =70%x)

### 程式碼（已經過改良，並非為參考文獻內原始程式碼）

```clink= c
const int SEG[7] = {6,7,8,9,10,11,12}; // 宣告顯示信號接腳
const int scan[4] = {2,3,4,5}; // 宣告掃描信號接腳
const int SEG_code [10] = { 
0xc0,0xf9,0xa4,0xb0,0x99, 
0x92,0x82,0xf8,0x80,0x90 };
const int PB[4] = {A2,A3,A4,A5};
const int DD = A1;
const int DIPSW = A0;
const int BZ = 13;
int disp[4]={0,0,0,0};
int DISP;
unsigned long x0,x1,x2;

boolean phase0;
int seconds = 0, sec = 0;

void beep(int pin, int counts);
void scanner(int x);

void setup() {
	for(int i = 0; i < 7; i++) 
		pinMode(SEG[i], OUTPUT); 
	for(int i = 0; i < 4; i++) 
    {
      pinMode(scan[i], OUTPUT);
      pinMode(PB[i], INPUT);
    }
  pinMode(DD, OUTPUT);
  pinMode(BZ, OUTPUT);
  pinMode(DIPSW, INPUT);
}

void loop()
{
  if(digitalRead(DIPSW))
    phase0=true;
  else
   {
     phase0=false;
     disp[3]=1;
     disp[2]=2;
     disp[1]=0;
     disp[0]=0;
   }
  
  while(phase0)
  {
    seconds=0;
    if(!digitalRead(PB[0]))
    {
      if(disp[3]==2 && disp[2]==3)
      {
       disp[3]=0;
       disp[2]=0;
      }
      else if(disp[2]==9)
      {
       disp[2]=0;
       disp[3]++;
      }
      else
       disp[2]++;
    }
    if(!digitalRead(PB[1]))
    {
      if(disp[3]==0 && disp[2]==0)
      {
       disp[3]=2;
       disp[2]=3;
      }
      else if(disp[2]==0)
      {
       disp[2]=9;
       disp[3]--;
      }
      else
       disp[2]--;
    }
  	if(!digitalRead(PB[2]))
  	{
      if(disp[1]==5 && disp[0]==9)
      {
       disp[1]=0;
       disp[0]=0;
      }
      else if(disp[0]==9)
      {
       disp[0]=0;
       disp[1]++;
      }
      else
       disp[0]++;
  }
  if(!digitalRead(PB[3]))
  {
    if(disp[1]==0 && disp[0]==0)
    {
      disp[1]=5;
      disp[0]=9;
    }
    else if(disp[0]==0)
    {
      disp[0]=9;
      disp[1]--;
    }
    else
      disp[0]--;
  }
    
   scanner(25);
   if(digitalRead(DIPSW))
     phase0=true;
   else
   {
     phase0=false;
     disp[3]=1;
     disp[2]=2;
     disp[1]=0;
     disp[0]=0;
   }
  }
  
  while(!phase0)
  {
    scanner(2);
    x1=millis();
    x2=x1-x0;
    if(x2>=500)
    {
      x0=x1;
      sec=!sec;
      digitalWrite(DD,sec);
      if(sec)
      {
        if(++seconds==60)
        {
          seconds=0;
          if(disp[0]==9)
          {
            disp[0]=0;
            if(disp[1]==5)
            {
              disp[1]=0;
              if(disp[2]==2 && disp[3]==2)
              {
                disp[2]=2;
                disp[3]=1;
              }
              else if(disp[2]==9)
              {
                disp[2]=0;
                disp[3]++;
              }
              else
                disp[2]++;
            }
            else
              disp[1]++;
          }
          else
            disp[0]++;
        }
      }
    }
    if(digitalRead(DIPSW))
      phase0=true;
    else
     phase0=false;
  }
}

void beep(int pin, int counts)
{
  for(int i=0; i<counts; i++)
  {
    tone(pin,1000,100);
    delay(100);
  }
}

void scanner(int x)
{
  for(int i=0; i<x; i++)
  {
    for(int j=0; j<4; j++)
    {
      for(int k=0; k<4; k++)
        digitalWrite(scan[k],1);
      DISP=SEG_code[disp[j]];
      for(int k=0; k<8; k++)
      {
        if(bitRead(DISP,k))
          digitalWrite(SEG[k],1);
        else
          digitalWrite(SEG[k],0);
      }
      digitalWrite(scan[j],0);
      delay(1);
    }
  }
}
```

## 實驗結果

**◎按鈕功能 由左到右分別為＂小時+＂、＂小時-＂、＂分鐘+＂、＂分鐘-＂**
![](https://i.imgur.com/98wCnSg.jpg =70%x)

**◎指撥開關1調至OFF時，秒數重整為0，暫停計時功能，並以按鈕調整時間**

* 尚未按鈕調整時間，指撥開關1為OFF
![](https://i.imgur.com/xJEZ02Z.png =70%x)
![](https://i.imgur.com/UW6lRYK.png =70%x)

* 按鈕＂小時+＂及＂分鐘+＂調整時間，指撥開關1為OFF
![](https://i.imgur.com/Ksh5pQv.png =70%x)

**◎指撥開關1調至ON時，秒數從0開始算，計時時間從1200計算到2200；
當秒數計算到60時，秒數重整重加，七段顯示器分鐘個位數加1；時間計算到2259後，時間重回1200**

* 指撥開關1為ON，LED以秒為單位閃爍（此處放照片以供參考）
![](https://i.imgur.com/vIVpAZl.png =70%x)

* 指撥開關1為ON，七段顯示器由1200開始計算。當秒數到60時，七段顯示器分鐘個位數由0加為1
![](https://i.imgur.com/0NknBrq.png =70%x)







## 實驗討論

* **運作過程中，無法使phase0=false，也就是無法計時**
我的解決方法：先檢查程式碼，確認程式碼沒有編譯上的錯誤後，再調整電路。原因是沒有將使用的指撥開關接腳接地。
* **運作過程中，臨時被我抓來的LED沒有亮**
我的解決方法：調整電路。接地沒有接在一起。
* **指撥開關是否可以4個中只用一個**
我的解決方法：將其他三腳清空，確定只使用一腳不會造成錯誤。

* **作者把小時顯示寫在內層，分鐘顯示寫在外層。如果把分鐘顯示寫在內層迴圈，小時顯示寫在外層會有什麼問題？**
我的解釋：將小時寫在內層並將分鐘寫在外層的做法，是因為數學及生活上即是「**分鐘算完之後，＂進位＂到小時；個位算完後，＂進位＂到十位。**」 程式中也反映了這點。最外層寫到最內層並依序寫出去，程式的解釋會變成「**由小時的十位算完後，＂進位＂到小時的十位；小時算完後，再＂進位＂至分鐘**」 的作法。 

## 實驗心得

應該要為我的LED燈拍個影片再傳上來的，就這點有些可惜。
整體來說的話，我覺得這次實驗很有趣！！

## 實驗文獻

>編者：艾迪諾
>出版日期：2017.01.06
>書名（頁數）：Arduino全能微處理機實習：強效解析（p4-67~p4-77）
>出版社：全華圖書
>[color=#CE0000]