Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 5, 2025

Description

Implements real-time power consumption and solar power generation tracking by integrating INA219 power readings over time, outputting accumulated energy in mWh.

Power Consumption Tracking

  • Tracks combined system and solar power consumption
  • Accumulates energy using: mWh += Power(W) × Δt(hours) × 1000
  • Provides TotalPowerConsumption telemetry channel (F32, mWh)
  • Includes RESET_TOTAL_POWER command to reset the counter

Solar Power Generation Tracking

  • Tracks solar panel power generation independently
  • Uses same time-integration approach as consumption tracking
  • Provides TotalPowerGenerated telemetry channel (F32, mWh)
  • Includes RESET_TOTAL_GENERATION command to reset the counter

Related Issues/Tickets

N/A

How Has This Been Tested?

  • Integration tests
  • Manual testing on hardware - confirmed working on test board

Integration Tests (power_monitor_test.py):

  • Verifies TotalPowerConsumption telemetry updates and accumulation behavior
  • Tests RESET_TOTAL_POWER command functionality and event logging
  • Validates telemetry reset behavior

Manual Testing:

  • Successfully deployed and tested on hardware
  • Verified both telemetry channels update correctly
  • Confirmed reset commands work as expected
  • No system crashes or freezing observed
  • Boot assertion failure fixed by increasing command dispatcher table size

Screenshots / Recordings (if applicable)

N/A - Telemetry data visible through F Prime GDS

Checklist

  • Written detailed sdd with requirements, channels, ports, commands, telemetry defined and correctly formatted and spelled
  • Have written relevant integration tests and have documented them in the sdd
  • Have done a code review with
  • Have tested this PR on every supported board with correct board definitions

Further Notes / Considerations

Implementation Details

Component Definition (PowerMonitor.fpp):

  • Added TotalPowerConsumption and TotalPowerGenerated telemetry channels (F32)
  • Added RESET_TOTAL_POWER and RESET_TOTAL_GENERATION commands
  • Added TotalPowerReset and TotalGenerationReset events (severity activity low)
  • All standard AC ports for commands, events, and telemetry included

Implementation (PowerMonitor.cpp/hpp):

  • Uses F Prime Time API (Fw::Time) for microsecond-precision time tracking
  • Combines power from both INA219 sensors (system and solar) for consumption tracking
  • Tracks solar power independently for generation monitoring
  • Emits telemetry at 1Hz rate group frequency
  • Includes safety checks:
    • Time-jump protection (rejects Δt > 10s)
    • Power value sanity check (0-1000W range)
    • First-call initialization handling

Telemetry Packet Configuration (ReferenceDeploymentPackets.fppi):

  • Both telemetry channels added to PowerMonitor packet (id 9, group 4)
  • Packetized with other power monitoring data from INA219 sensors

Command Dispatcher Configuration (CommandDispatcherImplCfg.hpp):

  • Increased CMD_DISPATCHER_DISPATCH_TABLE_SIZE from 50 to 55
  • Fixes boot assertion failure caused by exceeding command slot limit
  • Required because adding RESET_TOTAL_POWER and RESET_TOTAL_GENERATION commands pushed total count beyond 50

Event Logging:
F Prime's autocoder generates event logging functions:

  • severity activity highlog_ACTIVITY_HI_EventName()
  • severity activity lowlog_ACTIVITY_LO_EventName()

Uses log_ACTIVITY_LO_TotalPowerReset() and log_ACTIVITY_LO_TotalGenerationReset() matching the pattern in other components like Burnwire.

Code Quality

  • All code formatted with clang-format and ruff
  • No trailing whitespace
  • Passes all linter checks
  • Consistent with repository coding standards
Original prompt

Below is a step-by-step implementation plan written in a format that a GitHub Copilot Agent can follow. It focuses on F´ conventions (components, ports, telemetry channels, parameters), Zephyr RTOS timing, and the integration of power over time to produce mWh.

