Power ESP8266 with Mains Voltage using Hi-Link HLK-PM03 Converter

In this post you’ll learn how to power the ESP8266 (or ESP32) with mains voltage using the Hi-Link HLK-PM03 converter. As an example, we’ll use the ESP8266-01 to control a relay with a web server.

The ESP32 and ESP8266 are cheap Wi-Fi modules perfectly suited for DIY projects in the Internet of Things (IoT) and Home Automation fields. Using an ESP32 or ESP8266 with a relay allows you to control any AC electronics appliances over Wi-Fi (using a web-server, for example).

One of the biggest issues with these projects is to find a suitable power supply for the ESP32/ESP8266 with a small form factor at the same time (in a final application you don’t want to power the relay and the ESP32/ESP8266 using two different power supplies). One solution is to power the ESP8266 or ESP32 from mains voltage using the AC/DC converter Hi-Link HLK-PM03 (or HLK-PM01 model).

Introducing the Hi-Link HLK-PM03/01 Converter Modules

The Hi-Link HLK-PM03  is a small AC/DC converter module as shown in the figure below.

The HLK-PM03 AC/DC converter can supply 3.3V from either 110VAC or 220VAC. This makes it perfect for small projects that need a 3.3V supply from mains voltage. You can also get 5V output using the HLK-PM01 instead.

Build home automation projects with the ESP8266 Wi-Fi dev board using Arduino IDE and Lua firmware DOWNLOAD »

Build home automation projects with the ESP8266 Wi-Fi dev board using Arduino IDE and Lua firmware DOWNLOAD »

You can read more information about these modules’ specifications: HLK-PM03 and HLK-PM01. There’s also a really good article about the performance test of the HLK-PM01.

To power the ESP8266-01 from mains voltage, we’ll be using the HLK-PM03 to provide 3.3V to the VCC pin. If you need 5V to power other ESP8266 models or an ESP32 through the VIN pin, you can use the HLK-PM01 model that provides 5V output and works similarly.

Where to Buy?

You can check the HLK-PM03 or HLK-PM01 modules on Maker Advisor and find the best price.

Safety Warning

This project deals with mains voltage. Make sure you understand what you are doing. Please read the safety warning below carefully.

Powering the ESP8266 with AC using the Hi-Link HLK-PM03 module

You can use the HLK-PM03 without any circuitry and attach it directly to the ESP8266 VCC pin. However, I don’t recommend doing that. It is advisable to add a protection circuit with a thermal fuse and quick-blow fuses.

Adding capacitors to the HLK-PM03 output is also a good idea to smooth voltage peaks and prevent unexpected resets or unstable behavior powering the ESP8266. We’ve also added a varistor across the mains input to protect the circuit from voltage peaks.

Parts Required

Here’s a list of all the parts required to build the circuit for the project we’ll build:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Circuit Diagram

The following figure shows the circuit diagram.

Download our Free eBooks and Resources

The J1 terminal block is where you should connect mains voltage.

The 3.3V and GND after the capacitors will power the ESP8266-01.

We’ve also added a three terminal block connected to the ESP8266 to get access to 3.3V, GND and GPIO 2 to control an output (relay module). Because we’re dealing with 3.3V you should use a 3.3V relay module like this, for example.

For testing purposes, we’ve soldered the circuit on a prototype board. We plant to build a PCB with this circuit in a future project.

Soldering Thermal Fuses

The thermal fuse used in the circuit is a 73ºC fuse. This means you need to be very careful when soldering it as the heat from the soldering iron can cause it to blow. To learn more about how to solder thermal fuses, we recommend taking a look at the following resources:

Code

In this example we’ve programmed the ESP8266 with Arduino IDE. To program the ESP8266 using Arduino IDE, you need to have the ESP8266 add-on installed. Follow the next tutorial to install the ESP8266 add-on, if you haven’t already.

The following code creates a web server that you can access to control the relay connected to the ESP8266 (GPIO 2) via Wi-Fi in your local network.

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/

// Load Wi-Fi library
#include <ESP8266WiFi.h>

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output2State = "off";

// Assign output variables to GPIO pins
const int output2 = 2;

// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0; 
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;

