# 元件介紹
<br>
## ESP32 腳位

<br>
## 1. LED 燈
### 1-1 基本介紹

<br>
### 1-2 參考接法
| 元件 | 長腳 | 短腳 |
| -------- | -------- | -------- |
| LED | GPIO4(麵包版右側 5) | GND |

<br>
### 1-3 參考程式碼
```cpp=
// ====== 腳位設定 ======
#define LED_PIN 17
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_PIN, HIGH); // 亮
delay(1000);
digitalWrite(LED_PIN, LOW); // 滅
delay(1000);
}
```
<br>
<br>
## 2. RGB LED
### 2-1 基本介紹

<br>
### 2-2 參考接法
| 編號 | 腳位 |
| -------- | -------- |
| 1 | GPIO25(左側 11) |
| 2 | GND |
| 3 | GPIO26(左側 10) |
| 4 | GPIO27(左側 9) |

<br>
### 2-3 參考程式碼
```cpp=
// ===== 腳位 =====
#define PIN_R 25
#define PIN_G 26
#define PIN_B 27
void setup() {
pinMode(PIN_R, OUTPUT);
pinMode(PIN_G, OUTPUT);
pinMode(PIN_B, OUTPUT);
}
void loop() {
// 紅
digitalWrite(PIN_R, HIGH);
digitalWrite(PIN_G, LOW);
digitalWrite(PIN_B, LOW);
delay(1000);
// 綠
digitalWrite(PIN_R, LOW);
digitalWrite(PIN_G, HIGH);
digitalWrite(PIN_B, LOW);
delay(1000);
// 藍
digitalWrite(PIN_R, LOW);
digitalWrite(PIN_G, LOW);
digitalWrite(PIN_B, HIGH);
delay(1000);
// 白(RGB 全亮)
digitalWrite(PIN_R, HIGH);
digitalWrite(PIN_G, HIGH);
digitalWrite(PIN_B, HIGH);
delay(1000);
// 全關
digitalWrite(PIN_R, LOW);
digitalWrite(PIN_G, LOW);
digitalWrite(PIN_B, LOW);
delay(1000);
}
```
:::spoiler 調色版
```cpp=
// ===== 腳位 =====
#define PIN_R 25
#define PIN_G 26
#define PIN_B 27
void setup() {
// ledcAttach(腳位, 頻率, 解析度)
ledcAttach(PIN_R, 5000, 8);
ledcAttach(PIN_G, 5000, 8);
ledcAttach(PIN_B, 5000, 8);
}
void setColor(int r, int g, int b) {
// ledcWrite(腳位, 數值)
ledcWrite(PIN_R, r);
ledcWrite(PIN_G, g);
ledcWrite(PIN_B, b);
}
void loop() {
setColor(255, 0, 0); // 紅
delay(1000);
setColor(0, 255, 0); // 綠
delay(1000);
setColor(0, 0, 255); // 藍
delay(1000);
setColor(255, 255, 0); // 黃
delay(1000);
setColor(0, 255, 255); // 青
delay(1000);
setColor(255, 0, 255); // 紫
delay(1000);
setColor(255, 255, 255); // 白
delay(1000);
setColor(0, 0, 0); // 關
delay(1000);
}
```
:::
:::spoiler 漸變版
```cpp=
// ===== 腳位 =====
#define PIN_R 25
#define PIN_G 26
#define PIN_B 27
void setup() {
// ledcAttach(腳位, 頻率, 解析度)
ledcAttach(PIN_R, 5000, 8);
ledcAttach(PIN_G, 5000, 8);
ledcAttach(PIN_B, 5000, 8);
}
void setColor(int r, int g, int b) {
// ledcWrite(腳位, 數值)
ledcWrite(PIN_R, r);
ledcWrite(PIN_G, g);
ledcWrite(PIN_B, b);
}
void loop() {
for (int i = 0; i <= 255; i++) {
setColor(i, 0, 255 - i); // 紅 → 藍 漸變
delay(10);
}
}
```
:::
<br>
<br>
## 3. 蜂鳴器(無源)
### 3-1 基本介紹

