In this project, we designed an open-source and modular IoT Smart Energy Meter using ESP32 and Blynk IoT 2.0. A Wi-Fi-based IoT network has been created to monitor daily energy consumption in our homes through smartphones and web dashboards. The system uses the ACS712 current sensor connected to the ESP32 development board to measure current and the ZMPT101B voltage sensor to measure voltage values. Real power, apparent power, and power factors can be calculated using these measured values and the phase angle.
The ESP32 development board, equipped with the ACS712 sensor, sends these measured and calculated values to the Blynk IoT platform. It provides a cloud server-based user interface where we can view these calculations and actual values. The interface is accessible via a web browser and mobile application using TCP/IP protocols. The system’s efficacy for general-purpose applications, such as IoT energy monitoring systems for smart home automation, has been demonstrated through experimental studies.
The electricity demand is crucial in our daily lives for technological development. Grid loading is managed for both residential and commercial consumers, requiring operators to distribute the load accordingly. Smart homes are designed to optimize energy consumption and support smart grids. The Internet of Things (IoT) plays a significant role in this context, encompassing industries like automotive, logistics, healthcare, smart grids, metro cities, and smart homes.
In this project, we focus on the Internet of Consumer Things (CIoT) systems. By monitoring and controlling home appliances like water heaters, air conditioners, and dishwashers, we can efficiently manage energy consumption. Traditional measuring methods, often labour-intensive and complex, are replaced by user-friendly CIoT systems with Wi-Fi-enabled devices. With widespread access to Wi-Fi networks, computers, and smartphones, this approach simplifies energy monitoring and management. The project also integrates Blynk 2.0 for enhanced mobile application control and uses a Telegram bot to generate and deliver energy consumption bills to users.
Must Read Smart Energy Monitoring System Using ESP32
Overview of IoT Smart Energy Meter
In this project, the SCT-013 current (CT) sensor has been replaced by the ACS712 current sensor for single-phase current measurement. Additionally, a 9V AC step-down transformer is used to measure the RMS value of the voltage. Both sensors are connected to the ESP32 board. Using the measured current, RMS voltage values, and phase angle, we can calculate the power factor, real power, and apparent power values within the Arduino IDE software.
The measured and calculated values are processed and transmitted by the ESP32 development board, using the Arduino IDE software. The ESP32, cloud server, and smartphone device communicate with each other via TCP/IP protocol over a Wi-Fi access point, creating an efficient CIoT network.
Circuit Diagram
Hardware Components
- ESP32 Development Board
- ACS712 Current Sensor
- ZMPT101B Voltage Sensor
- 16×2 I2C LCD Display Module
- 40 Watt Bulb as Load
- 5 Volt AC DC Converter
- Connection Wires
- Multimeter to Measure Voltage & Current (Additional)
- AC Mains Power Supply
Software Components
- Arduino IDE (Uploading Code)
- Blynk 2.0 Platform (Configure Realtime Data Visualization)
- Telegram (Generate Monthly Energy Consumption & Bill)
Understanding Components
ESP32 Development Board
It is a low-cost, minimal-power system on a microcontroller with integrated Wi-Fi and Bluetooth facility. ESP32 was created and developed by Espressif Systems, a Shanghai-based Chinese company, and it is manufactured by TSMC using its 40nm chip technology. In this project, we can use ESP8266 NodeMCU but there is only one analog pin that comes with it. And ESP32 have so many Analog pins. So according to our needs (Voltage and Current), we choose ESP32 despite ESP8266 NodeMCU.
ACS712 Current Sensor
The ACS712 current sensor is a popular device used for measuring current in a variety of applications, including energy monitoring and control systems. Here are some key points about the ACS712 current sensor:
- Current Measurement: The ACS712 can measure both AC and DC. It comes in different variants to measure different ranges of current, such as 5A, 20A, and 30A.
- Output Voltage: The sensor provides an Analog voltage output that is proportional to the current passing through the sensing element. This output can be read by an analog-to-digital converter (ADC) on a microcontroller like the ESP32.
- Sensitivity: Depending on the version, the sensor has different sensitivities. For example, the ACS712-05B has a sensitivity of 185 mV/A, the ACS712-20A has a sensitivity of 100 mV/A, and the ACS712-30A has a sensitivity of 66 mV/A.
- Accuracy and Response Time: The sensor is known for its good accuracy and fast response time, making it suitable for real-time current monitoring.
- Isolation: The ACS712 provides electrical isolation between the high-power load and the low-power circuitry, ensuring safety and protecting the microcontroller.
ZMPT101B Voltage Sensor:
The ZMPT101B is a voltage sensor module designed to measure AC voltage in various applications. It’s commonly used in projects involving power monitoring, home automation, and other IoT applications where voltage measurement is needed. Here are some key features and details about the ZMPT101B voltage sensor:
- High Accuracy: The ZMPT101B offers high accuracy in measuring AC voltage, making it suitable for precise applications.
- Isolation: It provides electrical isolation between the high voltage being measured and the low voltage circuitry of the microcontroller, enhancing safety.
- Wide Measurement Range: It can measure various AC voltages depending on the circuit design and calibration.
- Analog Output: The sensor outputs an Analog voltage proportional to the input AC voltage, which can be read by an Analog-to-Digital converter (ADC) in a microcontroller.
Circuit Connection
ZMPT101B Voltage Sensor:
- VCC (Power): Connect to ESP32 3.3V pin.
- GND (Ground): Connect to ESP32 GND pin.
- OUT (Analog Output): Connect to an ESP32 ADC pin (e.g., GPIO 34).
ACS712 Current Sensor:
- VCC (Power): Connect to ESP32 3.3V pin.
- GND (Ground): Connect to ESP32 GND pin.
- OUT (Analog Output): Connect to another ESP32 ADC pin (e.g., GPIO 35).
I2C LCD Display:
- VCC (Power): Connect to ESP32 3.3V pin.
- GND (Ground): Connect to ESP32 GND pin.
- SDA (Data Line): Connect to ESP32 GPIO 21 (SDA).
- SCL (Clock Line): Connect to ESP32 GPIO 22 (SCL).
How to Create Blynk 2.0 Dashboard for IoT Smart Energy Meter
To set up Blynk 2.0 for your project, you’ll need to create a web dashboard and a mobile dashboard that can display real-time data for voltage, current, power, energy units, and total cost. Here’s a step-by-step guide:
Create a Blynk 2.0 Account and Project
Sign Up: If you don’t already have an account, sign up on the [Blynk 2.0 platform].
- Create a New Template:
- Go to the “Templates” tab.
- Click “New Template”.
- Give your template a name (e.g., “IoT Energy Meter”).
- Set the hardware to ESP32.
Create Datastreams:
- Navigate to the “Datastreams” section within your template.
- Create data streams for each parameter you want to monitor:
- Voltage: Select type
Virtual Pin
(V0). - Current: Select type
Virtual Pin
(V1). - Power: Select type
Virtual Pin
(V2). - Units Consumed: Select type
Virtual Pin
(V3). - Total Cost: Select type
Virtual Pin
(V4).
Save Template: Save your template and copy the “Template ID” and “Device Name” for later use.
Set Up the Blynk Web Dashboard
Create a New Device:
- Go to the “Devices” tab.
- Click “New Device” and select the template you created.
- Follow the prompts to configure the device.
Web Dashboard Setup:
- Navigate to the “Web Dashboard” tab of your device.
- Drag and drop widgets for displaying your data:
- Gauge and Label widgets for Voltage, Current, Power, Units Consumed, and Total Cost.
- Link each widget to the corresponding data stream.
Configure Widgets: For each widget, set the label, datastream, and display settings (e.g., units, range).
Set Up the Blynk Mobile Dashboard
- Download Blynk App: Install the Blynk IoT app from the App Store or Google Play.
- Log In: Log in with the same account credentials used for the web dashboard.
- Add a Device: Add the device corresponding to your template.
Mobile Dashboard Setup:
- Tap on the device to enter the dashboard setup.
- Add widgets similar to the web dashboard.
- “Gauge” and “Value Display” for Voltage, Current, Power, Units Consumed, and Total Cost.
- Assign each widget to the appropriate data stream.
Configure Widgets: Set the label, datastream, and display options (units, decimals, etc.).
This setup allows you to monitor voltage, current, power, energy units, and total cost through both web and mobile dashboards. You can also set up notifications and alerts using Blynk’s features for a comprehensive energy monitoring solution.
How to Create a Telegram Bot and Implement with IoT Smart Energy Meter
Creating and integrating a Telegram bot with an IoT smart energy meter for billing involves several steps, including setting up the bot, coding the ESP32 to communicate with Telegram, and implementing the billing logic. Here’s a step-by-step guide:
Create a Telegram Bot:
Create the Bot:
- Open the Telegram app and search for “BotFather”.
- Start a chat with BotFather and use the command
/start
. - Use the command
/newbot
to create a new bot. - Follow the prompts to name your bot and set a username. The username must end with “bot”.
- After creating the bot, you’ll receive a “Bot Token”. This token is essential for connecting your bot to Telegram’s API.
Get Your Chat ID:
- You’ll need their chat IDs to send messages to yourself or specific users.
- You can use the bot to find your chat ID by sending a message to your bot and then using an online service like ‘https://api.telegram.org/botYOUR_BOT_TOKEN/getUpdates‘ to get your user ID.
Set Up the ESP32 to Communicate with Telegram
Install Required Libraries: In the Arduino IDE, install the ‘UniversalTelegramBot’ and ‘WiFiClientSecure’ libraries.
Connect ESP32 to Wi-Fi: Configure the ESP32 to connect to your Wi-Fi network.
Send Messages to Telegram: Use the ‘UniversalTelegramBot’ library to send messages from the ESP32 to Telegram.
Implement Billing System:
Calculate Energy Consumption and Cost:
- Track the total energy consumed using the power data from your sensors.
- Calculate the total cost based on a predefined rate per unit of energy.
Send Billing Information to Telegram: Implement a function in your code to send billing details to the user via the Telegram bot.
ESP32 Code for IoT Smart Energy Meter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | #define BLYNK_TEMPLATE_ID "*********" // Define Blynk template ID #define BLYNK_TEMPLATE_NAME "*********" // Define Blynk template name #define BLYNK_PRINT Serial // Enable Serial printing for Blynk debug information #include "EmonLib.h" // Include EmonLib for energy monitoring #include <EEPROM.h> // Include EEPROM library for storing data #include <WiFi.h> // Include WiFi library for network connectivity #include <BlynkSimpleEsp32.h> // Include Blynk library for ESP32 #include <Wire.h> // Include Wire library for I2C communication #include <LiquidCrystal_I2C.h> // Include LiquidCrystal_I2C library for LCD display #include <HTTPClient.h> // Include HTTPClient library for HTTP requests #include <ArduinoJson.h> // Include ArduinoJson library for JSON handling LiquidCrystal_I2C lcd(0x27, 16, 2); // Initialize LCD with I2C address 0x27 and size 16x2 // Define your Telegram bot token and chat ID const char* telegramBotToken = "*********"; // Telegram bot token const char* telegramChatID = "*********"; // Telegram chat ID // Constants for calibration const float vCalibration = 42.5; // Voltage calibration factor const float currCalibration = 1.80; // Current calibration factor // Blynk and WiFi credentials const char auth[] = "*********"; // Blynk authentication token const char ssid[] = "*********"; // WiFi SSID const char pass[] = "*********"; // WiFi password // EnergyMonitor instance EnergyMonitor emon; // Create an instance of EnergyMonitor // Timer for regular updates BlynkTimer timer; // Create a Blynk timer instance // Variables for energy calculation float kWh = 0.0; // Variable to store energy consumed in kWh float cost = 0.0; // Variable to store cost of energy consumed const float ratePerkWh = 6.5; // Cost rate per kWh unsigned long lastMillis = millis(); // Variable to store last time in milliseconds // EEPROM addresses for each variable const int addrKWh = 12; // EEPROM address for kWh const int addrCost = 16; // EEPROM address for cost // Display page variable int displayPage = 0; // Variable to track current LCD display page // Reset button pin const int resetButtonPin = 4; // Pin for reset button (change to your button pin) // Function prototypes void sendEnergyDataToBlynk(); // Prototype for sending energy data to Blynk void readEnergyDataFromEEPROM(); // Prototype for reading energy data from EEPROM void saveEnergyDataToEEPROM(); // Prototype for saving energy data to EEPROM void updateLCD(); // Prototype for updating LCD display void changeDisplayPage(); // Prototype for changing LCD display page void sendBillToTelegram(); // Prototype for sending bill to Telegram void resetEEPROM(); // Prototype for resetting EEPROM data void setup() { WiFi.begin(ssid, pass); // Start WiFi connection while (WiFi.status() != WL_CONNECTED) { delay(500); // Wait for WiFi connection } Blynk.begin(auth, ssid, pass); // Start Blynk connection // Initialize the LCD lcd.init(); // Initialize the LCD lcd.backlight(); // Turn on LCD backlight // Initialize EEPROM EEPROM.begin(32); // Initialize EEPROM with 32 bytes of storage // Initialize the reset button pin pinMode(resetButtonPin, INPUT_PULLUP); // Set reset button pin as input with pull-up resistor // Read stored data from EEPROM readEnergyDataFromEEPROM(); // Read energy data from EEPROM // Setup voltage and current inputs emon.voltage(35, vCalibration, 1.7); // Configure voltage measurement: input pin, calibration, phase shift emon.current(34, currCalibration); // Configure current measurement: input pin, calibration // Setup timers timer.setInterval(2000L, sendEnergyDataToBlynk); // Set timer to send energy data to Blynk every 2 seconds timer.setInterval(2000L, changeDisplayPage); // Set timer to change display page every 2 seconds timer.setInterval(60000L, sendBillToTelegram); // Set timer to send bill to Telegram every 60 seconds } void loop() { Blynk.run(); // Run Blynk timer.run(); // Run timers // Check if the reset button is pressed if (digitalRead(resetButtonPin) == LOW) { // If reset button is pressed (assuming button press connects to ground) delay(200); // Debounce delay resetEEPROM(); // Reset EEPROM data } } void sendEnergyDataToBlynk() { emon.calcVI(20, 2000); // Calculate voltage and current: number of half wavelengths (crossings), time-out float Vrms = emon.Vrms; // Get root mean square voltage float Irms = emon.Irms; // Get root mean square current float apparentPower = emon.apparentPower; // Get apparent power // Calculate energy consumed in kWh unsigned long currentMillis = millis(); // Get current time in milliseconds kWh += apparentPower * (currentMillis - lastMillis) / 3600000000.0; // Update kWh lastMillis = currentMillis; // Update last time // Calculate the cost based on the rate per kWh cost = kWh * ratePerkWh; // Calculate cost // Save the latest values to EEPROM saveEnergyDataToEEPROM(); // Save energy data to EEPROM // Send data to Blynk Blynk.virtualWrite(V0, Vrms); // Send voltage to Blynk virtual pin V0 Blynk.virtualWrite(V1, Irms); // Send current to Blynk virtual pin V1 Blynk.virtualWrite(V2, apparentPower); // Send apparent power to Blynk virtual pin V2 Blynk.virtualWrite(V3, kWh); // Send energy in kWh to Blynk virtual pin V3 Blynk.virtualWrite(V4, cost); // Send cost to Blynk virtual pin V4 // Update the LCD with the new values updateLCD(); // Update LCD display } void readEnergyDataFromEEPROM() { EEPROM.get(addrKWh, kWh); // Read kWh from EEPROM EEPROM.get(addrCost, cost); // Read cost from EEPROM // Initialize to zero if values are invalid if (isnan(kWh)) { kWh = 0.0; // Set kWh to 0 if invalid saveEnergyDataToEEPROM(); // Save to EEPROM } if (isnan(cost)) { cost = 0.0; // Set cost to 0 if invalid saveEnergyDataToEEPROM(); // Save to EEPROM } } void saveEnergyDataToEEPROM() { EEPROM.put(addrKWh, kWh); // Save kWh to EEPROM EEPROM.put(addrCost, cost); // Save cost to EEPROM EEPROM.commit(); // Commit EEPROM changes } void updateLCD() { lcd.clear(); // Clear LCD display if (displayPage == 0) { lcd.setCursor(0, 0); // Set cursor to first row lcd.printf("V:%.fV I: %.fA", emon.Vrms, emon.Irms); // Print voltage and current lcd.setCursor(0, 1); // Set cursor to second row lcd.printf("P: %.f Watt", emon.apparentPower); // Print power and energy } else if (displayPage == 1) { lcd.setCursor(0, 0); // Set cursor to first row lcd.printf("Energy: %.2fkWh", kWh); // Print energy lcd.setCursor(0, 1); // Set cursor to second row lcd.printf("Cost: %.2f", cost); // Print cost } } void changeDisplayPage() { displayPage = (displayPage + 1) % 2; // Change display page updateLCD(); // Update LCD display } void sendBillToTelegram() { String message = "Total Energy Consumed: " + String(kWh, 2) + " kWh\nTotal Cost: ₹" + String(cost, 2); // Create message HTTPClient http; // Create HTTP client http.begin("https://api.telegram.org/bot" + String(telegramBotToken) + "/sendMessage"); // Begin HTTP request http.addHeader("Content-Type", "application/json"); // Add header DynamicJsonDocument jsonDoc(256); // Create JSON document jsonDoc["chat_id"] = telegramChatID; // Set chat ID jsonDoc["text"] = message; // Set message text String jsonString; // Create JSON string serializeJson(jsonDoc, jsonString); // Serialize JSON document int httpCode = http.POST(jsonString); // Send HTTP POST request // Optional: Handle HTTP errors here http.end(); // End HTTP request } void resetEEPROM() { kWh = 0.0; // Reset kWh to 0 cost = 0.0; // Reset cost to 0 saveEnergyDataToEEPROM(); // Save to EEPROM } |
Deploy and Monitor:
- Deploy the ESP32: Upload the code to your ESP32.
- Monitor Telegram: The bot will send billing information to the specified chat ID at regular intervals.
Additional Considerations
- Security: Ensure that your bot token and Wi-Fi credentials are kept secure. Avoid hardcoding sensitive information directly into your code if possible.
- Customizations: You can add more features, such as real-time alerts for high consumption, commands to request the current bill or additional data visualization.