Table of Contents
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.
- 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
- ESP32 Development Board: WiFi-enabled microcontroller
- PZEM-004T Module: AC voltage, current, power, energy meter
- SCT-013 Current Transformer: Non-invasive current sensing (0-100A)
- 5V Power Supply: For ESP32 and sensors
- Enclosure: DIN-rail mountable plastic box
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
- 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
- Plan Sensor Locations: Identify main feeders and major loads
- Mount CT Sensors: Clip around individual phase conductors
- Connect PZEM-004T:
- Voltage wires: Connect to L and N terminals
- CT cable: Plug into CT input
- UART: Connect to ESP32 (Tx/Rx)
- Power ESP32: Use isolated 5V supply
- 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
- Real-Time Power: Gauge showing current kW consumption
- Energy Trend: Time series of kWh per hour/day
- Power Factor: Indicator for power quality
- Cost Tracker: Running cost based on tariff
- Peak Demand: Maximum demand alert
- Machine Comparison: Bar chart of consumption by machine
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
- Specific Energy Consumption (SEC): kWh per unit produced
- Load Factor: Average load / Peak load
- Power Factor: Should be > 0.95
- Peak Demand: Maximum kW in billing period
- Energy Cost per Unit: Total cost / Production volume
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
- 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
Related Articles:
PLC & SCADA Integration |
Predictive Maintenance
Useful Tools:
All IoT Tools |
MQTT Message Generator