Basic Example
Explanation and detailing of the basic example. Understanding sensor functions. Understanding and purpose of units, special units.
Key Concepts. Difference Between Sensor and Unit
Before starting work with the RBgrid library, it's important to understand the fundamental difference between sensors and units.
Sensor
Sensor - is a physical device connected to an ESP32 GPIO pin that converts electrical parameters into a measurable signal.
Sensor characteristics:
- Bound to a specific GPIO pin
- Has physical characteristics
- Performs one function - measurement
- Has no data context
Sensor examples:
// Zero-crossing detector - for grid synchronization
rbgrid_config_add_zc_sensor(config_handle, (gpio_num_t)ZC_CROSS_PIN);
// Voltage sensor on GPIO35, sensor type for grid voltage measurement RBSENSOR_TYPE_VOLTAGE_ZMPT107_1
rbgrid_config_add_adc_sensor(config_handle, GPIO_NUM_35, RBSENSOR_TYPE_VOLTAGE_ZMPT107_1);
// Current sensor on GPIO34, sensor type for current measurement RBSENSOR_TYPE_CURRENT_SCT013_10A
rbgrid_config_add_adc_sensor(config_handle, GPIO_NUM_34, RBSENSOR_TYPE_CURRENT_SCT013_10A);
Voltage Sensors
| Type | Model | Range | Application |
|---|---|---|---|
RBSENSOR_TYPE_VOLTAGE_ZMPT107_1 |
ZMPT107-1 | 0-250V AC | Home grids |
RBSENSOR_TYPE_VOLTAGE_ZMPT101B |
ZMPT101B | 0-250V AC | Industrial |
RBSENSOR_TYPE_VOLTAGE_DIVIDER |
Resistive divider | Configurable | Universal |
Current Sensors
| Type | Model | Range | Application |
|---|---|---|---|
RBSENSOR_TYPE_CURRENT_SCT013_5A |
SCT-013-005 | 0-5A | Household appliances |
RBSENSOR_TYPE_CURRENT_SCT013_10A |
SCT-013-010 | 0-10A | Household appliances |
RBSENSOR_TYPE_CURRENT_SCT013_30A |
SCT-013-030 | 0-30A | Apartment input |
RBSENSOR_TYPE_CURRENT_SCT013_50A |
SCT-013-050 | 0-50A | House input |
RBSENSOR_TYPE_CURRENT_SCT013_100A |
SCT-013-100 | 0-100A | Industrial |
RBSENSOR_TYPE_CURRENT_ACS712_5A |
ACS712-05B | ±5A | Household appliances |
RBSENSOR_TYPE_CURRENT_ACS712_20A |
ACS712-20A | ±20A | Household appliances |
RBSENSOR_TYPE_CURRENT_ACS712_30A |
ACS712-30A | ±30A | Apartment input |
RBSENSOR_TYPE_CURRENT_ACS712_50A |
ACS712-50A | ±50A | House input |
Unit
Unit - is a logical abstraction representing a measurement point in an electrical grid with economic and functional context.
Unit characteristics:
- Uses data from one or more sensors
- Has business logic (tariffication, energy accounting)
- Accumulates statistics
- Can represent virtual or aggregated measurements
Unit examples:
// Create Voltage Bus
rbgrid_config_set_voltage_bus(config_handle, voltage_sensor_uid, "Main Voltage Bus");
// Main Supply - main electricity input
rbgrid_config_set_main_supply(config_handle, current_sensor_uid, "Main Supply Current", RBPOWER_STAT_PERIOD_1YEAR);
// Configure Alternative Supply
rbgrid_config_set_alternative_supply(config_handle, alt_sensor_uid, "Alternative Supply", RBPOWER_STAT_PERIOD_1YEAR);
// Regular unit - specific device
rbgrid_config_add_unit(config_handle, heater_sensor_uid, "Heater 10A", RBPOWER_STAT_PERIOD_1MONTH);
↓
[GPIO Pin] → [ADC Channel] → [Sensor]
↓
[Sensor UID] → [Unit] → [Statistics]
↓
[Tariffication] → [Energy accounting] → [Reports]
Unit Types
Special Units
1. Voltage Bus
Purpose: Central voltage bus for measuring current grid voltage.
// Mandatory unit - must be created first
rbgrid_config_set_voltage_bus(config_handle, voltage_sensor_uid, "Main Voltage Bus");
Features:
- Only one per system
- Mandatory for operation
- Provides reference voltage for power calculation
- Additionally: Measures power quality (THD)
2. Main Supply
Purpose: Main power input from utility provider.
rbgrid_config_set_main_supply(config_handle, current_sensor_uid, "Main Supply Current", RBPOWER_STAT_PERIOD_1YEAR);
Features:
- Accounts for consumption from power provider
- Supports bidirectional metering (net metering)
- Applies main tariffication
- Generates electricity bills
3. Alternative Supply
Purpose: Alternative energy source (solar panels, generator, batteries).
rbgrid_config_set_alternative_supply(config_handle, alt_sensor_uid, "Alternative Supply", RBPOWER_STAT_PERIOD_1HOUR);
Features:
- Accounts for energy generation
- Accounts for electricity consumption for battery charging
- Calculates conversion efficiency
- Supports separate tariffication (feed-in tariff)
- Included in consumption balance business logic together with Main Supply
Regular Units
Represent specific consumers or consumer groups.
// Regular unit examples
rbgrid_config_add_unit(config_handle, heater_sensor_uid, "Water Heater", RBPOWER_STAT_PERIOD_1HOUR);
rbgrid_config_add_unit(config_handle, livingroom_uid, "Living Room", RBPOWER_STAT_PERIOD_1MONTH);
rbgrid_config_add_unit(config_handle, kitchen_uid, "Kitchen", RBPOWER_STAT_PERIOD_1MONTH);
rbgrid_config_add_unit(config_handle, garage_uid, "Garage equipment", RBPOWER_STAT_PERIOD_1DAY);
rbgrid_config_add_unit(config_handle, air_uid, "Air Heater", RBPOWER_STAT_PERIOD_1HOUR);
Statistics Periods
Each unit accumulates statistics with a specified period, by specifying a period, accumulation will also be conducted for all shorter periods:
| Period | Value | Application |
|---|---|---|
RBPOWER_STAT_PERIOD_15MIN |
15 min | Variable loads |
RBPOWER_STAT_PERIOD_30MIN |
30 min | Standard devices |
RBPOWER_STAT_PERIOD_1HOUR |
1 hour | Constant loads |
RBPOWER_STAT_PERIOD_1DAY |
24 hours | Daily reports |
RBPOWER_STAT_PERIOD_1WEEK |
week | Weekly reports |
RBPOWER_STAT_PERIOD_1MONTH |
month | Monthly reports |
RBPOWER_STAT_PERIOD_1YEAR |
year | Annual reports |
Sensor and Unit Relationship
One sensor - one unit (typical case)
Sensor initialization functions return a unique UID, a 2-byte number containing source and channel.
The obtained UID is passed to the unit initialization function.
// Air conditioner current sensor
uid_ac = rbgrid_config_add_adc_sensor(config_handle, GPIO_NUM_34, RBSENSOR_TYPE_CURRENT_SCT013_10A);
// Air conditioner unit uses this sensor
rbgrid_config_add_unit(config, uid_ac, "Air Conditioner", RBPOWER_STAT_PERIOD_1MONTH);
Virtual units (without physical sensor)
// Virtual unit - sum of multiple sensors
// Implemented through callback functions
rbgrid_config_add_virtual_unit(config, "Total Consumption", calculate_total_callback, RBPOWER_STAT_PERIOD_1HOUR);
--
Initialization Lifecycle
Let's proceed to the initialization order, configuration and startup of the RBgrid system.
1. Create Configuration
rbgrid_config_handle_t config_handle = rbgrid_config_create("Test House", "HongKong");
2. Network Setup, Populate Basic Settings
// Configure network
config_err = rbgrid_config_set_network(config_handle);
3. Add Sensors
// 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) {
ESP_LOGE(TAG, "Failed to add ZC sensor: %d", config_err);
} else {
ESP_LOGI(TAG, "✅ Zero-Cross sensor configured on GPIO%d", ZC_CROSS_PIN);
rbpower_err_t zc_err = rbpower_init_zc(&zc_config);
if (zc_err != RBPOWER_OK) {
ESP_LOGE("APP", "ZC init failed: %d", (int)zc_err);
} else {
delay(200); // Allow time for stabilization
uint16_t measured_freq = rbpower_get_network_frequency();
ESP_LOGI("APP", "ZC initialized, measured frequency: %dHz", (int)measured_freq);
// Update frequency in configuration
base_hardware_config->network.nominal_frequency = measured_freq;
}
}
// Configure ADC sensors through new API function
// Add ZMPT107-1 voltage sensor on GPIO35 (ADC1_CH7)
rbgrid_unit_uid_t 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) {
ESP_LOGE(TAG, "Failed to add voltage sensor");
} else {
ESP_LOGI(TAG, "Voltage sensor added with unit_UID: 0x%04X", voltage_sensor_uid);
}
// Add SCT013-10A current sensor on GPIO34 (ADC1_CH6)
rbgrid_unit_uid_t 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) {
ESP_LOGE(TAG, "Failed to add main current sensor");
} else {
ESP_LOGI(TAG, "Main current sensor added with unit_UID: 0x%04X", current_sensor_uid);
}
// Add SCT013-50A current sensor on GPIO33 (ADC1_CH5)
rbgrid_unit_uid_t 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) {
ESP_LOGE(TAG, "Failed to add alternative current sensor");
} else {
ESP_LOGI(TAG, "Alternative current sensor added with unit_UID: 0x%04X", alt_sensor_uid);
}
// Add SCT013-10A current sensor on GPIO32 (ADC1_CH4)
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) {
ESP_LOGE(TAG, "Failed to add heater current sensor");
} else {
ESP_LOGI(TAG, "Heater current sensor added with unit_UID: 0x%04X", heater_sensor_uid);
}
4. Create Units
// Mandatory order for creating special units:
// 1. Create Voltage Bus using voltage sensor unit_UID
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) {
ESP_LOGE(TAG, "Failed to configure voltage bus: %d", config_err);
} else {
ESP_LOGI(TAG, "✅ Voltage bus configured successfully with unit_UID: 0x%04X", voltage_sensor_uid);
}
}
// 2. Create Main Supply using current sensor unit_UID
if (current_sensor_uid != RBGRID_INVALID_UNIT_UID) {
config_err = rbgrid_config_set_main_supply(config_handle, current_sensor_uid, "Main Supply Current", RBPOWER_STAT_PERIOD_1HOUR);
if (config_err != RBGRID_CONFIG_OK) {
ESP_LOGE(TAG, "Failed to configure main supply: %d", config_err);
} else {
ESP_LOGI(TAG, "✅ Main supply configured successfully with unit_UID: 0x%04X", current_sensor_uid);
}
}
// Configure Alternative Supply with third sensor
config_err = rbgrid_config_set_alternative_supply(config_handle, alt_sensor_uid, "Alternative Supply", RBPOWER_STAT_PERIOD_1HOUR);
if (config_err != RBGRID_CONFIG_OK) {
ESP_LOGE(TAG, "Failed to set alternative supply: %d", config_err);
} else {
ESP_LOGI(TAG, "✅ Alternative supply configured");
}
// Configure heater with 4th sensor
config_err = rbgrid_config_add_unit(config_handle, heater_sensor_uid, "Heater 10A", RBPOWER_STAT_PERIOD_1HOUR);
if (config_err != RBGRID_CONFIG_OK) {
ESP_LOGE(TAG, "Failed to set Heater: %d", config_err);
} else {
ESP_LOGI(TAG, "✅ Heater configured");
}
5. Initialization and Time Setup
For tariff application, the system must know real time. Real time is obtained at system startup from SNTP servers. WiFi connection must be established beforehand. In case of no connection to SNTP server, the system will apply fallback time settings.
// Time setup through API functions
config_err = rbgrid_config_set_sntp_time(config_handle,
"pool.ntp.org",
"time.nist.gov",
"UTC+0");
if (config_err != RBGRID_CONFIG_OK) {
ESP_LOGW(TAG, "Failed to configure SNTP time: %d", config_err);
} else {
ESP_LOGI(TAG, "✅ SNTP time configuration completed");
}
// Configure time fallback
config_err = rbgrid_config_set_time_fallback(config_handle,
true, // enable RTC fallback
true, // enable manual fallback
1704067200); // January 1, 2024, 00:00:00 UTC
if (config_err != RBGRID_CONFIG_OK) {
ESP_LOGW(TAG, "Failed to configure time fallback: %d", config_err);
}
// Advanced time settings
config_err = rbgrid_config_set_time_advanced(config_handle,
3600, // sync every hour
10000, // 10 second timeout
3, // 3 retry attempts
true); // enable DST
if (config_err != RBGRID_CONFIG_OK) {
ESP_LOGW(TAG, "Failed to configure advanced time settings: %d", config_err);
}
6. Tariff Configuration
Example of simplest tariff configuration.
// === TARIFF CONFIGURATION USING BUILDER ===
ESP_LOGI(TAG, "=== Configuring tariff plan ===");
// Create tariff builder for Germany. Set currency.
rbgrid_tariff_builder_t tariff_builder = rbgrid_tariff_builder_create("EUR", "DE");
if (!tariff_builder) {
ESP_LOGE(TAG, "Failed to create tariff builder");
} else {
// Basic tariff zones (EUR/kWh)
rbgrid_tariff_builder_add_time_zone(tariff_builder, "Night", 0.08f, "23:00-07:00");
rbgrid_tariff_builder_add_time_zone(tariff_builder, "Day", 0.15f, "07:00-18:00");
rbgrid_tariff_builder_add_time_zone(tariff_builder, "Peak", 0.25f, "18:00-23:00");
// Weekends (Saturday=0x40, Sunday=0x01)
rbgrid_tariff_builder_add_weekday_zone(tariff_builder, "Weekend", 0.09f, 0x41);
// German holidays
rbgrid_tariff_builder_set_country_holidays(tariff_builder, "DE", 0.085f);
// Subscription and grid fees
rbgrid_tariff_builder_set_monthly_fee(tariff_builder, 15.0f);
rbgrid_tariff_builder_add_custom_fee(tariff_builder, "Grid Fee", 8.5f, RBPOWER_TARIFF_FIXED_MONTHLY);
// Net metering for solar panels
rbgrid_tariff_builder_set_net_metering(tariff_builder, 0.12f, 0.7f);
// Apply tariff plan
config_err = rbgrid_config_apply_tariff_plan(config_handle, tariff_builder);
if (config_err != RBGRID_CONFIG_OK) {
ESP_LOGE(TAG, "Failed to apply tariff plan: %d", config_err);
} else {
ESP_LOGI(TAG, "✅ Tariff plan applied successfully");
}
// Clean up builder
rbgrid_tariff_builder_destroy(tariff_builder);
}
7. Apply Configuration. Initialize and Start
Validation of preliminary settings occurs.
rbgrid_init_system() - checks ESP32 hardware functionality, initializes and starts I/O system, checks memory, starts interrupts, timers.
rbgrid_init_extended() - starts data flow system, unit system, statistics system, economics system, initializes telemetry.
// Initialize system
rbgrid_init_system();
// Initialize RBgrid with configuration
rbgrid_init_extended(extended_config);
Configuration Validation
Mandatory requirements
- At least one Voltage Bus and Zero-Cross - system won't start without them
- Unique GPIO pins - each sensor on its own pin
- Correct UIDs - all UID assignments must be unique. Don't reassign UIDs.
Configuration Check
// Automatic validation during initialization
RBgrid_err_t err = RBgrid_init_extended(config);
if (err == RBPOWER_ERR_NO_VOLTAGE_BUS) {
ESP_LOGE(TAG, "Voltage Bus not configured!");
} else if (err == RBPOWER_ERR_INVALID_CONFIG) {
ESP_LOGE(TAG, "Invalid configuration!");
} else if (err == RBPOWER_OK) {
ESP_LOGI(TAG, "System initialized successfully");
}