rbgrid
Professional Power Measurement Library for ESP32
Real-time Monitoring • High Precision • Smart Energy Management
🚀 About the Library
rbgrid is a high-performance library for ESP32, designed for professional measurement and analysis of electrical parameters in real-time. Leveraging the full potential of ESP32's dual-core architecture and high-speed ADC with DMA, the library delivers unprecedented measurement accuracy and response speed for energy management systems.
💡 Key Advantages
- ⚡ Ultra-Fast Response: Real-time control with response times down to 10ms (1/100 second) — 100-300x faster than typical smart home solutions
- 📊 High Accuracy: ADC sampling rates up to 10kHz per channel provide detailed waveform analysis
- 🔄 Bidirectional Measurements: Automatic current direction detection for systems with generation and energy storage
- 💰 Intelligent Billing: Flexible cost calculation system with multi-zone tariffs and net-metering support
- 🌐 IoT Ready: Built-in support for web interface, MQTT, WebSocket for smart home integration
🎯 Applications
Home Energy Systems
- Solar Power: Monitor generation, consumption, and balance with accurate energy direction tracking
- Smart Home: Integration with Home Assistant, ESPHome for automation and energy optimization
- Protection & Safety: Instant disconnection on overloads, power quality monitoring
Commercial Solutions
- EV Charging Stations: Charging process control with dynamic load balancing
- Industrial Monitoring: Predictive maintenance based on power consumption analysis
- Metering & Billing: Multi-point metering with various tariff plan support
Energy Management
- Load Balancing: Automatic priority management of consumers with limited power capacity
- Peak Shaving: Reduce peak loads through intelligent control
- Generation Optimization: Maximize self-consumption before grid import
⚙️ Technical Features
Measurements & Analysis
- ✅ True RMS voltage and current measurements
- ✅ Power Calculations: Active (P), Reactive (Q), Apparent (S) power
- ✅ Power Factor (cos φ) and phase shift analysis
- ✅ THD Analysis and harmonic spectrum up to 25th harmonic
- ✅ Grid Frequency with ±0.01 Hz accuracy
- ✅ Energy Accumulation with separate consumption and generation tracking
Supported Sensors
- Voltage: ZMPT101B, ZMPT107-1, resistive voltage dividers
- Current: SCT-013 (all variants), ACS712, shunt resistors
- Calibration: Automatic and manual with NVS storage
Architecture & Performance
- 🔧 Dual-Core Processing: Core 0 for API and peripherals, Core 1 for calculations
- 🔧 ADC DMA: Hardware data acquisition without CPU load
- 🔧 Linear Processing: Optimized algorithms for embedded systems
- 🔧 Zero-Cross Synchronization: Precise grid phase locking
📈 Economic Features
Billing & Metering
- Multi-Zone Tariffs: Peak/off-peak, weekends, holidays
- Net-Metering: Separate tracking of import and export
- Forecasting: Expected cost calculations based on history
- Optimization: Load shifting recommendations for favorable tariff zones
Generation Monitoring
- Solar Panels: MPPT tracking, yield forecasting
- Wind Turbines: Efficiency analysis
- Batteries: Charge/discharge control, ROI calculations
- Hybrid Systems: Source optimization
🔮 Development Roadmap
In Development (v2.1)
- 🌐 Web Application: Modern interface for visualization and configuration
- 📡 Extended Telemetry: MQTT, HTTP API, WebSocket streaming
- 📱 Mobile App: iOS/Android clients
Planned (v2.2)
- 🔗 Wireless Sensors: BLE and ESP-NOW for remote measurement points
- 🎛️ Load Control: Integration with relays and AC dimmers
- 🤖 Automation: Energy management scenarios and rules
- 🏠 ESPHome/HA: Native integration via YAML configuration
Future (v3.0)
- ⚡ 3-Phase Systems: Full industrial grid support
- 🧠 ML Optimization: Predictive consumption algorithms
- 🔐 Blockchain: Decentralized metering for P2P energy trading
- 🌍 Cloud Platform: SaaS solution for fleet management
🛠️ Compatibility
Supported Hardware
- ✅ ESP32: Original series (recommended)
- ✅ ESP32-H: Dual-core architecture with improved ADC
- ❌ ESP32-C3/C6: Not supported (single-core)
- ❌ ESP8266: Not supported
Software Platforms
- ESP-IDF: v5.0+ (recommended for maximum performance)
- Arduino Core: v3.0+ (use VS code IDE, not Arduino IDE)
- PlatformIO: Not support support
📊 Comparison with Alternatives
Feature | rbgrid | PZEM-004T | EmonLib | IotaWatt |
---|---|---|---|---|
Sample Rate | 10 kHz | 1 Hz | 2 kHz | 2 kHz |
Response Time | 10 ms | 1000 ms | 100 ms | 1000 ms |
Current Direction | ✅ | ❌ | ❌ | ✅ |
THD Analysis | ✅ | ❌ | Basic | ✅ |
Web Interface | ✅ | ❌ | ❌ | ✅ |
Solution Cost | free | $$ | $ | $$$ |
🚀 Quick Start. Arduino example
/**
* @file basic_app.cpp
* @brief Basic application example with sensor initialization and terminal output
*/
#include "Arduino.h"
#include "rbgrid.h"
#include "rbtelemetry.h"
#include "rbgrid.h"
#include "rbgrid_config_api.h"
#include "esp_timer.h"
#include "driver/gpio.h"
// ====== PINS ======
#define ZC_CROSS_PIN 18 // GPIO18 for Zero Cross
// ====== GLOBAL VARIABLES ======
rbgrid_unit_uid_t voltage_sensor_uid;
rbgrid_unit_uid_t current_sensor_uid;
rbgrid_unit_uid_t alt_sensor_uid;
rbgrid_unit_uid_t heater_sensor_uid;
static rbgrid_extended_config_t* g_extended_config = NULL;
// Forward declaration for access to internal structures
struct rbgrid_config_context_s {
rbgrid_extended_config_t* extended_config;
rbgrid_hardware_config_t* hardware_config;
rbgrid_electrical_network_t* network;
rbgrid_unit_definition_t* units_array;
uint16_t units_allocated;
uint16_t units_count;
struct {
int next_sensor_id;
int next_unit_id;
uint8_t adc_channels_used;
bool has_zc_sensor;
bool has_voltage_bus;
bool has_main_supply;
bool has_alternative_supply;
} builder;
struct {
bool base_initialized;
bool network_configured;
bool sensors_configured;
bool units_configured;
} status;
bool is_initialized;
bool is_applied;
};
typedef struct rbgrid_config_context_s rbgrid_config_context_t;
// ====== SETUP ======
void setup() {
Serial.begin(115200);
Serial.println("\n=== Basic rbgrid example ===");
// Reset ADC pins
gpio_reset_pin(GPIO_NUM_33);
gpio_reset_pin(GPIO_NUM_34);
gpio_set_direction(GPIO_NUM_33, GPIO_MODE_INPUT);
gpio_set_direction(GPIO_NUM_34, GPIO_MODE_INPUT);
gpio_set_pull_mode(GPIO_NUM_33, GPIO_FLOATING);
gpio_set_pull_mode(GPIO_NUM_34, GPIO_FLOATING);
// Create configuration via API
rbgrid_config_handle_t config_handle = rbgrid_config_create("Test House", "HongKong");
if (!config_handle) {
Serial.println("ERROR: Failed to create configuration");
return;
}
// Configure network
int config_err = rbgrid_config_set_configuration(config_handle);
if (config_err != RBGRID_CONFIG_OK) {
Serial.print("ERROR: Failed to configure network: ");
Serial.println(config_err);
rbgrid_config_destroy(config_handle);
return;
}
// Get pointers to internal structures
rbgrid_config_context_t* config_ctx = (rbgrid_config_context_t*)config_handle;
rbgrid_extended_config_t* extended_config = config_ctx->extended_config;
rbgrid_hardware_config_t* base_hardware_config = config_ctx->hardware_config;
// Network frequency configuration
base_hardware_config->network.nominal_frequency = 50;
// Add voltage sensor ZMPT107-1 on GPIO35
voltage_sensor_uid = rbgrid_config_add_adc_sensor(config_handle, GPIO_NUM_35, RBSENSOR_TYPE_VOLTAGE_ZMPT107_1);
if (voltage_sensor_uid == RBGRID_INVALID_UNIT_UID) {
Serial.println("ERROR: Failed to add voltage sensor");
} else {
Serial.print("Voltage sensor added, UID: 0x");
Serial.println(voltage_sensor_uid, HEX);
}
// Add current sensor SCT013-10A on GPIO34
current_sensor_uid = rbgrid_config_add_adc_sensor(config_handle, GPIO_NUM_34, RBSENSOR_TYPE_CURRENT_SCT013_10A);
if (current_sensor_uid == RBGRID_INVALID_UNIT_UID) {
Serial.println("ERROR: Failed to add main current sensor");
} else {
Serial.print("Main current sensor added, UID: 0x");
Serial.println(current_sensor_uid, HEX);
}
// Add current sensor SCT013-50A on GPIO33
alt_sensor_uid = rbgrid_config_add_adc_sensor(config_handle, GPIO_NUM_33, RBSENSOR_TYPE_CURRENT_SCT013_50A);
if (alt_sensor_uid == RBGRID_INVALID_UNIT_UID) {
Serial.println("ERROR: Failed to add alternative current sensor");
} else {
Serial.print("Alternative current sensor added, UID: 0x");
Serial.println(alt_sensor_uid, HEX);
}
// Add current sensor for heater on GPIO32
heater_sensor_uid = rbgrid_config_add_adc_sensor(config_handle, GPIO_NUM_32, RBSENSOR_TYPE_CURRENT_SCT013_10A);
if (heater_sensor_uid == RBGRID_INVALID_UNIT_UID) {
Serial.println("ERROR: Failed to add heater sensor");
} else {
Serial.print("Heater sensor added, UID: 0x");
Serial.println(heater_sensor_uid, HEX);
}
// Add Zero-Cross sensor on GPIO18
config_err = rbgrid_config_add_zc_sensor(config_handle, (gpio_num_t)ZC_CROSS_PIN);
if (config_err != RBGRID_CONFIG_OK) {
Serial.print("ERROR: Failed to add ZC sensor: ");
Serial.println(config_err);
} else {
Serial.print("Zero-Cross sensor configured on GPIO");
Serial.println(ZC_CROSS_PIN);
// Initialize ZC
rbgrid_zc_config_t zc_config = RBPOWER_ZC_DEFAULT_CONFIG((rbgrid_gpio_t)ZC_CROSS_PIN);
rbgrid_err_t zc_err = rbgrid_init_zc(&zc_config);
if (zc_err != RBPOWER_OK) {
Serial.print("ERROR: ZC init failed: ");
Serial.println((int)zc_err);
} else {
delay(200);
uint16_t measured_freq = rbgrid_get_network_frequency();
Serial.print("ZC initialized, measured frequency: ");
Serial.print((int)measured_freq);
Serial.println("Hz");
base_hardware_config->network.nominal_frequency = measured_freq;
}
}
// Create Voltage Bus
if (voltage_sensor_uid != RBGRID_INVALID_UNIT_UID) {
config_err = rbgrid_config_set_voltage_bus(config_handle, voltage_sensor_uid, "Main Voltage Bus");
if (config_err != RBGRID_CONFIG_OK) {
Serial.print("ERROR: Failed to configure voltage bus: ");
Serial.println(config_err);
} else {
Serial.print("Voltage bus configured with UID: 0x");
Serial.println(voltage_sensor_uid, HEX);
}
}
// Create Main Supply
if (current_sensor_uid != RBGRID_INVALID_UNIT_UID) {
config_err = rbgrid_config_set_main_supply(config_handle, current_sensor_uid, "Main Supply", RBPOWER_STAT_PERIOD_1HOUR);
if (config_err != RBGRID_CONFIG_OK) {
Serial.print("ERROR: Failed to configure main supply: ");
Serial.println(config_err);
} else {
Serial.print("Main supply configured with UID: 0x");
Serial.println(current_sensor_uid, HEX);
}
}
// Configure Alternative Supply
config_err = rbgrid_config_set_alternative_supply(config_handle, alt_sensor_uid, "Alternative Supply", RBPOWER_STAT_PERIOD_1HOUR);
if (config_err != RBGRID_CONFIG_OK) {
Serial.print("ERROR: Failed to configure alternative supply: ");
Serial.println(config_err);
} else {
Serial.println("Alternative supply configured");
}
// Configure heater
config_err = rbgrid_config_add_unit(config_handle, heater_sensor_uid, "Heater 10A", RBPOWER_STAT_PERIOD_1HOUR);
if (config_err != RBGRID_CONFIG_OK) {
Serial.print("ERROR: Failed to configure heater: ");
Serial.println(config_err);
} else {
Serial.println("Heater configured");
}
// Additional settings
extended_config->rbhome_settings.logging_level = RBGRID_LOG_LEVEL_DEBUG;
extended_config->enable_time_synchronization = false;
extended_config->auto_start_measurements = true;
// Pass units array
extended_config->units_config.predefined_units = config_ctx->units_array;
extended_config->units_config.predefined_units_count = config_ctx->units_count;
extended_config->units_config.use_predefined_only = true;
g_extended_config = extended_config;
// Initialize rbgrid system
Serial.println("Initializing rbgrid system...");
rbgrid_err_t rbgrid_err = rbgrid_init_hardware();
if (rbgrid_err != RBGRID_OK) {
Serial.print("ERROR: rbgrid init failed: ");
Serial.println(rbgrid_err);
Serial.println("WARNING: Unit UID mapping features may be limited");
} else {
Serial.println("rbgrid system initialized");
}
// Initialize rbgrid
rbgrid_err_t power_err = rbgrid_init_extended(extended_config);
if (power_err != RBPOWER_OK) {
Serial.print("ERROR: rbgrid init failed: ");
Serial.println(power_err);
Serial.println("WARNING: Continuing with limited functionality");
}
Serial.println("\n===== Initialization completed =====");
}
// ====== LOOP ======
void loop() {
// Print data every 5 seconds
static unsigned long last_print = millis();
if (millis() - last_print >= 5000) {
last_print = millis();
Serial.println("\n========== Sensor Data ==========");
// Get voltage statistics
statistics_3sec_final_t voltage_stats;
rbgrid_err_t result = rbgrid_realtime_get_voltage(&voltage_stats);
if (result == RBGRID_OK) {
Serial.print("Voltage: ");
Serial.print(voltage_stats.voltage_rms_final, 2);
Serial.print(" V, Frequency: ");
Serial.print(voltage_stats.frequency_avg_final, 2);
Serial.print(" Hz, THD: ");
Serial.print(voltage_stats.thd_voltage_avg_final, 2);
Serial.println("%");
} else {
Serial.print("ERROR: Failed to get voltage data: ");
Serial.println(result);
}
// Get Main Supply data
float current_rms, power_active, power_reactive, power_apparent, power_factor, energy_increment;
uint32_t samples_count;
rbgrid_current_direction_t direction;
result = rbgrid_realtime_get_main_supply(¤t_rms, &power_active, &direction,
&power_reactive, &power_apparent, &power_factor,
&samples_count, &energy_increment);
if (result == RBGRID_OK) {
Serial.print("Main Supply: I=");
Serial.print(current_rms, 3);
Serial.print(" A, P=");
Serial.print(power_active, 1);
Serial.print(" W, PF=");
Serial.println(power_factor, 3);
} else {
Serial.print("ERROR: Failed to get main supply data: ");
Serial.println(result);
}
// Get Alternative Supply data
float alt_current_rms, alt_power_active, alt_efficiency, alt_dc_power;
result = rbgrid_realtime_get_alt_supply(&alt_current_rms, &alt_power_active, &direction,
&power_reactive, &power_apparent, &power_factor,
&samples_count, &energy_increment,
&alt_efficiency, &alt_dc_power);
if (result == RBGRID_OK) {
Serial.print("Alt Supply: I=");
Serial.print(alt_current_rms, 3);
Serial.print(" A, P=");
Serial.print(alt_power_active, 1);
Serial.print(" W, Efficiency=");
Serial.print(alt_efficiency, 1);
Serial.println("%");
} else {
Serial.print("ERROR: Failed to get alt supply data: ");
Serial.println(result);
}
// Get heater data
float unit_current, unit_power_active;
result = rbgrid_realtime_get_unit(heater_sensor_uid, &unit_current,
&unit_power_active, &power_reactive,
&power_apparent, &power_factor,
&samples_count);
if (result == RBGRID_OK) {
Serial.print("Heater: I=");
Serial.print(unit_current, 3);
Serial.print(" A, P=");
Serial.print(unit_power_active, 1);
Serial.print(" W, PF=");
Serial.println(power_factor, 3);
} else {
Serial.print("ERROR: Failed to get heater data: ");
Serial.println(result);
}
Serial.println("=====================================");
}
delay(100);
}
🔌 DIY Maker's Corner
Perfect for Hobbyists
Whether you're building your first energy monitor or designing a sophisticated home energy management system, rbgrid provides professional-grade measurements with maker-friendly simplicity.
Popular DIY Projects
- Solar MPPT Controller: Track your panels' performance and optimize energy harvest
- Smart Power Strip: Build an intelligent PDU with individual outlet monitoring
- Whole House Monitor: Non-invasive energy monitoring with split-core CTs
- Battery Bank Manager: Monitor charge/discharge cycles and calculate efficiency
- Workshop Power Analyzer: Check your tools' power quality and consumption
Maker-Friendly Features
- 🛠️ Breadboard Compatible: Works with common breakout boards
- 📐 No Complex Math: Library handles all calculations internally
- 🔧 Auto-Calibration: Self-calibrating routines for easy setup
- 📚 Extensive Examples: From basic to advanced projects
- 💬 Active Community: Get help from fellow makers
🧰 Hardware Tips for DIYers
Current Transformers (CTs)
- SCT-013-030: 30A non-invasive, perfect for home circuits
- SCT-013-100: 100A for main panel monitoring
- Burden Resistor: Library auto-calculates optimal values
Voltage Sensing
- ZMPT101B Module: Ready-to-use, isolated measurement
- Voltage Divider: Simple resistor network for direct sensing
- Safety First: Always use proper isolation for mains voltage!
Wiring Best Practices
- Keep sensor wires short and twisted
- Use shielded cable for noisy environments
- Add 100nF capacitors close to ADC pins
- Separate analog and digital grounds properly
📚 Documentation
- 📖 Full Documentation
- 🎯 Example Projects
- 🔧 API Reference
- ⚡ Wiring Diagrams
- 📊 Sensor Calibration
- 🛠️ Troubleshooting Guide
🤝 Community & Support
- GitHub Issues: Report bugs
- Discussions: Q&A and show-and-tell
- Discord: International community
- Forum: Detailed technical discussions
- YouTube: Video tutorials and demos
🏆 Showcase
Check out amazing projects built with rbgrid:
- 🏠 Smart Home Energy Dashboard
- ☀️ DIY Solar Tracker with MPPT
- 🔌 Industrial Power Quality Monitor
- 🚗 EV Charging Station Controller
📄 License
This project is released under the MIT License. See LICENSE file for details.
🙏 Acknowledgments
Standing on the Shoulders of Giants
- EmonLib: Inspiration for energy monitoring algorithms
- ESP32 Arduino Core: Making ESP32 accessible to makers
- OpenEnergyMonitor: Pioneering open-source energy monitoring
Made with ❤️ for the Maker Community and Energy Enthusiasts
[!WARNING] If you find this project useful, please give it