1 of 81

Arduino程式與探究實驗應用入門

國立東華大學物理學系 曾賢德

修訂日期: 2021/08/15

2 of 81

Arduino程式與探究實驗應用入門-1

20210814-1上午課程錄影

https://youtu.be/KNNatkjK8M4

Arduino程式與探究實驗應用入門-2

20210814-2上午課程錄影

https://youtu.be/Bb3Zd4FGDY4

Arduino程式與探究實驗應用入門-3

20210814-3下午課程錄影

https://youtu.be/ohSF5jxUPZQ

Arduino程式與探究實驗應用入門-4

20210814-4下午課程錄影

https://youtu.be/ueikbGRNCCc

Arduino程式與探究實驗應用入門-5

20210814-5下午課程錄影

https://youtu.be/nFmXScUzh70

Arduino程式與探究實驗應用入門-6

20210815-1上午課程錄影

https://youtu.be/M3LpROB11Mg

Arduino程式與探究實驗應用入門-7

20210815-2上午課程錄影

https://youtu.be/WnoDyY7Xp7Q

Arduino程式與探究實驗應用入門-8

20210815-3上午課程錄影

https://youtu.be/xw_KIMxQs5w

Arduino程式與探究實驗應用入門-9

20210815-4下午課程錄影

https://youtu.be/qSBp-5yq0tk

Arduino程式與探究實驗應用入門-10

20210811上午課程錄影

https://youtu.be/peVabbWxgPg

參考教學影片

3 of 81

數位程式是現今科學與工程應用上非常重要的輔助工具。

本課程將教學員Arduino程式入門,結合程式撰寫及科學實作,透過電子軟硬體讀取科學訊號、探究感測器原理,並做有趣的控制應用。

將數位程式融入科學探究與創新應用,啟發及引導學員對科技的興趣,強化學員在科技應用方面的素養與能力。

  • 學習 Arduino 入門基礎程式概念,學習結合LabVIEW程式做訊號觀察。
  • 利用 電子零件、感測器及生活中容易取得的材料,建構科學實驗系統。
  • 創作發明自己的數位裝置,應用於 科學探究 或 解決問題。

4 of 81

  • 現代資訊科技的硬體發展建構於大量的物理知識基礎上,
  • 許多物理科學實驗與計算,則有賴資訊軟硬體的輔助。
  • 資訊軟硬體的使用與了解是物理教學中相當重要的一環。

物理知識

資訊科技

發展

輔助

https://science.sciencemag.org/content/338/6114/1560/tab-figures-data

歐洲核子研究組織(CERN)

大型強子對撞機(LHC)

https://zh.m.wikipedia.org/wiki/歐洲核子研究組織

5 of 81

電腦

(程式)

硬體

LabVIEW or Arduino

Arduino

電子元件

實驗環境

科學實驗系統

https://www.imdb.com/title/tt0371746/mediaviewer/rm2227410432

簡介

(人機介面)

(類比、數位

通訊與控制)

(偵測、控制)

https://www.ni.com/zh-tw/shop/labview.html

https://science.sciencemag.org/content/338/6114/1560/tab-figures-data

6 of 81

參考資料: 維基百科 https://zh.wikipedia.org/zh-hant/Arduino

Arduino 簡介

Arduino,是一個開放原始碼的單晶片微控制器

建構於簡易輸出/輸入(I/O)介面板,並且具有使用類似Java、C語言的開發環境。

開發沿革:

馬西莫 之前是義大利一家 高科技設計學校 的老師。他的學生們經常抱怨找不到便宜好用的微控制器。

2005年冬天,馬西莫 跟 大衛 討論了這個問題。大衛 是一個晶片工程師,當時在這所學校做訪問學者。

兩人決定設計自己的電路板,並引入了 馬西莫 的學生 梅利斯 為電路板設計編程語言。

這塊電路板被命名為Arduino。幾乎任何人,即使不懂電腦編程,也能用 Arduino 做出很酷的東西。

比如對感測器作出回應,閃爍燈光,還能控制馬達。

特色:

開放原始碼,免費下載,可依需求自己修改。可使用燒入器,將程式燒入IC晶片。

可取得硬體的設計檔,加以調整電路板及元件,以符合自己實際設計的需求。

可簡單地與感測器,各種電子元件連接,如紅外線、超音波、熱敏電阻、光敏電阻、伺服馬達…等。使用低價格的微處理控制器。支援多樣的互動程式等。

USB介面,不需外接電源。提供直流電源輸入。

7 of 81

紅外線感測器 ~30元

(循跡感測器)

常見的 Arduino

電子零件價格

Arduino Uno ~220元

SG90 伺服馬達 ~30元

超音波測距感測器 ~30元

手指心跳感測器 ~25元

8 of 81

MQ-8 氫氣感測器

MQ-2: 液化氣、丁烷、丙烷、甲烷、煙霧 感測器 ~50元

MQ-9: 一氧化碳氣體感測器 一氧化碳,煤氣,液化天然氣 ~80元

MQ-5: 液化石油氣,天然氣,煤氣 感測器 ~70元

MQ-7: 一氧化碳 感測器 ~80元

MQ-8: 氫氣 感測器 ~80元

MQ-3: 酒精,汽油,甲烷,己烷,液化石油氣 感測器 ~70元

MQ-7一氧化碳感測器

MQ-3 酒精感測器

Arduino 氣體感測器 零件 參考價格

9 of 81

課程主要材料:

LED 發光二極體

杜邦線(公-公)

USB 連接線

Arduino Uno開發板

麵包板

手指心跳

感測器

可變電阻

1 kΩ

電阻

紅外線

感測器

蜂鳴器

伺服馬達

超音波感測器

熱敏

電阻

光敏

電阻

10 of 81

下載

至官方網址 https://www.arduino.cc/en/Main/Software

下載 Arduino介面開發環境(IDE)程式

11 of 81

連接Arduino開發板:

1. 安裝好 Arduino IDE 介面開發環境。如何安裝 https://youtu.be/hzQKGEsNAvc

2. 將Arduino Uno開發板用USB線連接電腦,等待自動安裝完成驅動程式。

3. 執行 Arduino.exe

4. 在 “工具” 選單 > “開發板” >

選擇 “Arduino Uno”

5. 在 “工具” 選單 > “序列埠” >

