Summit
EMQ Sponsors Open Source Summit Europe 2024 | Register Now →

Remotely Control an LED with ESP8266 and MQTT

Dekun Tao
Mar 14, 2024
Remotely Control an LED with ESP8266 and MQTT

Introduction

This tutorial explores how to leverage the ESP8266 Wi-Fi module and MQTT protocol for remote control of an LED light.

The ESP8266 is a cost-effective Wi-Fi module that offers a highly integrated Wi-Fi SoC solution, suitable for low-power applications, compact design, and high stability to meet user needs. It boasts complete and self-contained Wi-Fi networking capabilities, functioning independently or as a slave to another host MCU.

MQTT is a publish/subscribe messaging protocol where two roles exist: the publisher and the subscriber. The publisher sends messages to a topic, and the subscriber receives messages from topics they are interested in. In this tutorial, we'll use the ESP8266 as the publisher to send messages to a topic, which a subscriber will listen to, allowing us to control the on/off state of an LED light remotely.

Project Setup

Prepare the Environment

Before embarking on this project, ensure you have the following hardware and software:

  • Hardware:
    • 1 x NodeMCU ESP8266 development board
    • 1 x LED light
    • 1 x 330Ω resistor
    • 1 x Breadboard
    • Several Dupont wires
  • Software:

Hardware Connection

Connect the long leg (anode) of the LED through a resistor to the D1 (GPIO 5) pin on the NodeMCU, and the short leg (cathode) directly to GND. The resistor is used to limit the current flowing through the LED to prevent damage.

Connection Diagram

Connecting ESP8266 to the MQTT Server

Install ESP8266 Board Support

In the Arduino IDE, go to "File" > "Preferences" and add the following URL to the "Additional Board Manager URLs": http://arduino.esp8266.com/stable/package_esp8266com_index.json. Then, in "Tools" > "Board" > "Boards Manager," search for and install the ESP8266 board.

Install the PubSubClient Library

The PubSubClient library, necessary for connecting to MQTT servers, must be installed via the Arduino IDE's Library Manager by searching for PubSubClient and installing it.

Define the LED Pin and State

Considering our hardware setup, we need to define the LED pin. In this case, we'll use the GPIO 5 (D1) pin to connect to the LED.

#define LED 5 // GPIO 5 (D1) for LED
bool ledState = false;

Initialize Wi-Fi Connection

Before we can connect to the MQTT broker, we must first establish a Wi-Fi connection using the ESP8266WiFi library, an open-source Wi-Fi client library that facilitates connection to Wi-Fi networks.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// WiFi settings
const char *ssid = "YOUR_WIFI_SSID";             // Replace with your WiFi name
const char *password = "YOUR_WIFI_PASSWORD";   // Replace with your WiFi password

Configure MQTT Broker Connection Parameters

We'll use the free public MQTT broker provided by EMQX for this tutorial.

// MQTT Broker settings
const char *mqtt_broker = "broker.emqx.io";  // EMQX broker endpoint
const char *mqtt_topic = "emqx/esp8266/led";  // MQTT topic
const char *mqtt_username = "emqx";  // MQTT username for authentication (if required)
const char *mqtt_password = "public";  // MQTT password for authentication (if required)
const int mqtt_port = 1883;  // MQTT port (TCP)

Initialize Wi-Fi and MQTT Clients

WiFiClient espClient;
PubSubClient mqtt_client(espClient);

Connect to Wi-Fi

void connectToWiFi() {
    WiFi.begin(ssid, password);
    Serial.print("Connecting to WiFi");
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("\nConnected to the WiFi network");
}

Connect to the MQTT Server and Subscribing to Topics

In this section, we'll connect to the MQTT server and subscribe to a topic. We'll use the mqtt_client.connect() method to connect to the MQTT server and then mqtt_client.subscribe() to subscribe to a topic and publish a test message upon successful connection.

void connectToMQTTBroker() {
    while (!mqtt_client.connected()) {
        String client_id = "esp8266-client-" + String(WiFi.macAddress());
        Serial.printf("Connecting to MQTT Broker as %s.....\n", client_id.c_str());
        if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
            Serial.println("Connected to MQTT broker");
            mqtt_client.subscribe(mqtt_topic);
            // Publish message upon successful connection
            mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP8266 ^^");
        } else {
            Serial.print("Failed to connect to MQTT broker, rc=");
            Serial.print(mqtt_client.state());
            Serial.println(" try again in 5 seconds");
            delay(5000);
        }
    }
}

Write the Callback Function

When the MQTT client receives a message, we need to perform the LED light's on/off operation. We use the mqtt_client.setCallback() method to set up a callback function that executes when the MQTT client receives a message. If the message is "on," we turn on the LED; if "off," we turn it off.

