ESP32 튜토리얼 50/55 - 전 세계 어디서나 RGB LED 제어하기 | SunFounder의 ESP32 키트
이 튜토리얼에서는 MQTT 프로토콜과 Adafruit IO 서비스를 활용하여 ESP32 마이크로컨트롤러를 통해 Wi-Fi로 RGB LED의 색상을 제어하는 방법을 배웁니다. 이 설정을 통해 전 세계 어디서나 RGB LED의 색상을 변경할 수 있으며, IoT 기술의 실용적인 응용 사례를 제공합니다. 또한 슬라이더와 색상 선택기를 사용하여 원하는 색상을 선택하는 방법도 살펴보겠습니다.

ESP32는 Wi-Fi와 Bluetooth 기능이 내장된 강력한 마이크로컨트롤러로, IoT 프로젝트에 이상적입니다. 이 빌드에서는 RGB LED를 ESP32에 연결하고 Adafruit에서 제공하는 MQTT 브로커를 통해 색상을 제어합니다. 튜토리얼은 하드웨어 설정, 배선 지침, 그리고 모든 것이 원활하게 작동하도록 하는 데 필요한 코드를 안내합니다(비디오 00:00에서).
하드웨어 설명
이 프로젝트에서 사용할 주요 구성 요소는 ESP32 마이크로컨트롤러와 RGB LED입니다. ESP32는 Wi-Fi 네트워크에 연결할 수 있어 Adafruit IO 서비스와 통신할 수 있습니다. RGB LED에는 빨간색, 녹색, 파란색의 세 가지 개별 LED가 포함되어 있으며, 이를 혼합하여 다양한 색상을 만들 수 있습니다.
RGB LED는 공통 애노드 또는 공통 캐소드 원리로 작동하며, 이는 개별 LED의 애노드(양극) 또는 캐소드(음극)가 제대로 작동하려면 올바르게 연결되어야 함을 의미합니다. 각 색상은 듀티 사이클을 변화시켜 각 LED의 밝기를 조정하는 펄스 폭 변조(PWM)를 사용하여 제어할 수 있습니다.
데이터시트 세부 정보
| 제조업체 | SunFounder |
|---|---|
| 부품 번호 | RGB LED |
| 순방향 전압 (VF) | 2.0–3.4 V |
| 순방향 전류 (IF) | 20 mA |
| 피크 파장 (nm) | 빨간색: 620, 녹색: 525, 파란색: 465 |
| 패키지 | 표준 4핀 |
| 참고 사항 / 변형 | 공통 애노드 또는 공통 캐소드 옵션 사용 가능 |
- 각 LED 색상에 220옴 저항을 사용하여 전류를 제한하세요.
- 공통 애노드 또는 캐소드 구성에 맞는 올바른 배선을 확인하세요.
- 브라운아웃을 방지하기 위해 ESP32의 전원 공급을 확인하세요.
- 부드러운 색상 전환을 위해 PWM 주파수를 한도 내에서 유지하세요.
- Adafruit IO 서비스에 연결하려면 Wi-Fi 자격 증명이 올바른지 확인하세요.
배선 지침

