Skip to content

Conversation

@FredM67
Copy link
Owner

@FredM67 FredM67 commented Oct 16, 2025

Pull request

Proposed changes

Types of changes

  • New feature (non-breaking change which adds functionality).
  • Enhancement (non-breaking change which enhances functionality)
  • Bug Fix (non-breaking change which fixes an issue).
  • Breaking change (fix or feature that would cause existing functionality to change).

Checklist

  • I have read the README document.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.

Replace switch-case logic in ADC interrupt with circular linked list
for improved performance and reduced code size.

Based on florentbr's optimization suggestion #1 from issue #113.

- Add adc_ctx_t structure with minimal memory footprint
- Implement circular linked list for 6 ADC channels
- Eliminate branching in time-critical ISR code
- Maintain exact same functionality as original implementation
Reorganize code structure for better maintainability:
- Remove duplicate ADC definitions from top of file
- Keep all ADC optimization code together near the ISR
- Improve code organization and readability

No functional changes, just code organization improvement.
- Changed DC offset from per-cycle LPF to per-sample EMA filter
- Use Q16.16 fixed-point format for efficient calculation
- Enable ADLAR=1 for left-aligned ADC results
- Simplify voltage/current sample processing
- Reduce computational overhead in ISR
Move opening brace of the else branch to a new line for consistent brace style in processing.cpp
…n metadata

- Replace two type-specific overloads with a single constexpr template<typename T, size_t N>
  initializeArray(T (&array)[N], T value) to remove duplication and support any array element type.
- Expand and clarify Doxygen comments for initializeArray (usage, template params, notes).
- Update version.h CURRENT_TIME and reset
@FredM67 FredM67 linked an issue Oct 16, 2025 that may be closed by this pull request
FredM67 and others added 6 commits October 17, 2025 07:18
- Add mult_asm.h with optimized 16x16->32 signed multiplication (~3x faster)
- Integrate assembly multiplication in processCurrentRawSample() and processVoltage()
- Fix ADMUX timing issue (#125): move ADMUX assignment to end of ISR
- Change CT filter condition to 'if constexpr' for guaranteed dead code elimination
- Add unit tests for assembly multiplication functions

Performance improvements:
- ISR multiplication: ~15-20 cycles vs ~50+ cycles (library calls)
- Zero overhead for disabled CT filtering (compile-time elimination)
- Proper ADMUX timing: 128+ CPU cycles after trigger event per datasheet

Based on florentbr's optimization suggestions and ATmega328p datasheet requirements.
- Add multU16x16_to32 unsigned multiplication function
- Change l_sum_Vsquared from int32_t to uint32_t (V² always positive)
- Rename mult16x16_to32 to multS16x16_to32 for clarity
- Add comprehensive test coverage for unsigned multiplication
- Add voltage accumulation overflow tests (220 lines)
- Validates current shift strategy is safe for all datalog periods
- Proves uint32_t provides 2x headroom vs int32_t (4.3B vs 2.1B)

Related: #121, #125, PR #127
Make spacing consistent around template parameters and static_cast uses,
and tidy up stray blank/whitespace in test_main.cpp for the voltage
accumulation overflow tests.
@FredM67 FredM67 marked this pull request as ready for review October 17, 2025 16:50
…rocessCurrentRawSample

Add inline declarations (uint16_t sample parameter) in both header sections so the function signatures match the always_inline/optimized declarations and the Doxygen variants, avoiding mismatches.
…t scaling and tests

- In ISR-heavy paths, reduce voltage/current samples by >>2 (to 14-bit / x16 scale)
  prior to multS16x16_to32 to improve efficiency on 8-bit MCUs.
- Update scaling shifts to match the new pre-shift:
  - real power multiplication: use filt >>2 then mult, final shift >>8
  - V² accumulation: use filt >>2 then mult, final shift >>8 for <=10s or >>12 for >10s
  (effectively reducing previous right-shifts by 4 bits while preserving numeric scale)
- Update test/embedded/test_voltage_accumulation to use the 14-bit pre-shift strategy,
  adjust test cases and messages (including overflow demo) and refresh conclusions.
@FredM67
Copy link
Owner Author

FredM67 commented Oct 22, 2025

@florentbr Good news, at least for voltage on L1. The value are still correct ;-)

