至Arduino官方網站下載開發環境: (https://www.arduino.cc/en/Main/Software)
開起「裝置管理員」,將 Arduino 接上,看一下是否有新增 USB 序列裝置(COM6),不一定為 COM6。
若「USB序列裝置」出現無法辨識的裝置
方法一 : 按滑鼠右鍵,選擇「更新驅動程式」,並點選「自動搜尋更新的驅動程式軟體」,可以排除問題。
方法二 : 按滑鼠右鍵,選擇「更新驅動程式」,並點選「瀏覽電腦上的驅動程式軟體」,瀏覽下載Arduino的地方(arduino-1.8.8),找到drivers檔,點選並安裝。
方法三 : 搜尋COM port安裝檔,下載後執行 https://sparks.gogo.co.nz/ch340.html
開啟Arduino IDE
按下工具→序列埠,同時將arduino接上,選擇Uno,即可以使用。
1.setup()
設定程式參數,如:指定接腳的輸入輸出狀態,setup()裡的程式碼只會執行一次。
2.loop()
在loop()函式中的程式碼將會不停地重複執行,直到電源關閉為止。
Introduction of GPIO (General Purpose Input Output)
通用輸入/輸出,每個 GPIO 端口可透過軟件分別配置成 INPUT 或者 OUTPUT ,其接腳可以供使用者由程式控制自由使用。
- Input mode: MCU 透過 GPIO 腳從外面收資料/信號,可以進行外接感測器(溫度、紅外線感測器等)狀態、高低電位等資訊的獲取。
- Output mode: MCU 透過 GPIO 腳將資料/信號送出,可用於控制LED、蜂鳴器及伺服馬達…等。
- GPIO 端口可以當 I2C(LCD 16x2)、SPI (10~13)、UART(Bluetooth)…等多種用途,也能作為 IRQ (中斷要求)(2、3)的信號。
3.pinMode(pin,mode)
用於設定接腳模式,該函數無返回值,pin代表所要配置的接腳,mode代表設置的模式-INPUT或OUTPUT。
Ex:
pinMode(13,OUTPUT)//將第13腳設定成「輸出」模式
pinMode(12,INPUT)//將第12腳設定成「輸入」模式
4.digitalWrite(pin,value)
函數有兩個參數 digitalWrite(pin 接腳,電壓值), 電壓值為HIGH(高電位)與LOW(低電位)。
Ex:
digitalWrite(13,HIGH)//第13腳位為輸出「高電位」
5.digitalRead(pin)
在接腳為輸入的情況下,可以獲取接腳的電壓情況—HIGH或LOW。
6.delay(ms)
設定程式運行停止時間長度,單位為ms,故delay(1000)為延遲1秒。
7.millis()
millis()函數會回傳Arduino從執行程式碼開始至目前為止的milliseconds數值,其資料型態為unsigned long,該數值大約在50天之後會溢位(overflow),屆時會從0開始重新計數。
1. Serial.begin()
啟動Serial Port並設定鮑率(baud rate)
Ex:
Serial.begin(9600);//開啟Serial Port,且通訊速率為9600bps(Bits Per Second)
2. Serial.print()
將字串透過TX腳位傳遞出去,並且顯示在Serial Monitor中
3. Serial.println()
傳送資料到外部電腦並切換至下一行
4. Serial.write()
以二進位碼(byte)輸出
5. Serial.read()
讀取進來的第一個位元組 (first incoming byte)。
6. Serial.available()
取得 Serial Port 可讀取的資料位元組數目 (number of bytes),如果 Serial port 有資料進來,Serial.available() 會回傳大於 0 的數值。
通常我們會使用Serial.available()來檢查是否有資料進來,在使用Serial.read()把資料讀取出來放到變數後供後續使用。例如:
int incomingByte = 0; // 用來儲存收進來的 data byte
void setup() {
Serial.begin(9600);
Serial.println("Hello");
}
void loop() {
// 檢查是否有資料可供讀取
if (Serial.available() > 0) {
// 讀取進來的 byte
incomingByte = Serial.read();
// 印出收到的資料
Serial.print("data received: ");
Serial.print(incomingByte, DEC);
Serial.print(", ");
Serial.print(incomingByte, HEX);
Serial.println(" (HEX)");
}
<<Note>>
Arduino其他相關語法請參考:Arduino語言手冊
程式說明
const int LedPin = 8;
void setup() {
pinMode(LedPin, OUTPUT); //將第8腳位設定成OUTPUT模式
}
void loop() {
digitalWrite(LedPin, HIGH); //第8腳位輸出高電位,點亮LED
delay(500); //等待500ms
digitalWrite(LedPin, LOW); //第8腳位輸出低電位,熄滅LED
delay(500); //等待500ms
}
int Led[5] = {8, 9, 10, 11, 12};
void setup() {
for(int i=0; i<5; i++)
pinMode(Led[i], OUTPUT);
}
void loop() {
/*
Do something
*/
}
#define ROW 30
#define COLUMN 5
int Led[COLUMN] = {8, 9, 10, 11, 12};
int pos[ROW][COLUMN] = {
/*
模式
*/
};
void setup() {
for(int i=0; i<COLUMN; i++)
pinMode(Led[i], OUTPUT);
}
void loop() {
/*
Do smoething
*/
}
若未按下開關,Arduino的接腳沒接地,但也沒有接到高電位。輸入的訊號會在0到1之間飄移,造成浮動訊號,Arduino就無法正確判斷輸入值。
若開關沒有被按下,Pin2將會透過10kΩ接地,讀取到低電位(LOW);按下開關時,5V電源將流入Pin2,產生高電位(HIGH)。
若將電阻接到電源,則此電阻稱為「上拉(pull-up)電阻」(在開關接通時,輸入為「低電位」)。
使用Arduino內部的上拉電阻
Arduino內部的pin腳考量到拿來做數位輸入,有內建上拉電阻(除了D13腳位),可取代外接上拉電阻。
pinMode(pin,INPUT_PULLUP);
const int Led[5] = {8, 9, 10, 11, 12}; //LED
const int sw_up = 2; //按鈕1
const int sw_down = 3; //按鈕2
int pos = 2; //初始亮LED位置
void setup() {
for(int i=0; i<5; i++){
pinMode(Led[i], OUTPUT);
digitalWrite(Led[i], LOW);
}
digitalWrite(Led[2], HIGH);
pinMode(sw_up, INPUT_PULLUP); //內建上拉電阻
pinMode(sw_down,INPUT);
}
void loop() {
bool swstate_up = digitalRead(sw_up);
bool swstate_down = digitalRead(sw_down);
if(swstate_up==LOW){
/*
Do something
*/
}
else if(swstate_down==HIGH){
/*
Do something
*/
}
}
機械式開關在切換的過程中,訊號並非立即從1變成0或從0變成1,而是會經過如下圖一般有忽高忽低的情況。
雖然彈跳的時間很短暫,但arduino仍會讀取到其連續變化的開關訊號,而導致誤差。
消除彈跳(de-bouncing)方法
在發現訊號開始變化時先讀取,在經過一段時間後,若訊號仍為HIGH,則視為按下第二次按鈕。
const int button = 2;
const int led = 13; //UNO內建LED
const int tick_led = 8; //每秒亮暗的led
bool led_state = HIGH;
bool tick_led_state = HIGH;
void setup() {
pinMode(button, INPUT_PULLUP); //上拉
pinMode(led, OUTPUT);
digitalWrite(led, led_state);
pinMode(tick_led, OUTPUT);
digitalWrite(tick_led, tick_led_state);
}
void loop() {
if(digitalRead(button)==HIGH){ //沒按按鈕
/*
Do something
*/
}
else if(digitalRead(button)!=HIGH){ //按按鈕
/*
Do something
*/
}
if(/* What happen */){ //每秒閃爍LED
/*
Do something
*/
}
}
七段顯示器
<<Note>>
注意!!需額外增加限流電阻,否則內部可能會燒毀!!
依據電源連接方式的不同,七段顯示器可以分成「共陽極」與「共陰極」兩種:
共陰極代表所有的LED接地端都相連,故LED的另一端接「高電位」就會發光;相反地,共陽極則是輸入「低電位」來發光。
十進位數 | a | b | c | d | e | f | g |
---|---|---|---|---|---|---|---|
0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
2 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
3 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
4 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
5 | 1 | 0 | 1 | 1 | 0 | 1 | 1 |
6 | 1 | 0 | 1 | 1 | 1 | 1 | 1 |
7 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
8 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
9 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
多工七段顯示器
多工七段顯示器 | Arduino |
---|---|
0 | Pin10 |
1 | Pin11 |
2 | Pin12 |
3 | Pin13 |
a | Pin2 |
b | Pin3 |
c | Pin4 |
d | Pin5 |
e | Pin6 |
f | Pin7 |
g | Pin8 |
dp | Pin9 |
const int SEG_COM[4] = {10, 11, 12, 13}; //控制線
const int SEG_data[10][8] = {{1, 1, 1, 1, 1, 1, 0, 0}, //"0" //資料線
{0, 1, 1, 0, 0, 0, 0, 0}, //"1"
{1, 1, 0, 1, 1, 0, 1, 0}, //"2"
{1, 1, 1, 1, 0, 0, 1, 0}, //"3"
{0, 1, 1, 0, 0, 1, 1, 0}, //"4"
{1, 0, 1, 1, 0, 1, 1, 0}, //"5"
{1, 0, 1, 1, 1, 1, 1, 0}, //"6"
{1, 1, 1, 0, 0, 0, 0, 0}, //"7"
{1, 1, 1, 1, 1, 1, 1, 0}, //"8"
{1, 1, 1, 0, 0, 1, 1, 0}}; //"9"
int display[4] = {2, 0, 2, 1}; //欲顯示數字
void setup() {
for(int i=2; i<=13; i++){
pinMode(i, OUTPUT);
digitalWrite(i, HIGH); //共陽極
}
}
void loop() {
for(int i=0; i<=3; i++){ //個、十、百、千位數
digitalWrite(SEG_COM[i], LOW); //觸發第i位數顯示數字
SEG_Drive(disp[i]); //資料線寫入數值
delay(5);
digitalWrite(SEG_COM[i], HIGH); //結束觸發第i位數
}
}
void SEG_Drive(char number){ //將字元變數從SEG_data[][]找到相對應的位置,並寫入a~g中
/*
Do something
*/
}
const int SEG_COM[4] = {10, 11, 12, 13}; //控制線
const int SEG_data[10][8] = {{1, 1, 1, 1, 1, 1, 0, 0}, //"0" //資料線
{0, 1, 1, 0, 0, 0, 0, 0}, //"1"
{1, 1, 0, 1, 1, 0, 1, 0}, //"2"
{1, 1, 1, 1, 0, 0, 1, 0}, //"3"
{0, 1, 1, 0, 0, 1, 1, 0}, //"4"
{1, 0, 1, 1, 0, 1, 1, 0}, //"5"
{1, 0, 1, 1, 1, 1, 1, 0}, //"6"
{1, 1, 1, 0, 0, 0, 0, 0}, //"7"
{1, 1, 1, 1, 1, 1, 1, 0}, //"8"
{1, 1, 1, 0, 0, 1, 1, 0}}; //"9"
int disp[4]; //顯示數字
int number = 0;
int timer = 0;
void setup() {
for(int i=2; i<=13; i++){
pinMode(i, OUTPUT);
digitalWrite(i, HIGH); //共陽極
}
}
void loop() {
number_transfer(number); //數值轉換入陣列中
/*
Do something(改寫Lab3-1)
*/
}
void number_transfer(int Num){ //四位數拆成四個獨立的數字,存入陣列disp[]中
/*
Do something
*/
}
void SEG_Drive(char number){ //將字元變數從SEG_data[][]找到相對應的位置,並寫入a~g中
/*
Do something
*/
}
按鈕偵測與掃描原理(1x3簡化版)
假設開關的「行1」~「行3」輸入端全部都輸出高電位,則無論開關是否被按下,Arduino都將會接收到高電位。因此,為了偵測到使用者按下的開關鍵,撰寫程式時必須依序將「行1」~「行3」設置成低電位來檢測。
實際上的使用需要運用到雙重迴圈(4x4),才能夠分批掃描到每一列:
實際腳位配置
4x4 Keypad | Arduino |
---|---|
1(ROW1) | Pin A0 |
2(ROW2) | Pin A1 |
3(ROW3) | Pin A2 |
4(ROW4) | Pin A3 |
5(COL1) | Pin 2 |
6(COL2) | Pin 3 |
7(COL3) | Pin 4 |
8(COL4) | Pin 5 |
const byte colPins[4] = {2, 3, 4, 5}; //行腳位
const byte rowPins[4] = {A0, A1, A2, A3}; //列腳位
const char keymap[4][4] = {{'1', '2', '3', 'A'}, //Keypad對應符號
{'4', '5', '6' ,'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}};
void setup() {
Serial.begin(115200);
for(int i=0; i<=3; i++){
pinMode(rowPins[i], INPUT_PULLUP);
pinMode(colPins[i], OUTPUT);
digitalWrite(colPins[i], HIGH);
}
}
void loop() {
/*
Do something
*/
}
匯入Keypad函式庫
Keypad程式庫的運作方式與LAB 4-1 大致相同,且多了除彈跳(de-bouncing)的部分。LAB 4-1有助於了解掃瞄鍵盤的原理,實際使用上仍是Keypad程式庫為主。
使用Keypad函式庫,程式碼需定義按鍵模組的行(col)、列(row)、連接Arduino的腳位以及按鍵所代表的字元。
#include <Keypad.h> //引用Keypad函式庫
#define KEY_ROWS 4 //按鍵模組的列數
#define KEY_COLS 4 //按鍵模組的行數
const byte colPins[4] = {2, 3, 4, 5};
const byte rowPins[4] = {A0, A1, A2, A3};
const char keymap[KEY_ROWS][KEY_COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
Keypad myKeypad = Keypad(makeKeymap(keymap),rowPins,colPins,KEY_ROWS,KEY_COLS);
void setup(){
Serial.begin(115200);
}
void loop(){
//透過Keypad函式庫裡的getkey()方法讀取按鍵的字元
char key = myKeypad.getKey();
if(key){ //若有按鍵按下則顯示按下的字元
Serial.println(key);
}
}
實驗目的:學習如何使用掃描式鍵盤與七段顯示器之結合應用
實驗目標:利用Keypad輸入按鍵,按 'A' 會進入計時模式,按 'B' 則會進入倒數計時模式,按 'C' 為開始,按 'D' 為暫停,按 '*' 為重新開始,按 '#' 為離開並進入選擇模式。(註:進入倒數計時模式時須先輸入欲倒數秒數)
參考pin腳
多工七段顯示器 | Arduino | 4x4 Keypad | Arduino |
---|---|---|---|
0 | Pin10 | Row1 | A0 |
1 | Pin11 | Row2 | A1 |
2 | Pin12 | Row3 | A2 |
a | Pin2 | Row4 | A3 |
b | Pin3 | Col1 | Pin13 |
c | Pin4 | Col2 | Pin9 |
d | Pin5 | Col3 | A4 |
e | Pin6 | Col4 | A5 |
f | Pin7 | ||
g | Pin8 |
註 : 要使用 Pin 0 & 1 也可以,但不能使用Serial.print()等函式
實驗結果:
Learn More →
Arduino微處理器不僅包含MCU,還內建記憶體、類比/數位訊號轉換器以及周邊控制介面,相當於將完整的電腦功能塞入一個矽晶片中,所採用的微處理器是ATmega328P。根據下圖,標示在Arduino UNO板上的digital 與 analog I/O的位置、數量以及相關用途(如:通訊、中斷…)。
(1)描述機械式開關的彈跳現象
(2)在ATmeg328p微控器的數位接腳有內建上拉電阻,預設沒有啟用,該上拉電阻值介於20kΩ至50kΩ之間;而一般外接10kΩ的上拉電阻,甚至在要求高反應速率的電子訊號切換時會使用4.7kΩ或是1kΩ的上拉電阻。試問:上拉電阻值的高低對於處理雜訊干擾的能力之間的關係?
描述多工七段顯示器及鍵盤掃描的工作原理
心得
W2結報_第X組.zip
壓縮檔裡包含:
1.W2結報.pdf
2.資料夾:W2
Lab1-1.ino
Lab1-2.ino
…