Skip to content

SEL CWS: user-selectable sliding-DFT and IEEE C37.118 phase estimation#21

Merged
clackner-gpa merged 6 commits into
developmentfrom
SelCWSDualAlgorithm
May 27, 2026
Merged

SEL CWS: user-selectable sliding-DFT and IEEE C37.118 phase estimation#21
clackner-gpa merged 6 commits into
developmentfrom
SelCWSDualAlgorithm

Conversation

@ritchiecarroll
Copy link
Copy Markdown
Contributor

@ritchiecarroll ritchiecarroll commented May 23, 2026

Summary

Adds two user-selectable phasor/frequency/ROCOF estimation algorithms to the SEL CWS
protocol, chosen via connection parameters:

  • Sliding DFT — rolling sliding-DFT estimator with optional EMA smoothing
  • IEEE C37.118-2018 Annex D — FIR filter-based estimator with P-class and M-class support

This re-syncs Gemstone with the matching GSF implementation. (Gemstone had previously
replaced the sliding DFT with the IEEE algorithm for the PNNL project; this restores
both and makes the choice configurable.)

ALSO: Includes fix for SEL CWS data-frame sample misalignment (samples 1-49 read 16 bytes early)

What changed

  • Common.cs — new PhaseEstimationAlgorithm { SlidingDft, IEEEC37_118 } enum
  • PhaseEstimate.cs / IPhaseEstimator.cs — shared result type + estimator contract
  • SlidingDftPhaseEstimator.cs / IEEEC37_118PhaseEstimator.cs — the two algorithms behind
    IPhaseEstimator; replace the previous RollingPhaseEstimator
  • ConnectionParameters.csAlgorithm selector + sliding-DFT options, grouped into
    General / Sliding DFT / IEEE C37.118 property-grid categories
  • FrameParser.cs — constructs the configured estimator (rebuilt when parameters change)
  • UnitTests — replaced the console demo program with MSTest tests (9 sliding-DFT + 6 IEEE)

Notes for reviewers

  • Default is SlidingDft (consistent with GSF). This changes Gemstone's default
    behavior, which previously always used the IEEE estimator — set Algorithm = IEEEC37_118
    to retain the prior behavior.
  • Both estimators consume samples and emit results in VA, VB, VC, IA, IB, IC order,
    completing the alignment from "Updated voltage/current orders" (the IEEE positive-sequence
    was previously computed from the current channels).
  • Estimators / IPhaseEstimator are public (matching the prior public RollingPhaseEstimator).
  • The UnitTests project had no reference to the library; added a ProjectReference.

SEL Offset Fix Summary

  • SEL CWS FrameParser.ParseFrame advanced the buffer by 32 bytes (timestamp +
    first sample) after the base parser handled sample 0, omitting the 16-byte
    common header. Samples 1-49 of every 50-sample packet were therefore read 16
    bytes (4 analog channels) too early.
  • Effect: each misaligned sample returned [VC(prev), IA(prev), IB(prev), IC(prev), VA(cur), VB(cur)] mislabeled as [VA,VB,VC,IA,IB,IC]; only the
    first sample per packet was correct, corrupting analog values and phase
    estimates.
  • Fix: advance offset/length by 48 (header 16 + timestamp 8 + first sample
    24) so all 50 samples align; sample 49 now ends exactly at the 1224-byte
    frame boundary.

Root cause

base.ParseFrame takes offset by value and leaves the caller's offset at the
frame start, so the manual loop must skip the entire initial frame (48 bytes),
not just its body (32). The bare 32 literal hid the missing header.

Not affected

On-wire framing and the voltage-first channel order (VA,VB,VC,IA,IB,IC,
confirmed by config-frame SignalNames) parse correctly. This was a local
offset-arithmetic defect, not a protocol/device issue.

Lets users choose, via SEL CWS connection parameters, between the rolling
sliding DFT estimator (optional EMA smoothing, default) and the IEEE
C37.118-2018 Annex D filter-based estimator (P/M class); brings Gemstone
back in sync with the GSF implementation.

- Shared PhaseEstimate/PhaseEstimateHandler + IPhaseEstimator; new
  PhaseEstimationAlgorithm { SlidingDft, IEEEC37_118 } enum
- SlidingDftPhaseEstimator + IEEEC37_118PhaseEstimator replace
  RollingPhaseEstimator; both use VA,VB,VC,IA,IB,IC order (completes the
  voltage/current alignment, fixing the IEEE positive-sequence indexing)
- ConnectionParameters: Algorithm selector + sliding-DFT options grouped
  into General / Sliding DFT / IEEE C37.118 property categories
- FrameParser builds the selected estimator, rebuilding on parameter change
- Replaced the console demo with MSTest unit tests (9 sliding DFT + 6 IEEE)
Comment thread src/Gemstone.PhasorProtocols/SelCWS/ConfigurationCell.cs Dismissed
@ritchiecarroll ritchiecarroll changed the base branch from master to development May 23, 2026 21:40
ritchiecarroll and others added 2 commits May 23, 2026 17:42
…tructor or destructor'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
ritchiecarroll and others added 2 commits May 26, 2026 10:31
The initial CWS data frame spans 48 bytes: 16-byte common header + 8-byte
nanosecond timestamp + first 24-byte sample. ParseFrame advanced only 32
(timestamp + first sample) before parsing the remaining 49 samples, omitting
the common header. This read samples 1-49 of every packet 16 bytes (4 analog
channels) too early, scrambling channel/sample alignment -- only the first
sample of each 50-sample packet was correct -- and corrupting derived phase
estimates.

Advance offset/length by 48 instead of 32 so all 50 samples align and sample
49 ends exactly at the 1224-byte frame boundary. On-wire framing and the
voltage-first channel order (VA,VB,VC,IA,IB,IC) were already correct.
@clackner-gpa clackner-gpa merged commit 803dc8f into development May 27, 2026
@clackner-gpa clackner-gpa deleted the SelCWSDualAlgorithm branch May 27, 2026 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants