A quick reference for the IEEE C37.118.2 synchrophasor protocol as implemented in this tool. For the full specification, see docs/reference/README.md.
IEEE C37.118.2 defines the communication protocol for synchrophasor measurement systems. It specifies frame formats for exchanging configuration, data, header, and command information between PMUs (Phasor Measurement Units) and PDCs (Phasor Data Concentrators).
A typical TCP session from a microPMU:
[CFG-2 frame] → [Data frame] → [Data frame] → ... → [CFG-2 retransmit] → [Data frame] → ...
The CFG-2 frame describes the stream layout (phasor count, names, data types, encoding). Data frames follow at the configured reporting rate. Real PMUs periodically retransmit CFG-2; this tool supports that via --cfg2-interval.
| Type | Code | SYNC Byte 1 | Description |
|---|---|---|---|
| Data | 0 | 0x02 |
Measurement data |
| Header | 1 | 0x12 |
Human-readable ASCII header |
| CFG-1 | 2 | 0x22 |
Configuration (capabilities) |
| CFG-2 | 3 | 0x32 |
Configuration (current operating) |
| Command | 4 | 0x42 |
Control commands |
| CFG-3 | 5 | 0x52 |
Extended configuration |
SYNC byte 0 is always 0xAA. Byte 1 = (frame_type << 4) | version. Current version = 2.
Every frame starts with this header:
Offset Bytes Field Description
0 2 SYNC 0xAA + frame type/version
2 2 FRAMESIZE Total frame length including CRC
4 2 IDCODE PMU/PDC stream identifier (1–65534)
6 4 SOC Seconds since 1970-01-01 UTC
10 4 FRACSEC Fractional second + time quality
All multi-byte fields are big-endian (network byte order).
Bits 31–24: Time quality flags (8 bits)
Bits 23–0: Fractional second (24 bits)
Fractional second = fraction / TIME_BASE (TIME_BASE from CFG-2, typically 1,000,000).
Every frame ends with a 2-byte CRC computed over all preceding bytes in the frame.
| Parameter | Value |
|---|---|
| Polynomial | 0x1021 |
| Initial value | 0xFFFF |
| Reflect input | No |
| Reflect output | No |
| Final XOR | 0x0000 |
Canonical test vector: CRC of ASCII "123456789" = 0x29B1
Warning: Some online references and the bundled
crc16_ccitt_reference.htmldescribe CRC-CCITT with init=0x0000. That is a different algorithm. Always use init=0xFFFF per the IEEE standard.
Configuration Frame 2 describes the current operating configuration of a PMU.
Key fields after the common header:
| Field | Bytes | Description |
|---|---|---|
| TIME_BASE | 4 | Resolution of FRACSEC (typically 1,000,000) |
| NUM_PMU | 2 | Number of PMU blocks in this frame |
Per-PMU block:
| Field | Bytes | Description |
|---|---|---|
| STN | 16 | Station name (null-padded, not space-padded) |
| IDCODE | 2 | PMU data stream ID |
| FORMAT | 2 | Data format flags (see below) |
| PHNMR | 2 | Number of phasors |
| ANNMR | 2 | Number of analog values |
| DGNMR | 2 | Number of digital status words |
| CHNAM | 16×N | Channel names (16 bytes each, null-padded) |
| PHUNIT | 4×PHNMR | Phasor conversion factors |
| ANUNIT | 4×ANNMR | Analog conversion factors |
| DGUNIT | 4×DGNMR | Digital channel masks |
| FNOM | 2 | Nominal frequency (0 = 60 Hz, 1 = 50 Hz) |
| CFGCNT | 2 | Configuration change count |
Trailing fields (after all PMU blocks):
| Field | Bytes | Description |
|---|---|---|
| DATA_RATE | 2 | Reporting rate (positive = fps) |
| CRC | 2 | CRC-16 checksum |
Bit 3: Frequency/ROCOF format (0 = int16, 1 = float32)
Bit 2: Analog format (0 = int16, 1 = float32)
Bit 1: Phasor format (0 = int16, 1 = float32)
Bit 0: Phasor notation (0 = rectangular, 1 = polar)
Bits 31–24: Phasor type (0 = voltage, 1 = current)
Bits 23–0: Scale factor (ignored for float32)
Data frames carry the actual measurement data.
After the common header:
| Field | Bytes | Description |
|---|---|---|
| STAT | 2 | Status word |
| PHASORS | varies | Phasor values (see encoding) |
| FREQ | 2 or 4 | Frequency deviation |
| DFREQ | 2 or 4 | Rate of change of frequency |
| ANALOG | varies | Analog channel values |
| DIGITAL | varies | Digital status words |
| CRC | 2 | CRC-16 checksum |
Float32 polar (default):
- Magnitude: 4 bytes (IEEE 754 float, in engineering units)
- Angle: 4 bytes (IEEE 754 float, in radians)
- 8 bytes per phasor × 8 phasors = 64 bytes
Int16 polar:
- Magnitude: 2 bytes (signed, scaled by PHUNIT)
- Angle: 2 bytes (signed, ~0.0001 rad/LSB)
- 4 bytes per phasor × 8 phasors = 32 bytes
Bits 15–14: Data error (00=good, 01=PMU error, 10=test mode, 11=PMU error no data)
Bit 13: PMU sync (0=in sync, 1=out of sync)
Bit 12: Data sorting (0=by timestamp, 1=by arrival)
Bit 11: PMU trigger detected
Bit 10: Configuration change pending
Bit 9: Data modified indicator
Bits 8–6: Time quality (locked status)
Bits 5–4: Unlocked time (seconds since GPS lock)
Bits 3–0: Trigger reason (manual, mag low/high, angle diff, freq, df/dt, digital, user-defined)
- Float32: deviation from nominal in Hz (e.g., 0.05 means 60.05 Hz on a 60 Hz system)
- Int16: deviation in millihertz (value × 0.001 = Hz deviation)
- Float32: Hz/s
- Int16: centihertz per second (value × 0.01 = Hz/s)
The tool supports the full IEEE C37.118.2 parameter space, but the LBNL data sources and default synthetic configuration target microPMU (distribution-level) characteristics:
| Attribute | MicroPMU | Transmission PMU |
|---|---|---|
| Reporting rate | 120 Hz | 30–60 Hz |
| Voltage level | 120–480 V (secondary), 4–35 kV (primary) | 69–765 kV |
| Typical install | Distribution feeder, PV site | Substation |
| Captured events | Cap switching, motor starts, PV transients | System oscillations, islanding |
- Configurable phasor count (1-16, default 8): VA, VB, VC, V+ (voltage), IA, IB, IC, I+ (current)
- Positive sequence (V+, I+) derived via Fortescue transformation
- Configurable analog channels (0-N, with substation preset: temperature, tap position, MW, MVAR)
- Configurable digital words (0-N, with breaker preset: breaker status + relay flags)
- Multi-PMU aggregated streams (1-256 PMUs per config frame)
- Default encoding: float32 polar (90 bytes/frame for 8 phasors)
- Independent encoding per type: phasor, analog, and frequency can each be float32 or int16
- Polar or rectangular phasor notation
- Nominal frequency: 50 Hz or 60 Hz (configurable)
- Configurable TIME_BASE (default 1,000,000; supports 1,048,576 and other values)
- StatWord transitions: sync loss, config change, data quality degradation, trigger events
- TimeQuality transitions: GPS unlock/relock ramps, leap second flags
- Timing anomalies: frame gaps, duplicate timestamps, timing jitter
- Invalid measurement frames: NaN/zero phasor override with PmuErrorNoData status
- Periodic CFG-2 retransmission (configurable interval)
- Corpus generator for diverse test datasets across the full parameter space
See docs/reference/README.md for links to the IEEE standard, overview papers, and other reference materials.