### 3-2 參考接法
| 元件 | + | - |
| -------- | -------- | -------- |
| 蜂鳴器 | GPIO18(右側 11) | GND |

<br>
### 3-3 參考程式碼
```cpp=
// ===== 腳位 =====
#define BUZZER_PIN 18
void setup() {
ledcAttach(BUZZER_PIN, 2000, 8); // 2kHz, 8-bit
}
void loop() {
// 發聲
ledcWrite(BUZZER_PIN, 128); // 50% duty
delay(1000);
// 停止
ledcWrite(BUZZER_PIN, 0);
delay(1000);
}
```
:::spoiler 音調版
```cpp=
// ===== 腳位 =====
#define BUZZER_PIN 18
void setup() {
// 初始化腳位
ledcAttach(BUZZER_PIN, 2000, 8); // 2kHz, 8-bit
}
void playTone(int freq, int duration) {
// ledcWriteTone(腳位, 頻率)
ledcWriteTone(BUZZER_PIN, freq); // 50% duty
delay(duration);
// 停止發聲
ledcWriteTone(BUZZER_PIN, 0);
}
void loop() {
playTone(523, 300); // Do
playTone(587, 300); // Re
playTone(659, 300); // Mi
playTone(698, 300); // Fa
playTone(784, 300); // Sol
delay(1000);
}
```
:::
<br>
<br>
## 4. 溫濕度感測器(DHT11)
### 4-1 基本介紹

### 4-2 下載函式庫
```
DHT sensor library
```

<br>
### 4-3 參考接法
| 元件 | DATA | VCC | GND |
| -------- | -------- | -------- | -------- |
| DHT11 | GPIO17(右側 9) | 3.3V | GND |

<br>
### 4-4 參考程式碼
```cpp=
#include <DHT.h>
DHT dht(17, DHT11);
void setup() {
Serial.begin(115200);
dht.begin(); // 初始化 DHT 感測器
Serial.println("DHT11 Sensor Start");
}
void loop() {
float humidity = dht.readHumidity(); // 讀取濕度
float temperature = dht.readTemperature(); // 讀取溫度(攝氏)
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Failed to read from DHT sensor");
delay(2000);
return;
}
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.print(" % | ");
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" °C");
delay(2000); // 2 秒讀一次
}
```
<br>
<br>
## 5. LCD 螢幕(1602 LCD I2C)
### 5-1 基本介紹

<br>
### 5-2 下載函式庫
```
LiquidCrystal_I2C
```

<br>
### 5-3 參考接法
| 元件 | SDA | SCL | VCC | GND |
| -------- | -------- | -------- | -------- | -------- |
| 1602 LCD(I2C) | GPIO21(右側 14) | GPIO22(右側 17) | 5V | GND |

<br>
### 5-4 參考程式碼
```cpp=
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// ====== LCD 設定 ======
#define LCD_ADDRESS 0x27 // 常見位址:0x27 或 0x3F
#define LCD_COLS 16
#define LCD_ROWS 2
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLS, LCD_ROWS);
void setup() {
Wire.begin(21, 22); // ESP32 I2C 腳位
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Hello ESP32");
lcd.setCursor(0, 1);
lcd.print("I2C LCD Ready");
}
void loop() {
// 這個範例不需要 loop
}
```
<br>
<br>
## 6. 火焰傳感器(KY-026)
### 6-1 基本介紹

:::info
DO:判斷「**有沒有火焰**」
AO:讀取「**火焰強度數值**」
:::
<br>
### 6-2 參考接法
| 元件 | DO | AO | VCC | GND |
| -------- | -------- | -------- | -------- | -------- |
| KY-026 | GPIO16 (右側 8) | GPIO34(左側 15) | 3.3V | GND |

