diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8eb8f4e45ef..53da85a4502 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -36,6 +36,7 @@ set(CORE_SRCS
   cores/esp32/esp32-hal-matrix.c
   cores/esp32/esp32-hal-misc.c
   cores/esp32/esp32-hal-psram.c
+  cores/esp32/esp32-hal-rgb-led.c
   cores/esp32/esp32-hal-sigmadelta.c
   cores/esp32/esp32-hal-spi.c
   cores/esp32/esp32-hal-time.c
diff --git a/cores/esp32/esp32-hal-gpio.c b/cores/esp32/esp32-hal-gpio.c
index 359682c3433..ceef3bdfa5c 100644
--- a/cores/esp32/esp32-hal-gpio.c
+++ b/cores/esp32/esp32-hal-gpio.c
@@ -91,6 +91,13 @@ static InterruptHandle_t __pinInterruptHandlers[SOC_GPIO_PIN_COUNT] = {0,};
 
 extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
 {
+#ifdef BOARD_HAS_NEOPIXEL
+    if (pin == LED_BUILTIN){
+        __pinMode(LED_BUILTIN-SOC_GPIO_PIN_COUNT, mode);
+        return;
+    }
+#endif
+
     if (!GPIO_IS_VALID_GPIO(pin)) {
         log_e("Invalid pin selected");
         return;
@@ -127,6 +134,14 @@ extern void ARDUINO_ISR_ATTR __pinMode(uint8_t pin, uint8_t mode)
 
 extern void ARDUINO_ISR_ATTR __digitalWrite(uint8_t pin, uint8_t val)
 {
+    #ifdef BOARD_HAS_NEOPIXEL
+        if(pin == LED_BUILTIN){
+            //use RMT to set all channels on/off
+            const uint8_t comm_val = val != 0 ? LED_BRIGHTNESS : 0;
+            neopixelWrite(LED_BUILTIN, comm_val, comm_val, comm_val);
+            return;
+        }
+    #endif
 	gpio_set_level((gpio_num_t)pin, val);
 }
 
diff --git a/cores/esp32/esp32-hal-gpio.h b/cores/esp32/esp32-hal-gpio.h
index ff3808e9856..9f143811685 100644
--- a/cores/esp32/esp32-hal-gpio.h
+++ b/cores/esp32/esp32-hal-gpio.h
@@ -26,6 +26,7 @@ extern "C" {
 
 #include "esp32-hal.h"
 #include "soc/soc_caps.h"
+#include "pins_arduino.h"
 
 #if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
 #define NUM_OUPUT_PINS  46
@@ -63,6 +64,7 @@ extern "C" {
 #define ONLOW_WE  0x0C
 #define ONHIGH_WE 0x0D
 
+
 #define digitalPinIsValid(pin)          GPIO_IS_VALID_GPIO(pin)
 #define digitalPinCanOutput(pin)        GPIO_IS_VALID_OUTPUT_GPIO(pin)
 
diff --git a/cores/esp32/esp32-hal-rgb-led.c b/cores/esp32/esp32-hal-rgb-led.c
new file mode 100644
index 00000000000..6776d324d99
--- /dev/null
+++ b/cores/esp32/esp32-hal-rgb-led.c
@@ -0,0 +1,47 @@
+#include "esp32-hal-rgb-led.h"
+
+
+void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val){
+  rmt_data_t led_data[24];
+  static rmt_obj_t* rmt_send = NULL;
+  static bool initialized = false;
+
+  uint8_t _pin = pin;
+#ifdef BOARD_HAS_NEOPIXEL
+  if(pin == LED_BUILTIN){
+    _pin = LED_BUILTIN-SOC_GPIO_PIN_COUNT;
+  }
+#endif
+
+  if(!initialized){
+    if((rmt_send = rmtInit(_pin, RMT_TX_MODE, RMT_MEM_64)) == NULL){
+        log_e("RGB LED driver initialization failed!");
+        rmt_send = NULL;
+        return;
+    }
+    rmtSetTick(rmt_send, 100);
+    initialized = true;
+  }
+
+  int color[] = {green_val, red_val, blue_val};  // Color coding is in order GREEN, RED, BLUE
+  int i = 0;
+  for(int col=0; col<3; col++ ){
+    for(int bit=0; bit<8; bit++){
+      if((color[col] & (1<<(7-bit)))){
+        // HIGH bit
+        led_data[i].level0 = 1; // T1H
+        led_data[i].duration0 = 8; // 0.8us
+        led_data[i].level1 = 0; // T1L
+        led_data[i].duration1 = 4; // 0.4us
+      }else{
+        // LOW bit
+        led_data[i].level0 = 1; // T0H
+        led_data[i].duration0 = 4; // 0.4us
+        led_data[i].level1 = 0; // T0L
+        led_data[i].duration1 = 8; // 0.8us
+      }
+      i++;
+    }
+  }
+  rmtWrite(rmt_send, led_data, 24);
+}
diff --git a/cores/esp32/esp32-hal-rgb-led.h b/cores/esp32/esp32-hal-rgb-led.h
new file mode 100644
index 00000000000..e2db0e91046
--- /dev/null
+++ b/cores/esp32/esp32-hal-rgb-led.h
@@ -0,0 +1,20 @@
+#ifndef MAIN_ESP32_HAL_RGB_LED_H_
+#define MAIN_ESP32_HAL_RGB_LED_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "esp32-hal.h"
+
+#ifndef LED_BRIGHTNESS
+  #define LED_BRIGHTNESS 64
+#endif
+
+void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MAIN_ESP32_HAL_RGB_LED_H_ */
\ No newline at end of file
diff --git a/cores/esp32/esp32-hal.h b/cores/esp32/esp32-hal.h
index 55e9f95769b..9039d3544c8 100644
--- a/cores/esp32/esp32-hal.h
+++ b/cores/esp32/esp32-hal.h
@@ -88,6 +88,7 @@ void yield(void);
 #include "esp32-hal-timer.h"
 #include "esp32-hal-bt.h"
 #include "esp32-hal-psram.h"
+#include "esp32-hal-rgb-led.h"
 #include "esp32-hal-cpu.h"
 
 void analogWrite(uint8_t pin, int value);
diff --git a/libraries/ESP32/examples/GPIO/BlinkRGB/BlinkRGB.ino b/libraries/ESP32/examples/GPIO/BlinkRGB/BlinkRGB.ino
new file mode 100644
index 00000000000..3c2ed4864c1
--- /dev/null
+++ b/libraries/ESP32/examples/GPIO/BlinkRGB/BlinkRGB.ino
@@ -0,0 +1,39 @@
+/*
+  BlinkRGB
+
+  Demonstrates usage of onboard RGB LED on some ESP dev boards.
+
+  Calling digitalWrite(LED_BUILTIN, HIGH) will use hidden RGB driver.
+    
+  RGBLedWrite demonstrates controll of each channel:
+  void neopixelWrite(uint8_t pin, uint8_t red_val, uint8_t green_val, uint8_t blue_val)
+
+  WARNING: After using digitalWrite to drive RGB LED it will be impossible to drive the same pin
+    with normal HIGH/LOW level
+*/
+//#define LED_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 BOARD_HAS_NEOPIXEL
+  digitalWrite(LED_BUILTIN, HIGH);   // Turn the RGB LED white
+  delay(1000);
+  digitalWrite(LED_BUILTIN, LOW);    // Turn the RGB LED off
+  delay(1000);
+
+  neopixelWrite(LED_BUILTIN,LED_BRIGHTNESS,0,0); // Red
+  delay(1000);
+  neopixelWrite(LED_BUILTIN,0,LED_BRIGHTNESS,0); // Green
+  delay(1000);
+  neopixelWrite(LED_BUILTIN,0,0,LED_BRIGHTNESS); // Blue
+  delay(1000);
+  neopixelWrite(LED_BUILTIN,0,0,0); // Off / black
+  delay(1000);
+#endif
+}
diff --git a/variants/esp32c3/pins_arduino.h b/variants/esp32c3/pins_arduino.h
index 8ce191ad23a..0fce6340e08 100644
--- a/variants/esp32c3/pins_arduino.h
+++ b/variants/esp32c3/pins_arduino.h
@@ -2,11 +2,18 @@
 #define Pins_Arduino_h
 
 #include <stdint.h>
+#include "soc/soc_caps.h"
 
 #define EXTERNAL_NUM_INTERRUPTS 22
 #define NUM_DIGITAL_PINS        22
 #define NUM_ANALOG_INPUTS       6
 
+static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT+8;
+#define BUILTIN_LED  LED_BUILTIN // backward compatibility
+#define LED_BUILTIN LED_BUILTIN
+#define BOARD_HAS_NEOPIXEL
+#define LED_BRIGHTNESS 64
+
 #define analogInputToDigitalPin(p)  (((p)<NUM_ANALOG_INPUTS)?(analogChannelToDigitalPin(p)):-1)
 #define digitalPinToInterrupt(p)    (((p)<NUM_DIGITAL_PINS)?(p):-1)
 #define digitalPinHasPWM(p)         (p < EXTERNAL_NUM_INTERRUPTS)
diff --git a/variants/esp32s2/pins_arduino.h b/variants/esp32s2/pins_arduino.h
index 76d8bbf88c4..a08ca9e97ea 100644
--- a/variants/esp32s2/pins_arduino.h
+++ b/variants/esp32s2/pins_arduino.h
@@ -2,11 +2,19 @@
 #define Pins_Arduino_h
 
 #include <stdint.h>
+#include "soc/soc_caps.h"
 
 #define EXTERNAL_NUM_INTERRUPTS 46
 #define NUM_DIGITAL_PINS        48
 #define NUM_ANALOG_INPUTS       20
 
+static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT+18; // GPIO pin for Saola-1 & DevKitM-1 = 18
+//static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT+45; // GPIO pin for Kaluga = 45
+#define BUILTIN_LED  LED_BUILTIN // backward compatibility
+#define LED_BUILTIN LED_BUILTIN
+#define BOARD_HAS_NEOPIXEL
+#define LED_BRIGHTNESS 64
+
 #define analogInputToDigitalPin(p)  (((p)<20)?(analogChannelToDigitalPin(p)):-1)
 #define digitalPinToInterrupt(p)    (((p)<48)?(p):-1)
 #define digitalPinHasPWM(p)         (p < 46)
diff --git a/variants/esp32s3/pins_arduino.h b/variants/esp32s3/pins_arduino.h
index 59f298e4965..fc48ac691d5 100644
--- a/variants/esp32s3/pins_arduino.h
+++ b/variants/esp32s3/pins_arduino.h
@@ -2,6 +2,7 @@
 #define Pins_Arduino_h
 
 #include <stdint.h>
+#include "soc/soc_caps.h"
 
 #define USB_VID 0x303a
 #define USB_PID 0x1001
@@ -10,6 +11,15 @@
 #define NUM_DIGITAL_PINS        48
 #define NUM_ANALOG_INPUTS       20
 
+// Some boards have too low voltage on this pin (board design bug)
+// Use different pin with 3V and connect with 48
+// and change this setup for the chosen pin (for example 38)
+static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT+48;
+#define BUILTIN_LED  LED_BUILTIN // backward compatibility
+#define LED_BUILTIN LED_BUILTIN
+#define BOARD_HAS_NEOPIXEL
+#define LED_BRIGHTNESS 64
+
 #define analogInputToDigitalPin(p)  (((p)<20)?(analogChannelToDigitalPin(p)):-1)
 #define digitalPinToInterrupt(p)    (((p)<48)?(p):-1)
 #define digitalPinHasPWM(p)         (p < 46)