IoT Based Energy Monitoring System using ESP32 and Firebase

In today’s rapidly evolving world, where energy efficiency is crucial for sustainable living, the Internet of Things (IoT) offers innovative solutions to monitor and manage energy consumption. In this article, we will explore an IoT-based energy monitoring system that utilizes the ESP32 microcontroller and CT sensor to track and analyze energy usage in real time. By implementing such a system, individuals and businesses can gain insights into their energy consumption patterns and make informed decisions to optimize their energy usage.

Our other ESP32-related tutorials are:

Understanding IoT-based Energy Monitoring Systems

IoT-based energy monitoring systems leverage the power of interconnected devices to gather, analyze, and visualize energy consumption data. By integrating sensors, microcontrollers, and communication protocols, these systems enable users to track their energy usage in real-time and make data-driven decisions for energy optimization. Such systems provide valuable insights into energy consumption patterns, identify wastage, and help individuals and organizations adopt sustainable practices.

SCT-013 Current Sensor

The SCT013 CT sensor is a popular Current Transformer (CT) sensor used in energy monitoring systems. It is designed to measure alternating current (AC) flowing through a conductor without the need for direct electrical contact which means it’s a Non-invasive sensor. It is a clamp meter sensor which is clamped phase or neutral wire of a power line but clamping on a neutral wire provides us more appropriate result. We can measure 0 to 100A current using SCT-013. Depending on output there are two types of SCT-013 available in the market. One provides voltage (0 to 1V) output and the other provides current (0 to 50mA) output.

SCT-013 Current Sensor

The secondary of a Current Transformer (CT) cannot keep open because open secondary makes infinity voltage (practically 1000V) that causes damage to your sensor permanently. So we need a resistor to reduce this high voltage and it’s called a burden resistor.  The voltage output type SCT-013 has a built-in burden resistor but the current output type has no built-in burden resistor. For Arduino the value of the burden resistor is 33Ω and for ESP32 it is 22 Ω.

Understanding of ESP32 Analog to Digital Converter (ADC)

SCT-013 provides us 0-1V or 0-50mA output which means for 0A SCT-013 gives 0V, for 50A it gives 0.5V, for 100A it provides 1V.  These output values are not digital (i.e. 0V or 3.3V). these are analog values. So, we need to convert these values to digital. At this time ESP32 will help us. ESP32 has a 12-bit ADC with 18 measurement channels. 

ESP32 ADC Pins

To read the analog value, you need to trigger the ADC conversion and wait for it to complete. The ADC converts the analog voltage on the input pin into a digital value, which can be read from the ADC register. The value will be between 0 and 4095 (2^12=4096, one for 0 so it’s 4095), representing the voltage level in the range of 0V to the reference voltage (usually 3.3V). Once you have the digital value from the ADC, you can convert it back to the corresponding voltage using the formula:

Voltage = (Digital value / 4095) * Reference voltage

The resulting Voltage will represent the corresponding voltage value in the range of 0 to 3.3V. For example, if digital Value is 2048, the calculation would be:

Voltage = (2048 / 4095) * 3.3 = 1.65V

Therefore, a digital value of 2048 would correspond to a voltage of 1.65V.

Keep in mind that this calculation assumes a 3.3V reference voltage for the ADC. If your ESP32 is configured with a different reference voltage, you would need to adjust the formula accordingly.

Sending Data to an IoT Cloud