18:37:17.366 > ----------------------------------
18:37:17.397 > Sketch ID: Mk2_3phase_RFdatalog_temp
18:37:17.446 > From branch '121-suggestions-1-2', commit 5d202972
18:37:17.494 > Build on 2025-10-22 18:36:51+02:00
18:37:17.541 > ADC mode:       free-running
18:37:17.557 > Electrical settings
18:37:17.590 >  f_powerCal for L1 =    0.050000
18:37:17.622 >  f_voltageCal, for Vrms_L1 =    0.81510
18:37:17.670 >  f_powerCal for L2 =    0.050000
18:37:17.701 >  f_voltageCal, for Vrms_L2 =    0.81840
18:37:17.749 >  f_powerCal for L3 =    0.050000
18:37:17.782 >  f_voltageCal, for Vrms_L3 =    0.81950
18:37:17.814 >  f_phaseCal for all phases =     1.00
18:37:17.862 >  Export rate (Watts) = 20
18:37:17.893 >  zero-crossing persistence (sample sets) = 1
18:37:17.941 > Output mode:    normal
18:37:17.957 >  f_capacityOfEnergyBucket_main = 180000.00
18:37:18.006 >  f_lowerEnergyThreshold   = 90000.00
18:37:18.053 >  f_upperEnergyThreshold   = 90000.00
18:37:18.085 > Temperature capability is NOT present
18:37:18.133 > Dual-tariff capability is NOT present
18:37:18.165 > Load rotation feature is NOT present
18:37:18.213 > Relay diversion feature is NOT present
18:37:18.245 > Override feature is present
18:37:18.277 > *** Override Pins Configuration ***
18:37:18.325 >  Pin: 4  Bitmask: 0b11100000
18:37:18.342 > RF capability is NOT present
18:37:18.373 > Datalogging capability in Human-readable format
18:37:18.438 > Load Priorities:
18:37:18.454 >  load 0
18:37:18.454 >  load 1
18:37:18.469 >  load 2
18:37:18.485 > >>free RAM = 1611
18:37:18.502 > ----
18:37:30.385 > 5.64, P:0, P1:0, P2:0, P3:0, V1:234.44, V2:0.81, V3:0.81, (minSampleSets/MC 32, #ofSampleSets 8013)
18:37:35.376 > 7.52, P:0, P1:0, P2:0, P3:0, V1:234.54, V2:0.81, V3:0.81, (minSampleSets/MC 32, #ofSampleSets 8014)
18:37:40.382 > 11.07, P:0, P1:0, P2:0, P3:0, V1:234.55, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8015)
18:37:45.389 > 13.45, P:0, P1:0, P2:0, P3:0, V1:234.68, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8015)
18:37:50.379 > 15.74, P:0, P1:0, P2:0, P3:0, V1:234.39, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:37:55.386 > 18.17, P:0, P1:0, P2:0, P3:0, V1:234.26, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8015)
18:38:00.392 > 19.90, P:0, P1:0, P2:0, P3:0, V1:234.13, V2:0.81, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:38:05.399 > 22.55, P:0, P1:0, P2:0, P3:0, V1:234.51, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:38:10.389 > 24.43, P:0, P1:0, P2:0, P3:0, V1:234.55, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8014)
18:38:15.395 > 26.43, P:0, P1:0, P2:0, P3:0, V1:234.60, V2:0.00, V3:0.00, (minSampleSets/MC 31, #ofSampleSets 8013)
18:38:20.386 > 28.73, P:0, P1:0, P2:0, P3:0, V1:234.49, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8014)
18:38:25.392 > 30.85, P:0, P1:0, P2:0, P3:0, V1:234.63, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8014)
18:38:30.399 > 34.34, P:0, P1:0, P2:0, P3:0, V1:234.50, V2:0.00, V3:0.81, (minSampleSets/MC 32, #ofSampleSets 8015)
18:38:35.389 > 35.04, P:0, P1:0, P2:0, P3:0, V1:234.48, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8014)
18:38:40.396 > 38.91, P:0, P1:0, P2:0, P3:0, V1:234.22, V2:0.00, V3:0.81, (minSampleSets/MC 31, #ofSampleSets 8014)
18:38:45.402 > 41.13, P:0, P1:0, P2:0, P3:0, V1:234.31, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8013)
18:38:50.393 > 42.43, P:0, P1:0, P2:0, P3:0, V1:234.41, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8013)
18:38:55.400 > 44.17, P:0, P1:0, P2:0, P3:0, V1:234.46, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8014)
18:39:00.389 > 47.38, P:0, P1:0, P2:0, P3:0, V1:234.32, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8013)
18:39:05.396 > 50.13, P:0, P1:0, P2:0, P3:0, V1:234.09, V2:0.00, V3:0.00, (minSampleSets/MC 31, #ofSampleSets 8014)
18:39:10.403 > 51.61, P:0, P1:0, P2:0, P3:0, V1:234.05, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8014)
18:39:15.394 > 53.73, P:0, P1:0, P2:0, P3:0, V1:234.42, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8012)
18:39:20.400 > 57.18, P:0, P1:0, P2:0, P3:0, V1:234.63, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8013)
18:39:25.391 > 59.20, P:0, P1:0, P2:0, P3:0, V1:234.77, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8013)
18:39:30.396 > 62.84, P:0, P1:0, P2:0, P3:0, V1:234.67, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8014)
18:39:35.403 > 65.29, P:0, P1:0, P2:0, P3:0, V1:234.62, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8015)
18:39:40.409 > 67.60, P:0, P1:0, P2:0, P3:0, V1:234.75, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8015)
18:39:45.400 > 69.98, P:0, P1:0, P2:0, P3:0, V1:234.67, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8015)
18:39:50.407 > 72.59, P:0, P1:0, P2:0, P3:0, V1:234.72, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8015)
18:39:55.413 > 73.82, P:0, P1:0, P2:0, P3:0, V1:234.58, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8015)
18:40:00.404 > 75.37, P:0, P1:0, P2:0, P3:0, V1:234.71, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8015)
18:40:05.410 > 77.44, P:0, P1:0, P2:0, P3:0, V1:234.78, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:40:10.417 > 79.48, P:0, P1:0, P2:0, P3:0, V1:234.78, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:40:15.406 > 81.38, P:0, P1:0, P2:0, P3:0, V1:234.69, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:40:20.414 > 84.67, P:0, P1:0, P2:0, P3:0, V1:234.41, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:40:25.420 > 87.67, P:0, P1:0, P2:0, P3:0, V1:234.39, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:40:30.427 > 90.30, P:0, P1:0, P2:0, P3:0, V1:234.50, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8017)
18:40:35.416 > 92.40, P:0, P1:0, P2:0, P3:0, V1:234.49, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8017)
18:40:40.423 > 94.29, P:0, P1:0, P2:0, P3:0, V1:234.53, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8017)
18:40:45.429 > 96.73, P:0, P1:0, P2:0, P3:0, V1:234.70, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:40:50.436 > 99.96, P:0, P1:0, P2:0, P3:0, V1:234.80, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8015)
18:40:55.427 > 102.24, P:0, P1:0, P2:0, P3:0, V1:234.64, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:41:00.433 > 104.34, P:0, P1:0, P2:0, P3:0, V1:234.69, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:41:05.439 > 106.01, P:0, P1:0, P2:0, P3:0, V1:234.67, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:41:10.429 > 110.39, P:0, P1:0, P2:0, P3:0, V1:234.78, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8017)
18:41:15.436 > 114.01, P:0, P1:0, P2:0, P3:0, V1:234.81, V2:0.81, V3:0.81, (minSampleSets/MC 32, #ofSampleSets 8016)
18:41:20.442 > 115.98, P:0, P1:0, P2:0, P3:0, V1:234.73, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8016)
18:41:25.448 > 118.20, P:0, P1:0, P2:0, P3:0, V1:234.71, V2:0.00, V3:0.00, (minSampleSets/MC 32, #ofSampleSets 8015)

From time to time, there's a value of "0.81" for V2 and V3, even nothing is wired. Same exact effet with the "original" version :D

* fix: update ADMUX at end of ADC ISR to meet ATmega328P timing

Move ADMUX write to the end of the ADC_vect ISR so at least 128 CPU cycles
have passed since the trigger event (per ATmega328P datasheet). Prevents
premature channel switching and ensures correct sampling timing.

* #126 (comment)
@FredM67 FredM67 changed the base branch from main to dev December 27, 2025 12:35
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.

Suggestions 1 & 2

3 participants