<br>
### 6-3 參考程式碼
```cpp=
// ====== 腳位設定 ======
#define FLAME_DO 16 // 數位輸出 DO
#define FLAME_AO 34 // 類比輸出 AO(ADC 腳位)
void setup() {
Serial.begin(115200);
pinMode(FLAME_DO, INPUT);
Serial.println("KY-026 A0 + D0 Test Start");
}
void loop() {
int digitalState = digitalRead(FLAME_DO); // DO:有沒有火
int analogValue = analogRead(FLAME_AO); // AO:火焰強度
// 顯示數值
Serial.print("AO Value: ");
Serial.print(analogValue);
Serial.print(" | DO State: ");
if (digitalState == LOW) {
Serial.println("Flame Detected");
} else {
Serial.println("No Flame");
}
delay(300);
}
```
<br>
<br>
## 7. 紅外線感測器(HW-416)
### 7-1 基本介紹

:::info
Delay set 0.3s to 5 min:**維持時間**
Sensitivity set up 7 m:**感測距離**
:::
<br>
### 7-2 參考接法
| 元件 | OUT | VCC | GND |
| -------- | -------- | -------- | -------- |
| KY-026 | GPIO27 (左側 9) | 5V | GND |

<br>
### 7-3 參考程式碼
```cpp=
// ====== 腳位設定 ======
#define PIR_PIN 27 // OUT 接在 GPIO27
void setup() {
Serial.begin(115200);
pinMode(PIR_PIN, INPUT);
Serial.println("PIR Motion Sensor Start");
}
void loop() {
int motion = digitalRead(PIR_PIN);
if (motion == HIGH) {
Serial.println("🚶 Motion Detected");
} else {
Serial.println("No Motion");
}
delay(300);
}
```
<br>
<br>
## 8. 觸碰感測器(HW-139)
### 8-1 基本介紹

<br>
### 8-2 參考接法
| 元件 | SIG | VCC | GND |
| -------- | -------- | -------- | -------- |
| HW-139 | GPIO25 (左側 11) | 3.3V | GND |

<br>
### 8-3 參考程式碼
```cpp=
// ====== 腳位設定 ======
#define TOUCH_PIN 25 // SIG 接在 GPIO25
void setup() {
Serial.begin(115200);
pinMode(TOUCH_PIN, INPUT);
Serial.println("KY-036 Touch Sensor Start");
}
void loop() {
int state = digitalRead(TOUCH_PIN);
if (state == HIGH) {
Serial.println("Touch Detected");
} else {
Serial.println("No Touch");
}
delay(200);
}
```
<br>
<br>
## 9. 氣體感測器(MQ-2)
### 9-1 基本介紹

<br>
### 9-2 參考接法
| 元件 | DO | AO | VCC | GND |
| -------- | -------- | -------- | -------- | -------- |
| MQ-2 | GPIO16 (右側 8) | GPIO34(左側 15) | 5V | GND |

<br>
### 9-3 參考程式碼
```cpp=
// ====== 腳位設定 ======
#define MQ2_AO 34 // 類比輸出
#define MQ2_DO 16 // 數位輸出
void setup() {
Serial.begin(115200);
pinMode(MQ2_DO, INPUT);
Serial.println("MQ-2 Gas Sensor Start");
}
void loop() {
int gasValue = analogRead(MQ2_AO); // 氣體濃度
int gasAlarm = digitalRead(MQ2_DO); // 是否超標
Serial.print("AO Value: ");
Serial.print(gasValue);
Serial.print(" | DO State: ");
if (gasAlarm == LOW) {
Serial.println("Gas Detected");
} else {
Serial.println("Normal");
}
delay(500);
}
```
<br>
<br>
## 10. 超音波感測器(HC-SR04)
### 10-1 基本介紹