To send sensor data we will use Google Firebase in this project. Google Firebase is a comprehensive platform-as-a-service (PaaS) solution offered by Google that provides a range of tools and services for developing and managing web and mobile applications. While Firebase is commonly associated with mobile app development, its features and capabilities have proven to be valuable for Internet of Things (IoT) applications as well. Some core features of Google Firebase:

  • Real-time Database: Firebase’s Real-time Database is a NoSQL cloud-hosted database that enables real-time synchronization of data across connected devices. This feature is highly relevant to IoT applications, as it allows devices to communicate and share data seamlessly. IoT devices can push sensor readings, status updates, and other relevant information to the Firebase Real-time Database, ensuring that all connected devices receive the latest data instantly. This real-time synchronization is critical for IoT applications that require quick decision-making and timely responses.
  • Authentication and Security: IoT devices often handle sensitive data and require secure communication channels. Firebase provides robust authentication and security features, including user authentication, identity management, and access control. This allows developers to implement secure user authentication mechanisms, ensuring that only authorized individuals or devices can access and interact with IoT systems. Firebase’s security features help protect IoT applications from unauthorized access and potential data breaches.
  • Analytics and Monitoring: Firebase’s analytics and monitoring capabilities are valuable for gaining insights into IoT application usage, device performance, and user behavior. By integrating Firebase Analytics into an IoT application, developers can track and analyze metrics such as device connections, user engagement, data usage, and more. This data-driven approach helps optimize IoT applications, identify bottlenecks, and make informed decisions to enhance the overall user experience.
Firebase IoT Cloud

Creating a Google Firebase Account

Step 01: Go to firebase.com and sign up with your Google (Gmail) account.

Step 02: Click get started and create a project.

How to configure Forebase for ESP32
How to configure Forebase for ESP32

Step 03: Write your project name and continue.

4 min

Step 04: Disable Google Analytics and click create project.

5 min

Step 05: You can see your project name and click continue.

6 min

Step 06: Go to build>> Authentication

7 min

Step 07: Select the signup method. I selected Email/password.

8 min

Step 08: Enable Email/password and save.

9 min

Step 09: Click Add user

10 min

Step 10: Give an email and password.

11 min

Step 11: Go to Realtime Database

12 min 1

Step 12: Click Create Database

13 min

Step 13: Select your nearest server

14 min

Step 14: Select start in test mode and click enable

15 min

Step 15: go to real time database option and copy the database URL and paste it to DATABASE_URL of your esp32 code. 

19 min

Step 16: For the Firebase API key click the gear icon and go to project settings. Copy the API key and past into your ESP32 code at the Firebase API line.

18 min

Step 17: And you are done. After uploading ESP32 code you can see the value on this page.

16 min

Step 18: For the second time to find your project click Go to the console and you will see your project name.

17 min

Component list

Component NameQuantityPurchase Links
ESP32 Development Board1Amazon | AliExpress
SCT-013 Current Sensor1Amazon | AliExpress
One 10K Ohm, One 22 Ohm Resistor3Amazon | AliExpress
10 uF Capacitor1Amazon | AliExpress
Jumper Wire1Amazon | AliExpress
Breadboard1Amazon | AliExpress

Affiliate Disclosure: When you click on links to make a purchase, this can result in this website earning a commission. Affiliate programs and affiliations include, but are not limited to Amazon.com

Circuit Diagram

IoT based Energy Monitoring System circuit diagram

Install libraries in Arduino IDE

Before moving into the code, we need to install some libraries those will save your time.

Open your Arduino IDE. To install Eomon Library go to Tools>>Manage Libraries and search “EmonLib” and install.

emonlib

To install Firebase Library go to Tools>>Manage Libraries and search “firebase esp client” and install.

firebase

Code Description

Start with including some libraries such as wifi, Firebase, and EmonLib.

#include <Firebase_ESP_Client.h>
#include <Wire.h>
#include "EmonLib.h"

Define GPIO pin 35 as ADC input. You can choose any other ADC pin for your project. Define ADC_BITS as 12 because my ADC resolution is 12 bits. 

#define ADC_INPUT 35                  
#define ADC_BITS    12   

Create an instance as emon. Define wifi_ssid, and wifi_password where you will write your wifi name and password. In the firebase API section past your project API that is shown in the project settings. You added an email and password to your Firebase project in the Authentication section. Insert this email and its password. At last past your project URL. See “Creating Firebase Account and Project” section for more details. 

EnergyMonitor emon;                   
#define WIFI_SSID "write_your_wifi_ssid"                           
#define WIFI_PASSWORD "write_your_wifi_password"                     
#define API_KEY "past_Your_Firebase_API" 
#define USER_EMAIL "Write_your_email"   
#define USER_PASSWORD "Write_your_Authentication_email_password" 
#define DATABASE_URL "Past_your_real_time_database_URL"           

