10907 電資營 - 感應鬧鈴
大家手上都拿到一個實驗包,裡面主要包括一片 Arduino Uno 開發板,還有一塊麵包板上面插了許多元件
總計大概有下面這些東西,今天我們的軟體操控實驗就是基於這些裝置
基本元件
- 實驗麵包板
- 按鈕開關
- 發光二極體 LED
- 無源蜂鳴器
- 七段共陰極顯示器
- 超音波模組
單晶片 (微控制器, MCU) ATMega 328P
在萬物聯網的時代裡,我們要透過單晶片來擷取資料並且操控這些電子設備,這個單晶片就是在 Arduino UNO 板子中央那顆小小黑色的晶片
- 8 位元
- 20MHZ (20MIPS)
- AVR, 內建快閃儲存的設計
Arduino 開發版簡介
- Italy company
- 硬體、韌體開源設計,公開所有的設計資料,任何人或是廠商都可以基於這些資料修改或是設計新的電路
Uno
- 單晶片
- USB 接頭
- 9V 電源接頭,降壓電路
- 時脈產生電路
- 強制重置按鍵
- 5V, 地線(GND)
- 類比輸入(Analog IN, A0~A5)
- 數位輸入/輸出(Digital, 0~13)
- 類比輸出(PWM, 3,5,6,9,10,11)
Mega
Due
Nano
Pro mini
有趣的應用
開發軟體
界面
兩個重要按鈕:編譯(驗證)&上傳
簡單測試 Blink
實驗步驟:
1. 開啟 Arduino IDE
-
將 Arduino Uno 用 USB 連接線連上電腦
-
選擇 工具/開發板/Arduino Uno
-
選擇 工具/序列埠/COM??
-
選取 檔案/範例/Basic/Blink
-
驗證 (編譯)
-
上傳
上傳有點慢,需要一點點時間,如果失敗的話,調整一下 COM??,如果設定都是對的,別擔心,有時候重新上傳一次就會成功了
- 板子上除了有一個恆亮的 LED 之外,另一個 LED 一明一滅的,一秒鐘亮,一秒鐘暗,恭喜你成功了!! 整個程序到這裡如果一直出現問題,先找隊輔幫忙解決
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
電路檢查
接下來很快地檢查麵包板上的電路,請先將超音波模組拔下,看到下面這張照片,從左邊開始很快地核對這些接線,最後再將超音波模組插回圖裡面紅色方格:
實驗麵包板
如下圖麵包板是不需要經由焊接過程,就可以將實驗所使用的電子元件以杜邦線連接,進而量測電路的特性,以驗證電路功能是否正常的實驗室工具。
接下來所有的實驗,我們都不需要把麵包板上的元件拔下來,只需要用杜邦線連接 Arduino Uno 和 麵包板上的元件。
實驗 1: 按鈕開關與LED
實驗步驟:
- 拔掉 USB 與電腦的連線
- 連接5V (下圖中紅線,由麵包板火線+接到UNO 5V)
- 連接地線 (下圖中黑線,由麵包板地線-接到UNO GND)
- 連接 LED 正極(麵包板12) 到 UNO輸出 13 (下圖中黃線)
- 連接 按鈕開關(麵包板30) 到 UNO類比輸入 A0 (下圖中綠線)
- 插上 USB 與電腦連線
- IDE 中選取 檔案/新增,複製下列程式到視窗中
- 點選 上傳 按鈕,存檔,上傳完畢
- 程式已經開始執行,按下按鍵 LED 點亮,放開按鍵 LED 熄滅
void setup() {
pinMode(A0, INPUT);
pinMode(13, OUTPUT);
}
void loop() {
int switchStatus;
switchStatus = digitalRead(A0);
if (switchStatus==HIGH)
digitalWrite(13, HIGH);
else
digitalWrite(13, LOW);
}
當你按下按鍵,發生了什麼事?
UNO 輸入輸出腳位控制
- pinMode(設定腳位, 設定模式);
- pinMode(A0, INPUT); //腳位是A0,模式是輸入
- pinMode(13, OUTPUT);//腳位是13,模式是輸出
認識 if 敘述
if (switchStatus==HIGH) // 如果讀取的按鍵狀態是高電位,按鍵被按下
digitalWrite(13, HIGH); // 點亮 LED
想想看
怎樣修改程式功能變成「按鍵放開時 LED 長亮,按鍵按下時 LED 熄滅」
程式碼
void setup() {
pinMode(A0, INPUT);
pinMode(13, OUTPUT);
}
void loop() {
int switchStatus;
switchStatus = digitalRead(A0);
if (switchStatus==HIGH)
digitalWrite(13, LOW);
else
digitalWrite(13, HIGH);
}
資工領域特別強調軟體的操控模型
- BLINK 程式裡一個 LED 可以閃動,用 delay 來控制明亮各多長時間
- 兩個 LED 的話,當然可以同時用同樣頻率閃動;或是第一個先閃動,第二個接續閃動,這時候雖然可以用不同的頻率,但是第二個計時的時候,第一個的時間好像就凍結在那裡了
- 想想看, 怎樣可以讓兩個 LED 同時用不同的頻率閃動?
實驗步驟:
- 拔掉 USB 與電腦的連線
- 將 綠色 LED 接到 UNO 輸出 12
- 將 透明 LED 接到 UNO 輸出 11
- 插上 USB 與電腦連線
- IDE 中選取 檔案/新增,複製下列程式到視窗中
- 點選 上傳 按鈕,存檔,上傳完畢
- 程式已經開始執行,三個 LED 同時以不同頻率計時閃動
const int LEDYellow = 13;
const int LEDGreen = 12;
const int LEDRed = 11;
void blinkingLED() {
int i;
const int duration[3] = {700, 351, 571},
onDuration[3]={345, 147, 367};
const int outputPin[3] = {LEDRed, LEDYellow, LEDGreen};
static unsigned long lastOnTime[3]={0,0,0};
unsigned long currentTime = millis();
for (i=0; i<3; i++)
if((currentTime - lastOnTime[i]) > duration[i]) {
digitalWrite(outputPin[i], HIGH);
lastOnTime[i] = currentTime;
}
else if ((currentTime - lastOnTime[i]) > onDuration[i]) {
digitalWrite(outputPin[i], LOW);
}
}
void setup() {
pinMode(LEDRed, OUTPUT);
pinMode(LEDYellow, OUTPUT);
pinMode(LEDGreen, OUTPUT);
}
void loop() {
blinkingLED();
delay(10);
}
解釋與心得
關鍵在於「不要再用 delay() 這種佔著資源卻躺著什麼事都不做的函式了」,用 millis() 去檢查現在的時間,時間到了該做什麼事就做什麼事。
實驗 2: 蜂鳴器
實驗步驟:
- 拔掉 USB 與電腦的連線
- 拔掉 黃色 LED 接到 UNO 輸出 13
- 拔掉 綠色 LED 接到 UNO 輸出 12
- 拔掉 透明 LED 接到 UNO 輸出 11
- 把 蜂鳴器一端(麵包板22) 接到 UNO 輸出 13
- 插上 USB 與電腦連線
- IDE 中選取 檔案/新增,複製下列程式到視窗中
- 點選 上傳 按鈕,存檔,上傳完畢
- 程式已經開始執行,蜂鳴器長響三次後靜音
const int buzzer = 13;
int j=0;
void setup() {
pinMode(buzzer,OUTPUT);
}
void loop() {
int i;
for (i=0; i<10&&j<3; i++) {
tone(buzzer,1000);
delay(50);
tone(buzzer,500);
delay(50);
}
noTone(buzzer);
delay(2000);
j++;
}
無源蜂鳴器
無源蜂鳴器的優點是:
- 便宜
- 聲音頻率可控,可以做出音階 “Do Re Mi Fa Sol La Si” 的效果
- 在一些特例中,可以和 LED 共用一個控制腳
常用操控蜂鳴器函式
tone(腳位,頻率)
ex: tone(13,1000); //透過13腳輸出頻率1000的聲音
noTone(腳位)
ex: noTone(13); //13腳無聲
int i;
for (i=0; i<10; i++) { (執行10次)
想要重複執行的程式敘述
}
音階
66, 131, 262, (523), 1046 // C Do
74, 147, 294, (587), 1175 // D Re
83, 165, 330, (659), 1318 // E Mi
88, 175, 349, (698), 1397 // F Fa
98, 196, 392, (784), 1568 // G So
110, 220, 440, (880), 1760 // A La
124, 247, 494, (988), 1976 // B Si
來個 Do
tone(13,523);
delay(50)
Fa 呢? So 呢?
程式片段
Fa:
tone(13,523);
delay(50);
So:
tone(13,523);
delay(50);
寫一小段旋律吧
const int buzzer = 13;
int j = 0;
void setup() {
pinMode(buzzer,OUTPUT);
}
void loop() {
int i;
for (i=0; i<3&&j<2; i++) {
tone(buzzer,784); delay(333);
noTone(buzzer); delay(10);
tone(buzzer,659); delay(333);
noTone(buzzer); delay(10);
tone(buzzer,659); delay(333);
noTone(buzzer); delay(150);
tone(buzzer,698); delay(333);
noTone(buzzer); delay(10);
tone(buzzer,587); delay(333);
noTone(buzzer); delay(10);
tone(buzzer,587); delay(333);
noTone(buzzer); delay(150);
tone(buzzer,523); delay(333);
noTone(buzzer); delay(10);
tone(buzzer,587); delay(333);
noTone(buzzer); delay(10);
tone(buzzer,659); delay(333);
noTone(buzzer); delay(10);
tone(buzzer,698); delay(333);
noTone(buzzer); delay(10);
tone(buzzer,784); delay(333);
noTone(buzzer); delay(10);
tone(buzzer,784); delay(333);
noTone(buzzer); delay(10);
tone(buzzer,784); delay(333);
noTone(buzzer); delay(333);
}
noTone(buzzer);
delay(2000);
j++;
}
額、再一小段旋律???
小祕密
哈哈,哪是祕密呀!!
Google 大神
https://dragaosemchama.com/en/2019/02/songs-for-arduino/
https://github.com/robsoncouto/arduino-songs
實驗 3: 七段顯示器
實驗步驟:
- 拔掉 USB 與電腦的連線
- 參考下圖,接上共陰極七段顯示器的排線到 UNO 輸出 2,3,4,5,6,7,8 腳
- 插上 USB 與電腦連線
- IDE 中選取 檔案/新增,複製下列程式到視窗中
- 點選 上傳 按鈕,存檔,上傳完畢
- 程式已經開始執行,七段顯示器顯示 9,8,7,6,5,4,3,2,1,0 休息四秒鐘重複
byte seven_seg_digits[10][7] = { { 1,1,1,1,1,1,0 },
{ 0,1,1,0,0,0,0 },
{ 1,1,0,1,1,0,1 },
{ 1,1,1,1,0,0,1 },
{ 0,1,1,0,0,1,1 },
{ 1,0,1,1,0,1,1 },
{ 1,0,1,1,1,1,1 },
{ 1,1,1,0,0,0,0 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,0,0,1,1 }
};
void setup() {
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
digitalWrite(9, 0);
}
void sevenSegWrite(byte digit) {
byte seg;
for (seg=0; seg<7; ++seg)
digitalWrite(seg+2, seven_seg_digits[digit][seg]);
}
void loop() {
byte digit;
for (digit=10; digit>0; --digit) {
sevenSegWrite(digit-1);
delay(1000);
}
delay(4000);
}
七段顯示器
實際上只是 8 顆 LED 排列整齊
重要控制函式
sevenSegWrite(digit)
例如:sevenSegWrite(8); // 顯示數字 8
陣列
想要10個變數?
byte x1, x2, x3, x4, x5, x6, x7, x8, x9, x10;
你該試試「陣列」
byte x[10]; // 一行搞定
陣列有什麼功能特別強大嗎?
void sevenSegWrite(byte digit) {
byte seg;
for (seg=0; seg<7; ++seg)
digitalWrite(seg+2, seven_seg_digits[digit][seg]);
}
沒有陣列時
現在讓七段往上數
程式片段
for (byte digit=0; digit<10; ++digit) {
sevenSegWrite(digit);
delay(1000);
}
現在讓七段只數奇數
程式片段
for (byte digit=10; digit>0; digit=digit-2) {
sevenSegWrite(digit-1);
delay(1000);
}
實驗 4: 超音波感測器
超音波感測模組 HC-SR04 操作原理
上面是發射器 (Transmitter),會發出 40 kHz 的聲波,由於這個聲波的頻率超過人類可聽見的 20 kHz,因此被稱為超音波。下面是接收器 (Receiver),可以接收超音波。它可以感測的距離為 2cm 到 400cm,感應角度為 15 度。
如上圖,Trig 腳送進至少維持 10 微秒以上的高位準訊號,便能觸發模組中的超音波發射器送出 8 個連續的 40KHz 超音波脈衝,接收器收到反射波後便會在 Echo 腳輸出一個與量測距離成正比的高位準脈衝,此高位準脈衝上緣可以看成超音波開始發射時間;而下緣則是接收到反射波的時間,所以整個高位準脈衝的寬度就是超音波往返的總時間,要特別注意的地方是被測物體最好大於 0.5 平方公尺,否則反射的聲音沒有辦法接收到,而 Trig 時間間隔最好大於 60ms,避免 Trig 與 Echo 互相干擾。
量測物體距離
實驗步驟:
- 拔掉 USB 與電腦的連線
- 把超音波模組的 Echo(麵包板21) 接到 UNO 輸出 11
- 把超音波模組的 Trig(麵包板20) 接到 UNO 輸出 12
- 插上 USB 與電腦連線
- IDE 中選取 檔案/新增,複製下列程式到視窗中
- 點選 上傳 按鈕,存檔,上傳完畢
- 程式已經開始執行,如下圖在 IDE 右上角點選序列埠監控視窗
- 試試看拿一本書放在超音波感測器前方,看到監控視窗中的距離了嗎?
int trigPin = 12;
int echoPin = 11;
long duration, cm, inches;
void setup() {
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
cm = (duration/2) / 29.1;
inches = (duration/2) / 74;
Serial.print("Distance : ");
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(250);
}
倒車雷達
試試看常用到的倒車雷達,越接近時蜂鳴器越急促
int buzzer = 13;
int trigPin = 12;
int echoPin = 11;
long duration, cm, inches;
void setup() {
Serial.begin(9600);
pinMode(echoPin, INPUT);
pinMode(trigPin, OUTPUT);
pinMode(buzzer, OUTPUT);
}
void loop() {
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
cm = (duration/2) / 29.1;
inches = (duration/2) / 74;
Serial.print("Distance : ");
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.println("cm");
tone(buzzer,500);
delay(200);
noTone(buzzer);
delay(cm*30);
}
距離控制音階
讓我們用距離來控制蜂鳴器的頻率
int buzzer = 13;
int trigPin = 12;
int echoPin = 11;
long duration, cm, inches, step;
int freq[] = {523, 587, 659, 698, 784, 880, 988};
void setup() {
Serial.begin(9600);
pinMode(echoPin, INPUT);
pinMode(trigPin, OUTPUT);
pinMode(buzzer, OUTPUT);
}
void loop() {
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
cm = (duration/2) / 29.1;
inches = (duration/2) / 74;
Serial.print("Distance : ");
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.println("cm");
step = 10;
for (int i=0; i<7; i++) {
if (cm/step==i)
tone(buzzer, freq[i]);
delay(250);
}
綜合實驗: 感應鬧鈴
這個實驗裡,你可以按著按鍵來增加 LED 顯示的數字,然後只要在超音波感測器前揮揮手,可以開始倒數計時或是停下蜂鳴器的聲音,試看看吧!
byte seven_seg_digits[10][7] = { { 1,1,1,1,1,1,0 },
{ 0,1,1,0,0,0,0 },
{ 1,1,0,1,1,0,1 },
{ 1,1,1,1,0,0,1 },
{ 0,1,1,0,0,1,1 },
{ 1,0,1,1,0,1,1 },
{ 1,0,1,1,1,1,1 },
{ 1,1,1,0,0,0,0 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,0,0,1,1 }
};
const int buzzer = 13;
const int sevenSegA = 2;
int trigPin = 12;
int echoPin = 11;
long duration, cm, inches;
#define DEBOUNCE_DELAY 200
#define TEMPO 333
const int toneTable[7][5]={
{ 66, 131, 262, 523, 1046},
{ 74, 147, 294, 587, 1175},
{ 83, 165, 330, 659, 1318},
{ 88, 175, 349, 698, 1397},
{ 98, 196, 392, 784, 1568},
{110, 220, 440, 880, 1760},
{124, 247, 494, 988, 1976}
};
char beeTone[]="GEEFDDCDEFGGGGEEFDDCEGGEDDDDDEFEEEEEFGGEEFDDCEGGC";
char starTone[]="CCGGAAGFFEEDDCGGFFEEDGGFFEEDCCGGAAGFFEEDDC";
int beeBeat[]={
1,1,2, 1,1,2, 1,1,1,1,1,1,2,
1,1,2, 1,1,2, 1,1,1,1,4,
1,1,1,1,1,1,2, 1,1,1,1,1,1,2,
1,1,2, 1,1,2, 1,1,1,1,4
};
int starBeat[]={
1,1,1,1,1,1,2, 1,1,1,1,1,1,2,
1,1,1,1,1,1,2, 1,1,1,1,1,1,2,
1,1,1,1,1,1,2, 1,1,1,1,1,1,2
};
int getTone(char symbol) {
static const char *toneName="CDEFGAB";
for (int i=0; i<7; i++) {
if (toneName[i]==symbol) {
return i;
}
}
return 0;
}
void measuringDistance(){
digitalWrite(trigPin, LOW);
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
cm = (duration/2) / 29.1;
inches = (duration/2) / 74;
Serial.print("Distance : ");
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
}
void playMusic() {
int i, length, toneNo, duration;
while(1)
{
length = sizeof(beeTone)-1;
for (i=0; i<length; i++) {
toneNo = getTone(beeTone[i]);
duration = beeBeat[i]*TEMPO;
tone(buzzer,toneTable[toneNo][3]);
delay(duration);
noTone(buzzer);
delay(15);
measuringDistance();
if(cm <= 10) return;
}
delay(2000);
if(cm <= 10) return;
length = sizeof(starTone)-1;
for (i=0; i<length; i++) {
toneNo = getTone(starTone[i]);
duration = starBeat[i]*TEMPO;
tone(buzzer,toneTable[toneNo][3]);
delay(duration);
noTone(buzzer);
delay(15);
measuringDistance();
if(cm <= 10) return;
}
delay(2000);
if(cm <= 10) return;
}
}
void sevenSegWrite(int digit) {
int pin = sevenSegA;
for (int seg=0; seg<7; ++seg) {
digitalWrite(pin, seven_seg_digits[digit][seg]);
++pin;
}
}
static int ledCounter;
static int countDownActivated;
void debounceButtonInputA0() {
static unsigned long lastDebounceTime=0;
unsigned long currentTime = millis();
if((currentTime - lastDebounceTime) > DEBOUNCE_DELAY) {
lastDebounceTime = currentTime;
if(!countDownActivated) {
ledCounter++;
}
}
}
void debounceButtonInputA1() {
static unsigned long lastDebounceTime=0;
unsigned long currentTime = millis();
if((currentTime - lastDebounceTime) > DEBOUNCE_DELAY) {
lastDebounceTime = currentTime;
if (ledCounter>0)
countDownActivated = 1;
}
}
void setup() {
pinMode(buzzer, OUTPUT);
noTone(buzzer);
pinMode(A0, INPUT);
pinMode(A1, INPUT);
ledCounter = 0;
countDownActivated = 0;
for (int seg=0; seg<7; ++seg) {
pinMode(sevenSegA+seg, OUTPUT);
}
Serial.begin (9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
measuringDistance();
if(digitalRead(A0)) {
debounceButtonInputA0();
}
if(cm <= 10) {
debounceButtonInputA1();
}
if(countDownActivated==1) {
delay(1000);
ledCounter--;
if(ledCounter==-1) {
playMusic();
ledCounter = 0;
countDownActivated = 0;
}
}
if(ledCounter>9) {
ledCounter = 0;
}
sevenSegWrite(ledCounter);
delay(500);
}
微觀世界的彈跳現象
這裡的按鈕有點怪?
if (digitalRead(A0))
{
updateLed(0);
}
為什麼不寫成下面這樣就好?
digitalRead(A0);
原因就是彈跳現象
按鈕開關按下時會在極短時間內產生多次開合現象(稱為機械彈跳)
而使用控制板偵測腳位狀態時會讀取到多次的HIGH、LOW的切換 但實際上使用者只按下一次開關,因此會造成程式錯誤 所以設計者需加入「防彈跳」(Debounce)設計來避免此現象
unsigned long currentTime = millis();
if ((currentTime - lastDebounceTime) > DEBOUNCE_DELAY) {
//程式碼內容
lastDebounceTime = currentTime;
}
如果你還會有機會使用 Arduino 的話,下面的連結和小抄整理是有用的
10907 電資營 - 感應鬧鈴
大家手上都拿到一個實驗包,裡面主要包括一片 Arduino Uno 開發板,還有一塊麵包板上面插了許多元件
總計大概有下面這些東西,今天我們的軟體操控實驗就是基於這些裝置
基本元件
單晶片 (微控制器, MCU) ATMega 328P
在萬物聯網的時代裡,我們要透過單晶片來擷取資料並且操控這些電子設備,這個單晶片就是在 Arduino UNO 板子中央那顆小小黑色的晶片
Arduino 開發版簡介
Uno
Mega
Due
Nano
Pro mini
有趣的應用
開發軟體
界面
兩個重要按鈕:編譯(驗證)&上傳
簡單測試 Blink
實驗步驟:
1. 開啟 Arduino IDE將 Arduino Uno 用 USB 連接線連上電腦
選擇 工具/開發板/Arduino Uno
選擇 工具/序列埠/COM??
選取 檔案/範例/Basic/Blink
驗證 (編譯)
上傳
上傳有點慢,需要一點點時間,如果失敗的話,調整一下 COM??,如果設定都是對的,別擔心,有時候重新上傳一次就會成功了
電路檢查
接下來很快地檢查麵包板上的電路,請先將超音波模組拔下,看到下面這張照片,從左邊開始很快地核對這些接線,最後再將超音波模組插回圖裡面紅色方格:
實驗麵包板
如下圖麵包板是不需要經由焊接過程,就可以將實驗所使用的電子元件以杜邦線連接,進而量測電路的特性,以驗證電路功能是否正常的實驗室工具。
接下來所有的實驗,我們都不需要把麵包板上的元件拔下來,只需要用杜邦線連接 Arduino Uno 和 麵包板上的元件。
實驗 1: 按鈕開關與LED
實驗步驟:
當你按下按鍵,發生了什麼事?
UNO 輸入輸出腳位控制
認識 if 敘述
想想看
怎樣修改程式功能變成「按鍵放開時 LED 長亮,按鍵按下時 LED 熄滅」
程式碼
資工領域特別強調軟體的操控模型
實驗步驟:
解釋與心得
關鍵在於「不要再用 delay() 這種佔著資源卻躺著什麼事都不做的函式了」,用 millis() 去檢查現在的時間,時間到了該做什麼事就做什麼事。
實驗 2: 蜂鳴器
實驗步驟:
無源蜂鳴器
無源蜂鳴器的優點是:
常用操控蜂鳴器函式
tone(腳位,頻率)
ex: tone(13,1000); //透過13腳輸出頻率1000的聲音
noTone(腳位)
ex: noTone(13); //13腳無聲
音階
來個 Do
Fa 呢? So 呢?
程式片段
寫一小段旋律吧
額、再一小段旋律???
小祕密
哈哈,哪是祕密呀!!
Google 大神
https://dragaosemchama.com/en/2019/02/songs-for-arduino/
https://github.com/robsoncouto/arduino-songs
實驗 3: 七段顯示器
實驗步驟:
七段顯示器
實際上只是 8 顆 LED 排列整齊
重要控制函式
sevenSegWrite(digit)
例如:sevenSegWrite(8); // 顯示數字 8
陣列
想要10個變數?
byte x1, x2, x3, x4, x5, x6, x7, x8, x9, x10;
你該試試「陣列」
byte x[10]; // 一行搞定
陣列有什麼功能特別強大嗎?
沒有陣列時
現在讓七段往上數
程式片段
現在讓七段只數奇數
程式片段
實驗 4: 超音波感測器
超音波感測模組 HC-SR04 操作原理
上面是發射器 (Transmitter),會發出 40 kHz 的聲波,由於這個聲波的頻率超過人類可聽見的 20 kHz,因此被稱為超音波。下面是接收器 (Receiver),可以接收超音波。它可以感測的距離為 2cm 到 400cm,感應角度為 15 度。
如上圖,Trig 腳送進至少維持 10 微秒以上的高位準訊號,便能觸發模組中的超音波發射器送出 8 個連續的 40KHz 超音波脈衝,接收器收到反射波後便會在 Echo 腳輸出一個與量測距離成正比的高位準脈衝,此高位準脈衝上緣可以看成超音波開始發射時間;而下緣則是接收到反射波的時間,所以整個高位準脈衝的寬度就是超音波往返的總時間,要特別注意的地方是被測物體最好大於 0.5 平方公尺,否則反射的聲音沒有辦法接收到,而 Trig 時間間隔最好大於 60ms,避免 Trig 與 Echo 互相干擾。
量測物體距離
實驗步驟:
倒車雷達
試試看常用到的倒車雷達,越接近時蜂鳴器越急促
距離控制音階
讓我們用距離來控制蜂鳴器的頻率
綜合實驗: 感應鬧鈴
這個實驗裡,你可以按著按鍵來增加 LED 顯示的數字,然後只要在超音波感測器前揮揮手,可以開始倒數計時或是停下蜂鳴器的聲音,試看看吧!
微觀世界的彈跳現象
這裡的按鈕有點怪?
為什麼不寫成下面這樣就好?
原因就是彈跳現象
按鈕開關按下時會在極短時間內產生多次開合現象(稱為機械彈跳)
而使用控制板偵測腳位狀態時會讀取到多次的HIGH、LOW的切換 但實際上使用者只按下一次開關,因此會造成程式錯誤 所以設計者需加入「防彈跳」(Debounce)設計來避免此現象
如果你還會有機會使用 Arduino 的話,下面的連結和小抄整理是有用的