實驗物理技術
課程簡介 與 Arduino入門
日期: 2022/02/18
時間: 13:00-16:00
地點: 工PC1電腦教室
電腦
(軟體程式)
設備
(硬體介面)
LabVIEW or Arduino
Arduino or 電子元件
實驗
環境
科學實驗
https://www.imdb.com/title/tt0371746/mediaviewer/rm2227410432
簡介
(人機介面)
(類比、數位 通訊與控制)
(整合)
http://sine.ni.com/nips/cds/view/p/lang/zht/nid/207573
人
https://home.cern/resources/image/engineering/engineering-images-gallery
參考資料: 維基百科 https://zh.wikipedia.org/zh-hant/Arduino
Arduino 簡介
Arduino,是一個開放原始碼的單晶片微控制器,
建構於簡易輸出/輸入(I/O)介面板,並且具有使用類似Java、C語言的開發環境。
開發沿革:
馬西莫 之前是義大利一家 高科技設計學校 的老師。他的學生們經常抱怨找不到便宜好用的微控制器。
2005年冬天,馬西莫 跟 大衛 討論了這個問題。大衛 是一個晶片工程師,當時在這所學校做訪問學者。
兩人決定設計自己的電路板,並引入了 馬西莫 的學生 梅利斯 為電路板設計編程語言。
這塊電路板被命名為Arduino。幾乎任何人,即使不懂電腦編程,也能用 Arduino 做出很酷的東西。
比如對感測器作出回應,閃爍燈光,還能控制馬達。
特色:
開放原始碼,免費下載,可依需求自己修改。可使用燒入器,將程式燒入IC晶片。
可取得硬體的設計檔,加以調整電路板及元件,以符合自己實際設計的需求。
可簡單地與感測器,各種電子元件連接,如紅外線、超音波、熱敏電阻、光敏電阻、伺服馬達…等。使用低價格的微處理控制器。支援多樣的互動程式等。
USB介面,不需外接電源。提供直流電源輸入。
MQ-3 酒精感測器 ~68元
紅外線感測器 ~28元
(循跡感測器)
常見的 Arduino
電子零件價格
Arduino Uno ~170元
SG90 伺服馬達 ~34元
超音波測距感測器 ~27元
手指心跳感測器 ~25元
Arduino 氣體感測器 零件 參考價格
MQ-8 氫氣感測器
MQ-7 一氧化碳感測器模組
MQ-3 酒精感測器
LabVIEW 簡介
LabVIEW(Laboratory Virtual Instrumentation Engineering Workbench,實驗室虛擬儀器工程平台)是由美國國家儀器公司所開發的圖形化程式編譯平台,最初於1986年在蘋果電腦上發表。與傳統程式語言之不同點在於圖形化程式流程採用"資料流"之概念,在流程圖構思完畢時也完成了程式撰寫。簡單易懂的開發介面,縮短了開發原型的速度以及方便日後的軟體維護,受到系統開發及研究人員的喜愛。
§ LabVIEW 早期是為了儀器自動控制所設計,至今轉變成為一種逐漸成熟的高階程式語言。引入了特別的虛擬儀表的概念,使用者可透過人機介面直接控制自行開發之儀器。廣泛的被應用於工業自動化之領域上。
§ LabVIEW 提供豐富實用的函式庫
如 訊號擷取、訊號分析、機器視覺、數值運算、邏輯運算、聲音震動分析、資料儲存...等。
電腦
(軟體程式)
設備
(硬體介面)
LabVIEW
or Arduino
Arduino or 電子元件
(類比、數位 通訊與控制)
下載
至官方網址 https://www.arduino.cc/en/Main/Software
下載 Arduino開發介面程式
學程式第一招:
從範例開始理解
插上LED燈 🡺 LED閃爍??
Arduino Uno開發板
(測試開發板是否正常。閃爍 →開發板OK)
13號孔(pin 13)
/*
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…
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
原程式 去除備註之後,剩沒幾行
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH); delay(1000);
digitalWrite(13, LOW); delay(1000);
}
原程式 寫成這樣更容易理解
探究實驗:
讀取類比數值到電腦 AnalogReadSerial
Arduino Uno開發板
類比輸入端第0號孔: A0
/*
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
讀取類比電壓值到電腦
Read_Analog_Signal_simple.ino
/*
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…
void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A0);
Serial.println(sensorValue);
delay(1);
}
AnalogReadSerial.ino
鮑率(Baud Rate) 預設值9600其實相當慢,建議可增高,例如增至 115200 。
要注意 序列埠監控視窗 或 繪圖家 等軟體的 baud rate 也要用一樣的設定值,不然會出現亂碼。
原程式 去除備註之後,剩沒幾行
//開發板功能設定:
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
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”,
執行結果會有甚麼不同??
LabVIEW 程式: Get Signals from Arduino.exe
此程式可到 <自造實驗基地的小科學家培育計畫> 網站免費下載使用,
網址: https://sites.google.com/view/lab-maker
LabVIEW 搭配Arduino程式
可利用 LabVIEW程式讀取Arduino送出到序列埠上的訊號。
可透過序列埠讀取Arduino訊號,可同時讀取3組訊號。
執行 裡面的 setup.exe 可安裝 LabVIEW Run-Time。
測量未知電阻
光敏電阻、光控開關與自動控制
讀取電阻值到電腦 Resistance-value.ino
Rx = (5.0/voltage - 1)*R0
+5V
GND
voltage
R0
Rx
A0
光敏電阻
/* 此程式將 未知電阻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
Temperature-R-type.ino
( 將熱敏電阻與已知電阻R0串聯,由分壓得到熱敏電阻值,換算成溫度,傳送到電腦 )
Temperature-LED.ino
( 當熱敏電阻溫度過高時,使LED燈亮起 )
熱敏電阻、溫度量測與溫控開關
試試看以下程式
5V
GND
5V
GND
R0
Rx
10 KΩ電阻
/* 此程式使用熱敏電阻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
/* 此程式使用熱敏電阻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
探究 LED 發光電壓 vs 光波長 的關係
旋轉可變電阻,觀察中間點讀到的電壓值
探究 LED燈 的 波長 與 所需電壓 的關係。
+5V
GND
voltage
可變電阻
A0
| 紅色 ~ 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
全班數據統計
探究 LED 發光電壓 vs 光波長 的關係
E = h (普朗克常數) x ν (光頻率) = hc/λ = 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
全班數據統計
手指測心跳的探究與實作
1. (數位技能)
利用Arduino連接 手指心跳感測器。如右圖。
執行電壓讀取程式:
Read_Analog_Signal_simple
執行LabVIEW程式讀取arduino回傳的訊號:
[LabVIEW] Get Signals from Arduino.exe
了解程式介面操作。(雜訊平均,精度的概念)
2. (感測器物理原理)
探究心跳感測器上 紅外線LED 與紅外線接收器的相對位置、角度 對訊號的影響。
接 5V
-端
接 Gnd
S端
接 A0
手指心跳感測器
3. (進階、自選實驗) 將紅外線LED 與紅外線接收器彼此正對並固定不動,插入不同張數的紙(先放一疊再逐一抽走比較容易)
探究電壓訊號隨紙張張數的變化。
(關係曲線可應用於修正紅外線吸收率方面的實驗)
4. 將手指放在 紅外線LED 與紅外線接收器之間,觀察電壓訊號變化週期是否與心跳(另一手放胸前測)有對應關係。是否同步?
5. 由訊號電壓的變化週期,推算心跳頻率(次/分鐘)。
6. 觀察電壓波形的特徵,並記錄。
探究心跳信號波形是否隨 坐姿、站姿、蹲姿 (心臟比感測器低時) 而改變。
7. 觀察不同根手指 (或手指上不同位置,手掌側邊等等) 的訊號跳動。
找出訊號最明顯的手指(位置)。
8. 探究不同力道捏住手腕脈搏時,對所測得手指心跳訊號的影響。
9. (進階) 觀察在做完不同運動後,心跳的頻率變化 (及回復時間),
探究波形是否受運動而改變。(各測量時需維持相同坐姿)
探究實驗: 尺的震動頻率
IYPT Problem #17. Popsicle Chain Reaction
Wooden popsicle sticks can be joined together by slightly bending each of them so that they interlock in a so-called “cobra weave” chain. When such a chain has one of its ends released, the sticks rapidly dislodge, and a wave front travels along the chain. Investigate the phenomenon.
相關實驗:
探究實驗: 尺的震動頻率
使用紅外線偵測器量得震動。探究直尺長度與震動頻率的關係。
紅外線偵測器原理:
1. 一顆LED發射紅外線
2. 發出的紅外線照射到物體表面,散射回來 (散射能力與表面材質、顏色有關)
3. 另一顆紅外線接收器收到散射回來的紅外線,其訊號經放大器處理後送至AO
物體距離遠(回來的光甚弱)時,AO 🡺 5 V
物體距離近(回來的光較強)時,AO 🡺 0 V
紅外線模組 | Arduino |
1 - VCC 電源 | 5 V |
2 - GND 接地 | GND |
3 - DO 數位電壓輸出 | Digital In (ex. pin 12) |
4 - AO 類比電壓輸出 | Analog In (ex. A0) |
紅外線偵測器原理:
1. 一顆LED發射紅外線
2. 發出的紅外線照射到物體表面,散射回來 (散射能力與表面材質、顏色有關)
3. 另一顆紅外線接收器收到散射回來的紅外線,其訊號經放大器處理後送至AO
物體距離遠(回來的光甚弱)時,AO 🡺 5 V
物體距離近(回來的光較強)時,AO 🡺 0 V
探究直尺長度與震動頻率的關係
20190810-11 寫Arduino程式做探究實驗入門
花蓮女中學員數據
使用超音波感測器量得距離
Sonar_Distance.ino
( 觸發超音波感測器,將回音訊號換算成距離,傳送到電腦 )
HC-SR04 測距模組 | Arduino |
1 - VCC | 5 V |
2 - Trig (Trigger) 觸發 | Pin 12 |
3 - Echo 回音 | Pin 11 |
4 - GND | GND |
https://atceiling.blogspot.com/2017/03/arduino_28.html
//定義:
int trigPin = 12; //定義 觸發輸出腳位 Trig Pin
int echoPin = 11; //定義 回音接收腳位 Echo Pin
double duration, distance; //定義 變數格式為 雙精度(double)浮點數
double distancelimit = 250.0; //定義 最遠測量距離限制 250公分 (避免太遠回音訊號不佳&等候回音過久)
double distancealarm = 5.0; //定義 警報距離。距離小於5公分(盲區)時 發出LED警示 (內建LED訊號LED_BUILTIN=pin 13)
double timeout = distancelimit/0.017; //設定 超過最遠測量距離時的時間(等候回音時間上限)[ 假設聲波速率為 340 m/s ]
//開發粄功能設定:
void setup() {
Serial.begin(115200); //設定 序列埠 鮑率 Serial Port begin
pinMode(trigPin, OUTPUT); //設定 觸發輸出腳位(trigPin)的功能為 輸出(OUTPUT)
pinMode(echoPin, INPUT); //設定 回音接收腳位(echoPin)的功能為 輸入(INPUT)
pinMode(LED_BUILTIN, OUTPUT); //設定 內建LED (LED_BUILTIN = pin 13 腳位) 的功能為 輸出(OUTPUT)
}
Sonar_Distance.ino
//不斷重複執行迴圈:
void loop()
{
//於 觸發輸出腳位 Trig Pin 產生觸發脈衝(建議大於 10微秒)
digitalWrite(trigPin, LOW); //觸發腳位trigPin 先降回低電位,持續 4微秒 (us)
delayMicroseconds(8);
digitalWrite(trigPin, HIGH); //觸發腳位trigPin 變成高電位,持續 12微秒 (us)
delayMicroseconds(12);
digitalWrite(trigPin, LOW); //觸發腳位trigPin 再降回低電位,完成脈衝,使HC-SR04產生聲音脈衝出去
/******************************/
duration = pulseIn(echoPin, HIGH, timeout); // 於回音接收腳位(Echo Pin) 收到高電位(High) 的時間 (微秒 us)。等待超過 timeout時間上限 則跳出,回傳0
distance = duration*0.0170; // 將聲音 "來回" 時間(us) 換算成距離 (cm) [ 假設聲波速率為 340 m/s ]
if(distance <= distancealarm){ distance = distancealarm; }
//若距離小於警告最小距離(或超過timeout)時,距離回傳為 警報距離
Sonar_Distance.ino
if(distance < distancelimit){ //若距離在 測量距離範圍 時,回傳距離數值
// Serial.print("Distance : ");
Serial.print(distance); //將 distance 傳送到序列埠(Serial Port) 暫存器(buffer)
// Serial.print("cm");
Serial.println(); //將 '換行' 傳送到序列埠(Serial Port) 暫存器(buffer)
Serial.flush(); // 等待序列埠暫存器中的數據傳送至電腦完畢
}
if(distance <= distancealarm){ //若距離小於 警報距離 時,內建LED亮起
digitalWrite(LED_BUILTIN, HIGH);
}
else{ //否則 內建LED變暗
digitalWrite(LED_BUILTIN, LOW);
}
}
Sonar_Distance.ino
控制伺服馬達
排線 | 至 |
棕 | GND |
紅 | 5 V |
橙 | Arduino Digital pin |
執行 SG90_servo_center.ino
測試 伺服馬達 功能
將角度設定成90度,並將十字板以平行角度插上馬達,如右圖
int pulse = 1450;
int pin = 9;
void setup() {
pinMode(pin,OUTPUT);
}
void loop() {
pulse = 1450; //Check center position 用脈衝長度1450us確認中心位置(角度)
digitalWrite(pin,HIGH);
delayMicroseconds(pulse);
digitalWrite(pin,LOW);
delayMicroseconds(100);
}
SG90_servo_center.ino
伺服馬達 是用脈衝長度(時間) 控制角度。SG90的脈衝時間與角度對應約是:
500 us 🡸🡺 0度
2400 us 🡸🡺 180度
可改變 pulse 的設定數值,看看角度怎麼變化
改執行 SG90_servo_sweep.ino 試試看!!
頻率(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: 持續某音調的時間長度(秒)
/* 本程式讀取 紅外線偵測器(IR循跡感測器)的 類比輸出(Analog Out, AO)電壓。
* 預設從 A0 (Analog #0) 輸入孔將電壓訊號讀入(0-1023),並轉換為電壓值(0-5V)。
* 紅外線偵測器 的電壓V-距離x 關係 V(x) 並非線性對應關係。可自行測試找出 V(x)。
* 距離x約1-3公分時 V會靈敏的變化(x減小V越小),距離x較大時V趨近於4.8V。 */
void setup() {
Serial.begin(115200);
}
void loop() {
float voltage = 5.0*analogRead(A0)/1023; // 從 A0輸入孔將電壓訊號讀入(0-1023),轉換為電壓值voltage(0-5V)
float frequency = 440+440*voltage;
tone(9, frequency, 0.1);
Serial.print(voltage,3); // 將 電壓值取到3位小數,傳送到序列埠(Serial Port)暫存器(buffer)
Serial.print(",\t");
Serial.println(frequency);
Serial.flush(); // 等待序列埠暫存器中的數據傳送至電腦完畢
}
IR_tone.ino
恭喜你完成 Arduino 做實驗的入門練習。
寫程式時遇到問題可參考其他人的範例教材。
更多指令使用方法可參考官方網頁。
====== The End ======