<br>
### 10-2 參考接法
| 元件 | Trig | Echo | VCC | GND |
| -------- | -------- | -------- | -------- | -------- |
| KY-026 | GPIO26 (左側 10) | GPIO25(左側 11) | 5V | GND |

<br>
### 10-3 參考程式碼
```cpp=
// ====== 腳位設定 ======
#define TRIG_PIN 26
#define ECHO_PIN 25
void setup() {
Serial.begin(115200);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
Serial.println("HC-SR04 Start");
}
void loop() {
// 發送超音波
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// 讀取回波時間(微秒)
long duration = pulseIn(ECHO_PIN, HIGH, 30000); // 30ms timeout
// 距離計算(cm)
float distance = duration * 0.034 / 2;
if (duration == 0) {
Serial.println("Out of range");
} else {
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
}
delay(500);
}
```
<br>
<br>
## 11. 光敏電阻模組(LM393)
### 11-1 基本介紹

<br>
### 11-2 參考接法
| 元件 | DO | AO | VCC | GND |
| -------- | -------- | -------- | -------- | -------- |
| LM393 | GPIO16 (右側 8) | GPIO34(左側 15) | 5V | GND |

<br>
### 11-3 參考程式碼
```cpp=
// ====== 腳位設定 ======
#define LIGHT_AO 34 // 類比亮度
#define LIGHT_DO 16 // 數位判斷
void setup() {
Serial.begin(115200);
pinMode(LIGHT_DO, INPUT);
Serial.println("Photoresistor Sensor Start");
}
void loop() {
int lightValue = analogRead(LIGHT_AO); // 亮度數值
int lightState = digitalRead(LIGHT_DO); // 亮 / 暗判斷
Serial.print("AO Value: ");
Serial.print(lightValue);
Serial.print(" | DO State: ");
if (lightState == LOW) {
Serial.println("Bright / Triggered");
} else {
Serial.println("Dark / Normal");
}
delay(300);
}
```
<br>
<br>
## 12. 震動感測器(SW-420)
### 12-1 基本介紹

<br>
### 12-2 參考接法
| 元件 | DO | VCC | GND |
| -------- | -------- | -------- | -------- |
| HW-139 | GPIO16 (右側 8) | 3.3V | GND |

<br>
### 12-3 參考程式碼
```cpp=
// ====== 腳位設定 ======
#define VIB_PIN 16 // DO 接在 GPIO16
void setup() {
Serial.begin(115200);
pinMode(VIB_PIN, INPUT);
Serial.println("SW-420 Vibration Sensor Start");
}
void loop() {
int state = digitalRead(VIB_PIN);
if (state == LOW) {
Serial.println("Vibration Detected");
} else {
Serial.println("No Vibration");
}
delay(200);
}
```
<br>
<br>
## 13. 水位感測器(HW-038)
### 13-1 基本介紹

<br>
### 13-2 參考接法
| 元件 | AO | VCC | GND |
| -------- | -------- | -------- | -------- |
| HW-038 | GPIO34 (左側 15) | 3.3V | GND |

<br>
### 13-3 參考程式碼
```cpp=
// ====== 腳位設定 ======
#define WATER_PIN 34 // AO 接在 GPIO34
void setup() {
Serial.begin(115200);
Serial.println("HW-038 Water Level Sensor Start");
}
void loop() {
int waterValue = analogRead(WATER_PIN);
Serial.print("Water Level Value: ");
Serial.println(waterValue);
delay(500);
}
```
<br>
<br>
## 14. 繼電器模組(HW-482)
### 14-1 基本介紹

:::info
NO:平常斷開,啟動才接通
NC:平常接通,啟動才斷開
:::
<br>
### 14-2 參考接法
| 元件 | IN | VCC | GND |
| -------- | -------- | -------- | -------- |
| HW-482 | GPIO17 (右側 9) | 5V | GND |
#### 繼電器關閉想通電
| NC | COM | NO |
| -------- | -------- | -------- |
| VCC | 白線 | X |
#### 繼電器開啟想通電
| NC | COM | NO |
| -------- | -------- | -------- |
| X | 白線 | VCC |
:::info
**黑線都接 GND**
:::