void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(output2, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output2, LOW);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
      currentTime = millis();
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            
            // turns the GPIOs on and off
            if (header.indexOf("GET /2/on") >= 0) {
              Serial.println("GPIO 2 on");
              output2State = "on";
              digitalWrite(output2, HIGH);
            } else if (header.indexOf("GET /2/off") >= 0) {
              Serial.println("GPIO 2 off");
              output2State = "off";
              digitalWrite(output2, LOW);
            }
            
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons 
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #77878A;}</style></head>");
            
            // Web Page Heading
            client.println("<body><h1>ESP8266 Web Server</h1>");
            
            // Display current state, and ON/OFF buttons for GPIO 5  
            client.println("<p>GPIO 2 - State " + output2State + "</p>");
            // If the output5State is off, it displays the ON button       
            if (output2State=="off") {
              client.println("<p><a href=\"/2/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/2/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 
               
            client.println("</body></html>");
            
            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

View raw code

Setting Your Network Credentials

You need to modify the following lines with your network credentials: SSID and password before uploading the code. The code is well commented on where you should make the changes.

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

For an explanation of the code, you can read the following tutorial: ESP8266 Web Server with Arduino IDE.

Note: if you’re using an ESP32 with the HLK-PM01 module, you can use the code in this tutorial.

Uploading the Code

Upload the code provided to the ESP8266-01 board using an FTDI programmer or a ESP8266-01 serial adapter.

If you’re using an FTDI programmer like this, you need to make a connection as shown in the following schematic diagram:

After uploading the code, open the Serial Monitor to get the ESP8266-01 IP address. You’ll need it to access the web server.

Demonstration

After uploading the code to your ESP8266 and getting the IP address, place it in the circuit and apply power to the circuit.

Warning: don’t touch the circuit while it is connected to mains voltage!

Open your browser, type the ESP IP address and the following page should load.

You should be able to control the relay remotely on your local network.

Note: we’re using the circuit on a prototype board for demonstration purposes. If you want to use the circuit in a final application, we recommend building a PCB and place it inside a proper project box enclosure.

We plan to build this circuit on a PCB in the upcoming weeks if there’s enough interest, and we’ll share all the files and resources you need to build your own PCB with the HLK-PM03 or HLK-PM01 modules.

Wrapping Up

The HLK-PM01 and HLK-PM03 are converter modules that provide 5V and 3.3V respectively, from mains voltage. This provides an easy way to power your ESP8266 or ESP32 in your IoT and Home Automation projects.

We hope you’ve found this project helpful! If you like these subjects, you may also like:


Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

10 thoughts on “Power ESP8266 with Mains Voltage using Hi-Link HLK-PM03 Converter”

  1. I would not trust these cheap components from China when dealing with high dangerous voltages. In the link you gave some of the HLK-PM03 do not seem to have CE Certification or ANY type of certification. The one you used does.

    I think another idea might be to use a 5v phone charger and a 3.3v zener diode to get the required 3.3v. At least with the phone charger you know it’s safe if it’s from a reputable company. The other big advantage of using a phone charger is that the source 220v is far away from the circuit board so no creepage problems. Most homes have plenty of chargers lying around in drawers.

    Yet another idea might be to use the 5v phone charger with two or three diode in series to provide the needed voltage drop. Each diode should give about 0.7v drop. Anyway, let’s be very careful out there with high voltages.

  2. Excellent article qui va me faire progresser pour l’utilisation des ESP en domotique.
    J’attends la suite avec impatience
    Merci pour ce que vous faites

  3. Super fine example- Nice to be able to build it all together, and with good security, it is all well protected.

    But why two electrolyte capacitors just after each other?

  4. Good idea with a PCB, but then there will probably be room for a Wemos D1 Mini, so there are more input / output to work with, and more terminals to connect sensors, push bottons, LED’s with more …

  5. Hello, very nice tutorial! But please help me for this component: Fuse Quick Blow (630mA). Can you explain me the function and give me an example for this part? I’m not an electric-specialist. Thank you!

    • Hi Markus.
      The fuse quick blow protects your circuit (the ESP8266) in case of voltage spikes. It can be a bit overkill adding that fuse, and the circuit works without it. However, for safety reasons, and to be sure that it will not burn the ESP8266, we add that fuse. You can get one from any electronics components store.
      Regards,
      Sara

Leave a Comment

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.