11. Embedded Networking and Communications
Group assignment:
Send a message between two projects Document your work to the group work page and reflect on your individual page what you learned
Individual assignment:
design, build and connect wired or wireless node(s) with network or bus addresses and a local input and/or output devices
GROUP ASSIGNMENT
In the group assignment Page you could see how we communicate between boards .
I2C Protocol
I2C (Inter-Integrated Circuit) is a well-known and widely used protocol. It allows us to connect multiple readers to a single writer, which means you can have multiple sensors connected to the same pins of your Arduino board through I2C. The only requirement is that each sensor must have a unique address.
The I2C protocol uses two lines to send and receive data: a serial clock pin (SCL), where the Arduino writer board pulses at a regular interval, and a serial data pin (SDA), which carries data between the two devices.
When the clock line changes from low to high, a single bit of information is transferred over the SDA line. This information forms the address of a specific device along with a command or data. After receiving this information, the addressed device executes the request and, if required, sends its data back to the board over the same line, using the clock signal that the writer continues to generate on SCL.
I have decided to use the I2C protocol as part of my network and communication week, replicate the board, and add a servomotor to it. For this project, I have selected the ATtiny 412 as my microcontroller.
SCHEMATICS
Looking at the schematics below, we can see the detailed circuit layout for connecting the ATtiny 412 microcontroller with the necessary components for I2C communication. The circuit includes pull-up resistors for the SDA and SCL lines, which are essential for proper I2C operation. The servomotor is connected to one of the available GPIO pins of the ATtiny 412, allowing for precise control through PWM signals.
PCB BOARD LAYOUT
The PCB board layout was designed with careful consideration of component placement and signal routing. The I2C lines (SDA and SCL) are routed with minimal length and maintained equal trace lengths to ensure reliable communication. Special attention was given to the placement of pull-up resistors and bypass capacitors near the ATtiny 412 for optimal performance.
I was about to Mill then my instructor told to do something with Http protocol using Esp . So i decided to Change my circuit as a whole and start once Again .
CONCEPTS TO DO THIS WEEK
+----------------------------------------+
| ESP32 WROOM 02D |
+----------------------------------------+
|
v
+----------------------------------------+
| Network and Communication Week |
| - Exploring HTTP Protocol |
| - Exploring ESP-NOW Protocol |
+----------------------------------------+
|
v
+----------------------------------------+
| Communication with Two ESP Boards |
| - Action: Clicking a Switch |
| - Result: OLED Display on Other Board |
| Turns On and Displays Time |
+----------------------------------------+
HTTP PROTOCOL
HTTP (Hypertext Transfer Protocol) is a fundamental protocol used for transmitting data over the internet. It follows a client-server model where the client (usually a web browser) sends requests to a server, and the server responds with the requested data. In our project, we'll be using the ESP-WROOM-02 module to implement HTTP communication, allowing our device to interact with web services and send/receive data over WiFi.
The below image shows the basic Pinout Diagram of ESP- Wroom- 02
To connect the Peripherals i have checked their Peripheral schematics on their data sheet .
ESP WROOM 02 Schematics
The schematic diagram shows the essential connections required for the ESP-WROOM-02 module, including the power supply circuitry, reset circuit, and programming interface. I've included pull-up resistors on the necessary GPIO pins and decoupling capacitors to ensure stable operation. The design also incorporates a USB-to-UART bridge for easy programming and debugging capabilities.
ESP WROOM 02D PCB LAYOUT
The PCB layout for the ESP-WROOM-02D was designed with careful consideration of RF performance and signal integrity. I ensured proper ground plane continuity and kept the antenna area free from any copper pour or traces that could interfere with WiFi performance. The layout also includes dedicated power planes and follows recommended design guidelines for high-frequency circuits.
PCB MILLING
The PCB milling process was executed using the Roland Modela MDX-20 milling machine. Following the standard milling workflow, I first milled the traces using a 1/64" endmill, followed by cutting the board outline with a 1/32" endmill. The process required careful attention to milling parameters and proper fixation of the copper board to ensure precise cutting of the traces and clean board edges.
XTOOLS
XTools is an advanced PCB milling software that provides precise control over the milling process. It offers features like automatic tool path generation, depth control, and optimization for different mill bit sizes. I used XTools specifically for its ability to handle fine traces and complex board layouts efficiently.
I milled two boards, using XTools for one of them.
Then i have Soldered The components To one Board . This is the board that i have made .
ESP WROOM 02 library addition arduino
Here are the steps to install the library:
TThe ESP-WROOM-02D is a module based on the ESP8266 chip, not a development board itself. To program this module using the Arduino IDE, follow these steps:
- Install the ESP8266 board package in the Arduino IDE if you haven't already. Add the following URL to your Additional Board Manager URLs:https://arduino.esp8266.com/stable/package_esp8266com_index.json
- Navigate to Tools > Board > Boards Manager, search for "ESP8266" and install the package.
- After installation, select Tools > Board and choose either "Generic ESP8266 Module" or "NodeMCU 1.0 (ESP-12E Module)" as these are compatible with the ESP-WROOM-02D.
- Before uploading code, put the module in flash mode by connecting GPIO0 to GND during power-up or reset.
- Unless your development board includes USB-to-Serial functionality, you'll need an external USB-to-Serial adapter (such as an FTDI adapter) to program the module.
Code To Find Mac Address For ESP WROOM 02 D
#include <espnow.h>
#include <ESP8266WiFi.h>
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.println("ESP-NOW MAC Address:");
Serial.println(WiFi.macAddress());
}
void loop() {
// Your main code here
}
16:58:42.727 -> CC:50:E3:36:4C:AC
ESPNOW
ESP-NOW is a protocol developed by Espressif that enables direct device-to-device communication without requiring a traditional WiFi network infrastructure. It allows ESP32 and ESP8266 devices to communicate with each other using their MAC addresses, making it ideal for simple, low-latency applications. In our project, we're using ESP-NOW to establish communication between two ESP-WROOM-02D boards, where one board acts as a sender (transmitting switch state) and the other as a receiver (controlling the OLED display).
Sender Code
#include <esp_now.h>
#include <WiFi.h>
// REPLACE WITH THE MAC Address of your receiver ESP8266
uint8_t broadcastAddress[] = {0xCC, 0x50, 0xE3, 0x36, 0x4C, 0xAC}; // REPLACE THIS with your ESP8266 MAC
// Define pins for rotary encoder - USING YOUR WORKING PINS
#define ENCODER_A 27
#define ENCODER_B 14
#define BUTTON 39
// Variables for rotary encoder
volatile int counter = 0;
volatile boolean TurnDetected = false;
volatile boolean up = false;
// Structure to send data
typedef struct struct_message {
int encoderValue;
bool buttonState;
} struct_message;
// Create a structured object
struct_message myData;
bool buttonPressed = false;
// Callback function when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Last Packet Send Status: ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
// Interrupt handler for encoder
void IRAM_ATTR readEncoder() {
TurnDetected = true;
up = (digitalRead(ENCODER_A) == digitalRead(ENCODER_B));
}
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Register peer
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
return;
}
// Register for a callback function that will be called when data is sent
esp_now_register_send_cb(OnDataSent);
// Set up rotary encoder pins
pinMode(ENCODER_A, INPUT);
pinMode(ENCODER_B, INPUT);
pinMode(BUTTON, INPUT);
// Attach interrupt - USING YOUR WORKING APPROACH
attachInterrupt(digitalPinToInterrupt(ENCODER_B), readEncoder, RISING);
// Print MAC Address for reference
Serial.print("ESP32 MAC Address: ");
Serial.println(WiFi.macAddress());
}
void loop() {
// Check for button press
if (digitalRead(BUTTON) == LOW) {
buttonPressed = !buttonPressed;
// Send the value via ESP-NOW
myData.encoderValue = counter;
myData.buttonState = buttonPressed;
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
Serial.print("Button State: ");
Serial.println(buttonPressed ? "Pressed" : "Released");
delay(200); // Debounce delay
}
// Check for encoder rotation
if (TurnDetected) {
if (up) {
counter++;
} else {
counter--;
}
Serial.print("Counter: ");
Serial.println(counter);
// Send the value via ESP-NOW
myData.encoderValue = counter;
myData.buttonState = buttonPressed;
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
TurnDetected = false; // Reset the flag
}
delay(10); // Small delay to avoid excessive CPU usage
}
RECEIVER CODE
#include <ESP8266WiFi.h>
#include <espnow.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define I2C_ADDRESS 0x3C
// Define I2C pins for ESP8266
#define SDA_PIN 2 // GPIO4 on ESP-WROOM-02D
#define SCL_PIN 14 // GPIO5 on ESP-WROOM-02D
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Data structure - must match the sender
typedef struct struct_message {
int counter;
char message[32];
} struct_message;
struct_message myData;
// Callback function when data is received
void OnDataRecv(uint8_t *mac, uint8_t *incomingData, uint8_t len) {
memcpy(&myData, incomingData, sizeof(myData));
Serial.println("Data received!");
Serial.print("Bytes received: ");
Serial.println(len);
Serial.print("Counter: ");
Serial.println(myData.counter);
Serial.print("Message: ");
Serial.println(myData.message);
// Update OLED display
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("ESP-NOW Received:");
display.setCursor(0, 16);
display.print("Counter: ");
display.println(myData.counter);
display.setCursor(0, 32);
display.println(myData.message);
display.display();
}
void setup() {
Serial.begin(115200);
// Initialize I2C
Wire.begin(SDA_PIN, SCL_PIN);
// Initialize OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, I2C_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("ESP-NOW Receiver");
display.println("Waiting for data...");
display.display();
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// Initialize ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Set ESP8266 as a slave
esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
// Register callback function
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
// Nothing to do here
}
There was some ERRORS SO i Tried to Code something Simple .
TURNING ON THE LED USING ESPNOW
To implement a basic LED control system using ESP-NOW protocol, I used two ESP-WROOM-02D boards - one as a sender and one as a receiver. The sender board is programmed to send an LED state command when reset, while the receiver board controls the LED based on the received command. This simple implementation helped me understand the basics of ESP-NOW communication before attempting more complex applications.
SENDER CODE
#include <esp_now.h>
#include <WiFi.h>
// ESP-WROOM-02D MAC Address (replace with your receiver's MAC)
uint8_t receiverAddress[] = {0xCC, 0x50, 0xE3, 0x36, 0x4C, 0xAC};
// Structure to send data
typedef struct struct_message {
bool ledState;
} struct_message;
struct_message myData;
// Callback function when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Last Packet Send Status: ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void setup() {
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Initialize ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Register send callback
esp_now_register_send_cb(OnDataSent);
// Register peer
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, receiverAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
// Send LED ON command on boot (after reset)
myData.ledState = true;
esp_now_send(receiverAddress, (uint8_t *) &myData, sizeof(myData));
Serial.println("Reset button pressed - LED ON command sent");
}
void loop() {
// Nothing needed in loop - message is sent once after reset
}
RECEIVER CODE
#include <ESP8266WiFi.h>
#include <espnow.h>
// Define LED pin
#define LED_PIN 16 // GPIO4 on ESP-WROOM-02D
// Data structure - must match the sender
typedef struct struct_message {
bool ledState;
} struct_message;
struct_message myData;
// Callback function when data is received
void OnDataRecv(uint8_t *mac, uint8_t *incomingData, uint8_t len) {
memcpy(&myData, incomingData, sizeof(myData));
Serial.println("Data received!");
Serial.print("LED State: ");
Serial.println(myData.ledState ? "ON" : "OFF");
// Set LED state based on received data
digitalWrite(LED_PIN, myData.ledState ? HIGH : LOW);
}
void setup() {
Serial.begin(115200);
// Initialize LED pin
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW); // Start with LED off
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// Initialize ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Set ESP8266 as a slave
esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
// Register callback function
esp_now_register_recv_cb(OnDataRecv);
Serial.println("Receiver ready");
}
void loop() {
// Nothing to do here
}
NEOPIXEL WORKING USING ESPNOW
For the NeoPixel implementation with ESP-NOW, I created a system where one ESP-WROOM-02D board acts as a controller to change the colors and patterns of a NeoPixel LED strip connected to another ESP board. The sender board sends RGB color values and pattern selection commands, while the receiver interprets these commands to create dynamic lighting effects. This allowed for wireless control of the LED strip with minimal latency.
#include <esp_now.h>
#include <WiFi.h>
// ESP-WROOM-02D MAC Address (replace with your receiver's MAC)
uint8_t receiverAddress[] = {0xCC, 0x50, 0xE3, 0x36, 0x4C, 0xAC};
// Structure to send data
typedef struct struct_message {
bool neopixelState;
uint8_t r, g, b;
uint8_t ledNumber; // Which LED to control (0-2)
} struct_message;
struct_message myData;
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Last Packet Send Status: ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_send_cb(OnDataSent);
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, receiverAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
// Turn on all three LEDs with different colors
for (int i = 0; i < 3; i++) {
myData.neopixelState = true;
myData.ledNumber = i;
```
// Different color for each LED
if (i == 0) {
myData.r = 255; myData.g = 0; myData.b = 0; // Red
} else if (i == 1) {
myData.r = 0; myData.g = 255; myData.b = 0; // Green
} else {
myData.r = 0; myData.g = 0; myData.b = 255; // Blue
}
esp_now_send(receiverAddress, (uint8_t *) &myData, sizeof(myData));
delay(100); // Small delay between messages
```
}
Serial.println("Reset button pressed - NeoPixel commands sent");
}
void loop() {
// Nothing needed in loop - messages sent once after reset
}
RECEIVER CODE
#include <ESP8266WiFi.h>
#include <espnow.h>
#include <Adafruit_NeoPixel.h>
// Define NeoPixel parameters
#define NUM_PIXELS 3 // Three NeoPixels in the strip
#define NEOPIXEL_PIN 4 // GPIO4 on ESP-WROOM-02D
// Initialize NeoPixel strip
Adafruit_NeoPixel pixels(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
// Data structure - must match the sender
typedef struct struct_message {
bool neopixelState;
uint8_t r, g, b;
uint8_t ledNumber; // Which LED to control (0-2)
} struct_message;
struct_message myData;
void OnDataRecv(uint8_t *mac, uint8_t *incomingData, uint8_t len) {
memcpy(&myData, incomingData, sizeof(myData));
Serial.println("Data received!");
Serial.print("NeoPixel State: ");
Serial.println(myData.neopixelState ? "ON" : "OFF");
Serial.printf("Color: R=%d, G=%d, B=%d\n", myData.r, myData.g, myData.b);
Serial.printf("LED Number: %d\n", myData.ledNumber);
// Check if the LED number is valid
if (myData.ledNumber < NUM_PIXELS) {
if (myData.neopixelState) {
pixels.setPixelColor(myData.ledNumber, pixels.Color(myData.r, myData.g, myData.b));
} else {
pixels.setPixelColor(myData.ledNumber, pixels.Color(0, 0, 0)); // Turn off
}
pixels.show();
}
}
void setup() {
Serial.begin(115200);
// Initialize NeoPixel
pixels.begin();
pixels.clear();
pixels.show();
WiFi.mode(WIFI_STA);
WiFi.disconnect();
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
esp_now_register_recv_cb(OnDataRecv);
Serial.println("Receiver ready");
}
void loop() {
// Nothing to do here
}
MULTIBOARD COMMUNICATION USING ESPNOW
Sender Code
#include <WiFi.h>
#include <esp_now.h>
#include <esp_wifi.h>
// MAC Addresses of your two ESP-WROOM-02D boards
uint8_t board1Address[] = {0xCC, 0x50, 0xE3, 0x36, 0x4C, 0xAC}; // First ESP-WROOM-02D
uint8_t board2Address[] = {0x80, 0x7D, 0x3A, 0x07, 0xED, 0xCA}; // Second ESP-WROOM-02D
// Track which board should be active
int activeBoard = 0; // 0 = none, 1 = board1, 2 = board2
// Callback function when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Last Packet Send Status: ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void setup() {
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Set WiFi channel
esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE);
// Initialize ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Register for a callback function that will be called when data is sent
esp_now_register_send_cb(OnDataSent);
// Register peers - initialize the struct properly
esp_now_peer_info_t peerInfo = {};
// Register first board
memcpy(peerInfo.peer_addr, board1Address, 6);
peerInfo.channel = 1;
peerInfo.encrypt = false;
peerInfo.ifidx = WIFI_IF_STA;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer 1");
} else {
Serial.println("Successfully added peer 1");
}
// Register second board
memcpy(peerInfo.peer_addr, board2Address, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer 2");
} else {
Serial.println("Successfully added peer 2");
}
// Cycle to next board on reset
activeBoard = (activeBoard % 3) + 1;
if (activeBoard == 3) activeBoard = 0;
// Send commands to both boards
uint8_t dataToBoard1 = (activeBoard == 1) ? 1 : 0;
uint8_t dataToBoard2 = (activeBoard == 2) ? 1 : 0;
esp_now_send(board1Address, &dataToBoard1, sizeof(dataToBoard1));
esp_now_send(board2Address, &dataToBoard2, sizeof(dataToBoard2));
Serial.print("Active board: ");
Serial.println(activeBoard);
}
void loop() {
// Nothing to do here - all happens on reset
}
RECEIVER CODE FOR 2 BOARDS
#include <ESP8266WiFi.h>
#include <espnow.h>
#include <Adafruit_NeoPixel.h>
// Define NeoPixel parameters
#define NEOPIXEL_PIN 4 // GPIO4 on ESP-WROOM-02D
#define NUM_PIXELS 3 // Number of NeoPixels in your strip
// Initialize NeoPixel strip
Adafruit_NeoPixel pixels(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
// Callback function when data is received
void OnDataRecv(uint8_t *mac, uint8_t *incomingData, uint8_t len) {
uint8_t command = incomingData[0];
Serial.print("Command received: ");
Serial.println(command);
if (command == 1) {
// Turn on NeoPixels with a color
for (int i = 0; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(255, 0, 255)); // Purple color
}
pixels.show();
Serial.println("NeoPixels ON");
} else {
// Turn off NeoPixels
for (int i = 0; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
}
pixels.show();
Serial.println("NeoPixels OFF");
}
}
void setup() {
Serial.begin(115200);
// Initialize NeoPixel
pixels.begin();
pixels.clear();
pixels.show();
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// Print MAC Address for reference
Serial.print("ESP8266 MAC Address: ");
Serial.println(WiFi.macAddress());
// Initialize ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Set ESP8266 as a slave
esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
// Register callback function
esp_now_register_recv_cb(OnDataRecv);
Serial.println("Receiver ready");
}
void loop() {
// Nothing to do here - all handled in callback
}
NeoPixel Controlling Using Http
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <Adafruit_NeoPixel.h>
// Define NeoPixel parameters
#define NEOPIXEL_PIN 4 // GPIO4 (D2) on ESP8266
#define NUM_PIXELS 3 // Number of pixels in your strip
// Initialize the NeoPixel strip
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
// SSID and Password of your WiFi router
const char* ssid = "FabGuest";
const char* password = "4fabGUEST";
// Create web server object
ESP8266WebServer server(80);
// Our HTML webpage contents in program memory
const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head>
<title>NeoPixel Control</title>
<style>
body { font-family: Arial; text-align: center; margin-top: 50px; }
.button {
background-color: #4CAF50;
color: white;
padding: 10px 20px;
margin: 10px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.button:hover { background-color: #45a049; }
.red { background-color: #f44336; }
.blue { background-color: #2196F3; }
.green { background-color: #4CAF50; }
.purple { background-color: #9C27B0; }
.off { background-color: #607D8B; }
</style>
</head>
<body>
<h1>ESP8266 NeoPixel Control</h1>
<p>Click a button to control the NeoPixels</p>
<div>
<a href="/neopixel?color=red"><button class="button red">RED</button></a>
<a href="/neopixel?color=green"><button class="button green">GREEN</button></a>
<a href="/neopixel?color=blue"><button class="button blue">BLUE</button></a>
<a href="/neopixel?color=purple"><button class="button purple">PURPLE</button></a>
<a href="/neopixel?color=off"><button class="button off">OFF</button></a>
</div>
</body>
</html>
)=====";
void setup() {
Serial.begin(115200);
// Initialize NeoPixel strip
pixels.begin();
pixels.clear();
pixels.show();
// Connect to WiFi
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Define server routes
server.on("/", handleRoot);
server.on("/neopixel", handleNeoPixel);
// Start the server
server.begin();
Serial.println("HTTP server started");
}
void loop() {
server.handleClient(); // Handle client requests
}
// Root page handler
void handleRoot() {
Serial.println("Main page requested");
server.send(200, "text/html", MAIN_page);
}
// NeoPixel control handler
void handleNeoPixel() {
String color = server.arg("color");
Serial.print("NeoPixel color: ");
Serial.println(color);
if (color == "red") {
setAllPixels(255, 0, 0); // Red
server.send(200, "text/plain", "NeoPixels set to RED");
}
else if (color == "green") {
setAllPixels(0, 255, 0); // Green
server.send(200, "text/plain", "NeoPixels set to GREEN");
}
else if (color == "blue") {
setAllPixels(0, 0, 255); // Blue
server.send(200, "text/plain", "NeoPixels set to BLUE");
}
else if (color == "purple") {
setAllPixels(180, 0, 255); // Purple
server.send(200, "text/plain", "NeoPixels set to PURPLE");
}
else if (color == "off") {
setAllPixels(0, 0, 0); // Off
server.send(200, "text/plain", "NeoPixels turned OFF");
}
else {
server.send(400, "text/plain", "Invalid color");
}
}
// Helper function to set all pixels to the same color
void setAllPixels(int red, int green, int blue) {
for (int i = 0; i < NUM_PIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(red, green, blue));
}
pixels.show();
}
This is how my Neopixel program to controll