# 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.紀錄輸出
### 電路連接完整圖

#### 電路部分放大
▽右下

▽中

▽上

### 程式碼(已經過改良,並非為參考文獻內原始程式碼)
```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);
}
}
}
```
## 實驗結果
**◎按鈕功能 由左到右分別為"小時+"、"小時-"、"分鐘+"、"分鐘-"**

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


* 按鈕"小時+"及"分鐘+"調整時間,指撥開關1為OFF

**◎指撥開關1調至ON時,秒數從0開始算,計時時間從1200計算到2200;
當秒數計算到60時,秒數重整重加,七段顯示器分鐘個位數加1;時間計算到2259後,時間重回1200**
* 指撥開關1為ON,LED以秒為單位閃爍(此處放照片以供參考)

* 指撥開關1為ON,七段顯示器由1200開始計算。當秒數到60時,七段顯示器分鐘個位數由0加為1

## 實驗討論
* **運作過程中,無法使phase0=false,也就是無法計時**
我的解決方法:先檢查程式碼,確認程式碼沒有編譯上的錯誤後,再調整電路。原因是沒有將使用的指撥開關接腳接地。
* **運作過程中,臨時被我抓來的LED沒有亮**
我的解決方法:調整電路。接地沒有接在一起。
* **指撥開關是否可以4個中只用一個**
我的解決方法:將其他三腳清空,確定只使用一腳不會造成錯誤。
* **作者把小時顯示寫在內層,分鐘顯示寫在外層。如果把分鐘顯示寫在內層迴圈,小時顯示寫在外層會有什麼問題?**
我的解釋:將小時寫在內層並將分鐘寫在外層的做法,是因為數學及生活上即是「**分鐘算完之後,"進位"到小時;個位算完後,"進位"到十位。**」 程式中也反映了這點。最外層寫到最內層並依序寫出去,程式的解釋會變成「**由小時的十位算完後,"進位"到小時的十位;小時算完後,再"進位"至分鐘**」 的作法。
## 實驗心得
應該要為我的LED燈拍個影片再傳上來的,就這點有些可惜。
整體來說的話,我覺得這次實驗很有趣!!
## 實驗文獻
>編者:艾迪諾
>出版日期:2017.01.06
>書名(頁數):Arduino全能微處理機實習:強效解析(p4-67~p4-77)
>出版社:全華圖書
>[color=#CE0000]