void mqttCallback(char *topic, byte *payload, unsigned int length) {
    Serial.print("Message received on topic: ");
    Serial.println(topic);
    Serial.print("Message:");
    String message;
    for (int i = 0; i < length; i++) {
        message += (char)payload[i];  // Convert *byte to string
    }
    // Control the LED based on the message received
    if (message == "on" && !ledState) {
        digitalWrite(LED, HIGH);  // Turn on the LED
        ledState = true;
        Serial.println("LED is turned on");
    }
    if (message == "off" && ledState) {
        digitalWrite(LED, LOW); // Turn off the LED
        ledState = false;
        Serial.println("LED is turned off");
    }
    Serial.println();
    Serial.println("-----------------------");
}

Full Code

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#define LED 5 // GPIO 5 (D1) for LED
bool ledState = false;

// WiFi settings
const char *ssid = "WIFI_SSID";             // Replace with your WiFi name
const char *password = "WIFI_PASSWORD";   // Replace with your WiFi password

// MQTT Broker settings
const char *mqtt_broker = "broker.emqx.io";  // EMQX broker endpoint
const char *mqtt_topic = "emqx/esp8266";     // MQTT topic
const char *mqtt_username = "emqx";  // MQTT username for authentication
const char *mqtt_password = "public";  // MQTT password for authentication
const int mqtt_port = 1883;  // MQTT port (TCP)

WiFiClient espClient;
PubSubClient mqtt_client(espClient);

void connectToWiFi();

void connectToMQTTBroker();

void mqttCallback(char *topic, byte *payload, unsigned int length);

void setup() {
    Serial.begin(115200);
    connectToWiFi();
    mqtt_client.setServer(mqtt_broker, mqtt_port);
    mqtt_client.setCallback(mqttCallback);
    connectToMQTTBroker();
}

void connectToWiFi() {
    WiFi.begin(ssid, password);
    Serial.print("Connecting to WiFi");
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("\nConnected to the WiFi network");
}

void connectToMQTTBroker() {
    while (!mqtt_client.connected()) {
        String client_id = "esp8266-client-" + String(WiFi.macAddress());
        Serial.printf("Connecting to MQTT Broker as %s.....\n", client_id.c_str());
        if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
            Serial.println("Connected to MQTT broker");
            mqtt_client.subscribe(mqtt_topic);
            // Publish message upon successful connection
            mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP8266 ^^");
        } else {
            Serial.print("Failed to connect to MQTT broker, rc=");
            Serial.print(mqtt_client.state());
            Serial.println(" try again in 5 seconds");
            delay(5000);
        }
    }
}

void mqttCallback(char *topic, byte *payload, unsigned int length) {
    Serial.print("Message received on topic: ");
    Serial.println(topic);
    Serial.print("Message:");
    String message;
    for (int i = 0; i < length; i++) {
        message += (char) payload[i];  // Convert *byte to string
    }
    // Control the LED based on the message received
    if (message == "on" && !ledState) {
        digitalWrite(LED, HIGH);  // Turn on the LED
        ledState = true;
        Serial.println("LED is turned on");
    }
    if (message == "off" && ledState) {
        digitalWrite(LED, LOW); // Turn off the LED
        ledState = false;
        Serial.println("LED is turned off");
    }
    Serial.println();
    Serial.println("-----------------------");
}

void loop() {
    if (!mqtt_client.connected()) {
        connectToMQTTBroker();
    }
    mqtt_client.loop();
}

Connecting and Testing

Upload Code to ESP8266

Copy the complete code into the Arduino IDE and upload it to the ESP8266 development board. Open the serial monitor to observe the board connecting to the Wi-Fi network and then to the MQTT server.

Upload Code to ESP8266

Control the LED with MQTTX

Use the MQTTX client to connect to the MQTT server, subscribe to the emqx/esp8266/led topic, and publish "on" messages to turn the LED on and "off" messages to turn it off.

MQTTX

Conclusion

This tutorial guided you through using the ESP8266 and MQTT protocol for remote LED control. This project is just the tip of the iceberg in IoT applications. You can expand upon it by adding more sensors and actuators or integrating it into a home automation system.

Talk to an Expert
Contact Us →

Related Posts

Jun 3, 2023Saiteng You
How to Use MQTT on Raspberry Pi with Paho Python Client

The Paho Python Client provides a client class with support for both MQTT v3.1 and v3.1.1 on Python 2.7 or 3.x. This article introduces how to use the Paho MQTT client library in the Python project.

Oct 12, 2020Saiteng You
Comparison of Python MQTT Clients

This article collects three common Python MQTT client libraries, and compares them in library development, and complexity of use, for readers to select easily.