ESP32 WebSlider 예제 듀얼 슬라이더 제어 인터페이스 튜토리얼

개요

WebSlider 예제는 웹 브라우저를 통해 접근 가능한 두 개의 독립적인 슬라이더 컨트롤을 제공합니다. ESP32 교육 플랫폼용으로 설계되었으며 향상된 아날로그 기능, 정밀 제어 기능, 그리고 PWM 및 아날로그 전자 공학 학습을 위한 내장 교육 모듈을 포함하고 있습니다. 각 슬라이더는 0에서 255까지의 값을 제공합니다. 따라서 PWM 제어, 밝기 조정, 모터 속도 제어 및 아날로그와 유사한 제어 값이 필요한 모든 응용에 완벽하게 적합합니다.

아두이노 webslider 예제 - 이중 슬라이더 제어 인터페이스 튜토리얼

기능

  • 이중 슬라이더: 두 개의 독립적인 슬라이더 컨트롤(각 0-255 범위)
  • 실시간 값: WebSocket 통신을 통한 실시간 값 업데이트
  • PWM 호환: 8비트 값(0-255)이 analogWrite() 함수에 완벽하게 적합
  • 시각적 피드백: 각 슬라이더의 실시간 값 표시
  • 프리셋 버튼: 일반 구성에 대한 빠른 프리셋 값
  • 터치 및 마우스 지원: 데스크톱, 태블릿 및 모바일 기기에서 작동
  • 반응형 디자인: 다양한 화면 크기에 맞게 조정됩니다
  • 값 지속성: 페이지를 새로 고침해도 슬라이더가 마지막 위치를 기억합니다

준비물

1×ESP32 ESP-WROOM-32 개발 모듈 쿠팡 | 아마존
1×USB 케이블 타입-A to 타입-C (USB-A PC용) 쿠팡 | 아마존
1×USB 케이블 타입-C to 타입-C (USB-C PC용) 아마존
1×(추천) ESP32용 스크루 터미널 확장 보드 쿠팡 | 아마존
1×(추천) Breakout Expansion Board for ESP32 쿠팡 | 아마존
1×(추천) ESP32용 전원 분배기 쿠팡 | 아마존
공개: 이 포스팅 에 제공된 일부 링크는 아마존 제휴 링크입니다. 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

설정 지침

빠른 단계

다음 지시를 단계별로 따라가세요:

  • ESP32를 처음 사용하는 경우, ESP32 - 소프트웨어 설치 튜토리얼을 참조하십시오.
  • ESP32 보드를 USB 케이블로 컴퓨터에 연결합니다.
  • 컴퓨터에서 Arduino IDE를 시작합니다.
  • 적절한 ESP32 보드(예: ESP32 Dev Module)와 COM 포트를 선택합니다.
  • Arduino IDE 왼쪽 바의 Libraries 아이콘으로 이동합니다.
  • "DIYables ESP32 WebApps"를 검색한 다음 DIYables에서 제공하는 DIYables ESP32 WebApps 라이브러리를 찾으십시오.
  • 라이브러리를 설치하려면 Install 버튼을 클릭합니다.
diyables ESP32 webapps 라이브러리
  • 다른 라이브러리 의존성 설치가 요청됩니다
  • 모든 라이브러리 의존성을 설치하려면 Install All 버튼을 클릭하세요.
diyables ESP32 webapps의 의존성
  • Arduino IDE에서 File 예제 DIYables ESP32 WebApps WebSlider 예제를 확인하거나, 위의 코드를 복사하여 Arduino IDE의 편집기에 붙여넣으세요