In this project, our main goal is to understand how to use a CT sensor and sending data to firebase. Hence to measure power we assume that the value of voltage and power factor are constant. So take two variables voltage and power factor(pf). In my country, the voltage is approximately 220V and the power factor is about 0.95. you can change these if you want.

float voltage=220.00;                                 
float pf=0.95;

Define some Firebase objects to send data to the Firebase database.

FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;

Assign some variables for Firebase database path.

String databasePath;
String voltagePath;
String currentPath;
String powerPath;

Initialize wifi. When the wifi SSID and password will be matched then an IP address will print on the serial monitor. If SSID and password doesn’t match then and line …… will show on the Arduino serial monitor.

void initWiFi() {
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println(WiFi.localIP());
  Serial.println();
}

Create a function named sendFloat that will send the current, power and voltage value to the  Firebase server. There are two arguments one is path and another one is value. For example, if we want to send a current value then we will call this function like this sendFloat(currentPath, current). When all the data will be passed a message “PASSED” will be shown on Arduino serial monitor and if fail to send data a “FAILED” message will show on the serial monitor.

void sendFloat(String path, float value){
  if (Firebase.RTDB.setFloat(&fbdo, path.c_str(), value)){
    Serial.print("Writing value: ");
    Serial.print (value);
    Serial.print(" on the following path: ");
    Serial.println(path);
    Serial.println("PASSED");
    Serial.println("PATH: " + fbdo.dataPath());
    Serial.println("TYPE: " + fbdo.dataType());
  }
  else {
    Serial.println("FAILED");
    Serial.println("REASON: " + fbdo.errorReason());
  }
}

Although ESP32 has maximum 12 bit resolution ADC you can change it by analogReadResolution() function. In this project we select 12 bit resolution. In setup function emon.current() function take two arguments the first one is ADC pin number and the second one is calibration. You may need to change calibration value for finding right reading. Rest of the lines are using to Initialize API, User email and password, database URL.

Serial.begin(115200);
analogReadResolution(ADC_BITS);    
emon.current(35, 26);             
initWiFi();
config.api_key = API_KEY;
auth.user.email = USER_EMAIL;
auth.user.password = USER_PASSWORD;
config.database_url = DATABASE_URL;

In the loop function, ESP32 reads the current value with the help of emon.Irms and send it to the Firebase server. Every 10 seconds the value will be updated and the updated value will send to the Firebase database. The values of current, power will be shown on Arduino serial monitor also.

if (Firebase.ready() && (millis() - sendDataPrevMillis > timerDelay || sendDataPrevMillis == 0)){
    sendDataPrevMillis = millis();
    emon.calcVI(20,2000);         
    current = emon.Irms;                           
    power = voltage*current*pf;                  
    sendFloat(currentPath, current);                 
    sendFloat(powerPath, power);                     
  }
  
      Serial.print("Cureent: ");
      Serial.print(current);
      Serial.println(" Amps");
      Serial.print("Power: ");
      Serial.print(power);
      Serial.println(" Watts");  
      delay(100);
}

Project Output

You can see your data from anywhere in the world in the real-time database section of Firebase.

esp32 firebase iot project output

Full code

Arduino IDE .ino file

#include <Arduino.h>
#if defined(ESP32)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <Firebase_ESP_Client.h>
#include <Wire.h>
#include "EmonLib.h"                   // Include Emon Library
#include <driver/adc.h>

#define ADC_INPUT 35                  // define IO pin 35 to read CT sensor value
#define ADC_BITS    12                // define ADC bit 12 for esp32 resulation

EnergyMonitor emon;                   // Create an instance
/******* You may need to change these lines *******/
// Insert your network credentials
#define WIFI_SSID "write_your_wifi_ssid"                           // Write your Wifi SSID or neme here
#define WIFI_PASSWORD "write_your_wifi_password"                     // Write your wifi password
// Insert Firebase project API Key
#define API_KEY "past_Your_Firebase_API" // Past your firebase api key here
// Insert Authorized Email and Corresponding Password
#define USER_EMAIL "Write_your_email"  // Write your firebase Authentication email and password
#define USER_PASSWORD "Write_your_Authentication_email_password" // Write your firebase Authentication password
// Insert RTDB URLefine the RTDB URL
#define DATABASE_URL "Past_your_real_time_database_URL"           // Past your real time batabase URL here