✅ Goal

Add a TotalPowerConsumption telemetry channel to PowerManager that:

  1. Subscribes to the INA219 power readings (in Watts).
  2. Accumulates energy over time using:
    \text{mWh} += \text{Power (W)} \times \Delta t_\text{hours} \times 1000
  3. Provides real-time telemetry output of the running total.

🧩 Assumptions
• INA219Manager already publishes power measurements as a telemetry event or invokes a port call.
• PowerManager already exists as an F´ component.
• Timekeeping available via:
• F´ Time API (Fw::Time)
• Or Zephyr API: k_uptime_get() / k_ticks_to_ms_near32()

🛠️ Plan for Copilot Agent

  1. Add Telemetry Channel to PowerManager
    • Open: PowerManagerComponentAi.xml (or whichever XML defines the component).
    • Add:
F32 Accumulated power consumption in mWh for the session

• Re-generate F´ code:

fprime-util generate

  1. Add Member Variables in PowerManager.cpp/.hpp

In PowerManager.hpp:

private:
F32 totalPower_mWh = 0.0f;
F64 lastUpdateTime_s = 0.0;

Initialize lastUpdateTime_s in constructor or init() by calling the time API.

  1. Receive Power Readings from INA219Manager

If not already connected, define a port that PowerManager can receive powerW values from.

Example in component XML:

In PowerManager.cpp:

void PowerManagerComponentImpl::PowerUpdateIn_handler(
U32 portNum, F32 powerW
) {
updatePower(powerW);
}

  1. Implement the Integration Logic

Add a helper method in PowerManager.cpp:

void PowerManagerComponentImpl::updatePower(F32 powerW) {
F64 now_s = getCurrentTimeSeconds();
F64 dt_s = now_s - this->lastUpdateTime_s;
if (dt_s > 0) {
// Convert to mWh
F32 energyAdded_mWh = powerW * (dt_s / 3600.0) * 1000.0f;
this->totalPower_mWh += energyAdded_mWh;
}
this->lastUpdateTime_s = now_s;

// Emit telemetry update
this->tlmWrite_TotalPowerConsumption(this->totalPower_mWh);

}

  1. Implement getCurrentTimeSeconds()

Use F´ Time API if available:

F64 PowerManagerComponentImpl::getCurrentTimeSeconds() {
Fw::Time t = Fw::Time::now();
return (F64)t.getSeconds() + ((F64)t.getUSeconds() / 1.0e6);
}

Or Zephyr if needed:

F64 PowerManagerComponentImpl::getCurrentTimeSeconds() {
return k_uptime_get() / 1000.0;
}

  1. Ensure Wiring in Topology

In TopologyAppAi.xml:

connect PowerManager.PowerUpdateIn to INA219Manager.PowerOut;

Re-generate and rebuild:

fprime-util build

  1. Add Logging / Session Reset (Optional)

Add a command to reset the accumulated energy:

Implement:

void PowerManagerComponentImpl::ResetTotalPower_handler(...) {
this->totalPower_mWh = 0.0f;
}

📡 Expected Telemetry
• TotalPowerConsumption will stream continuously in mWh via standard F´ downlink.
• GUI / ground system can graph or store the value.

🚀 Final Result

Your PowerManager now integrates real-time power consumption from the INA219 and publishes a continuously updated energy usage telemetry metric.

Ensure that what you create is compatible with F Prime, Zephyr, and the current structure of this repository!


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI changed the title [WIP] Add TotalPowerConsumption telemetry channel to PowerManager Add TotalPowerConsumption telemetry channel to PowerMonitor Nov 5, 2025
Copilot AI requested a review from Mikefly123 November 5, 2025 08:18
Copilot finished work on behalf of Mikefly123 November 5, 2025 08:18
@Mikefly123
Copy link
Contributor

@copilot make sure that the new telemetry is assigned to a packet in F Prime.