/* * DIYables WebApp Library - Web Slider Example * * This example demonstrates the Web Slider feature: * - Two independent sliders (0-255) * - Real-time value monitoring * - Template for hardware control * * Hardware: ESP32 Boards * * Setup: * 1. Update WiFi credentials below * 2. Upload the sketch to your Arduino * 3. Open Serial Monitor to see the IP address * 4. Navigate to http://[IP_ADDRESS]/webslider */ #include <DIYables_ESP32_Platform.h> #include <DIYablesWebApps.h> // WiFi credentials - UPDATE THESE WITH YOUR NETWORK const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD"; // Create WebApp server and page instances ESP32ServerFactory serverFactory; DIYablesWebAppServer webAppsServer(serverFactory, 80, 81); DIYablesHomePage homePage; DIYablesWebSliderPage webSliderPage; // Current slider values int slider1Value = 64; // Default 25% int slider2Value = 128; // Default 50% void setup() { Serial.begin(9600); delay(1000); // TODO: Initialize your hardware pins here Serial.println("DIYables ESP32 WebApp - Web Slider Example"); // Add home and web slider pages webAppsServer.addApp(&homePage); webAppsServer.addApp(&webSliderPage); // Optional: Add 404 page for better user experience webAppsServer.setNotFoundPage(DIYablesNotFoundPage()); // Start the WebApp server if (!webAppsServer.begin(WIFI_SSID, WIFI_PASSWORD)) { while (1) { Serial.println("Failed to start WebApp server!"); delay(1000); } } // Set up slider callback for value changes webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { // Store the received values slider1Value = slider1; slider2Value = slider2; // Print slider values (0-255) Serial.println("Slider 1: " + String(slider1) + ", Slider 2: " + String(slider2)); // TODO: Add your control logic here based on slider values // Examples: // - Control PWM: analogWrite(LED_PIN, slider1); // - Control servos: servo.write(map(slider1, 0, 255, 0, 180)); // - Control motor speed: analogWrite(MOTOR_PIN, slider2); // - Control brightness: strip.setBrightness(slider1); // - Send values via Serial, I2C, SPI, etc. }); // Set up callback for config requests (when client requests current values) webSliderPage.onSliderValueToWeb([]() { webSliderPage.sendToWebSlider(slider1Value, slider2Value); Serial.println("Web client requested values - Sent: Slider1=" + String(slider1Value) + ", Slider2=" + String(slider2Value)); }); } void loop() { // Handle WebApp server communications webAppsServer.loop(); // TODO: Add your main application code here delay(10); }
  • 다음 줄을 업데이트하여 코드에서 WiFi 자격 증명을 구성합니다:
const char WIFI_SSID[] = "YOUR_WIFI_NETWORK"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";
  • Arduino IDE에서 ESP32에 코드를 업로드하려면 Upload 버튼을 클릭합니다
  • 시리얼 모니터를 엽니다
  • 시리얼 모니터에서 결과를 확인하세요. 다음과 같이 나타납니다
COM6
Send
DIYables WebApp - Web Slider Example INFO: Added app / INFO: Added app /web-slider DIYables WebApp Library Platform: ESP32 Network connected! IP address: 192.168.0.2 HTTP server started on port 80 Configuring WebSocket server callbacks... WebSocket server started on port 81 WebSocket URL: ws://192.168.0.2:81 WebSocket server started on port 81 ========================================== DIYables WebApp Ready! ========================================== 📱 Web Interface: http://192.168.0.2 🔗 WebSocket: ws://192.168.0.2:81 📋 Available Applications: 🏠 Home Page: http://192.168.0.2/ 🎚️ Web Slider: http://192.168.0.2/web-slider ==========================================
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  
  • 아무 것도 보이지 않으면 ESP32 보드를 재부팅하세요.
  • 표시된 IP 주소를 메모해 두고, 이 주소를 스마트폰이나 PC의 웹 브라우저 주소 표시줄에 입력하세요.
  • 예: http://192.168.0.2
  • 아래 이미지와 같은 홈 페이지가 표시됩니다:
ESP32 diyables 웹앱 홈 페이지 및 웹 슬라이더 앱
  • Web Slider 링크를 클릭하면 아래와 같이 Web Slider 앱의 UI가 표시됩니다:
ESP32 diyables 웹앱 웹 슬라이더 앱
  • 또는 IP 주소 뒤에 /web-slider를 붙여 페이지에 직접 접속할 수도 있습니다. 예를 들어: http://192.168.0.2/web-slider
  • 두 개의 슬라이더를 움직여 아날로그 값(0-255)을 제어하고 시리얼 모니터에서 실시간 피드백을 확인해 보세요.

창의적 맞춤화 - 코드를 프로젝트에 맞게 조정하기

