- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
Carlo Gavazzi EM580 Power Meter Driver
Driver module for the Carlo Gavazzi EM580 power meter using Modbus via EVerest's serial_communication_hub interface.
It implements the standardized EVerest powermeter interface and supports OCMF/Eichrecht transaction flows.
Overview
This is an EVerest Hardware Driver module that:
- Implements:
powermeterinterface - Communicates: Modbus RTU (through
SerialCommHub) - Provides: Live meter values, OCMF transaction start/stop handling, public key publishing
Features
- Live measurements: Publishes
powermeterreadings periodically (live_measurement_interval_ms) - OCMF transactions:
start_transaction: writes OCMF identification fields + tariff text (TT) + start commandstop_transaction: ends transaction, waits for READY, reads OCMF file, confirms file read
- Modbus protocol compliance: transport splits writes into chunks (max 123 registers per request)
- Resilience / retries:
- Separate initial connection retry settings vs. normal operation retry settings
- Communication-fault raise/clear hooks
- Device state monitoring: periodic read of device state bitfield (
device_state_read_interval_ms) - Signature key readout: reads signature type and public keys; publishes public key (hex) via
public_key_ocmf
Hardware requirements & compatibility
Supported devices
- Carlo Gavazzi EM580 with Modbus RTU enabled/available.
- OCMF/Eichrecht flow: requires a meter variant/firmware that supports the OCMF register set used by this driver.
If you are unsure which EM580 variant you have, check the device documentation/ordering code and confirm:
-
Modbus RTU via RS-485 is supported and enabled
-
The meter is configured for a known Modbus unit id (device address)
-
Carlo Gavazzi EM300 with Modbus RTU enabled/available. These models do not support OCMF/Eichrecht and can only be used as usual power meter. All transaction related configuration etc. does not apply for such devices.
Bus / physical layer
- RS-485 (2-wire, half duplex): correct A/B wiring is essential.
- Termination: enable 120Ω termination at the ends of the RS-485 bus (and only at the ends).
- Biasing: ensure the bus has proper bias resistors (often provided by the adapter/master or by dedicated biasing).
Host requirements
- A Linux host running EVerest with access to a serial device (e.g.
/dev/ttyUSB0). - A USB-to-RS485 adapter (or equivalent RS-485 interface) supported by the OS.
- Permissions to access the serial device node (group membership / udev rules).
Configuration
Required connections
The module requires a serial_communication_hub implementation (typically SerialCommHub) via its modbus requirement.
SerialCommHub encapsulates the serial port settings (port, baudrate, parity, timeouts). The EM580 module only needs the
hub connection plus its Modbus unit id (powermeter_device_id).
Example configuration (bringup)
See config/bringup/config-bringup-CGEM580.yaml:
active_modules:
cgem580:
module: CarloGavazzi_EM580
config_implementation:
main:
powermeter_device_id: 1
communication_retry_count: 3
communication_retry_delay_ms: 500
communication_error_pause_delay_s: 10
initial_connection_retry_count: 10
initial_connection_retry_delay_ms: 2000
timezone_offset_minutes: 60
live_measurement_interval_ms: 1000
device_state_read_interval_ms: 10000
connections:
modbus:
- module_id: comm_hub
implementation_id: main
Multiple EM580 devices on one RS-485 bus
You can run multiple EM580 devices on the same RS-485 line by:
- Creating multiple
CarloGavazzi_EM580module instances - Pointing them all to the same
SerialCommHub - Giving each instance a unique
powermeter_device_id(Modbus unit id)
Configuration parameters
All parameters are defined in modules/HardwareDrivers/PowerMeters/CarloGavazzi_EM580/manifest.yaml:
| Parameter | Type | Default | Description |
|---|---|---|---|
powermeter_device_id |
integer | 1 |
Modbus device ID on the bus |
communication_retry_count |
integer | 3 |
Retries for regular Modbus operations |
communication_retry_delay_ms |
integer | 500 |
Delay between regular retries |
communication_error_pause_delay_s |
integer | 10 |
Pause after a communication failure in the live measurement thread before retrying (also applies to initial communication) |
initial_connection_retry_count |
integer | 10 (0 = infinite) |
Retries during initial device setup/signature config reads |
initial_connection_retry_delay_ms |
integer | 2000 |
Delay between initialization retries |
timezone_offset_minutes |
integer | 0 |
Timezone offset from UTC (minutes) |
live_measurement_interval_ms |
integer | 1000 |
Interval for reading/publishing live measurements |
device_state_read_interval_ms |
integer | 10000 |
Interval for reading device-state bitfield (VendorError reporting) |
public_key_format |
enum | binary |
The key format to use for the public key. |
Parameter tuning notes
initial_connection_*:- Used during module startup for device setup / signature config reads.
initial_connection_retry_count: 0means retry forever.initial_connection_retry_delay_mshas a minimum of 100ms (seemanifest.yaml).
communication_*:- Used for regular Modbus operations during runtime.
communication_retry_delay_mshas a minimum of 10ms (seemanifest.yaml).
communication_error_pause_delay_s:- After a communication exception in the live thread, the module waits this long before retrying.
- If the line is physically broken (wrong wiring / adapter unplugged), increasing this value reduces log spam.
live_measurement_interval_ms/device_state_read_interval_ms:- Keep live measurements reasonable for your bus speed and number of devices.
- For multi-drop RS-485, consider increasing intervals if you see bus contention/timeouts.
Interfaces
Provides
main:powermeter
Requires
modbus:serial_communication_hub
Transaction flow (OCMF)
start_transaction
High-level flow:
- Read OCMF state register and ensure it is
NOT_READYbefore starting. - Write OCMF transaction registers:
- Identification status/level/flags/type
- Identification data (ID)
- Charging point identifier type + value (EVSE ID)
- Tariff text (TT) as
tariff_text + "<=>" + transaction_id- Written as 0-terminated and only the used portion (no full padding).
- Write session modality (charging vehicle).
- Write the start command (
'B').
stop_transaction
High-level flow:
- Write end command (
'E') if stopping the currently tracked transaction. - Wait for OCMF state
READY. - Read OCMF file (size + content).
- Confirm file read by writing
NOT_READYto OCMF state. - Return OCMF report in
signed_meter_value(withpublic_keyattached).
Signature validation (recommended)
For troubleshooting and integration testing, this module ships a small signature validation tool under:
modules/HardwareDrivers/PowerMeters/CarloGavazzi_EM580/ocmf_validation/.
It can validate EM580 OCMF signatures (ECDSA-brainpoolP384r1-SHA256) against the public key read from the meter.
See ocmf_validation/README.md for usage details.
Troubleshooting
No communication / timeouts
Common causes and checks:
- Wrong unit id:
- Verify
powermeter_device_idmatches the meter’s Modbus address. - If you have multiple meters, ensure each has a unique id (1..247 are typical).
- Verify
- Wrong serial settings:
- Ensure
SerialCommHubsettings match the meter configuration (baudrate, parity). - If you are unsure, start with conservative settings and increase once stable.
- Ensure
- RS-485 wiring / termination:
- Swap A/B if you see only timeouts.
- Ensure termination is correct (only at bus ends).
- Keep cables short / twisted pair; avoid star topologies where possible.
- Adapter / permissions:
- Confirm the serial device path exists and is stable (
/dev/ttyUSB0can change between boots). - Ensure the EVerest process has permissions to open the device node.
- Confirm the serial device path exists and is stable (
Repeated CommunicationFault raises
The module raises a communication fault when Modbus operations fail and clears it once communication is restored. If you see frequent toggling:
- Reduce bus load (increase
live_measurement_interval_ms, especially with multiple meters) - Increase
communication_retry_countmodestly (and keepcommunication_retry_delay_ms≥ 10ms) - Consider increasing
communication_error_pause_delay_sto reduce retry storms on hard faults
OCMF transaction does not complete / stuck waiting for READY
- Check that the meter is in the expected OCMF state and is not holding a previous transaction open.
- Ensure the transaction ids passed to
start_transaction/stop_transactionmatch your intended flow. - Inspect logs around OCMF state transitions and file readout to see which step fails.
Tariff text (TT) is truncated
The EM580 TT field is limited to CHAR[252]. The driver logs a warning and truncates overlong strings.
Shorten tariff_text and/or the appended data (e.g. transaction id formatting).
Signature verification fails
Use the validation tool in ocmf_validation/ to validate the produced OCMF string against the published public key.
If it fails:
- Ensure public key and OCMF data come from the same device and same transaction
- Ensure the OCMF data is not modified (OCMF signatures are over compact JSON)
Notes / Limitations
- Write-multiple-registers limit: the Modbus transport enforces the protocol limit by chunking into max 123 registers.
- Tariff text length: TT is a
CHAR[252]field (126 words). The driver logs a warning and truncates if needed.
References
- Module docs:
modules/HardwareDrivers/PowerMeters/CarloGavazzi_EM580/docs/index.rst - OCMF spec: see SAFE-eV OCMF specification
Unit tests
Unit tests live under modules/HardwareDrivers/PowerMeters/CarloGavazzi_EM580/tests/ and include:
- Helper-level tests (
helper.hpp) powermeterImplbehavior tests using a fake Modbus transport and small test hooks
Build/run example (target name may vary by build system settings):
ninja -C build everest-core_carlo_gavazzi_em580_helper_tests
./build/modules/HardwareDrivers/PowerMeters/CarloGavazzi_EM580/tests/everest-core_carlo_gavazzi_em580_helper_tests