選擇Arduino開發版的接口 “COM?

(在工具選單,確認序列埠有打勾,如右)

12 of 81

  1. 點選 “檔案” > “範例” > “01.Basics” > “Blink
  2. 執行 “上傳” ( “🡺” 圖示),等上傳完畢
  3. 觀察開發板上的燈號 🡺 燈閃爍??

Arduino Uno開發板

(測試開發板是否正常。閃爍 →開發板OK)

檢核:

我會上傳程式 到開發板

我的開發板 功能正常

測試Arduino開發板:

13 of 81

13號孔(pin 13)

接地孔(Gnd)

Arduino Uno開發板

4. 在Digital I/O 的13號孔(pin 13)與接地(Gnd)上,插上LED燈 🡺 LED閃爍??

注意: LED的接腳有 正 負 之分

長腳為正、短腳為負

電流由正極流入,負極流出,LED才會亮

檢核:

我會判斷LED接腳的正負

正極,長腳

負極,短腳

14 of 81

/*

Turns an LED on for one second, then off for one second, repeatedly. Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO, it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to the correct LED pin independent of which board is used.

*/

// the setup function runs once when you press reset or power the board

void setup() {

// initialize digital pin LED_BUILTIN as an output.

pinMode(LED_BUILTIN, OUTPUT);

}

// the loop function runs over and over again forever

void loop() {

digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)

delay(1000); // wait for a second

digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW

delay(1000); // wait for a second

}

Blink.ino

程式中的 “備註”

(不執行的文字):

備註方式1:

/* abc…

*/

備註方式2:

// abc…

學程式第一招 從範例開始理解

15 of 81

void setup() {

pinMode(LED_BUILTIN, OUTPUT);

}

void loop() {

digitalWrite(LED_BUILTIN, HIGH);

delay(1000);

digitalWrite(LED_BUILTIN, LOW);

delay(1000);

}

Blink.ino 程式 去除備註之後,剩沒幾行

學程式第一招 從範例開始理解

指令參考網頁

https://www.arduino.cc/reference/en/

pinMode(pin, mode)

指定 某一接孔 pin

模式為 輸入INPUT 或 輸出 OUTPUT

digitalWrite(pin, value) 數位寫出

delay(ms) 延遲等待多少毫秒(ms)

1 ms = 1/1000 s = 0.001 秒

16 of 81

void setup() {

pinMode(13, OUTPUT);

}

void loop() {

digitalWrite(13, HIGH); delay(1000);

digitalWrite(13, LOW); delay(1000);

}

這樣寫更容易理解

檢核:

□ 我知道指令結束時要加 分號 ;

□ 我知道 pinMode() 的用法

□ 我知道 digitalWrite() 的用法

□ 我知道 delay() 的用法

學程式第一招 從範例開始理解

17 of 81

使用麵包板

注意事項:

  1. 麵包板5個洞一組5個洞彼此相連(導通)。
  2. 杜邦線外皮有多種顏色,雖然顏色不影響導電,但是各種顏色有助於辨識接線功能
  3. 時常 電壓源、訊號 等等用暖色系接地 常用黑色冷色系

檢核:

□ 我會使用麵包板

□ 我會使用杜邦線

□ 我知道可以使用顏色幫助區分接線功能

改用杜邦線將LED連接到麵包板上。

杜邦線

麵包板

breadboard

用杜邦線連接LED正極到 pin13 ,負極到 Gnd。

18 of 81

探究實驗: 閃爍的光 與 視覺暫留

1. 閃爍的光與視覺暫留:

LED燈 亮/暗 的delay時間縮短,多短時眼睛會看不出LED燈在閃爍?

2. (續) 用手拿起LED燈(連同麵包板),快速擺動,觀察其在空間中的軌跡。

注意: 擺動時注意不要扯掉了電線。

3. (探究實驗) 改用其他顏色的LED燈,

將結果紀錄於下表。

紅色LED

黃色LED

綠色LED

視覺暫留

時間 (ms)

各種顏色的光的視覺暫留時間

19 of 81

程式應用:

利用麵包板,將紅、黃、綠色LED分別接到 Digital I/O的 pin 11、12、13,

寫一個 紅綠燈 控制程式

注意: 每個 pin 都要設定 pinMode

20 of 81

void setup() {

pinMode(13, OUTPUT); // Green LED

pinMode(12, OUTPUT); // Yellow LED

pinMode(11, OUTPUT); // Red LED

}

void loop() {

digitalWrite(13, HIGH); digitalWrite(12, LOW); digitalWrite(11, LOW); delay(3000);

digitalWrite(13, LOW); digitalWrite(12, HIGH); digitalWrite(11, LOW); delay(1000);

digitalWrite(13, LOW); digitalWrite(12, LOW); digitalWrite(11, HIGH); delay(2000);

}

// 這樣寫更容易理解,以及變換花樣

紅綠燈 控制程式 Traffic_light_LED.ino

也可以這樣寫

缺點: 執行 delay() 的時候,系統在發呆,不能做其他事。

可以怎麼改 ??

digitalWrite(13, 1); digitalWrite(12, 0); digitalWrite(11, 0); delay(3000);

digitalWrite(13, 0); digitalWrite(12, 1); digitalWrite(11, 0); delay(1000);

digitalWrite(13, 0); digitalWrite(12, 0); digitalWrite(11, 1); delay(2000);

21 of 81

本範例有以下幾個 指令的用法:

  • millis() 取得 毫秒(ms)時間

  • == 判斷是否相等

  • if-else (如果...就,不然就...)

https://www.arduino.cc/reference/en/

進階範例:

Blink_without_delay.ino

22 of 81

本範例 改用 經過時間 以及 餘數

來判斷是要亮

Syntax

x %= divisor;

// equivalent to the expression x = x % divisor;

Parameters

x: variable. Allowed data types: int.

divisor: non zero variable or constant.

Allowed data types: int.

Example Code

int x = 7;

x %= 5; // x now contains 2

https://www.arduino.cc/reference/en/

進階範例:

Blink_with_Time.ino

23 of 81

休息一下...

學習檢核:

我會用 millis() 讀取 開發板上的時間

我知道 判斷AB相同 的寫法 A==B

我理解 if – else 的用法

24 of 81

