---
# System prepended metadata

title: Arduino 電路實驗 人機介面

---

---
###### tag：`Arduino` `人機介面`
---


# Arduino 電路實驗 人機介面
[TOC]
* 系級：資工三乙
* 座號：16
* 姓名：王君翔
* 指導老師：林宏益


---

## 1.實驗目的 
透過實際操作電路，並實作程式碼，了解人機介面之運作模式。


---


## 2.實驗原理
透過 4x4 鍵盤控制輸入，以蜂鳴器表示接收到輸入，並於七段顯示器上顯示對應之輸出。


---


## 3.實驗材料

| 名稱 | 數量 | 備註 |
| -------- | -------- | -------- |
| Arduino uno板 | 1 | 附USB線 |
| KTduino 積極體驗板 | 1 | 附變壓器 |
| 杜邦線 | 26 | 公對公 |

* 以下簡稱KTduino 積極體驗板為體驗板


---


## 4.實驗步驟
1. 將以下腳位連接：

| 來源板子 | 來源位置 | 連接板子 | 連接位置 | 備註 |
| -------- | -------- | -------- | -------- | -------- |
| 體驗板    | P14-2  | Uno板 | 13 | 驅動蜂鳴器 |
| 體驗板    | P11A-7 ~ P11A-1  | Uno板 | 12 ~ 6 | 連接七段顯示器 |
| 體驗板    | P11B-5 ~ P11B-1  | 體驗板 | P4-1 ~ P4-5 | 擴充接點 |
| 體驗板    | P4-2 ~ P4-5  | Uno板 | 5 ~ 2 | 連接七段顯示器之共用極 |
| 體驗板    | P4-2 ~ P4-5  | 體驗板 | P6-4 ~ P6-1 |共用掃描訊號|
| 體驗板    | P4-1  | Uno板 | A1 | 將七段顯示器中間兩圓點 DD 連接|
| 體驗板    | P6-5 ~ P6-8  | Uno板 | A2 ~ A5 | 連接 4x4 鍵盤|

2. 將以下程式完成後，透過USB線上傳至Uno板
``` C=
const int SEG[7] = {6,7,8,9,10,11,12}; // pins (show number)
const int scan[4] = {2,3,4,5}; // pins (coms)
const int SEG_code[10] = {
  0xc0, 0xf9, 0x4a, 0xb0, 0x99,
  0x92, 0x82, 0xf8, 0x80, 0x90
}; // Seven-segment display's number code
const int column[4] = {A2, A3, A4, A5}; // input pins
const int BZ = 13; // pin of buzzer
unsigned char KN; //input number
int disp[4] = {0, 0, 0, 0}; // buffer of the seven-segment display's numbers
int DISP; // number which will being showed on the seven-segment display
void beep(int pin, int counts); // function of playing sound (prototype)

void setup() {
  for(int i = 0; i < 7; i++)
    pinMode(SEG[i], OUTPUT); // set pin mode
  for(int i = 0; i < 4; i++){
    pinMode(scan[i], OUTPUT); // set pin mode
    pinMode(column[i], INPUT); // set pin mode
  }
  pinMode(BZ, OUTPUT); // set pin mode
}

void loop() {
  for(int i = 0; i < 4; i++){ // scanning
    for(int j = 0; j < 7; j++)
      digitalWrite(SEG[j], 1); // init
    for(int j = 0; j < 4; j++)
      digitalWrite(scan[j], 1); // init
    digitalWrite(i, 0); // enable seven-segment display to output
    DISP = SEG_code[disp[i]]; // get code of the number
    for(int j = 0; j < 8; j++) // show number
      if(bitRead(DISP, j))
        digitalWrite(SEG[j], 1);
      else
        digitalWrite(SEG[j], 0);
    for(int col = 0; col < 4; col++){ // read input
      if(!digitalRead(column[col])){
        while(!digitalRead(column[col])); // waiting until the switch disconnected
        KN = 4*i + col; // get number
        beep(BZ, 1); // play sound
        if(KN >= 0 && KN < 10){ // ensure input is available
          for(int j = 0; j < 3; j++) // swap the numbers in buffer
            disp[3-j] = disp[2-j];
          disp[0] = KN;
        }
        delay(3); // waitin'
        break; // leave the loop
      }
    }
  }
}

void beep(int pin, int counts){ // play sound
  for(int i = 0; i < counts; i++){
    tone(pin, 1000, 100);
    delay(100);
  }
}
```
3. 在體驗板上進行操作，並紀錄實驗結果。


---


## 5.實驗結果
![](https://i.imgur.com/Bm49MLY.jpg)
Δ接線完成圖

![](https://i.imgur.com/vjcV41E.jpg)
Δ運作圖

當按下 4x4 鍵盤上代表 0 ~ 9 之按鍵後，蜂鳴器有產生聲音，且七段顯示器也有確實顯示數字，符合預期結果。

---


## 6.實驗討論
在本次實驗中的範例程式，仍可被優化，以下提出個人重構後的程式碼。
``` C=
const int seg[7] = {6,7,8,9,10,11,12},
  scan[4] = {2,3,4,5},
  seg_code[10] = {
    0xc0, 0xf9, 0x4a, 0xb0, 0x99,
    0x92, 0x82, 0xf8, 0x80, 0x90},
  column[4] = {A2, A3, A4, A5};
unsigned char kn;
int disp_bf[4] = {0, 0, 0, 0}, disp;
void beep(int pin, int counts);
void inputProcess(int i, int c);
void scan_init();

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(column[i], INPUT);
  }
  pinMode(13, OUTPUT);
}

void loop() {
  for(int i = 0; i < 4; i++){
    scan_init();
    digitalWrite(i, 0);
    disp = seg_code[disp_bf[i]];
    for(int j = 0 ; j < 7; j++)
      digitalWrite(seg[j], (int)bitRead(disp, j));
    for(int col = 0; col < 4; col++)
      if(!digitalRead(column[col])){
        inputProcess(i, col);
        break;
      }
  }
}

void scan_init(){
  for(int j = 0; j < 7; j++)
    digitalWrite(seg[j], 1);
  for(int j = 0; j < 4; j++)
    digitalWrite(scan[j], 1);
}

void inputProcess(int i, int c){
  while(!digitalRead(column[c]));
  kn = (i << 2) + c;
  
  tone(13, 1000, 100);
  delay(100);
  
  if(kn > -1 && kn < 10){
    for(int j = 0; j < 3; j++)
      disp_bf[3-j] = disp_bf[2-j];
    disp_bf[0] = kn;
  }
  delay(3);
}
```


---


## 7.實驗心得
這種實驗，在之前的課程十分少見，感覺頗為新鮮，程式的難度也很低，很好理解。
第一次使用HackMD製作實驗報告，在語法上有諸多的不熟悉，需要找時間練習。


---


## 8.參考文獻
* 艾迪諾 2017 Arduino全能微處理機實習-強效解析第四版第4-50頁至4-55頁 全華圖書股份有限公司