<br>
### 14-3 參考程式碼
```cpp=
// ====== 腳位設定 ======
#define RELAY_PIN 17 // IN 接在 GPIO17
void setup() {
pinMode(RELAY_PIN, OUTPUT);
// 預設關閉
digitalWrite(RELAY_PIN, LOW);
}
void loop() {
// 開啟繼電器
digitalWrite(RELAY_PIN, HIGH);
delay(2000);
// 關閉繼電器
digitalWrite(RELAY_PIN, LOW);
delay(2000);
}
```
<br>
<br>
## 15. 土壤感測器(HW-103 × 080)
### 15-1 基本介紹

<br>
### 15-2 參考接法
| 元件 | DO | AO | VCC | GND |
| -------- | -------- | -------- | -------- | -------- |
| HW-103 | GPIO16 (右側 8) | GPIO34(左側 15) | 5V | GND |

<br>
### 15-3 參考程式碼
```cpp=
// ===== 腳位 =====
#define SOIL_AO 34
#define SOIL_DO 27
// 你一定要自己量一次再填:
// 空氣中(乾) 的 analogRead 值通常比較大
// 濕土中(濕) 的 analogRead 值通常比較小
int DRY_RAW = 3000; // 乾值:探針在空氣中
int WET_RAW = 1200; // 濕值:探針插在完全濕的土
int rawToPercent(int raw) {
// 0% = 乾、100% = 濕
int p = map(raw, DRY_RAW, WET_RAW, 0, 100);
return constrain(p, 0, 100);
}
void setup() {
Serial.begin(115200);
pinMode(SOIL_DO, INPUT);
// ESP32 ADC 設定(可選但建議)
analogReadResolution(12); // 0~4095
analogSetPinAttenuation(SOIL_AO, ADC_11db); // 量測範圍較大,讀值更穩
}
void loop() {
int aoRaw = analogRead(SOIL_AO); // 0~4095
int aoPct = rawToPercent(aoRaw); // 0~100%
int doVal = digitalRead(SOIL_DO); // 0/1,門檻由電位器決定
// 多數這類模組:DO 的 LED 標示「低電平亮」
// 所以 doVal==0 常表示「達到你設定的濕度門檻」(但以你調的為準)
Serial.print("AO_raw=");
Serial.print(aoRaw);
Serial.print(" AO%=");
Serial.print(aoPct);
Serial.print("% DO=");
Serial.print(doVal);
Serial.print(" DO_meaning=");
Serial.println(doVal == 0 ? "TRIGGER(<=threshold)" : "NOT_TRIGGER(>threshold)");
delay(500);
}
```
<br>
<br>
## 16. 伺服馬達(SG90)
### 16-1 基本介紹

<br>
### 16-2 下載函式庫
```
ESP32Servo
```
<br>
### 16-3 參考接法
| 元件 | Control | VCC | GND |
| -------- | -------- | -------- | -------- |
| SG90 | GPIO18 (右側 11) | 5V | GND |
<br>
### 16-4 參考程式碼
```cpp=
#include <ESP32Servo.h>
#define SERVO_PIN 18
Servo myServo;
void setup() {
myServo.attach(SERVO_PIN, 500, 2400);
}
void loop() {
myServo.write(0); // 轉到 0°
delay(1000);
myServo.write(90); // 轉到 90°
delay(1000);
myServo.write(180); // 轉到 180°
delay(1000);
}
```
<br>
<br>
## 其他章節
**上一篇:[ESP32 × AIOT](https://hackmd.io/@BeiDesign/ESP32×AIOT)**
**下一篇:[通知與 AI 應用](https://hackmd.io/@BeiDesign/Notifications_AI)**