讀取類比數值到電腦 AnalogReadSerial

  1. 點選 “檔案” > “範例” > “01.Basics” > “AnalogReadSerial”
  2. 執行 “上傳” ( “🡺” 圖示) ,等上傳完畢
  3. 點選 “功能” > “序列埠監控視窗
  4. 監控視窗開啟後,右下角選擇 “9600 baud”
  5. 是否有呈現數值??
  6. 在 類比(Analog)輸入端第0號孔 A0 插入杜邦線
  7. 用手碰觸A0電線,觀察序列埠監控視窗數值範圍
  8. 關閉監控視窗🡸重要
  9. 點選 “功能” > “序列繪圖家”,開啟序列繪圖家
  10. 是否有呈現數據變化圖?? 數值範圍??

類比輸入端第0號孔: A0

學習檢核:

我有讀到電壓?

我會使用序列埠監控視窗?

我會使用序列繪圖家?

我知道上面兩者不能同時開啟?

25 of 81

/*

AnalogReadSerial

Reads an analog input on pin 0, prints the result to the Serial Monitor.

This example code is in the public domain.

http://www.arduino.cc/en/Tutorial/AnalogReadSerial

*/

// the setup routine runs once when you press reset:

void setup() {

// initialize serial communication at 9600 bits per second:

Serial.begin(9600);

}

// the loop routine runs over and over again forever:

void loop() {

// read the input on analog pin 0:

int sensorValue = analogRead(A0);

// print out the value you read:

Serial.println(sensorValue);

delay(1); // delay in between reads for stability

}

AnalogReadSerial.ino

26 of 81

/*

AnalogReadSerial

Reads an analog input on pin 0, prints the result to the Serial Monitor.

This example code is in the public domain.

http://www.arduino.cc/en/Tutorial/AnalogReadSerial

*/

// the setup routine runs once when you press reset:

void setup() {

// initialize serial communication at 9600 bits per second:

Serial.begin(9600);

}

// the loop routine runs over and over again forever:

void loop() {

// read the input on analog pin 0:

int sensorValue = analogRead(A0);

// print out the value you read:

Serial.println(sensorValue);

delay(1); // delay in between reads for stability

}

AnalogReadSerial.ino

程式中的 “備註”

(不執行的文字):

方式1:

/* abc…

*/

方式2:

// abc…

27 of 81

void setup() {

Serial.begin(9600);

}

void loop() {

int sensorValue = analogRead(A0);

Serial.println(sensorValue);

delay(1);

}

AnalogReadSerial.ino

鮑率(Baud Rate) 預設值9600其實相當慢,建議可增高,例如增至 115200 。

要注意 序列埠監控視窗 或 繪圖家 等軟體的 baud rate 也要用一樣的設定值,不然會出現亂碼

原程式 去除備註之後,剩沒幾行

28 of 81

//開發板功能設定:

void setup() {

Serial.begin(115200); //設定 序列埠 鮑率 Serial Port begin (為提高傳輸效率,此值較一般設定值9600高出許多)

while (!Serial) { ;} //當 序列埠(Serial) 未就位時,等待(執行空白)

}

//不斷重複執行迴圈:

void loop() {

float voltage = 5.0 * analogRead(A0)/1023; //將 第0號類比輸入口 (A0) 的讀值(0-1023)換算成電壓值voltage (0V-5V)

Serial.println(voltage,4); //將 電壓值(voltage) 傳送到序列埠(Serial Port) 暫存器(buffer),4位精度

Serial.flush(); // 等待序列埠暫存器中的數據傳送至電腦完畢

}

Read_Analog_Signal_simple.ino

29 of 81

void setup() {

Serial.begin(115200);

while (!Serial) { ;}

}

void loop() {

float voltage = 5.0 * analogRead(A0)/1023;

Serial.println(voltage,4);

Serial.flush();

}

Read_Analog_Signal_simple.ino 去掉註解後

試試看:

若將 “5.0” 改成 “5”,

執行結果會有甚麼不同??

30 of 81

讀取類比電壓值到電腦

[探究]

  1. 執行 “Read_Analog_Signal_simple.ino”並上傳至開發板
  2. 用“序列埠監控視窗”或“序列繪圖家”觀察數值
  3. 將電線一端接 “類比輸入端A0”,另一端碰觸不同東西
  4. 當 A0 訊號線碰觸 手、Gnd 、 5V、3.3V 等等位置時,訊號讀值如何變化??

下載範例:

Read_Analog_Signal_simple.ino

Arduino程式可到本課程 雲端資料夾 下載: [Arduino Programs].zip

上面的.zip 檔案為壓縮檔,請務必先 "解壓縮" 成一般資料夾,才能正常使用。

學習檢核:

我有讀到電壓?

我會使用序列埠監控視窗?

我會使用序列繪圖家?

我知道上面兩者不能同時開啟?

31 of 81

覺得用 Arduino 序列埠監控視窗 或是 序列繪圖家 太難觀察訊號?

不方便做存檔紀錄?

怎麼辦?

  • 搭配 LabVIEW 程式

32 of 81

LabVIEW 簡介

Laboratory Virtual Instrumentation Engineering Workbench,實驗室虛擬儀器工程平台

§ 由美國國家儀器公司所開發的圖形化程式編譯平台,最初於1986年在蘋果電腦上發表。與傳統程式語言之不同點在於圖形化程式流程採用"資料流"之概念,在流程圖構思完畢時也完成了程式撰寫。簡單易懂的開發介面,縮短了開發原型的速度以及方便日後的軟體維護,受到系統開發及研究人員的喜愛。

§ LabVIEW 早期是為了儀器自動控制所設計,至今轉變成為一種逐漸成熟的高階程式語言。引入了特別的虛擬儀表的概念,使用者可透過人機介面直接控制自行開發之儀器。廣泛的被應用於工業自動化之領域上。

§ LabVIEW 提供豐富實用的函式庫,如 訊號擷取、訊號分析、機器視覺、數值運算、邏輯運算、聲音震動分析、資料儲存...等。

33 of 81

LabVIEW 程式: Get 3Signals from Arduino.exe

LabVIEW程式可到本課程 雲端資料夾 下載: [LabVIEW Programs].zip

上面的.zip 檔案為壓縮檔,請務必先 "解壓縮" 成一般資料夾,才能正常使用。

34 of 81

