Back to All Blog Posts
Tutorial EltroNerd Engineering

ESP32 LED Matrix Display using Bluetooth and Wi-Fi Control

Let’s design a full-featured ESP32 LED matrix display system that can display dynamic text/ads (DS) and be controlled via Bluetooth or local Wi-Fi

📢 ESP32 LED Matrix Display (Bluetooth + Wi-Fi Control)

This project allows you to:

  • Display dynamic text or ads on an RGB LED matrix.
  • Control messages and colors via Bluetooth or local Wi-Fi.
  • Optional: display scrolling text, colors, or patterns.

⚡ Hardware Required

  • ESP32 (Wi-Fi + Bluetooth capable)
  • RGB LED Matrix (8x8, 16x16, or larger, WS2812 / NeoPixel)
  • 470Ω resistor (data line)
  • Capacitor 1000 µF (across power supply for matrix)
  • 5V power supply (sufficient for LEDs)
  • Jumper wires, breadboard

🔌 Connections

Device ESP32 Pin Notes
LED Data In GPIO 5 Connect via 470Ω resistor
5V Power 5V External supply recommended
GND GND Common ground with ESP32
Capacitor 1000 µF Across power supply for stability

🖥️ Full Code Example (Wi-Fi + BLE Control)

c
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_NeoPixel.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>

// LED Matrix
#define LED_PIN 5
#define NUM_LEDS 64
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

// Wi-Fi credentials
const char* ssid = "YOUR_WIFI";
const char* password = "YOUR_PASS";

// BLE UUIDs
#define SERVICE_UUID        "12345678-1234-1234-1234-1234567890ab"
#define CHARACTERISTIC_UUID "abcd1234-5678-90ab-cdef-1234567890ab"

// Dynamic text / ad message
String dsMessage = "WELCOME! ";

// BLE
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;

// BLE callbacks
class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) { deviceConnected = true; }
  void onDisconnect(BLEServer* pServer) { deviceConnected = false; }
};

class MyCallbacks : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic* pChar) {
    std::string value = pChar->getValue();
    dsMessage = String(value.c_str());
  }
};

// Wi-Fi web server
AsyncWebServer server(80);

const char htmlPage[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<title>LED Matrix Control</title>
</head>
<body>
<h1>Update Message</h1>
<input type="text" id="msg" size="30" placeholder="Type your ad">
<button onclick="sendMsg()">Update</button>
<script>
function sendMsg(){
  var msg = document.getElementById("msg").value;
  fetch("/update?msg="+encodeURIComponent(msg));
}
</script>
</body>
</html>
)rawliteral";

// Function to scroll message
void scrollMessage(String msg){
  int len = msg.length();
  for(int i=0; i<len*6; i++){
    strip.clear();
    for(int c=0; c<NUM_LEDS; c++){
      if((c+i)%6==0) strip.setPixelColor(c, strip.Color(255,0,0));
    }
    strip.show();
    delay(150);
  }
}

void setup() {
  Serial.begin(115200);

  // LED
  strip.begin();
  strip.show();

  // Wi-Fi
  WiFi.begin(ssid,password);
  while(WiFi.status()!=WL_CONNECTED){
    delay(500); Serial.print(".");
  }
  Serial.println("Wi-Fi connected: " + WiFi.localIP().toString());

  // Web server
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200,"text/html",htmlPage);
  });
  server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){
    if(request->hasParam("msg")){
      dsMessage = request->getParam("msg")->value();
    }
    request->send(200,"text/plain","OK");
  });
  server.begin();

  // BLE setup
  BLEDevice::init("ESP32_LED_Display");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_WRITE
                    );
  pCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->start();
  Serial.println("BLE ready to connect");
}

void loop() {
  // Continuously scroll current message
  scrollMessage(dsMessage);
}

Try this project in your browser

Compile code and simulate hardware output with EltroNerd Cloud IDE.

Launch Cloud IDE