WI-FI Neopixel Display

by elektro majster in Circuits > LEDs

34 Views, 0 Favorites, 0 Comments

WI-FI Neopixel Display

Obrázok WhatsApp 2025-08-16 o 15.01.38_9f70d103.jpg
Obrázok WhatsApp 2025-08-16 o 15.03.49_f912fdbe.jpg
Obrázok WhatsApp 2025-08-16 o 15.03.49_06c3ec96.jpg
Obrázok WhatsApp 2025-08-16 o 15.03.50_15aa4106.jpg
Obrázok WhatsApp 2025-08-16 o 15.03.50_f9bac2b8.jpg
Obrázok WhatsApp 2025-08-16 o 15.03.50_a8a974ca.jpg
Obrázok WhatsApp 2025-08-16 o 15.03.50_eb684d4a.jpg
IMG-20250816-WA0003.jpg
IMG-20250816-WA0006.jpg

Wi-Fi Controlled RGB 8x8 NeoPixel LED

Supplies

Obrázok WhatsApp 2025-08-16 o 15.06.21_089605df.jpg

ESP8266 - https://www.aliexpress.com/item/4001225134179.html?spm=a2g0o.productlist.main.43.7949b69dJsZ41z&algo_pvid=4c66820b-aaca-4b36-a41d-0f78a92dce78&algo_exp_id=4c66820b-aaca-4b36-a41d-0f78a92dce78-42&pdp_ext_f=%7B%22order%22%3A%222%22%2C%22eval%22%3A%221%22%7D&pdp_npi=6%40dis%21EUR%211.76%211.53%21%21%2114.39%2112.52%21%40211b804117553497614417631e4445%2110000015358288483%21sea%21SK%210%21ABX%211%210%21n_tag%3A-29910%3Bm03_new_user%3A-29895&curPageLogUid=PQnsJiGqa0h9&utparam-url=scene%3Asearch%7Cquery_from%3A%7Cx_object_id%3A4001225134179%7C_p_origin_prod%3A

NEOPIXEL 8x8 - https://www.aliexpress.com/item/1005008088871285.html?spm=a2g0o.productlist.main.9.2f0423d1frHLyT&algo_pvid=746b6185-6075-45e6-bad8-86f14113aabf&algo_exp_id=746b6185-6075-45e6-bad8-86f14113aabf-8&pdp_ext_f=%7B%22order%22%3A%2263%22%2C%22eval%22%3A%221%22%7D&pdp_npi=6%40dis%21EUR%212.00%210.87%21%21%2116.36%217.13%21%40211b431017553498167338603e21b5%2112000043651874505%21sea%21SK%210%21ABX%211%210%21m03_new_user%3A-29895%3Bn_tag%3A-29910%3BpisId%3A5000000174216173&curPageLogUid=Z0NuTi7Zhdn2&utparam-url=scene%3Asearch%7Cquery_from%3A%7Cx_object_id%3A1005008088871285%7C_p_origin_prod%3A

USB C -https://www.aliexpress.com/item/1005007457909582.html?spm=a2g0o.detail.pcDetailTopMoreOtherSeller.5.43dasuqJsuqJFF&gps-id=pcDetailTopMoreOtherSeller&scm=1007.40050.354490.0&scm_id=1007.40050.354490.0&scm-url=1007.40050.354490.0&pvid=498dd464-7067-4023-9276-a278e1c68e65&_t=gps-id:pcDetailTopMoreOtherSeller,scm-url:1007.40050.354490.0,pvid:498dd464-7067-4023-9276-a278e1c68e65,tpp_buckets:668%232846%238116%232002&pdp_ext_f=%7B%22order%22%3A%224494%22%2C%22eval%22%3A%221%22%2C%22sceneId%22%3A%2230050%22%7D&pdp_npi=6%40dis%21EUR%211.63%210.87%21%21%2113.33%217.12%21%40211b819117553501990968479e6d5a%2112000040837026422%21rec%21SK%21%21ABXZ%211%210%21m03_new_user%3A-29895%3Bn_tag%3A-29910%3BpisId%3A5000000174216174&utparam-url=scene%3ApcDetailTopMoreOtherSeller%7Cquery_from%3A%7Cx_object_id%3A1005007457909582%7C_p_origin_prod%3A

SOLDERING