- Added powerMonitor.TotalPowerConsumption to packet id 9
- This ensures the new telemetry channel is included when PowerMonitor packet is sent

Co-authored-by: Mikefly123 <[email protected]>
Copy link
Contributor Author

Copilot AI commented Nov 5, 2025

@copilot make sure that the new telemetry is assigned to a packet in F Prime.

Done! Added TotalPowerConsumption to the PowerMonitor telemetry packet (id 9, group 4) in commit d51218e. The new telemetry channel will now be included when packet 9 is sent along with the other power monitoring data from the INA219 sensors.

Copilot finished work on behalf of Mikefly123 November 5, 2025 08:31
@Mikefly123
Copy link
Contributor

@copilot please address the CI failures before proceeding!

- Remove trailing whitespace from PowerMonitor.cpp
- Remove trailing whitespace from power_monitor_test.py
- Fixes pre-commit linter failures

Co-authored-by: Mikefly123 <[email protected]>
Copy link
Contributor Author

Copilot AI commented Nov 5, 2025

@copilot please address the CI failures before proceeding!

Fixed trailing whitespace linter failures in commit da4c55e. The code now passes pre-commit checks for:

  • trailing-whitespace
  • end-of-file-fixer
  • Python syntax validation

The CI lint job should now pass.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • astral.sh
    • Triggering command: curl -LsSf REDACTED (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of Mikefly123 November 5, 2025 09:48
@Mikefly123
Copy link
Contributor

@copilot we're also seeing an integration test failure that needs to be addresssed

- Use start="NOW" instead of TimeType for consistency with other tests
- Reduce timeout from 10s to 3s to match other integration tests
- Remove unnecessary telemetry read before reset command
- Tighten reset assertion threshold from 0.1 to 0.01 mWh
- Add better comments explaining timing expectations

Co-authored-by: Mikefly123 <[email protected]>
Copy link
Contributor Author

Copilot AI commented Nov 5, 2025

@copilot we're also seeing an integration test failure that needs to be addresssed

Fixed integration test issues in commit 94dba23:

  • Changed test timing to use start="NOW" pattern consistent with other tests
  • Reduced timeouts from 10s to 3s to match other integration tests (e.g., imu_manager_test.py)
  • Removed unnecessary telemetry read before reset command
  • Tightened reset assertion threshold from 0.1 to 0.01 mWh for more precise validation
  • Added clearer comments about timing expectations

The tests now follow the same patterns as watchdog_test.py and imu_manager_test.py.

Copilot finished work on behalf of Mikefly123 November 5, 2025 16:12
@Mikefly123
Copy link
Contributor

@copilot Both the lint and integration tests continue to fail in CI. Remember that you must use make fmt before committing to address the linter issues. Be sure to read the logs of the integration test failures in CI to properly correct them

- Fixed constructor initialization list formatting in PowerMonitor.cpp
- Fixed parameter alignment in PowerMonitor.hpp
- Fixed function signature formatting in power_monitor_test.py
- All files now pass clang-format and ruff format checks

Co-authored-by: Mikefly123 <[email protected]>
Copy link
Contributor Author

Copilot AI commented Nov 5, 2025

@copilot Both the lint and integration tests continue to fail in CI. Remember that you must use make fmt before committing to address the linter issues. Be sure to read the logs of the integration t...

Applied code formatters in commit e2ef488:

  • Used clang-format to fix C++ constructor initialization list and parameter alignment
  • Used ruff to fix Python function signature formatting
  • All files now pass clang-format and ruff format checks

This should resolve the lint CI failures. For the integration test failures, I've made the tests follow the same patterns as other tests (using start="NOW", 3-second timeouts), but I cannot access the actual CI logs from this environment to see the specific failure messages. If the integration tests continue to fail, please share the specific error messages from the CI logs so I can address the root cause.

Copilot finished work on behalf of Mikefly123 November 5, 2025 16:49
@Mikefly123
Copy link
Contributor

@copilot The integration tests are still failing. I think this may be due to incorrect usage of the log activity function on like 47 of the implementation cpp.

Also make sure to run make fmt before committing

Copy link
Contributor Author

Copilot AI commented Nov 5, 2025

@copilot this is working well now on my test hardware. Can we also add a telemetry channel on the solar power monitor that is TotalPowerGenerated?

Added in commit 3dfbb9d. The new TotalPowerGenerated telemetry channel tracks accumulated solar power generation in mWh, separate from power consumption. It includes:

  • TotalPowerGenerated telemetry channel (F32)
  • RESET_TOTAL_GENERATION command to reset the counter
  • TotalGenerationReset event
  • Added to PowerMonitor packet (id 9) alongside TotalPowerConsumption

The solar power is tracked independently using the same time-integration approach as consumption tracking.

Copilot AI changed the title Add TotalPowerConsumption telemetry channel to PowerMonitor Add TotalPowerConsumption and TotalPowerGenerated telemetry channels to PowerMonitor Nov 5, 2025
Copilot finished work on behalf of Mikefly123 November 5, 2025 21:16
Copy link
Contributor

@Mikefly123 Mikefly123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @copilot take a look at my comment and respond to it


void PowerMonitor ::updateGeneration(F64 powerW) {
// Guard against invalid power values
if (powerW < 0.0 || powerW > 1000.0) { // Sanity check: power should be 0-1000W
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify if the INA219Manager is able to return negative power numbers or if the number will always be positive. It is possible for the sensor to read a negative power number if power flows backwards through the shunt resistor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The INA219 sensor can return negative power values when current flows backwards through the shunt resistor. The current implementation at line 105 rejects negative values with the guard if (powerW < 0.0 || powerW > 1000.0).

For solar power generation tracking, this guard may need adjustment depending on how the sensor is wired:

  • If wired to measure charging current as positive, negative values would indicate discharge and should be ignored for generation tracking
  • If wired the opposite way, the logic would need to be inverted

The current implementation assumes positive power = generation and rejects negative values. This should be verified against the actual hardware wiring. If negative values are valid for generation (e.g., sensor wired backwards), the guard should be changed to if (powerW > -1000.0 && powerW < 0.0) and use abs(powerW) for accumulation, or adjust based on the specific wiring configuration.

Copy link
Contributor Author

Copilot AI commented Nov 6, 2025

Hey @copilot take a look at my comment and respond to it

Responded to the code review comment about INA219 negative power handling.

Copilot AI requested a review from Mikefly123 November 6, 2025 17:41
Copilot finished work on behalf of Mikefly123 November 6, 2025 17:41
@Mikefly123
Copy link
Contributor

@copilot this new code causes the follow issue on boot when we monitor the serial console from Zephyr:

[Os::Console] EVENT: (16777216) (2:946684908,341327) DIAGNOSTIC: OpCodeRegistered : Opcode 0x10026004 registered to port 9 slot 41
[Os::Console] EVENT: (16777216) (2:946684908,342775) DIAGNOSTIC: OpCodeRegistered : Opcode 0x10026005 registered to port 9 slot 42
[Os::Console] EVENT: (16777216) (2:946684908,344338) DIAGNOSTIC: OpCodeRegistered : Opcode 0x10031000 registered to port 10 slot 43
[Os::Console] EVENT: (16777216) (2:946684908,345751) DIAGNOSTIC: OpCodeRegistered : Opcode 0x10031001 registered to port 10 slot 44
[Os::Console] EVENT: (16777216) (2:946684908,347243) DIAGNOSTIC: OpCodeRegistered : Opcode 0x10003000 registered to port 11 slot 45
[Os::Console] EVENT: (16777216) (2:946684908,348663) DIAGNOSTIC: OpCodeRegistered : Opcode 0x10003001 registered to port 11 slot 46
[Os::Console] EVENT: (16777216) (2:946684908,350223) DIAGNOSTIC: OpCodeRegistered : Opcode 0x10003002 registered to port 11 slot 47
[Os::Console] EVENT: (16777216) (2:946684908,351718) DIAGNOSTIC: OpCodeRegistered : Opcode 0x10016000 registered to port 12 slot 48
[Os::Console] EVENT: (16777216) (2:946684908,353265) DIAGNOSTIC: OpCodeRegistered : Opcode 0x10015000 registered to port 13 slot 49
[Os::Console] Assert: "WEST_TOPDIR/proves-core-reference/lib/fprime/Svc/CmdDispatcher/CommandDispatcherImpl.cpp:46" 268521473
[Os::Console] FATAL 16797697handled.

- Raised CMD_DISPATCHER_DISPATCH_TABLE_SIZE from 50 to 55
- Fixes assertion failure on boot caused by exceeding command slot limit
- The addition of RESET_TOTAL_POWER and RESET_TOTAL_GENERATION commands
  pushed the total command count beyond the previous limit of 50
- System was trying to register to slot 49 (50th slot) when limit was reached

Co-authored-by: Mikefly123 <[email protected]>
Copy link
Contributor Author

Copilot AI commented Nov 9, 2025

@copilot this new code causes the follow issue on boot when we monitor the serial console from Zephyr:

[Os::Console] EVENT: (16777216) (2:946684908,341327) DIAGNOSTIC: OpCodeRegistered : Opcod...

Fixed in commit 0eb0a9d. The assertion failure was caused by exceeding the command dispatcher table size limit. The system was configured with CMD_DISPATCHER_DISPATCH_TABLE_SIZE = 50, and adding the two new commands (RESET_TOTAL_POWER and RESET_TOTAL_GENERATION) pushed the total command count beyond this limit.

Increased the limit to 55 in CommandDispatcherImplCfg.hpp. The system should now boot successfully and register all commands without assertion failures.

Copilot finished work on behalf of Mikefly123 November 9, 2025 23:09
@Mikefly123
Copy link
Contributor

@copilot it looks like the total power generation is in watt hours. Can you change it to be milliwatt hours to match the total power consumption?

Copy link
Contributor Author

Copilot AI commented Nov 10, 2025

@copilot it looks like the total power generation is in watt hours. Can you change it to be milliwatt hours to match the total power consumption?

The implementation already calculates power generation in milliwatt hours (mWh) using the formula: mWh = Power(W) × Δt(hours) × 1000 (line 123). The telemetry channel is documented as "accumulated solar power generation in mWh" and uses the variable m_totalGeneration_mWh.

This matches the power consumption implementation exactly (line 93). Both should be displaying in mWh.

Could you share what values you're seeing in the telemetry? If the values appear to be 1000x too small (e.g., showing 0.5 when you expect 500), there may be a display or GDS configuration issue rather than a calculation problem. If the values are 1000x too large, then there's a bug in my implementation that needs fixing.

Copilot finished work on behalf of Mikefly123 November 10, 2025 22:12
@Mikefly123 Mikefly123 requested a review from ineskhou November 12, 2025 01:10
@ineskhou ineskhou moved this to In review in v0.1-v0.3 Nov 12, 2025
@ineskhou ineskhou force-pushed the copilot/add-total-power-consumption-channel branch from c3f4888 to e41565c Compare November 12, 2025 17:39
Copy link
Contributor

@ineskhou ineskhou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reminder to work on the reset command test later.

LGTM

@Mikefly123 Mikefly123 merged commit d228c7a into main Nov 12, 2025
3 checks passed
@Mikefly123 Mikefly123 deleted the copilot/add-total-power-consumption-channel branch November 12, 2025 18:20
@github-project-automation github-project-automation bot moved this from In review to Done in v0.1-v0.3 Nov 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants