前置知識
之前提到,ESP32 有分很多種系列,
而 ESP32-C3 是 C 系列的其中一個型號。
因為這次用的是 C3,在上一篇文設定開發版的地方,
開發板類型記得選 ESP32C3 Dev Module
。
你需要先設定好 Arduino IDE 才能繼續往下喔。 看看上一篇文寫的設定方法吧。 關於 Arduino 程式的基本運作,也請看看上一篇文的介紹。
關於我們的 ESP32-C3
(上面文檔的板子和我們的不大一樣,因為我們的 C3 是雙 USB Type-C 的,但大部分資訊應該沒有差很多)
這邊我寫幾個有趣的點:
- 板子上的 LED 是 RGB 的
- 它支援 WiFi、藍芽
- 上面有好多電源和接地針腳
Pinout (針腳定位)
來看看我們手上這塊板子的針腳。
可以看到我們有 3V3
(3.3V) 和 5V0
(5V) 但針腳各兩個、還有好幾個接地、剩餘的都是 GPIO ,
也就是我們可以自由運用的輸入 / 輸出針腳。
Blink,開發板界的你好世界
拿到新板子,還是來 Blink 一下,測試設定有沒有問題、板子能不能正常運作吧。
在「File > Examples > 01.Basics > Blink」,找到 Blink 的範例程式:
/*
Blink
...
*/
// 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
}
這次因為 ESP32C3 Dev Module 已經有定義好 LED_BUILTIN
的值,
所以不用再自己 #define
。
因為 C3 上的 LED 是 RGB 的,所以我們甚至可以指定顏色——打開「File > Examples > ESP32 > GPIO > BlinkRGB」:
/*
BlinkRGB
...
*/
//#define RGB_BRIGHTNESS 64 // Change white brightness (max 255)
// the setup function runs once when you press reset or power the board
void setup() {
// No need to initialize the RGB LED
}
// the loop function runs over and over again forever
void loop() {
#ifdef RGB_BUILTIN
digitalWrite(RGB_BUILTIN, HIGH); // Turn the RGB LED white
delay(1000);
digitalWrite(RGB_BUILTIN, LOW); // Turn the RGB LED off
delay(1000);
neopixelWrite(RGB_BUILTIN,RGB_BRIGHTNESS,0,0); // Red
delay(1000);
neopixelWrite(RGB_BUILTIN,0,RGB_BRIGHTNESS,0); // Green
delay(1000);
neopixelWrite(RGB_BUILTIN,0,0,RGB_BRIGHTNESS); // Blue
delay(1000);
neopixelWrite(RGB_BUILTIN,0,0,0); // Off / black
delay(1000);
#endif
}
成品:空氣鋼琴
新增專案,我們來做個真正的成品吧。來看看這是什麼:
它的組成其實很簡單:
- 距離感測器
- 發聲器官
- 一堆
if
判斷。
超音波測距
參考:https://shop.mirotek.com.tw/iot/esp32-start-10/
簡單來講,給 TRIG pin 一個訊號(10 微秒的 HIGH
),他就會發射超音播進行測距,
期間 ECHO pin 會給一個訊號代表超音波來回的時間,接著就能在程式裡運用這段時間、計算距離了。
然後有佬幫算完 ECHO pin 的回傳時間除以 58
就是公分的距離了。
使用範例
修改自 https://shop.mirotek.com.tw/iot/esp32-start-10/
接線:
#define TRIG_PIN 3 // 發出觸發訊號腳位
#define ECHO_PIN 2 // 接收測量結果訊號腳位
void setup() {
pinMode(TRIG_PIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
unsigned long d = ping() / 58; // 計算距離
Serial.print(d);
Serial.println("cm");
delay(1000);
}
unsigned long ping() {
digitalWrite(TRIG_PIN, HIGH); // 啟動超音波
delayMicroseconds(10); // 維持 10 微秒的 HIGH 訊號
digitalWrite(TRIG_PIN, LOW); // 關閉超音波
return pulseIn(ECHO_PIN, HIGH); // 計算傳回時間
}
蜂鳴器
這邊先介紹一些觀念:
-
PWM 就是像這樣的一高一低的訊號,同時可以控制 工作週期(Duty Cycle)(寬度?)、 頻率(Frequency),送出不同的資訊。不過在這邊頻率的調整對我們比較重要。
音調
大家都知道,音調的高低是用頻率控制的。
Google 一下,我們就找得到各音階的頻率了。
發送訊號
接線:
我們可以用 Arduino 內建的 tone()
函式,直接控制發出 PWM 訊號。
tone(PIN, 262);
tone(PIN, 262, 200);
// tone(PIN, FREQUENCY [, DURATION(ms)])
// tone(針腳, 頻率 [, 時間(毫秒)])
noTone(PIN);
// 停止 `tone()` 函式開始的訊號。
// 因為 `tone()` 函式呼叫後會在程式運行的同時持續發送訊號,
// 如果你沒有指定時間(DURATION),你就需要 `noTone()` 停止這個訊號。
當然,還有其他送出 PWM 訊號的方法(tone()
完全就是為了發出聲音才存在的啊),
像是 analogWrite()
(只能改變工作週期)、ledc
等。
停止聲音
剛剛講了 noTone()
可以讓 tone()
的訊號停止,不過你可能會發現,
呼叫了 tone()
之後蜂鳴器的聲音還是繼續在播放,為什麼呢?
仔細看到 MH-FMD 板子上:
可以看到「低電平觸發」的字樣。
所以,在訊號停止後,蜂鳴器收到的 LOW
訊號(0 伏特,也就是沒有訊號)反而會讓它繼續發聲!
既然如此,那我們就用 HIGH
訊號讓他停止:
digitalWrite(PIN, HIGH);
雖然這會讓蜂鳴器停止,但如果你沒有先呼叫 noTone()
, tone()
的訊號可能還是會持續發送直到指定的時間。
組合你的零件
我們的目標是讓距離在不同地方時發出的聲音不同,所以只要把剛剛兩個零件結合, 搭配程式碼,就可以完成啦!
先把兩個零件都接上:
再來想想:
既然我們的目標是在不同的感測距離,讓蜂鳴器發出不同聲音, 那麼我們就修改既有的距離感測的程式,讓它在不同的距離下發送不同的訊號不就行了?
#define TRIG_PIN 3 // 發出觸發訊號腳位
#define ECHO_PIN 2 // 接收測量結果訊號腳位
#define BUZZER_PIN 10 // 發出蜂鳴器訊號的腳位
void setup() {
pinMode(TRIG_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
unsigned long d = ping() / 58; // 計算距離
Serial.print(d);
Serial.println("cm");
delay(200);
if (d <= 5) { // 小於等於 5 公分
tone(BUZZER_PIN, 262); // 262 Hz 是中央 Do
} else if (d <= 10) {
tone(BUZZER_PIN, 294);
} else if (d <= 15) {
tone(BUZZER_PIN, 330);
} else {
noTone(BUZZER_PIN);
// digitalWrite(BUZZER_PIN, HIGH);
}
}
unsigned long ping() {
digitalWrite(TRIG_PIN, HIGH); // 啟動超音波
delayMicroseconds(10); // 維持 10 微秒的 HIGH 訊號
digitalWrite(TRIG_PIN, LOW); // 關閉超音波
return pulseIn(ECHO_PIN, HIGH); // 計算傳回時間
}
如果你用的是 MH-FMD 板子,因為「低電平觸發」的關係,
你需要在 noTone()
之後再加 digitalWrite(PIN, HIGH)
讓它停止!
當然,這邊只會在 5 公分內、10 公分內、15 公分內分別發出中央 Do、Re、Mi 的音, 剩下的音就讓你們自由發揮了!