기본 슬라이더 값 설정

초기 슬라이더 위치 설정:

// Current slider values (0-255) int slider1Value = 64; // Default 25% (64/255) int slider2Value = 128; // Default 50% (128/255)

슬라이더 사용 방법

웹 인터페이스 컨트롤

슬라이더 인터페이스는 다음을 제공합니다:

  • 슬라이더 1: 값 표시가 있는 첫 번째 컨트롤 슬라이더(0-255)
  • 슬라이더 2: 값 표시가 있는 두 번째 컨트롤 슬라이더(0-255)
  • 값 표시: 두 슬라이더의 실시간 숫자 값
  • 프리셋 버튼: 일반 값에 빠르게 접근할 수 있는 옵션(0%, 25%, 50%, 75%, 100%)

슬라이더 조작 방법

데스크탑 (마우스 제어)

  1. 클릭 및 드래그: 슬라이더 핸들을 클릭한 채로 드래그하여 값을 조정합니다.
  2. 클릭 위치: 슬라이더 트랙의 아무 곳이나 클릭하여 해당 값으로 점프합니다.
  3. 정밀 제어: 정밀하게 조정하려면 작은 마우스 움직임을 사용합니다.

모바일/태블릿 (터치 제어)

  1. 터치 및 드래그: 슬라이더 핸들을 터치하고 새 위치로 드래그하기
  2. 탭 위치: 슬라이더 트랙을 탭하여 값을 설정하기
  3. 매끄러운 제어: 손가락으로 드래그하면 값이 부드럽게 변합니다

값의 범위

각 슬라이더는 다음을 제공합니다:

  • 최소값: 0 (0% - 완전히 꺼짐)
  • 최대값: 255 (100% - 최대 밝기)
  • 해상도: 256개의 이산 단계(8비트 정밀도)
  • PWM 호환성: analogWrite() 함수와 직접 사용 가능

프로그래밍 예제

기본 슬라이더 핸들러