RGB LED를 ESP32에 배선하려면 먼저 RGB LED의 핀을 식별하세요. 가장 긴 핀이 공통 핀입니다. 공통 애노드 구성의 경우 이 핀을 양전압 공급부(3.3V)에 연결합니다. 나머지 세 개의 핀은 빨간색, 녹색, 파란색 LED에 해당합니다. 빨간색 핀을 GPIO 27에, 녹색 핀을 GPIO 26에, 파란색 핀을 GPIO 25에 연결하세요. 각 연결은 LED를 통해 흐르는 전류를 제한하기 위해 220옴 저항을 통해 이루어져야 합니다.
다음으로 ESP32의 접지(GND)를 회로의 접지선에 연결하세요. 간헐적인 연결을 방지하기 위해 배선이 안전한지 확인하세요. 공통 캐소드 RGB LED를 사용하는 경우 공통 핀을 접지에 연결하고 개별 색상 핀을 저항을 통해 양전원에 연결하세요. 회로에 전원을 공급하기 전에 모든 연결을 다시 확인하세요.
코드 예제 및 설명
Arduino 코드에서는 redPin, greenPin, bluePin 식별자를 사용하여 빨간색, 녹색, 파란색 LED의 핀을 정의하는 것으로 시작합니다. 또한 redChannel, greenChannel, blueChannel을 사용하여 각 색상의 PWM 채널을 정의합니다. PWM 주파수는 8비트 해상도로 5000Hz로 설정됩니다.
const int redPin = 27;
const int greenPin = 26;
const int bluePin = 25;
const int redChannel = 0;
const int greenChannel = 1;
const int blueChannel = 2;
setup() 함수에서는 PWM 채널을 초기화하고 해당 핀을 연결합니다. 또한 정의된 자격 증명을 사용하여 Wi-Fi 네트워크에 연결하고 Adafruit IO와 통신하기 위한 MQTT 클라이언트를 설정합니다.
void setup() {
ledcSetup(redChannel, freq, resolution);
ledcAttachPin(redPin, redChannel);
// WiFi 연결
WiFi.begin(WLAN_SSID, WLAN_PASS);
}
메인 루프는 MQTT 연결을 확인하고 수신된 메시지를 처리합니다. 또한 현재 RGB 값을 시리얼 모니터에 출력합니다. LED의 색상은 MQTT 구독을 통해 수신된 값에 따라 업데이트됩니다.
void loop() {
MQTT_connect();
mqtt.processPackets(500);
setColor();
}
전체 코드에 대한 자세한 내용은 기사 아래에 로드된 전체 코드를 참조하세요.
시연 / 기대 효과
모든 것이 설정되고 코드가 업로드되면, Adafruit IO 대시보드를 통해 변경한 색상에 RGB LED가 반응하는 것을 볼 수 있습니다. 빨간색, 초록색, 파란색 슬라이더를 조정하면 LED의 색상이 그에 맞게 변경되어야 합니다. 문제가 발생하는 경우, Wi-Fi 연결이 안정적인지, MQTT 토픽 이름이 코드에 정의된 것과 일치하는지 확인하세요(비디오 17:30 참조).
흔한 실수로는 잘못된 배선, 일치하지 않는 토픽 이름, 올바른 Wi-Fi 자격 증명 설정을 잊는 것이 있습니다. LED가 켜지지 않으면 저항 연결을 다시 확인하고 ESP32가 올바르게 전원이 공급되는지 확인하세요.
비디오 타임스탬프
- 00:00 시작
- 2:23 프로젝트 소개
- 4:43 MQTT란 무엇인가
- 7:55 Adafruit IO 설정
- 14:09 배선 설명
- 16:07 코드 설명
- 27:03 Arduino IDE에서 ESP32 보드 및 COM 포트 선택
- 29:12 프로젝트 시연
- 31:25 RGB LED란 무엇인가?
- 35:26 RGB 색상
/***********************************************************************
This is Arduino sketch for ESP32 to control RGB LED using MQTT service of Adafruit
video instruction https://youtu.be/-9q1GfGsnr0
📚⬇️ Download and resource page https://robojax.com/RJT672
Written By Ahamd Shamshiri
on Feb 18, 2024
Adafruit MQTT Library ESP32 Adafruit IO SSL/TLS example
/// ref: https://www.electronicwings.com/esp32/esp32-mqtt-client
*/
// Define RGB LED pins
const int redPin = 27;
const int greenPin = 26;
const int bluePin = 25;
// Define PWM channels
const int redChannel = 0;
const int greenChannel = 1;
const int blueChannel = 2;
// Define PWM frequency and resolution
const int freq = 5000;
const int resolution = 8;
int colorR, colorG, colorB;
#include <WiFi.h>
#include "WiFiClientSecure.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
/************************* WiFi Access Point *********************************/
#define WLAN_SSID "Book"
#define WLAN_PASS "888-888"
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "io.adafruit.com"
// Using port 8883 for MQTTS
#define AIO_SERVERPORT 8883
// Adafruit IO Account Configuration
// (to obtain these values, visit https://io.adafruit.com and click on Active Key)
// #define AIO_USERNAME "YOUR_ADAFRUIT_IO_USERNAME"
// #define AIO_KEY "YOUR_ADAFRUIT_IO_KEY"
#define AIO_USERNAME "robojax"
#define AIO_KEY "aio_NBQQ75Rn7liRNcRn5uGUBMsBYmjD"
/************ Global State (you don't need to change this!) ******************/
// WiFiFlientSecure for SSL/TLS support
WiFiClientSecure client;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
// io.adafruit.com root CA
const char* adafruitio_root_ca = \
"-----BEGIN CERTIFICATE-----\n"
"MIIEjTCCA3WgAwIBAgIQDQd4KhM/xvmlcpbhMf/ReTANBgkqhkiG9w0BAQsFADBh\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n"
"MjAeFw0xNzExMDIxMjIzMzdaFw0yNzExMDIxMjIzMzdaMGAxCzAJBgNVBAYTAlVT\n"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
"b20xHzAdBgNVBAMTFkdlb1RydXN0IFRMUyBSU0EgQ0EgRzEwggEiMA0GCSqGSIb3\n"
"DQEBAQUAA4IBDwAwggEKAoIBAQC+F+jsvikKy/65LWEx/TMkCDIuWegh1Ngwvm4Q\n"
"yISgP7oU5d79eoySG3vOhC3w/3jEMuipoH1fBtp7m0tTpsYbAhch4XA7rfuD6whU\n"
"gajeErLVxoiWMPkC/DnUvbgi74BJmdBiuGHQSd7LwsuXpTEGG9fYXcbTVN5SATYq\n"
"DfbexbYxTMwVJWoVb6lrBEgM3gBBqiiAiy800xu1Nq07JdCIQkBsNpFtZbIZhsDS\n"
"fzlGWP4wEmBQ3O67c+ZXkFr2DcrXBEtHam80Gp2SNhou2U5U7UesDL/xgLK6/0d7\n"
"6TnEVMSUVJkZ8VeZr+IUIlvoLrtjLbqugb0T3OYXW+CQU0kBAgMBAAGjggFAMIIB\n"
"PDAdBgNVHQ4EFgQUlE/UXYvkpOKmgP792PkA76O+AlcwHwYDVR0jBBgwFoAUTiJU\n"
"IBiV5uNu5g/6+rkS7QYXjzkwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsG\n"
"AQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMDQGCCsGAQUFBwEB\n"
"BCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEIGA1Ud\n"
"HwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEds\n"
"b2JhbFJvb3RHMi5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEW\n"
"HGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwDQYJKoZIhvcNAQELBQADggEB\n"
"AIIcBDqC6cWpyGUSXAjjAcYwsK4iiGF7KweG97i1RJz1kwZhRoo6orU1JtBYnjzB\n"
"c4+/sXmnHJk3mlPyL1xuIAt9sMeC7+vreRIF5wFBC0MCN5sbHwhNN1JzKbifNeP5\n"
"ozpZdQFmkCo+neBiKR6HqIA+LMTMCMMuv2khGGuPHmtDze4GmEGZtYLyF8EQpa5Y\n"
"jPuV6k2Cr/N3XxFpT3hRpt/3usU/Zb9wfKPtWpoznZ4/44c1p9rzFcZYrWkj3A+7\n"
"TNBJE0GmP2fhXhP1D/XVfIW/h0yCJGEiV9Glm/uGOa3DXHlmbAcxSyCRraG+ZBkA\n"
"7h4SeM6Y8l/7MBRpPCz6l8Y=\n"
"-----END CERTIFICATE-----\n";
/****************************** Feeds ***************************************/
// Setup a feed called 'test' for publishing and 'test2' for subscription.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Subscribe COLOR_R = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/rgb-led-color.red");
Adafruit_MQTT_Subscribe COLOR_G = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/rgb-led-color.green");
Adafruit_MQTT_Subscribe COLOR_B = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/rgb-led-color.blue");
Adafruit_MQTT_Subscribe COLOR_RGB = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/color-picker");
/*************************** Sketch Code ************************************/
void setup() {
// Set up PWM channels
ledcSetup(redChannel, freq, resolution);
ledcSetup(greenChannel, freq, resolution);
ledcSetup(blueChannel, freq, resolution);
// Attach pins to corresponding PWM channels
ledcAttachPin(redPin, redChannel);
ledcAttachPin(greenPin, greenChannel);
ledcAttachPin(bluePin, blueChannel);
Serial.begin(115200);
delay(10);
Serial.println(F("Adafruit IO MQTTS (SSL/TLS) Example"));
// Connect to WiFi access point.
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
delay(1000);
WiFi.begin(WLAN_SSID, WLAN_PASS);
delay(2000);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Set Adafruit IO's root CA
client.setCACert(adafruitio_root_ca);
// register callback for feed
COLOR_R.setCallback(color_R_Callback);
// Setup MQTT subscription for time feed.
mqtt.subscribe(&COLOR_R);
// register callback for feed
COLOR_G.setCallback(color_G_Callback);
// Setup MQTT subscription for time feed.
mqtt.subscribe(&COLOR_G);
// register callback for feed
COLOR_B.setCallback(color_B_Callback);
// Setup MQTT subscription for time feed.
mqtt.subscribe(&COLOR_B);
// register callback for feed
COLOR_RGB.setCallback(color_RGB_Callback);
// Setup MQTT subscription for time feed.
mqtt.subscribe(&COLOR_RGB);
}
// uint32_t x=0;
void loop() {
// Ensure the connection to the MQTT server is alive (this will make the first
// connection and automatically reconnect when disconnected). See the MQTT_connect
// function definition further below.
MQTT_connect();
Serial.print("R: ");
Serial.print (colorR);
Serial.print(" G: ");
Serial.print (colorG);
Serial.print(" B: ");
Serial.println(colorB);
// wait 0.5 seconds for subscription messages
mqtt.processPackets(500);
setColor();
// wait a couple seconds to avoid rate limit
//delay(2000);
}
void color_R_Callback(char* message, uint16_t len) {
char messageBuffer[40];
//snprintf(messageBuffer, sizeof(messageBuffer), "Color status is :: %s, len :: %u", message, len);
//Serial.println(messageBuffer);
Serial.println(message);
String inString = message;//sotre the message to String
colorR = inString.toInt();//convert the message to Integer
if(colorR >255 || colorR < 0)
{
colorR = 0;
}
}
void color_G_Callback(char* message, uint16_t len) {
char messageBuffer[40];
//snprintf(messageBuffer, sizeof(messageBuffer), "Color status is :: %s, len :: %u", message, len);
//Serial.println(messageBuffer);
Serial.println(message);
String inString = message;//sotre the message to String
colorG = inString.toInt();//convert the message to Integer
if(colorG >255 || colorG < 0)
{
colorG = 0;
}
}
void color_B_Callback(char* message, uint16_t len) {
char messageBuffer[40];
//snprintf(messageBuffer, sizeof(messageBuffer), "Color status is :: %s, len :: %u", message, len);
//Serial.println(messageBuffer);
Serial.println(message);
String inString = message;//sotre the message to String
colorB = inString.toInt();//convert the message to Integer
if(colorB >255 || colorB < 0)
{
colorB = 0;
}
}
void color_RGB_Callback(char* message, uint16_t len) {
char messageBuffer[40];
//snprintf(messageBuffer, sizeof(messageBuffer), "Color status is :: %s, len :: %u", message, len);
//Serial.println(messageBuffer);
Serial.println(message);
String newColor = String( message);//
if(newColor.length() == 7)
{
String theColorR = newColor.substring(1, 3);//extract B2 from #B2a48d for example
String theColorG = newColor.substring(3, 5);//extract a4 from #B2a48d for example
String theColorB = newColor.substring(5, 7);//extract 8d from #B2a48d for example
colorR = StrToHex(theColorR.c_str());//convert String to HEX for R
colorG = StrToHex(theColorG.c_str());//convert String to HEX for G
colorB = StrToHex(theColorB.c_str());//convert String to HEX for B
}
}
//from https://stackoverflow.com/questions/44683071/convert-string-as-hex-to-hexadecimal
uint64_t StrToHex(const char* str)
{
return (uint64_t) strtoull(str, 0, 16);
}
void setColor() {
// For common-anode RGB LEDs, use 255 minus the color value
ledcWrite(redChannel, colorR);
ledcWrite(greenChannel, colorG);
ledcWrite(blueChannel, colorB);
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if (retries == 0) {
// basically die and wait for WDT to reset me
while (1)
;
}
}
Serial.println("MQTT Connected!");
}
Common Course Links
Common Course Files
필요할 수 있는 것들
-
알리익스프레스ESP32-S3 N16R8 on AliExpresss.click.aliexpress.com
자원 및 참고자료
아직 자원이 없습니다.
파일📁
데이터시트 (pdf)
-
ESP32 C3 Datasheet English
esp32-c3_datasheet_en[1].pdf0.86 MB