float voltage=220.00;                                 // change voltage
float pf=0.95;                                        // change power factor(pf)
               
WiFiClient client; //Initialize WiFi as client

// Provide the token generation process info.
#include "addons/TokenHelper.h"
// Provide the RTDB payload printing info and other helper functions.
#include "addons/RTDBHelper.h"

// Define Firebase objects
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;

// Variable to save USER UID
String uid;

// Variables to save database paths
String databasePath;
String voltagePath;
String currentPath;
String powerPath;

// Take some valiable 
float current;
float power;

// Timer variables (send new readings every three minutes)
unsigned long sendDataPrevMillis = 0;
unsigned long timerDelay = 10000;

// Initialize WiFi
void initWiFi() {
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println(WiFi.localIP());
  Serial.println();
}

// Write float values to the database
void sendFloat(String path, float value){
  if (Firebase.RTDB.setFloat(&fbdo, path.c_str(), value)){
    Serial.print("Writing value: ");
    Serial.print (value);
    Serial.print(" on the following path: ");
    Serial.println(path);
    Serial.println("PASSED");
    Serial.println("PATH: " + fbdo.dataPath());
    Serial.println("TYPE: " + fbdo.dataType());
  }
  else {
    Serial.println("FAILED");
    Serial.println("REASON: " + fbdo.errorReason());
  }
}

void setup(){
  Serial.begin(115200);
  analogReadResolution(ADC_BITS);    // 12 bit ADC
  
  emon.current(35, 26);             // Current: input pin, calibration // you can increase or decrease calibration argument to get right value from CT sensor 
  initWiFi();

  // Assign the api key (required)
  config.api_key = API_KEY;

  // Assign the user sign in credentials
  auth.user.email = USER_EMAIL;
  auth.user.password = USER_PASSWORD;

  // Assign the RTDB URL (required)
  config.database_url = DATABASE_URL;

  Firebase.reconnectWiFi(true);
  fbdo.setResponseSize(4096);

  // Assign the callback function for the long running token generation task */
  config.token_status_callback = tokenStatusCallback; //see addons/TokenHelper.h

  // Assign the maximum retry of token generation
  config.max_token_generation_retry = 5;

  // Initialize the library with the Firebase authen and config
  Firebase.begin(&config, &auth);

  // Getting the user UID might take a few seconds
  Serial.println("Getting User UID");
  while ((auth.token.uid) == "") {
    Serial.print('.');
    delay(1000);
  }
  // Print user UID
  uid = auth.token.uid.c_str();
  Serial.print("User UID: ");
  Serial.println(uid);

  // Update database path
  databasePath = "/UsersData/" + uid;

  // Update database path for sensor readings
  voltagePath = databasePath + "/voltage"; // --> UsersData/<user_uid>/voltage
  currentPath = databasePath + "/current"; // --> UsersData/<user_uid>/current
  powerPath = databasePath + "/power"; // --> UsersData/<user_uid>/power
}

void loop(){
    
  // Send new readings to Firebase database
  if (Firebase.ready() && (millis() - sendDataPrevMillis > timerDelay || sendDataPrevMillis == 0)){
    sendDataPrevMillis = millis();
    emon.calcVI(20,2000);         
    current = emon.Irms;                           // RMS value of current 
    power = voltage*current*pf;                  // calculate power // take power factor as 0.95  
    sendFloat(currentPath, current);                 // send current value to firebase
    sendFloat(powerPath, power);                     // send power value to firebase
  }
  
      Serial.print("Cureent: ");
      Serial.print(current);
      Serial.println(" Amps");
      Serial.print("Power: ");
      Serial.print(power);
      Serial.println(" Watts");  
      delay(100);
}

Rana Bhuiyan

I hold a B.Sc degree in Electrical & Electronic Engineering from Daffodil International University, Bangladesh. I am an Electronic circuit designer and Microcontroller programmer. I am interested in Robotics, Embedded System Design and IoT.

Recent Posts