void setup() { // Set up slider callback for value changes webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { // Store the received values slider1Value = slider1; slider2Value = slider2; // Print slider values (0-255) Serial.println("Slider 1: " + String(slider1) + ", Slider 2: " + String(slider2)); // Add your control logic here }); }

LED 밝기 제어

// Pin definitions for PWM LEDs const int LED1_PIN = 9; // PWM pin for first LED const int LED2_PIN = 10; // PWM pin for second LED void setup() { // Configure LED pins as outputs pinMode(LED1_PIN, OUTPUT); pinMode(LED2_PIN, OUTPUT); // Set initial brightness analogWrite(LED1_PIN, slider1Value); analogWrite(LED2_PIN, slider2Value); webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { // Store values slider1Value = slider1; slider2Value = slider2; // Control LED brightness directly (0-255 PWM) analogWrite(LED1_PIN, slider1); analogWrite(LED2_PIN, slider2); Serial.println("LED1 Brightness: " + String(slider1) + ", LED2 Brightness: " + String(slider2)); }); }

서보 위치 제어

#include <Servo.h> Servo servo1, servo2; void setup() { // Attach servos to PWM pins servo1.attach(9); servo2.attach(10); // Set initial positions servo1.write(map(slider1Value, 0, 255, 0, 180)); servo2.write(map(slider2Value, 0, 255, 0, 180)); webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { slider1Value = slider1; slider2Value = slider2; // Map slider values (0-255) to servo angles (0-180°) int angle1 = map(slider1, 0, 255, 0, 180); int angle2 = map(slider2, 0, 255, 0, 180); // Move servos to calculated positions servo1.write(angle1); servo2.write(angle2); Serial.println("Servo1: " + String(angle1) + "°, Servo2: " + String(angle2) + "°"); }); }

모터 속도 제어

// Motor driver pins const int MOTOR1_PWM = 9; // Motor 1 speed control const int MOTOR1_DIR1 = 2; // Motor 1 direction pin 1 const int MOTOR1_DIR2 = 3; // Motor 1 direction pin 2 const int MOTOR2_PWM = 10; // Motor 2 speed control const int MOTOR2_DIR1 = 4; // Motor 2 direction pin 1 const int MOTOR2_DIR2 = 5; // Motor 2 direction pin 2 void setup() { // Configure motor pins pinMode(MOTOR1_PWM, OUTPUT); pinMode(MOTOR1_DIR1, OUTPUT); pinMode(MOTOR1_DIR2, OUTPUT); pinMode(MOTOR2_PWM, OUTPUT); pinMode(MOTOR2_DIR1, OUTPUT); pinMode(MOTOR2_DIR2, OUTPUT); // Set initial motor directions (forward) digitalWrite(MOTOR1_DIR1, HIGH); digitalWrite(MOTOR1_DIR2, LOW); digitalWrite(MOTOR2_DIR1, HIGH); digitalWrite(MOTOR2_DIR2, LOW); webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { slider1Value = slider1; slider2Value = slider2; // Control motor speeds directly analogWrite(MOTOR1_PWM, slider1); analogWrite(MOTOR2_PWM, slider2); // Calculate percentage for display int speed1Percent = map(slider1, 0, 255, 0, 100); int speed2Percent = map(slider2, 0, 255, 0, 100); Serial.println("Motor1: " + String(speed1Percent) + "%, " + "Motor2: " + String(speed2Percent) + "%"); }); }

RGB LED 색상 제어

// RGB LED pins const int RED_PIN = 9; const int GREEN_PIN = 10; const int BLUE_PIN = 11; void setup() { pinMode(RED_PIN, OUTPUT); pinMode(GREEN_PIN, OUTPUT); pinMode(BLUE_PIN, OUTPUT); webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { slider1Value = slider1; slider2Value = slider2; // Use sliders to control RGB components // Slider 1 controls red intensity // Slider 2 controls blue intensity // Green is calculated based on both sliders int redValue = slider1; int blueValue = slider2; int greenValue = (slider1 + slider2) / 2; // Average of both sliders analogWrite(RED_PIN, redValue); analogWrite(GREEN_PIN, greenValue); analogWrite(BLUE_PIN, blueValue); Serial.println("RGB - R:" + String(redValue) + " G:" + String(greenValue) + " B:" + String(blueValue)); }); }

고급 프로그래밍 기법

가치 평활화

class SliderSmoother { private: int currentValue = 0; int targetValue = 0; unsigned long lastUpdate = 0; const int SMOOTH_RATE = 5; // Change per update cycle public: void setTarget(int target) { targetValue = target; } int getCurrentValue() { return currentValue; } bool update() { if (millis() - lastUpdate > 10) { // Update every 10ms bool changed = false; if (currentValue < targetValue) { currentValue = min(currentValue + SMOOTH_RATE, targetValue); changed = true; } else if (currentValue > targetValue) { currentValue = max(currentValue - SMOOTH_RATE, targetValue); changed = true; } lastUpdate = millis(); return changed; } return false; } }; SliderSmoother smoother1, smoother2; void setup() { webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { // Set target values for smooth transition smoother1.setTarget(slider1); smoother2.setTarget(slider2); }); } void loop() { server.loop(); // Update smoothed values bool changed1 = smoother1.update(); bool changed2 = smoother2.update(); if (changed1 || changed2) { // Apply smoothed values to hardware analogWrite(9, smoother1.getCurrentValue()); analogWrite(10, smoother2.getCurrentValue()); } }

임계값 기반 제어

void setupThresholdControl() { webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { slider1Value = slider1; slider2Value = slider2; // Threshold-based control for discrete outputs const int LOW_THRESHOLD = 85; // 33% const int MEDIUM_THRESHOLD = 170; // 66% // Control digital outputs based on slider 1 thresholds if (slider1 < LOW_THRESHOLD) { // Low level: Turn off all outputs digitalWrite(2, LOW); digitalWrite(3, LOW); digitalWrite(4, LOW); } else if (slider1 < MEDIUM_THRESHOLD) { // Medium level: Turn on first output digitalWrite(2, HIGH); digitalWrite(3, LOW); digitalWrite(4, LOW); } else { // High level: Turn on all outputs digitalWrite(2, HIGH); digitalWrite(3, HIGH); digitalWrite(4, HIGH); } // Use slider 2 for analog PWM control analogWrite(9, slider2); }); }

프리셋 값 시스템

// Predefined preset values const int PRESETS[][2] = { {0, 0}, // Preset 0: Both off {64, 128}, // Preset 1: Low/Medium {128, 128}, // Preset 2: Both medium {255, 128}, // Preset 3: High/Medium {255, 255} // Preset 4: Both maximum }; void applyPreset(int presetNumber) { if (presetNumber >= 0 && presetNumber < 5) { slider1Value = PRESETS[presetNumber][0]; slider2Value = PRESETS[presetNumber][1]; // Update hardware analogWrite(9, slider1Value); analogWrite(10, slider2Value); // Send updated values to web interface webSliderPage.sendToWebSlider(slider1Value, slider2Value); Serial.println("Applied preset " + String(presetNumber) + ": " + String(slider1Value) + ", " + String(slider2Value)); } } void setupPresetSystem() { // You could trigger presets based on other inputs // For example, reading digital pins for preset buttons webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { slider1Value = slider1; slider2Value = slider2; // Your normal slider handling analogWrite(9, slider1); analogWrite(10, slider2); }); } void loop() { server.loop(); // Check for preset trigger conditions // Example: Read buttons connected to digital pins static bool lastButton = false; bool currentButton = digitalRead(7); // Preset button on pin 7 if (currentButton && !lastButton) { // Button pressed static int currentPreset = 0; applyPreset(currentPreset); currentPreset = (currentPreset + 1) % 5; // Cycle through presets } lastButton = currentButton; }

하드웨어 연동 예제

LED 스트립 제어

// For WS2812B or similar addressable LED strips // (requires additional libraries like FastLED or Adafruit NeoPixel) const int LED_STRIP_PIN = 6; const int NUM_LEDS = 30; void setupLEDStrip() { // Initialize LED strip (depends on library used) webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { slider1Value = slider1; slider2Value = slider2; // Slider 1 controls brightness (0-255) // Slider 2 controls color temperature or hue uint8_t brightness = slider1; uint8_t hue = slider2; // Update LED strip (example with conceptual functions) // strip.setBrightness(brightness); // strip.fill(CHSV(hue, 255, 255)); // strip.show(); Serial.println("LED Strip - Brightness: " + String(brightness) + ", Hue: " + String(hue)); }); }

팬 속도 제어

const int FAN1_PIN = 9; const int FAN2_PIN = 10; void setupFanControl() { pinMode(FAN1_PIN, OUTPUT); pinMode(FAN2_PIN, OUTPUT); webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { slider1Value = slider1; slider2Value = slider2; // Control fan speeds with minimum threshold for startup int fan1Speed = (slider1 > 50) ? map(slider1, 50, 255, 100, 255) : 0; int fan2Speed = (slider2 > 50) ? map(slider2, 50, 255, 100, 255) : 0; analogWrite(FAN1_PIN, fan1Speed); analogWrite(FAN2_PIN, fan2Speed); Serial.println("Fan1: " + String(map(fan1Speed, 0, 255, 0, 100)) + "%, " + "Fan2: " + String(map(fan2Speed, 0, 255, 0, 100)) + "%"); }); }

오디오 볼륨 제어

// For controlling audio amplifier or volume IC const int VOLUME1_PIN = 9; // PWM output to volume control const int VOLUME2_PIN = 10; // Second channel or tone control void setupAudioControl() { pinMode(VOLUME1_PIN, OUTPUT); pinMode(VOLUME2_PIN, OUTPUT); webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { slider1Value = slider1; slider2Value = slider2; // Use logarithmic scaling for better audio perception float volume1 = pow(slider1 / 255.0, 2) * 255; // Square law float volume2 = pow(slider2 / 255.0, 2) * 255; analogWrite(VOLUME1_PIN, (int)volume1); analogWrite(VOLUME2_PIN, (int)volume2); Serial.println("Volume1: " + String((int)volume1) + ", Volume2: " + String((int)volume2)); }); }

문제 해결

일반적인 문제

1. 슬라이더가 반응하지 않음

  • 브라우저 콘솔에서 WebSocket 연결 확인
  • 장치와 Arduino 간의 네트워크 연결 확인
  • 브라우저 페이지를 새로고침하여 연결을 재설정
  • 시리얼 모니터에서 연결 오류를 확인

2. 전체 범위에 도달하지 못하는 값들

  • 웹 인터페이스에서 슬라이더 범위 설정을 확인합니다
  • 콜백 함수에서 값 매핑 문제를 확인합니다
  • 다른 브라우저나 기기에서 테스트합니다

3. 거칠고 일관성 없는 제어

  • 점진적 변화에 대한 값 스무딩 구현
  • 네트워크 지연 문제 점검
  • 빠른 값 변화에 대한 디바운싱 추가

4. PWM 출력이 작동하지 않음

  • 핀들이 PWM을 지원하는지 확인 (ESP32 핀아웃 확인)
  • AnalogWrite()가 올바른 핀 번호로 호출되었는지 확인
  • 하드웨어 연결 및 부하 요건을 확인

디버깅 팁

포괄적인 디버깅 추가:

void debugSliderValues(int slider1, int slider2) { Serial.println("=== Slider Debug ==="); Serial.println("Slider 1: " + String(slider1) + " (" + String(map(slider1, 0, 255, 0, 100)) + "%)"); Serial.println("Slider 2: " + String(slider2) + " (" + String(map(slider2, 0, 255, 0, 100)) + "%)"); Serial.println("PWM Pin 9: " + String(slider1)); Serial.println("PWM Pin 10: " + String(slider2)); Serial.println("==================="); }

프로젝트 아이디어

조명 제어 프로젝트

  • 실내 조명 밝기 조절
  • RGB 색상 혼합 인터페이스
  • LED 스트립 애니메이션 속도 조절
  • 무대 조명 강도 조절

모터 제어 프로젝트

  • 로봇 속도 제어
  • 팬 속도 조절
  • 펌프 유량 제어
  • 컨베이어 벨트 속도

오디오 프로젝트들

  • 볼륨 제어 인터페이스
  • 음색/이퀄라이저 제어
  • 효과음 강도
  • 음악 시각화 제어

홈 자동화

  • 실내 온도 제어(난방/냉방 강도)
  • 창문 블라인드 위치 제어
  • 관개 시스템 유량 제어
  • 스마트 기기 밝기/음량

다른 예제와의 통합

WebJoystick와 결합

속도 제한에는 슬라이더를, 방향에는 조이스틱을 사용하십시오.

// Global speed limit from sliders int maxSpeed = 255; // In WebSlider callback webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { maxSpeed = slider1; // Use slider 1 as global speed limit }); // In WebJoystick callback webJoystickPage.onJoystickValueFromWeb([](int x, int y) { // Scale joystick values by slider-controlled speed limit int scaledX = map(x, -100, 100, -maxSpeed, maxSpeed); int scaledY = map(y, -100, 100, -maxSpeed, maxSpeed); controlRobot(scaledX, scaledY); });

WebDigitalPins과 결합하기

PWM과 디지털 핀의 켜짐/꺼짐을 제어하려면 슬라이더를 사용하세요:

webSliderPage.onSliderValueFromWeb([](int slider1, int slider2) { // Only apply PWM if corresponding digital pins are ON if (webDigitalPinsPage.getPinState(2)) { analogWrite(9, slider1); } else { analogWrite(9, 0); } if (webDigitalPinsPage.getPinState(3)) { analogWrite(10, slider2); } else { analogWrite(10, 0); } });

다음 단계

WebSlider 예제를 마스터한 후 시도해 보십시오:

  1. WebJoystick - 2D 방향 제어를 위한
  2. WebDigitalPins - 이산 온/오프 제어를 위한
  3. WebMonitor - 슬라이더 값을 디버깅하기 위한
  4. MultipleWebApps - 다른 컨트롤과 슬라이더를 결합하기 위한

지원

추가 도움이 필요하신 경우:

  • API 참조 문서를 확인하세요
  • DIYables 튜토리얼을 방문하세요: https://esp32io.com/tutorials/diyables-esp32-webapps
  • ESP32 커뮤니티 포럼