Back to IoT Blog
Industrial IoT 25 min read

Factory Energy Monitoring System

Build a comprehensive energy monitoring system for factories. Track real-time power consumption, identify energy waste, and optimize industrial equipment usage with IoT sensors.

System Overview

Industrial facilities can reduce energy costs by 10-30% through proper monitoring and optimization. This system provides real-time visibility into power consumption across all major equipment.

Key Benefits:
  • Real-time power monitoring per machine
  • Energy consumption trending and analytics
  • Peak demand alerts and load shedding
  • Power quality monitoring (voltage, frequency)
  • Cost allocation by department/production line
  • Predictive maintenance through power signatures

System Architecture

[Current Transformers] → [ESP32 Nodes] → [MQTT Broker]
                                                    ↓
                                          [InfluxDB/TimescaleDB]
                                                    ↓
                                          [Grafana Dashboard]

Hardware Components

Per Monitoring Node

PZEM-004T Specifications

Parameter Range Accuracy
Voltage 80-260V AC ±0.5%
Current 0-100A AC ±1%
Power 0-23kW ±0.5%
Energy 0-9999 kWh ±0.5%
Frequency 45-65 Hz ±0.5%
Power Factor 0.00-1.00 ±2%

Sensor Installation

⚠️ HIGH VOLTAGE WARNING:
  • Only qualified electricians should install CT sensors
  • Turn off main power before working in electrical panels
  • Use proper PPE (insulated gloves, safety glasses)
  • Follow local electrical codes and regulations
  • Never open current transformer secondary while primary is energized

Installation Steps

  1. Plan Sensor Locations: Identify main feeders and major loads
  2. Mount CT Sensors: Clip around individual phase conductors
  3. Connect PZEM-004T:
    • Voltage wires: Connect to L and N terminals
    • CT cable: Plug into CT input
    • UART: Connect to ESP32 (Tx/Rx)
  4. Power ESP32: Use isolated 5V supply
  5. Test Communication: Verify serial data from PZEM

Wiring Diagram

Mains Power
    │
    ├───[CT Sensor]───┐
    │                 │
    └───[PZEM-004T]───┘
              │
         UART (Tx/Rx)
              │
         [ESP32]
              │
         WiFi → Router

ESP32 Firmware

Reading data from PZEM-004T and publishing via MQTT:

#include <WiFi.h>
#include <PubSubClient.h>
#include <PZEM004Tv30.h>
#include <ArduinoJson.h>

// WiFi credentials
const char* ssid = "FACTORY_WIFI";
const char* password = "your_password";

// MQTT configuration
const char* mqtt_server = "192.168.1.100";
const int mqtt_port = 1883;
const char* mqtt_topic = "factory/energy/machine1";

// PZEM-004T on Serial2
PZEM004Tv30 pzem(Serial2, 16, 17); // Tx=16, Rx=17

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, 17, 16);
  
  // Connect to WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected");
  
  // MQTT setup
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
}

void reconnect() {
  while (!client.connected()) {
    if (client.connect("EnergyMonitor1")) {
      client.subscribe("factory/energy/commands");
    } else {
      delay(5000);
    }
  }
}

void loop() {
  if (!client.connected()) reconnect();
  client.loop();
  
  // Read PZEM measurements
  float voltage = pzem.voltage();
  float current = pzem.current();
  float power = pzem.power();
  float energy = pzem.energy();
  float frequency = pzem.frequency();
  float pf = pzem.pf();
  
  // Create JSON payload
  StaticJsonDocument<256> doc;
  doc["voltage"] = voltage;
  doc["current"] = current;
  doc["power"] = power;
  doc["energy"] = energy;
  doc["frequency"] = frequency;
  doc["pf"] = pf;
  doc["timestamp"] = millis();
  
  char jsonBuffer[512];
  serializeJson(doc, jsonBuffer);
  
  // Publish to MQTT
  client.publish(mqtt_topic, jsonBuffer);
  
  delay(5000); // Read every 5 seconds
}

void callback(char* topic, byte* payload, unsigned int length) {
  // Handle commands (e.g., change reporting interval)
  Serial.print("Message arrived: ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

Cloud Integration

Setting up the backend for data storage and visualization:

InfluxDB Setup

# Docker Compose for InfluxDB + Telegraf + Grafana
version: '3'
services:
  influxdb:
    image: influxdb:2.7
    ports:
      - "8086:8086"
    volumes:
      - influxdb-data:/var/lib/influxdb2
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=secure_password
      - DOCKER_INFLUXDB_INIT_ORG=factory
      - DOCKER_INFLUXDB_INIT_BUCKET=energy
  
  telegraf:
    image: telegraf:1.24
    volumes:
      - ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
    depends_on:
      - influxdb
  
  grafana:
    image: grafana/grafana:9.5
    ports:
      - "3000:3000"
    volumes:
      - grafana-data:/var/lib/grafana
    depends_on:
      - influxdb

volumes:
  influxdb-data:
  grafana-data:

Telegraf MQTT Configuration

[[inputs.mqtt_consumer]]
  servers = ["tcp://192.168.1.100:1883"]
  topics = ["factory/energy/+/+"]
  qos = 0
  data_format = "json"
  tag_keys = ["machine_id"]
  timestamp_key = "timestamp"
  timestamp_format = "ms"

[[outputs.influxdb_v2]]
  urls = ["http://influxdb:8086"]
  token = "your-influx-token"
  organization = "factory"
  bucket = "energy"

Dashboard Setup

Create Grafana dashboards for energy monitoring:

Key Panels

Sample InfluxQL Queries

-- Real-time power consumption
SELECT mean("power") FROM "energy" 
WHERE $timeFilter GROUP BY time(1m)

-- Daily energy consumption
SELECT sum("energy") FROM "energy" 
WHERE $timeFilter GROUP BY time(1d), "machine"

-- Power factor over time
SELECT mean("pf") FROM "energy" 
WHERE $timeFilter GROUP BY time(5m)

Energy Analytics

Key Metrics to Track

Alert Rules

-- High power consumption alert
SELECT mean("power") FROM "energy" 
WHERE time > now() - 5m GROUP BY "machine"
-- Alert if > threshold

-- Low power factor alert
SELECT mean("pf") FROM "energy" 
WHERE time > now() - 15m
-- Alert if < 0.85

-- Equipment running off-hours
SELECT count("power") FROM "energy" 
WHERE time > now() - 1h AND power > 100
-- Alert if equipment running outside schedule
Energy Saving Opportunities:
  • Identify equipment running unnecessarily
  • Detect compressed air leaks (continuous baseline)
  • Optimize startup/shutdown sequences
  • Schedule high-power operations during off-peak
  • Right-size motors (avoid oversized equipment)
  • Install VFDs on variable load motors

Next Steps

Expand your energy monitoring system:

  • Add water and gas metering
  • Integrate with production data for OEE calculation
  • Implement automated demand response
  • Add solar generation monitoring
  • Connect to building management system (BMS)
  • Implement ISO 50001 energy management