Obrázok WhatsApp 2025-08-16 o 15.17.32_c28cfbe5.jpg

V- (neopixel) solder to GND (ESP-8366) and - (USB C)

V+(neopixel) solder to VN (ESP-8266) and + (USB C)

IN (neopixel) solder to D4 (esp-8266)


Use double-sided tape to attach the ESP8266 to the bottom left side of the NeoPixel.

3D Printing

https://www.thingiverse.com/thing:7119396

ASSEMBLY

Obrázok WhatsApp 2025-08-16 o 15.34.53_f44716d6.jpg

Secure the NeoPixel matrix to the grid with a 3D pen.

Next, place the diffuser onto the grid and seal the edges using a soldering iron (around 200 °C works best).

nsert the USB connector into the enclosure and secure it with epoxy.

Close the enclosure with the diffuser.

PROGRAMING

#include <ESP8266WiFi.h>

#include <ESPAsyncWebServer.h>

#include <ESPAsyncTCP.h>

#include <Adafruit_NeoPixel.h>


// ======= KONFIGURÁCIA =======

#define LED_PIN 2 // GPIO2 (D4 na NodeMCU)

#define WIDTH 8

#define HEIGHT 8

#define LED_COUNT (WIDTH * HEIGHT)

#define SERPENTINE true // true = hadovité (riadkovo opačné smery), false = každý riadok zľava doprava


const char* ssid = "WIFI NAME";

const char* password = "PASSWORLD";

// ===========================


// NeoPixel

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);


// WebServer a WebSocket

AsyncWebServer server(80);

AsyncWebSocket ws("/ws");


// --- mapovanie (x,y) -> index do pásu/panela ---

// --- mapovanie (x,y) -> index do pásu/panela (hadovitá 8x8) ---

int xyToIndex(int x, int y) {

// Jednoduché riadkové mapovanie: 0,0 = ľavý horný roh

return y * WIDTH + x;

}






// HTML stránka – 8×8 mriežka, väčšie políčka, kreslenie ťahaním (Pointer Events)

const char htmlPage[] PROGMEM = R"rawliteral(

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">

<style>

:root { --px: 36px; } /* veľkosť jedného políčka */

body { font-family: Arial, sans-serif; background:#111; color:#fff; margin:0; padding:18px; text-align:center; }

h2 { margin: 0 0 12px 0; font-weight:600; }

.toolbar { margin: 10px auto 16px auto; display:flex; gap:12px; justify-content:center; align-items:center; flex-wrap:wrap; }

#colorPicker { width: 44px; height: 44px; padding:0; border:none; background:transparent; }

#grid {

margin: 0 auto;

display: grid;

grid-template-columns: repeat(8, var(--px));

grid-template-rows: repeat(8, var(--px));

gap: 2px;

touch-action: none; /* dôležité pre plynulé ťahanie na mobile */

user-select: none;

}

.pixel {

width: var(--px);

height: var(--px);

background: #000;

border: 1px solid #333;

border-radius: 4px;

}

button {

padding: 8px 12px; border: 0; border-radius: 8px; background:#2b2b2b; color:#fff; cursor:pointer;

}

button:hover { filter: brightness(1.15); }

</style>

</head>

<body>

<h2>NeoPixel 8×8 – kreslenie</h2>

<div class="toolbar">

<input type="color" id="colorPicker" value="#ff0000" />

<button id="clearBtn">Vyčistiť</button>

<button id="fillBtn">Vyplniť</button>

</div>


<div id="grid"></div>


<script>

const W = 8, H = 8;

let ws;

let drawing = false;

let color = "#ff0000";


function connectWS() {

ws = new WebSocket(`ws://${location.host}/ws`);

ws.onclose = () => setTimeout(connectWS, 1000);

}

connectWS();


const picker = document.getElementById('colorPicker');

picker.addEventListener('input', e => color = e.target.value);


const grid = document.getElementById('grid');


// posielanie farby na (x,y)

function sendXY(x, y, hex) {

const r = parseInt(hex.substr(1,2),16);

const g = parseInt(hex.substr(3,2),16);

const b = parseInt(hex.substr(5,2),16);

if (ws && ws.readyState === 1) {

// formát: "XY,x,y,r,g,b"

ws.send(`XY,${x},${y},${r},${g},${b}`);

}

}