LabVIEW 搭配Arduino程式

可利用 LabVIEW程式讀取Arduino送出到序列埠上的訊號。

  1. 在 課程雲端資料夾找到 [LabVIEW RT2020 Installer]

  • 執行 install.exe 可安裝 LabVIEW Run-Time。(大約2分鐘)

如何解壓縮與安裝LabVIEW Runtime (for Arduino): https://youtu.be/OTWl5B3RlpI

  1. 在 [LabVIEW Programs] 資料夾找到 Read Arduino by LabVIEW
  2. 執行 Read Arduino by LabVIEW.exe

LabVIEW程式可到課程資料雲端資料夾下載

程式亦可到 <自造實驗基地的小科學家培育計畫> 網站免費下載使用,

網址: https://sites.google.com/view/lab-maker

35 of 81

探究實驗: 尺的震動頻率

使用紅外線偵測器量得震動。探究直尺長度與震動頻率的關係。

紅外線偵測器原理:

1. 一顆LED發射紅外線

2. 發出的紅外線照射到物體表面,散射回來 (散射能力與表面材質、顏色有關)

3. 另一顆紅外線接收器收到散射回來的紅外線,其訊號經放大器處理後送至AO (Analog Out)

AO (Analog Out):

  • 物體距離遠(回來的光甚弱)時,AO 🡺 5 V
  • 物體距離近(回來的光較強)時,AO 🡺 0 V

DO (Digital Out):

  • AO電壓大於臨界值(由電阻調整),

DO 輸出為 1 (High, 約 5 V)

  • AO電壓小於臨界值(由電阻調整),

DO 輸出為 0 (Low, 約 0 V)

接收器 隔板 發射器

36 of 81

紅外線模組 接腳

接到 Arduino

1 - VCC 電源

5 V

2 - GND 接地

GND

3 - DO 數位電壓輸出

Digital In

(ex. pin 12)

4 - AO 類比電壓輸出

Analog In

(ex. A0)

紅外線偵測器 與 Arduino 的連接方式

37 of 81

1. 探究紅外線感測器與直尺之間不同距離 d 時,感測器的類比電壓 V 隨 d 之變化。

畫出 V(d) 曲線。

20190810-11

寫Arduino程式做探究實驗入門

花蓮女中學員數據

2021.07.10 數位探究實作科學營 (遠距教學實作) 學員數據

探究實驗(示範): 尺的震動頻率

使用紅外線偵測器量得震動。探究直尺長度與震動頻率的關係。

38 of 81

探究實驗(示範): 尺的震動頻率

使用紅外線偵測器量得震動。探究直尺長度與震動頻率的關係。

2. 探究直尺長度與震動頻率的關係

  • 決定適當的感應距離 d ,震動直尺(伸出長度為L),測量頻率 f 。
  • 量測不同直尺長度 L 時的頻率 f 。畫出 f(L) 曲線。
  • 透過擬合,得到 f – L 之間的關係。

39 of 81

LabVIEW 程式 freq-amp-analysis.exe 功能解說

此程式從Arduino讀電壓到電腦中,進行 主頻率 f(t),震幅 A(t) 隨 時間t 變化的分析。

在Arduino 上執行 V-time.ino

此程式 快速讀入電壓(且取多點平均) 並傳出 時間t 與 平均電壓V

接著 執行 freq-amp-analysis.exe,從 Arduino 接收 時間t 與 平均電壓V 得到 V(t)圖。

可擷取片刻 V(t) 曲線 (波形wavefrom),進行 快速傅立葉轉換 (FFT),

得到此片刻波形的 主頻率frequency f(t) 與其 震幅amplitude A(t) 隨 時間t 的變化。

擷取的片刻時間 (time interval)可自行調整,以符合應用需求。

可手動設定欲觀察(找尋)的 主頻率 約略值 (approx. freq.)。

可手動設定頻率尋找範圍 (search range) 上下變化多少百分比。

例如設定 60 Hz +/- 50% 則尋找範圍約 30 Hz - 90 Hz。

若連續執行太久,紀錄的數據資料太龐大,每次繪圖(更新繪圖)時會花越多時間,讓畫面看起來有延遲的現象。實際的數據讀取並不會有太多延遲。欲消除 更新繪圖延遲現象,可以把繪圖 清除(Clear)。

注意: 可先繪圖數據 匯出(export),不然一旦 清除(Clear)繪圖,圖上的數據即被清除了!!

freq-amp-analysis.vi 為 LabVIEW 程式。可用 LabVIEW 編輯軟體開啟程式。

其中使用到 自編的子程式 tone-around-freq.vi,

因此開啟 freq-amp-analysis.vi 時須將 tone-around-freq.vi 放在同一資料夾中。

40 of 81

LabVIEW 程式 freq-amp-analysis.exe 操作 與 實驗示範

示範實驗: 指尖陀螺轉速與半衰期、颶風球 (IYPT 2019 Problem 6 Hurricane Balls)。

此程式從Arduino讀電壓到電腦中,進行 主頻率 f(t),震幅 A(t) 隨 時間t 變化的分析。

41 of 81

LabVIEW 程式 freq-amp-analysis.exe 操作 與 實驗示範

示範實驗: 指尖陀螺轉速與半衰期、颶風球 (IYPT 2019 Problem 6 Hurricane Balls)。

指尖陀螺的轉速分析。從 主頻率 f(t) 隨 時間t 的變化,可知指尖陀螺的轉速半衰期約22秒。

42 of 81

休息一下...

學習檢核:

我會使用 紅外線(循跡)感測器

我知道 紅外線(循跡)感測器 的原理與特性

我會用 LabVIEW 程式 輔助觀察 Arduino傳來的數據

我會用 LabVIEW 程式 儲存 Arduino傳來的數據

我會用 LabVIEW 程式 測得物體震動(轉動)的頻率

43 of 81

int pin = 9;

void setup() {

pinMode(pin, OUTPUT);

}

void loop() {

digitalWrite(pin, 1); delayMicroseconds(568);

digitalWrite(pin, 0); delayMicroseconds(568);

}

產生聲音

用 High-Low 交替的電壓

讓 無源蜂鳴器 發出 高音La ( 880 Hz )的聲音

延遲時間為 1000000 微秒 / 880 / 2 = 568 微秒

pin: 蜂鳴器(+)腳接pin孔,蜂鳴器(-)腳接地Gnd

蜂鳴器

44 of 81

頻率(Hz)

Do

C

Re

D

Mi

E

Fa

F

Sol

G

La

A

Si

B

低(4)

262

294

330

349

392

440

494

中(5)

523

587

659

698

784

880

988

高(6)

1046

1175

1318

1397

1568

1760

1967

tone()演奏音樂

指令 tone(pin, frequency, duration);

pin: 蜂鳴器(+)腳接的孔,蜂鳴器(-)腳接地Gnd

frequency: 頻率值(Hz),各音調的頻率參考下表

duration: 持續某音調的時間長度(單位毫秒 ms)

45 of 81

int pin = 9;

void setup() { pinMode(pin, OUTPUT); }

void loop() {

tone(pin, 523, 200); delay(250); // Do

tone(pin, 523, 200); delay(250); // Do

tone(pin, 784, 200); delay(250); // Sol

tone(pin, 784, 200); delay(250); // Sol

tone(pin, 880, 200); delay(250); // La

tone(pin, 880, 200); delay(250); // La

tone(pin, 784, 400); delay(500); // Sol

tone(pin, 698, 200); delay(250); // Fa

tone(pin, 698, 200); delay(250); // Fa

tone(pin, 659, 200); delay(250); // Mi

tone(pin, 659, 200); delay(250); // Mi

tone(pin, 587, 200); delay(250); // Re

tone(pin, 587, 200); delay(250); // Re

tone(pin, 523, 400); delay(500); // Do

}

範例程式 小星星 toneLittleStar.ino

重複性的動作,可改用 “迴圈” 來執行!!

例如 for(){} // for迴圈

使用 tone 指令

https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/

開發板同一時間只能執行一個 tone()

執行tone()後,該pin會自動以頻率frequency進行 HIGH/LOW 震盪。

如果要該pin的頻率震盪停止,可下指令 noTone(pin)。

如果有一個pin正在執行 tone(),則重下指令 tone() 到同一個 pin 會立即更新頻率

如果有一個pin正在執行 tone(),則下tone() 到另一個 pin 會無效果,必須先下noTone(pin)才能切換到其他pin。

46 of 81

int pin = 9; // buzzer 蜂鳴器接腳

float melody[] = { m5, h3, h2, h5, h3, h2, h1, m5, m6, m5, h1, h3, h2 };

int noteNumber = sizeof(melody)/4; // Size of each "float" is 4

float noteDuration[] = { 1, 2, 1, 1, 1.5, 0.5, 1, 1, 2, 1, 1, 2, 1 }; // 1: 1/4節, 2: 2/4節, ...

void setup() { pinMode(pin, OUTPUT); }

void loop() {

int thisNote = 0;

for (thisNote = 0; thisNote < noteNumber; thisNote++) {

tone(pin, melody[thisNote], 250*noteDuration[thisNote]); // 1拍 = 250 ms

delay(250*noteDuration[thisNote]*1.20); // *1.2 = wait tone() over 20%

}

}

範例程式 toneMelody.ino ( 陣列 array )

for(){} // for迴圈,依照預設好的初始、結束條件來做重複執行。