// vytvor mriežku 8×8, ulož x/y do datasetu

for (let y = 0; y < H; y++) {

for (let x = 0; x < W; x++) {

const d = document.createElement('div');

d.className = 'pixel';

d.dataset.x = x;

d.dataset.y = y;

grid.appendChild(d);

}

}


// zafarbiť políčko lokálne aj poslať na ESP

function paintCell(el) {

if (!el || !el.classList.contains('pixel')) return;

el.style.background = color;

const x = parseInt(el.dataset.x, 10);

const y = parseInt(el.dataset.y, 10);

sendXY(x, y, color);

}


// podpora myš/touch/pero cez Pointer Events

grid.addEventListener('pointerdown', e => {

drawing = true;

paintCell(e.target);

});

grid.addEventListener('pointermove', e => {

if (!drawing) return;

const el = document.elementFromPoint(e.clientX, e.clientY);

paintCell(el);

});

window.addEventListener('pointerup', () => drawing = false);

window.addEventListener('pointercancel', () => drawing = false);

window.addEventListener('pointerleave', () => drawing = false);


// Vyčistenie a vyplnenie

document.getElementById('clearBtn').onclick = () => {

[...grid.children].forEach(c => c.style.background = '#000000');

if (ws && ws.readyState === 1) ws.send('CLR');

};

document.getElementById('fillBtn').onclick = () => {

[...grid.children].forEach(c => c.style.background = color);

if (ws && ws.readyState === 1) {

const r = parseInt(color.substr(1,2),16);

const g = parseInt(color.substr(3,2),16);

const b = parseInt(color.substr(5,2),16);

ws.send(`FILL,${r},${g},${b}`);

}

};

</script>

</body>

</html>

)rawliteral";


// --- spracovanie WebSocket správ ---

void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {

AwsFrameInfo *info = (AwsFrameInfo*)arg;

if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {

// očakávané formáty:

// "XY,x,y,r,g,b"

// "CLR"

// "FILL,r,g,b"

String msg = String((char*)data);


if (msg.startsWith("XY")) {

// XY,x,y,r,g,b

int x, y, r, g, b;

char cmd[3];

if (sscanf(msg.c_str(), "%2[^,],%d,%d,%d,%d,%d", cmd, &x, &y, &r, &g, &b) == 6) {

if (x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT) {

int idx = xyToIndex(x, y);

strip.setPixelColor(idx, strip.Color(r, g, b));

strip.show();

}

}

} else if (msg.startsWith("CLR")) {

for (int i = 0; i < LED_COUNT; i++) strip.setPixelColor(i, 0);

strip.show();

} else if (msg.startsWith("FILL")) {

int r, g, b;

char cmd[5];

if (sscanf(msg.c_str(), "%4[^,],%d,%d,%d", cmd, &r, &g, &b) == 4) {

uint32_t c = strip.Color(r, g, b);

for (int i = 0; i < LED_COUNT; i++) strip.setPixelColor(i, c);

strip.show();

}

}

}

}


void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,

void *arg, uint8_t *data, size_t len) {

if (type == WS_EVT_DATA) {

handleWebSocketMessage(arg, data, len);

}

}


void setup() {

strip.begin();

strip.show(); // všetko na čierno


Serial.begin(115200);

Serial.println();

Serial.println("Startujem Wi-Fi...");


WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

delay(400);

Serial.print(".");

}

Serial.println("\nWiFi pripojené!");

Serial.print("IP adresa: ");

Serial.println(WiFi.localIP());


ws.onEvent(onEvent);

server.addHandler(&ws);


// hlavná stránka

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){

request->send_P(200, "text/html", htmlPage);

});


// tiché favicon (aby nezahlcovalo log)

server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){

request->send(204);

});


server.begin();

Serial.println("Webserver beží.");

}


void loop() {

ws.cleanupClients();

}



Replace "WIFI NAME" with your Wi-Fi network name and "PASSWORD" with your Wi-Fi password!!!







CONECTING TO PHONE

Obr&aacute;zok WhatsApp 2025-08-16 o&nbsp;15.43.31_8950db40.jpg

in Serial Monitor will display something like: IP: 123.456.7.890

Open this number (IP address) on a device connected to the same Wi-Fi network.

(RED wheel is collor picker) ("Vyčistiť" is clean) (Vyplniť is Color the entire)