for (initialization; condition; increment) { // statement(s); }

https://www.arduino.cc/reference/en/language/structure/control-structure/for/

47 of 81

控制 伺服馬達 Servo (SG90)

執行 SG90_servo_center.ino

讓 伺服馬達 角度置中 (角度為 90度)

int pulse = 1450; //脈衝長度1450us 使SG90 角度置中

int pin = 9;

void setup() {

pinMode(pin,OUTPUT);

}

void loop() {

digitalWrite(pin,HIGH);

delayMicroseconds(pulse);

digitalWrite(pin,LOW);

delayMicroseconds(100);

}

伺服馬達 是用脈衝長度(時間) 控制角度。

SG90的脈衝時間與角度對應約是:

500 us 🡸🡺 0度

2400 us 🡸🡺 180度

可改變 pulse 的設定數值,看看角度怎麼變化

排線

至 開發板

Gnd

5 V

Digital pin

48 of 81

改執行範例程式 SG90_servo_sweep.ino 試試看!!

int pulse = 1450;

int pin = 9;

void setup() { pinMode(pin,OUTPUT); }

void loop() {

//Sweep 左右來回轉動

for(pulse = 500; pulse <=2400; pulse = pulse+10) // goes from 0 degrees to 180 degrees, pulse += 10

{

digitalWrite(pin,HIGH); delayMicroseconds(pulse);

digitalWrite(pin,LOW); delayMicroseconds(1000);

}

for(pulse = 2400; pulse >=500; pulse = pulse-10) // goes from 180 degrees to 0 degrees, pulse += -10

{

digitalWrite(pin,HIGH); delayMicroseconds(pulse);

digitalWrite(pin,LOW); delayMicroseconds(1000);

}

}

for(){} // for迴圈,依照預設好的初始、結束條件來做重複執行。

for (initialization; condition; increment) { // statement(s); }

https://www.arduino.cc/reference/en/language/structure/control-structure/for/

49 of 81

學習檢核:

我會使用 tone 產生頻率

我知道 for 迴圈的用法

□ 我可以讓伺服馬達停在我要的角度

休息一下...

50 of 81

範例程式: V_to_tone.ino

利用 可變電阻 連續改變電壓,

並藉此控制 蜂鳴器 發出的音調

int pin = 9;

int duration = 50; // the time interval to renew the sound (ms)

float voltage;

float frequency;

void setup() { pinMode(pin, INPUT);}

void loop() {

voltage = 5.0*analogRead(A0)/1023.0;

frequency = 440.0*voltage; // 設定電壓與音調頻率的對應關係

tone(pin, frequency, duration); // 產生音調頻率frequency, 持續50 ms

delay(duration); // delay延遲時間 duration(ms),等一下聲音播完

}

+5V

GND

voltage

可變電阻

A0

可變電阻

51 of 81

What is PWM?

Pulse Width Modulation, or PWM, is a technique for getting analog results with digital means. Digital control is used to create a square wave, a signal switched between on and off. This on-off pattern can simulate voltages in between the full Vcc of the board (e.g., 5 V on Uno, 3.3 V on a MKR board) and off (0 Volts) by changing the portion of the time the signal spends on versus the time that the signal spends off. The duration of "on time" is called the pulse width. To get varying analog values, you change, or modulate, that pulse width. If you repeat this on-off pattern fast enough with an LED for example, the result is as if the signal is a steady voltage between 0 and Vcc controlling the brightness of the LED.

52 of 81

試試看:

你可以用 可變電阻 連續改變電壓,

並藉此控制 伺服馬達 的角度變化 ??

int ledPin = 9; // LED connected to digital pin 9 (with PWM)

int analogPin = 0; // potentiometer connected to analog pin 0

void setup() {

pinMode(ledPin, OUTPUT); // sets the pin as output

Serial.begin(115200);

}

void loop() {

int val = analogRead(analogPin); // read the input pin

int pwmValue = map(val,0,1023,62,255); // 做數值對應

analogWrite(ledPin, pwmValue); // PWM 調變輸出

}

範例程式 PWMtoServo.ino

analogWrite() 與 PWM

53 of 81

學習檢核:

我會使用 PWM 調整LED平均亮度

休息一下...

int ledPin = 9; // LED connected to digital pin 9 (with PWM)

int analogPin = 0; // potentiometer connected to analog pin 0

int val = 0; // variable to store the read value

void setup() {

pinMode(ledPin, OUTPUT); // sets the pin as output

Serial.begin(115200);

}

void loop() {

val = analogRead(analogPin); // read the input pin

// 當讀得的電壓越高,LED越亮 (PWM 脈衝寬度越大)

analogWrite(ledPin, val / 4);

// analogRead values go from 0 to 1023, analogWrite values from 0 to 255

Serial.println(val);

}

範例程式 R-tune-PWM.ino

使用 PWM 調整LED平均亮度

54 of 81

+5V

GND

voltage

可變電阻

A0

[探究與實作] LED 發光電壓 vs 光波長 的關係

  1. 可變電阻的兩端分別接到Arduino的 Gnd 5V
  2. 可變電阻的中間點接到Arduino “類比輸入端A0
  3. 執行程式Read_Analog_Signal_simple.ino

旋轉可變電阻,觀察中間點讀到的電壓值

  1. 在可變電阻 中間點 與 Gnd 之間接上一顆 LED燈
  2. 觀察使 LED燈 亮起所需要的電壓
  3. 使用不同顏色的LED燈,

探究 LED燈 的 波長 與 所需電壓 的關係

55 of 81

紅色

~ 640 nm

黃色

~ 590 nm

綠色

~ 515 nm

藍色

~ 450 nm

啟動電壓 (V)

1.68 +/- 0.07

1.82 +/- 0.06

2.11 +/- 0.08

2.48 +/- 0.07

參考:

2021/01/23

學員數據統計

56 of 81

探究 LED 發光電壓 vs 光波長 的關係

E = h (普朗克常數) x ν (光頻率) = h c/λ = e ΔV

ΔV λ = hc/e = 1.2398 x 10-6 ( Volt ∙ m )

1240 ( Volt ∙ nm )

h = 6.62607015 x 10-34 ( J∙s ) 2019/05/20 常數,定義公斤

c = 299792458 ( m/s ) 常數,定義長度

e = 1.6021766208 x 10-19 ( C ) 電子電量

紅色

~ 640 nm

黃色

~ 590 nm

綠色

~ 515 nm

藍色

~ 450 nm

波長(nm) x

電壓(V)

1073

1072

1088

1117

參考:

2021/01/23

學員數據統計

57 of 81

測量 LED 的電流電壓曲線(示範)

58 of 81

  1. [Arduino Programs] 資料夾找到 LED_IV_curve.ino,執行
  2. [LabVIEW Programs] 資料夾找到 XY plot.exe ,執行
  3. 轉動可變電阻,得到 IV 曲線。推得 LED 的啟動電壓。

測量 LED 的電流電壓曲線(示範)

59 of 81

XY plot.vi 程式內部

60 of 81

??? 的電流電壓曲線 IV curve

[探究]

移除右圖的 LED,改接上其他電子零件 (例如馬達),會得到怎樣的 IV 曲線??

61 of 81

學習檢核:

我知道 PWM 的意思與特性

□ 我可以用 digitalWrite() 讓LED燈看起來變亮或變暗

我知道使 LED發光所需的 電壓波長(顏色) 有關

休息一下...

62 of 81

測量未知電阻

光敏電阻、光控開關與自動控制

  1. 開啟”自造實驗基地”網頁 https://sites.google.com/view/lab-maker
  2. 在 Arduino 專區下載 “Resistance-value.ino” 並上傳至開發板
  3. 光敏電阻(未知電阻Rx) 與 1 kΩ電阻(已知電阻R0)串聯
  4. Rx電阻一端接5V,R0電阻一端接地
  5. 中間分壓送到 Arduino A0 讀取電壓
  6. 程式換算得到 Rx電阻值,傳回電腦

  • 觀察光敏電阻 照光強弱時,電阻值的變化

Rx = (5.0/voltage - 1)*R0

+5V

GND

voltage

R0

Rx

A0

光敏電阻

63 of 81

+5V

GND

voltage

R0

Rx

A0

光敏電阻

5 = I * (Rx + R0)

voltage = I * R0

消去I

🡺 Rx = (5.0/voltage - 1)*R0

64 of 81

/* 此程式將 未知電阻Rx 與 已知電阻R0 串聯,Rx電阻一端接5V,R0電阻一端接地,

中間分壓送到 Arduino A0 讀取電壓,再換算成 未知電阻Rx 值傳送到電腦。*/

float R0 = 1000; // 設定 已知電阻 R0 的電阻值,此處 R0 = 1千歐姆 (1 kΩ)

void setup() {

Serial.begin(115200);

while (!Serial) { ;}

}

void loop() {

float voltage = 5.0*analogRead(A0)/1023;

// 從 A0 腳位讀入 類比訊號,換算成 電壓值 (存入變數 voltage 中)

float Rx = (5.0/voltage - 1)*R0;

// 從 已知電阻 R0 與未知電阻 Rx 的中間點分壓,計算出未知電阻 Rx 的電阻值

Serial.println(Rx,2); // 將溫度值 T 送到 序列埠 暫存器(取精度小數下2位),並換行

Serial.flush(); // 等待 序列埠暫存器 傳完(清空)

}

Resistance-value.ino

65 of 81

Temperature-R-type.ino

( 將熱敏電阻與已知電阻R0串聯,由分壓得到熱敏電阻值,換算成溫度,傳送到電腦 )

Temperature-LED.ino

( 當熱敏電阻溫度過高時,使LED燈亮起 )

熱敏電阻、溫度量測與溫控開關

試試看以下程式

5V

GND

5V

GND

R0

Rx

66 of 81

/* 此程式使用熱敏電阻Rx 與 已知電阻R0 串聯,熱敏電阻一端接5V,已知電阻一端接地,中間分壓送到 Arduino A0 讀取電壓,再換算成 溫度值 T 傳送到電腦。 */

float R0 = 1000; // 設定 已知電阻 R0 的電阻值

void setup() {

Serial.begin(115200);

while (!Serial) { ;}

}

void loop() {

float voltage = 5.0*analogRead(A0)/1023;

float Rx = (5.0/voltage - 1)*R0;

float temp = 0.001129148+0.000234125*log(Rx)+0.0000000876741*(log(Rx))*(log(Rx))*(log(Rx));

//將熱敏電阻值 Rx 換算成 絕對溫度值的倒數

float T = 1/temp -273.15; // 得到溫度值,單位為 度C

Serial.println(T,4); // 將溫度值 T 送到 序列埠 暫存器(取精度小數下4位),並換行

Serial.flush(); // 等待 序列埠暫存器 傳完(清空)

}

Temperature-R-type.ino

67 of 81

/* 此程式使用熱敏電阻Rx 與 已知電阻R0 串聯,熱敏電阻一端接5V,已知電阻一端接地,

中間分壓送到 Arduino A0 讀取電壓,再換算成 溫度值 T 傳送到電腦。

此外,當溫度大於 30 度C時,接在 digital I/O 的 pin 13 的LED燈亮起。*/

float R0 = 1000; const int ledPin = 13;

void setup() {

Serial.begin(115200); while (!Serial) { ;}

pinMode(ledPin, OUTPUT);}

void loop() {

float voltage = 5.0*analogRead(A0)/1023; float Rx = (5.0/voltage - 1)*R0;

float temp = 0.001129148+0.000234125*log(Rx)+0.0000000876741*(log(Rx))*(log(Rx))*(log(Rx));

float T = 1/temp -273.15;

if (T >= 30) { // 設定當溫度大於 30 度C 時,執行IF迴圈的內容

digitalWrite(ledPin, HIGH); //輸出高電位給LED (讓LED燈亮)

}

else { digitalWrite(ledPin, LOW); } //輸出低電位給LED (LED燈不亮)

Serial.println(T,4); // 將溫度值 T 送到 序列埠 暫存器(取精度小數下4位),並換行

Serial.flush(); // 等待 序列埠暫存器 傳完(清空)

}

Temperature-LED.ino

68 of 81

使用超音波感測器量得距離

Sonar_Distance.ino

( 觸發超音波感測器,將回音訊號換算成距離,傳送到電腦 )

HC-SR04 測距模組

Arduino

1 - VCC

5 V

2 - Trig (Trigger) 觸發

Pin 12

3 - Echo 回音

Pin 11

4 - GND

GND

69 of 81

https://lastminuteengineers.com/arduino-sr04-ultrasonic-sensor-tutorial/

How HC-SR04 Ultrasonic Sensor Works & Interface It With Arduino

duration = pulseIn(echoPin, HIGH, timeout);

digitalWrite(trigPin, LOW);

delayMicroseconds(100);

digitalWrite(trigPin, HIGH);

delayMicroseconds(10);

digitalWrite(trigPin, LOW);

70 of 81

//定義:

int ledPin = 13;

int trigPin = 12; //定義 觸發輸出腳位 Trig Pin

int echoPin = 11; //定義 回音接收腳位 Echo Pin

float duration, distance; //定義 時間長度duration 與 距離distance 格式為 浮點數

//開發板功能設定:

void setup(){

Serial.begin(115200); //設定 序列埠 鮑率

while (!Serial){ ;} //等待序列埠接通

pinMode(ledPin, OUTPUT);

pinMode(trigPin, OUTPUT); //設定 觸發輸出腳位(trigPin)的功能為 輸出(OUTPUT)

pinMode(echoPin, INPUT); //設定 回音接收腳位(echoPin)的功能為 輸入(INPUT)

}

Sonar_Distance.ino

71 of 81

void loop(){

//於 觸發輸出腳位 Trig Pin 產生觸發脈衝(應大於 10微秒)

digitalWrite(trigPin, LOW); // 讓觸發腳位trigPin 確實降回低電位,持續 20微秒 (us)

delayMicroseconds(20);

digitalWrite(trigPin, HIGH); // 觸發腳位trigPin 變成高電位,持續 20微秒 (us)

delayMicroseconds(20);

digitalWrite(trigPin, LOW); // 觸發腳位trigPin 再降回低電位,使HC-SR04產生聲音脈衝出去

/********************************/

duration = pulseIn(echoPin, HIGH); // 於Echo Pin 收到高電位(High) 的脈衝時間 (微秒 us)

distance = duration*0.0170; // 將聲音 “來回” 時間(us) 換算成距離 (cm)

if (distance >= 10 and distance <= 30) // 設定當距離 大於10 且 小於30 時,執行IF迴圈的內容

{digitalWrite(ledPin, HIGH);} // 輸出高電位給LED (讓LED燈亮)

else {digitalWrite(ledPin, LOW);} // 輸出低電位給LED (LED燈不亮)

Serial.println(distance); // 將 距離distance 傳送到序列埠暫存器

Serial.flush(); // 等待序列埠暫存器中的數據傳送至電腦完畢

delayMicroseconds(duration*1.5); // 避免收到 更早發出的聲音脈衝 回音

// 注意: 若沒有外加此delay,感測器可能收到的是 更早發出的聲音脈衝 的回音,造成錯誤 (常出現測距的大雜訊)

}

Sonar_Distance.ino

72 of 81

範例 Blink_with_Time.ino

範例 IrReadCode.ino

電阻色碼

Extra Content 外加內容、補充內容

73 of 81

[探究與實作] 手指測心跳感測器

1. (數位技能)

利用Arduino連接 手指心跳感測器。如右圖。

執行Arduino電壓讀取程式:

Read_Analog_Signal_simple.ino

或 ReadAnalogAvg1ch.ino 更佳

執行LabVIEW程式讀取Arduino回傳的訊號:

Read Arduino by LabVIEW.exe

了解程式介面操作。(雜訊平均,精度的概念)

2. (感測器物理原理)

探究心跳感測器上 紅外線LED 與紅外線接收器的相對位置、角度 對訊號的影響。

接 5V

-端

接 Gnd

S端

接 A0

手指心跳感測器

74 of 81

範例:

Read Arduino by LabVIEW.exe 搭配 ReadAnalogAvg1ch.ino 量測心跳訊號

75 of 81

3. (進階、自選實驗) 將紅外線LED 與紅外線接收器彼此正對並固定不動,插入不同張數的紙(先放一疊再逐一抽走比較容易)

探究電壓訊號紙張張數的變化。

(關係曲線可應用於修正紅外線吸收率方面的實驗)

4. 將手指放在 紅外線LED 與紅外線接收器之間,觀察電壓訊號變化週期是否與心跳(另一手放胸前測)有對應關係。是否同步?

5. 由訊號電壓的變化週期,推算心跳頻率(次/分鐘)。

6. 觀察電壓波形的特徵,並記錄。

探究心跳信號波形是否隨 坐姿、站姿、蹲姿 (心臟比感測器低時) 而改變

[探究與實作] 手指測心跳感測器

76 of 81

[探究與實作] 手指測心跳感測器

7. 觀察不同根手指 (或手指上不同位置,手掌側邊等等) 的訊號跳動。

找出訊號最明顯的手指(位置)。

8. 探究不同力道捏住手腕脈搏時,對所測得手指心跳訊號的影響。

9. (進階) 觀察在做完不同運動後,心跳的頻率變化 (及回復時間),

探究波形是否受運動而改變。(各測量時需維持相同坐姿)

10. (試試看) 執行 Arduino 程式 HeartBeatAvg.ino,將手指放感測位置,用序列埠監控視窗看能否顯示你的心跳。

77 of 81

可接收 紅外線遙控器 所發出的訊號。

例如一般 電視、冷氣等等 所使用的遙控器。

可用Arduino讀取遙控器按鍵的編碼,然後做控制反應。

使用時需要先下載 IRremote函式庫 (library)

可參考官方網頁

https://www.arduino.cc/reference/en/libraries/irremote/

下載函式庫,例如 3.3.0版 (IRremote-3.3.0.zip)

解壓縮後 將 IRremote-3.3.0 資料夾放到 C:\Program Files (x86)\Arduino\libraries 資料夾中

即可在程式中引用 IRremote.h 函式庫

#include <IRremote.h>

程式範例 可參考 IrReadCode.ino

紅外線遙控接收器

78 of 81

#define case1 0x401002C2 // 定義 case1 為某一遙控器按鍵的編碼(例如 401002C2),

// 0x表示用16進位編碼呈現: 1234567890ABCDEF

#include <IRremote.h> // 引用 IRremote.h 函式庫

const int irPin = 3; // 將 IR 接收器訊號端接到 digital pin 3

const int ledPin = 13; // LED接 pin 13

IRrecv irrecv (irPin); // 建立 IRrecv 物件

decode_results results; // 建立 存放解碼的 decode_results 結構變數

void setup()

{

Serial.begin (115200);

irrecv.enableIRIn(); // 用指令 enableIRIn() 啟動紅外線解碼

pinMode(ledPin, OUTPUT);

}

void showIRProtocol(decode_results * results) { // 自己定義一個函數名稱,以及其功能

Serial.print("irCode: ");

Serial.print(results->value, HEX); // Infrared code, HEX 表示以16進位編碼呈現

Serial.print(", bits: ");

Serial.println(results->bits); // Number of bits infrared, 呈現編碼所佔的位元數

} // End function

程式範例 IrReadCode.ino

79 of 81

void loop() {

if(irrecv.decode(& results)) { // 檢查是否接收到訊號並解碼,

//成功則decode()函式回傳true並把解碼結果放result變數中

showIRProtocol(& results); // 執行 showIRProtocol,將資訊印回電腦上呈現

if(results.value == case1) { // 如果符合遙控器case1按鍵編碼,就做以下動作。

Serial.println("LED on"); // 本行可替換成 做某一動作

digitalWrite(ledPin, HIGH); // turn the LED on

}

if(results.value == case2) { // 如果符合遙控器case2按鍵編碼,就做以下動作。

Serial.println("LED off"); // 本行可替換成 做某一動作

digitalWrite(ledPin, LOW); // turn the LED off

}

irrecv.resume(); // 呼叫 resume() 函式,重設decode()狀態,繼續檢查解碼

}

} // End loop

程式範例 IrReadCode.ino

80 of 81

電阻色碼

一般電阻

通常電阻器上印有4個色環,每一個色環顏色皆代表不同的數值。

第一個色環a代表第一位數,第二個色環b代表第二位數,

第三個色環c代表第三位數,稱為倍數或者是乘數,

第四個色環d代表電阻器可能的誤差值。

一般電阻的大小標示為

ab×10c ± d

左圖的電阻的色環顏色:「棕」、「棕」、「黑」 代表110,

「金」代表誤差 ±5%,因此這個電阻器的電阻值為

11×100 Ω ± 5% = 11 Ω ± 5%

abc d

顏色

無色

數值

-2

-1

0

1

2

3

4

5

6

7

8

9

 

誤差

±10%

±5%

 

 

 

 

 

 

 

 

 

 

±20%

81 of 81

顏色

無色

數值

-2

-1

0

1

2

3

4

5

6

7

8

9

 

誤差

±10%

±5%

 

 

 

 

 

 

 

 

 

 

±20%

電阻色碼

abcd e

新式精密電阻

新式精密電阻的標示方式如一般電阻,但增加一位有效數值。

新式精密電阻的大小標示為

abc×10d ± e

左圖的電阻的色環顏色:「棕」、「棕」、「黑」、「黑」代表1100,

「金」代表誤差 ±5%,因此這個電阻器的電阻值為

110×100 Ω ± 5%=110 Ω ± 5%

0022

4701

4.7 kΩ

220 Ω