diff --git a/FprimeZephyrReference/Components/CMakeLists.txt b/FprimeZephyrReference/Components/CMakeLists.txt index 26405d0..9b9cab9 100644 --- a/FprimeZephyrReference/Components/CMakeLists.txt +++ b/FprimeZephyrReference/Components/CMakeLists.txt @@ -1,12 +1,13 @@ # Include project-wide components here -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Drv/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/AntennaDeployer/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/BootloaderTrigger/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Burnwire/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ComDelay/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Drv/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FatalHandler") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FsSpace/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ImuManager/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/NullPrmDb/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/PowerMonitor/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Watchdog") -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Burnwire/") -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/BootloaderTrigger/") -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/AntennaDeployer/") -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FsSpace/") diff --git a/FprimeZephyrReference/Components/Drv/CMakeLists.txt b/FprimeZephyrReference/Components/Drv/CMakeLists.txt index 6945424..c37c4d2 100644 --- a/FprimeZephyrReference/Components/Drv/CMakeLists.txt +++ b/FprimeZephyrReference/Components/Drv/CMakeLists.txt @@ -1,4 +1,5 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Helpers/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Ina219Manager/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Lis2mdlManager/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Lsm6dsoManager/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/RtcManager") diff --git a/FprimeZephyrReference/Components/Drv/Ina219Manager/CMakeLists.txt b/FprimeZephyrReference/Components/Drv/Ina219Manager/CMakeLists.txt new file mode 100644 index 0000000..0f2d868 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/Ina219Manager/CMakeLists.txt @@ -0,0 +1,36 @@ +#### +# F Prime CMakeLists.txt: +# +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/ +# +#### + +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. + +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/Ina219Manager.fpp" + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/Ina219Manager.cpp" +# DEPENDS +# MyPackage_MyOtherModule +) + +### Unit Tests ### +# register_fprime_ut( +# AUTOCODER_INPUTS +# "${CMAKE_CURRENT_LIST_DIR}/Ina219Manager.fpp" +# SOURCES +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/Ina219ManagerTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/Ina219ManagerTester.cpp" +# DEPENDS +# STest # For rules-based testing +# UT_AUTO_HELPERS +# ) diff --git a/FprimeZephyrReference/Components/Drv/Ina219Manager/Ina219Manager.cpp b/FprimeZephyrReference/Components/Drv/Ina219Manager/Ina219Manager.cpp new file mode 100644 index 0000000..46eef48 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/Ina219Manager/Ina219Manager.cpp @@ -0,0 +1,85 @@ +// ====================================================================== +// \title Ina219Manager.cpp +// \brief cpp file for Ina219Manager component implementation class +// ====================================================================== + +#include "FprimeZephyrReference/Components/Drv/Ina219Manager/Ina219Manager.hpp" +#include + +namespace Drv { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +Ina219Manager ::Ina219Manager(const char* const compName) : Ina219ManagerComponentBase(compName) {} + +Ina219Manager ::~Ina219Manager() {} + +// ---------------------------------------------------------------------- +// Helper methods +// ---------------------------------------------------------------------- + +void Ina219Manager::configure(const struct device* dev) { + this->m_dev = dev; +} + +// ---------------------------------------------------------------------- +// Handler implementations for typed input ports +// ---------------------------------------------------------------------- + +F64 Ina219Manager ::currentGet_handler(FwIndexType portNum) { + if (!device_is_ready(this->m_dev)) { + this->log_WARNING_HI_DeviceNotReady(); + return 0; + } + this->log_WARNING_HI_DeviceNotReady_ThrottleClear(); + + struct sensor_value current; + + sensor_sample_fetch_chan(this->m_dev, SENSOR_CHAN_CURRENT); + + sensor_channel_get(this->m_dev, SENSOR_CHAN_CURRENT, ¤t); + + this->tlmWrite_Current(sensor_value_to_double(¤t)); + + return sensor_value_to_double(¤t); +} + +F64 Ina219Manager ::powerGet_handler(FwIndexType portNum) { + if (!device_is_ready(this->m_dev)) { + this->log_WARNING_HI_DeviceNotReady(); + return 0; + } + this->log_WARNING_HI_DeviceNotReady_ThrottleClear(); + + struct sensor_value power; + + sensor_sample_fetch_chan(this->m_dev, SENSOR_CHAN_POWER); + + sensor_channel_get(this->m_dev, SENSOR_CHAN_POWER, &power); + + this->tlmWrite_Power(sensor_value_to_double(&power)); + + return sensor_value_to_double(&power); +} + +F64 Ina219Manager ::voltageGet_handler(FwIndexType portNum) { + if (!device_is_ready(this->m_dev)) { + this->log_WARNING_HI_DeviceNotReady(); + return 0; + } + this->log_WARNING_HI_DeviceNotReady_ThrottleClear(); + + struct sensor_value voltage; + + sensor_sample_fetch_chan(this->m_dev, SENSOR_CHAN_VOLTAGE); + + sensor_channel_get(this->m_dev, SENSOR_CHAN_VOLTAGE, &voltage); + + this->tlmWrite_Voltage(sensor_value_to_double(&voltage)); + + return sensor_value_to_double(&voltage); +} + +} // namespace Drv diff --git a/FprimeZephyrReference/Components/Drv/Ina219Manager/Ina219Manager.fpp b/FprimeZephyrReference/Components/Drv/Ina219Manager/Ina219Manager.fpp new file mode 100644 index 0000000..b2abcc3 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/Ina219Manager/Ina219Manager.fpp @@ -0,0 +1,50 @@ +module Drv { + port VoltageGet -> F64 + port CurrentGet -> F64 + port PowerGet -> F64 +} + +module Drv { + @ Manager for Ina219 device + passive component Ina219Manager { + # Ports + @ Port to read the voltage in volts + sync input port voltageGet: VoltageGet + + @ Port to read the current in amps + sync input port currentGet: CurrentGet + + @ Port to read the power in watts + sync input port powerGet: PowerGet + + # Telemetry channels + + @ Telemetry channel for voltage in volts + telemetry Voltage: F64 + + @ Telemetry channel for current in amps + telemetry Current: F64 + + @ Telemetry channel for power in watts + telemetry Power: F64 + + @ Event for reporting INA219 not ready error + event DeviceNotReady() severity warning high format "INA219 device not ready" throttle 5 + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + @ Port for sending telemetry channels to downlink + telemetry port tlmOut + + } +} diff --git a/FprimeZephyrReference/Components/Drv/Ina219Manager/Ina219Manager.hpp b/FprimeZephyrReference/Components/Drv/Ina219Manager/Ina219Manager.hpp new file mode 100644 index 0000000..a76245c --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/Ina219Manager/Ina219Manager.hpp @@ -0,0 +1,70 @@ +// ====================================================================== +// \title Ina219Manager.hpp +// \brief hpp file for Ina219Manager component implementation class +// ====================================================================== + +#ifndef Drv_Ina219Manager_HPP +#define Drv_Ina219Manager_HPP + +#include "FprimeZephyrReference/Components/Drv/Ina219Manager/Ina219ManagerComponentAc.hpp" + +#include +#include +#include +namespace Drv { + +class Ina219Manager final : public Ina219ManagerComponentBase { + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct Ina219Manager object + Ina219Manager(const char* const compName //!< The component name + ); + + //! Destroy Ina219Manager object + ~Ina219Manager(); + + public: + // ---------------------------------------------------------------------- + // Helper methods + // ---------------------------------------------------------------------- + + //! Configure the INA219 device + void configure(const struct device* dev); + + private: + // ---------------------------------------------------------------------- + // Handler implementations for typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for currentGet + //! + //! Port to read the current in amps + F64 currentGet_handler(FwIndexType portNum //!< The port number + ) override; + + //! Handler implementation for powerGet + //! + //! Port to read the power in watts + F64 powerGet_handler(FwIndexType portNum //!< The port number + ) override; + + //! Handler implementation for voltageGet + //! + //! Port to read the voltage in volts + F64 voltageGet_handler(FwIndexType portNum //!< The port number + ) override; + + // ---------------------------------------------------------------------- + // Member variables + // ---------------------------------------------------------------------- + + //! Zephyr device stores the initialized LIS2MDL sensor + const struct device* m_dev; +}; + +} // namespace Drv + +#endif diff --git a/FprimeZephyrReference/Components/Drv/Ina219Manager/docs/sdd.md b/FprimeZephyrReference/Components/Drv/Ina219Manager/docs/sdd.md new file mode 100644 index 0000000..7d57e4d --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/Ina219Manager/docs/sdd.md @@ -0,0 +1,111 @@ +# Drv::Ina219Manager + +The INA219 Manager component interfaces with the INA219 current/power monitor to provide voltage, current, and power measurements. + +## Usage Examples + +The INA219 Manager component is designed to be called periodically to collect and return sensor data. It operates as a passive component that responds to manager calls. + +### Typical Usage + +1. The component is instantiated and initialized during system startup +2. A manager calls any of the input ports: `VoltageGet`, `CurrentGet`, or `PowerGet` +3. On each call, the component: + - Fetches fresh sensor samples from the sensor + - Converts sensor data to double precision floating point + - Writes telemetry data + - Returns data in SI units + +## Class Diagram + +```mermaid +classDiagram + namespace Drv { + class Ina219ManagerComponentBase { + <> + } + class Ina219Manager { + - m_dev: const struct device* + + Ina219Manager(const char* compName) + + ~Ina219Manager() + + configure(const struct device* dev) + - voltageGet_handler(const FwIndexType portNum): F64 + - currentGet_handler(const FwIndexType portNum): F64 + - powerGet_handler(const FwIndexType portNum): F64 + } + } + Ina219ManagerComponentBase <|-- Ina219Manager : inherits +``` + +## Port Descriptions +| Name | Type | Description | +|---|---|---| +| VoltageGet | sync input | Triggers voltage data collection and returns voltage in volts | +| CurrentGet | sync input | Triggers current data collection and returns current in amps | +| PowerGet | sync input | Triggers power data collection and returns power in watts | + +## Sequence Diagrams + +### VoltageGet +```mermaid +sequenceDiagram + participant Manager + participant INA219 Manager + participant Zephyr Sensor API + participant INA219 Sensor + + Manager-->>INA219 Manager: Call VoltageGet synchronous input port + INA219 Manager->>Zephyr Sensor API: Fetch sensor data + Zephyr Sensor API->>INA219 Sensor: Read sensor + INA219 Sensor->>Zephyr Sensor API: Return sensor data + Zephyr Sensor API->>INA219 Manager: Return voltage sensor_value struct + INA219 Manager->>INA219 Manager: Write telemetry + INA219 Manager-->>Manager: Return F64 voltage in volts +``` + +### CurrentGet +```mermaid +sequenceDiagram + participant Manager + participant INA219 Manager + participant Zephyr Sensor API + participant INA219 Sensor + + Manager-->>INA219 Manager: Call CurrentGet synchronous input port + INA219 Manager->>Zephyr Sensor API: Fetch sensor data + Zephyr Sensor API->>INA219 Sensor: Read sensor + INA219 Sensor->>Zephyr Sensor API: Return sensor data + Zephyr Sensor API->>INA219 Manager: Return current sensor_value struct + INA219 Manager->>INA219 Manager: Write telemetry + INA219 Manager-->>Manager: Return F64 current in amps +``` + +### PowerGet +```mermaid +sequenceDiagram + participant Manager + participant INA219 Manager + participant Zephyr Sensor API + participant INA219 Sensor + + Manager-->>INA219 Manager: Call PowerGet synchronous input port + INA219 Manager->>Zephyr Sensor API: Fetch sensor data + Zephyr Sensor API->>INA219 Sensor: Read sensor + INA219 Sensor->>Zephyr Sensor API: Return sensor data + Zephyr Sensor API->>INA219 Manager: Return power sensor_value struct + INA219 Manager->>INA219 Manager: Write telemetry + INA219 Manager-->>Manager: Return F64 power in watts +``` + +## Requirements +| Name | Description | Validation | +|---|---|---| +| VoltageGet Port | The component shall provide access to voltage sensor data and return in volts | Integration test | +| CurrentGet Port | The component shall provide access to current sensor data and return in amps | Integration test | +| PowerGet Port | The component shall provide access to power sensor data and return in watts | Integration test | +| DeviceNotReady Event | The component shall emit a throttled warning event when the device is not ready | Verify event is emitted and throttled to 5 occurrences | + +## Change Log +| Date | Description | +|---|---| +| 2025-11-03 | Initial INA219 Manager component | diff --git a/FprimeZephyrReference/Components/PowerMonitor/CMakeLists.txt b/FprimeZephyrReference/Components/PowerMonitor/CMakeLists.txt new file mode 100644 index 0000000..13726b4 --- /dev/null +++ b/FprimeZephyrReference/Components/PowerMonitor/CMakeLists.txt @@ -0,0 +1,36 @@ +#### +# F Prime CMakeLists.txt: +# +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/ +# +#### + +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. + +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/PowerMonitor.fpp" + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/PowerMonitor.cpp" +# DEPENDS +# MyPackage_MyOtherModule +) + +### Unit Tests ### +# register_fprime_ut( +# AUTOCODER_INPUTS +# "${CMAKE_CURRENT_LIST_DIR}/PowerMonitor.fpp" +# SOURCES +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/PowerMonitorTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/PowerMonitorTester.cpp" +# DEPENDS +# STest # For rules-based testing +# UT_AUTO_HELPERS +# ) diff --git a/FprimeZephyrReference/Components/PowerMonitor/PowerMonitor.cpp b/FprimeZephyrReference/Components/PowerMonitor/PowerMonitor.cpp new file mode 100644 index 0000000..55d093d --- /dev/null +++ b/FprimeZephyrReference/Components/PowerMonitor/PowerMonitor.cpp @@ -0,0 +1,34 @@ +// ====================================================================== +// \title PowerMonitor.cpp +// \brief cpp file for PowerMonitor component implementation class +// ====================================================================== + +#include "FprimeZephyrReference/Components/PowerMonitor/PowerMonitor.hpp" + +namespace Components { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +PowerMonitor ::PowerMonitor(const char* const compName) : PowerMonitorComponentBase(compName) {} + +PowerMonitor ::~PowerMonitor() {} + +// ---------------------------------------------------------------------- +// Handler implementations for typed input ports +// ---------------------------------------------------------------------- + +void PowerMonitor ::run_handler(FwIndexType portNum, U32 context) { + // System Power Monitor Requests + this->sysVoltageGet_out(0); + this->sysCurrentGet_out(0); + this->sysPowerGet_out(0); + + // Solar Panel Power Monitor Requests + this->solVoltageGet_out(0); + this->solCurrentGet_out(0); + this->solPowerGet_out(0); +} + +} // namespace Components diff --git a/FprimeZephyrReference/Components/PowerMonitor/PowerMonitor.fpp b/FprimeZephyrReference/Components/PowerMonitor/PowerMonitor.fpp new file mode 100644 index 0000000..5859934 --- /dev/null +++ b/FprimeZephyrReference/Components/PowerMonitor/PowerMonitor.fpp @@ -0,0 +1,31 @@ +module Components { + @ Power Monitor Manager + passive component PowerMonitor { + sync input port run: Svc.Sched + + @ Port for sending voltageGet calls to the System Driver + output port sysVoltageGet: Drv.VoltageGet + + @ Port for sending currentGet calls to the System Driver + output port sysCurrentGet: Drv.CurrentGet + + @ Port for sending powerGet calls to the System Driver + output port sysPowerGet: Drv.PowerGet + + @ Port for sending voltageGet calls to the Solar Panel Driver + output port solVoltageGet: Drv.VoltageGet + + @ Port for sending currentGet calls to the Solar Panel Driver + output port solCurrentGet: Drv.CurrentGet + + @ Port for sending powerGet calls to the Solar Panel Driver + output port solPowerGet: Drv.PowerGet + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + } +} diff --git a/FprimeZephyrReference/Components/PowerMonitor/PowerMonitor.hpp b/FprimeZephyrReference/Components/PowerMonitor/PowerMonitor.hpp new file mode 100644 index 0000000..ec4595b --- /dev/null +++ b/FprimeZephyrReference/Components/PowerMonitor/PowerMonitor.hpp @@ -0,0 +1,39 @@ +// ====================================================================== +// \title PowerMonitor.hpp +// \brief hpp file for PowerMonitor component implementation class +// ====================================================================== + +#ifndef Components_PowerMonitor_HPP +#define Components_PowerMonitor_HPP + +#include "FprimeZephyrReference/Components/PowerMonitor/PowerMonitorComponentAc.hpp" + +namespace Components { + +class PowerMonitor final : public PowerMonitorComponentBase { + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct PowerMonitor object + PowerMonitor(const char* const compName //!< The component name + ); + + //! Destroy PowerMonitor object + ~PowerMonitor(); + + private: + // ---------------------------------------------------------------------- + // Handler implementations for typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for run + void run_handler(FwIndexType portNum, //!< The port number + U32 context //!< The call order + ) override; +}; + +} // namespace Components + +#endif diff --git a/FprimeZephyrReference/Components/PowerMonitor/docs/sdd.md b/FprimeZephyrReference/Components/PowerMonitor/docs/sdd.md new file mode 100644 index 0000000..ac331b4 --- /dev/null +++ b/FprimeZephyrReference/Components/PowerMonitor/docs/sdd.md @@ -0,0 +1,94 @@ +# Components::PowerMonitor + +The Power Monitor component is a manager that coordinates power monitoring across multiple power sources. It periodically polls voltage, current, and power measurements from both system power and solar panel power sources. + +## Usage Examples + +The Power Monitor component is designed to run periodically via a rate group scheduler. It operates as a passive component that coordinates data collection from multiple power monitoring drivers. + +### Typical Usage + +1. The component is instantiated and initialized during system startup +2. The component is connected to: + - A rate group scheduler (via the `run` input port) + - System power monitoring driver (via `sys*` output ports) + - Solar panel power monitoring driver (via `sol*` output ports) +3. On each scheduler cycle: + - The component calls all six output ports to trigger measurements + - Each connected driver fetches sensor data and writes telemetry + - Power monitoring data becomes available system-wide + +## Class Diagram + +```mermaid +classDiagram + namespace Components { + class PowerMonitorComponentBase { + <> + } + class PowerMonitor { + + PowerMonitor(const char* compName) + + ~PowerMonitor() + - run_handler(FwIndexType portNum, U32 context) + } + } + PowerMonitorComponentBase <|-- PowerMonitor : inherits +``` + +## Port Descriptions +| Name | Type | Description | +|---|---|---| +| run | sync input | Scheduler port that triggers periodic power monitoring cycle | +| sysVoltageGet | output | Requests voltage measurement from system power driver | +| sysCurrentGet | output | Requests current measurement from system power driver | +| sysPowerGet | output | Requests power measurement from system power driver | +| solVoltageGet | output | Requests voltage measurement from solar panel power driver | +| solCurrentGet | output | Requests current measurement from solar panel power driver | +| solPowerGet | output | Requests power measurement from solar panel power driver | + +## Sequence Diagrams + +### Run Cycle +```mermaid +sequenceDiagram + participant Rate Group + participant Power Monitor + participant System Power Driver + participant Solar Power Driver + + Rate Group->>Power Monitor: run(portNum, context) + + Power Monitor->>System Power Driver: sysVoltageGet() + System Power Driver-->>Power Monitor: voltage + + Power Monitor->>System Power Driver: sysCurrentGet() + System Power Driver-->>Power Monitor: current + + Power Monitor->>System Power Driver: sysPowerGet() + System Power Driver-->>Power Monitor: power + + Power Monitor->>Solar Power Driver: solVoltageGet() + Solar Power Driver-->>Power Monitor: voltage + + Power Monitor->>Solar Power Driver: solCurrentGet() + Solar Power Driver-->>Power Monitor: current + + Power Monitor->>Solar Power Driver: solPowerGet() + Solar Power Driver-->>Power Monitor: power +``` + +## Requirements +| Name | Description | Validation | +|---|---|---| +| PWR-MON-REQ-001 | The component shall respond to scheduler calls via the run port | Integration test | +| PWR-MON-REQ-002 | The component shall request voltage measurements from the system power driver on each run cycle | Integration test | +| PWR-MON-REQ-003 | The component shall request current measurements from the system power driver on each run cycle | Integration test | +| PWR-MON-REQ-004 | The component shall request power measurements from the system power driver on each run cycle | Integration test | +| PWR-MON-REQ-005 | The component shall request voltage measurements from the solar panel power driver on each run cycle | Integration test | +| PWR-MON-REQ-006 | The component shall request current measurements from the solar panel power driver on each run cycle | Integration test | +| PWR-MON-REQ-007 | The component shall request power measurements from the solar panel power driver on each run cycle | Integration test | + +## Change Log +| Date | Description | +|---|---| +| 2025-11-03 | Initial Power Monitor component | diff --git a/FprimeZephyrReference/ReferenceDeployment/Main.cpp b/FprimeZephyrReference/ReferenceDeployment/Main.cpp index 705a7f2..9c95ac8 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Main.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Main.cpp @@ -10,6 +10,8 @@ #include #include +const struct device* ina219Sys = device_get_binding("INA219 sys"); +const struct device* ina219Sol = device_get_binding("INA219 sol"); const struct device* serial = DEVICE_DT_GET(DT_NODELABEL(cdc_acm_uart0)); const struct device* lora = DEVICE_DT_GET(DT_NODELABEL(lora0)); @@ -22,6 +24,8 @@ int main(int argc, char* argv[]) { Os::init(); // Object for communicating state to the topology ReferenceDeployment::TopologyState inputs; + inputs.ina219SysDevice = ina219Sys; + inputs.ina219SolDevice = ina219Sol; inputs.loraDevice = lora; inputs.uartDevice = serial; inputs.baudRate = 115200; diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi index 43f0bbf..e8e74ee 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi @@ -61,6 +61,15 @@ telemetry packets ReferenceDeploymentPackets { ReferenceDeployment.antennaDeployer.LastDistance } + packet PowerMonitor id 9 group 4 { + ReferenceDeployment.ina219SysManager.Voltage + ReferenceDeployment.ina219SysManager.Current + ReferenceDeployment.ina219SysManager.Power + ReferenceDeployment.ina219SolManager.Voltage + ReferenceDeployment.ina219SolManager.Current + ReferenceDeployment.ina219SolManager.Power + } + } omit { CdhCore.cmdDisp.CommandErrors # Only has one library, no custom versions diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp index ccef907..35871a2 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp @@ -87,6 +87,8 @@ void setupTopology(const TopologyState& state) { // for over-the-air communications. lora.start(state.loraDevice, Zephyr::TransmitState::DISABLED); comDriver.configure(state.uartDevice, state.baudRate); + ina219SysManager.configure(state.ina219SysDevice); + ina219SolManager.configure(state.ina219SolDevice); } void startRateGroups() { diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp index 81064f6..40e6680 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp @@ -69,6 +69,8 @@ namespace ReferenceDeployment { * autocoder. The contents are entirely up to the definition of the project. This deployment uses subtopologies. */ struct TopologyState { + const device* ina219SysDevice; //!< device path for battery board ina219 + const device* ina219SolDevice; //!< device path for solar panel ina219 const device* uartDevice; //!< UART device path for communication const device* loraDevice; //!< LoRa device path for communication U32 baudRate; //!< Baud rate for UART communication diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp index 26eebbf..4cf1dbf 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp @@ -89,4 +89,10 @@ module ReferenceDeployment { instance antennaDeployer: Components.AntennaDeployer base id 0x10029000 instance fsSpace: Components.FsSpace base id 0x10030000 + + instance powerMonitor: Components.PowerMonitor base id 0x10031000 + + instance ina219SysManager: Drv.Ina219Manager base id 0x10032000 + + instance ina219SolManager: Drv.Ina219Manager base id 0x10033000 } diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp index ec3bcfb..79169a2 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp @@ -44,6 +44,9 @@ module ReferenceDeployment { # For UART sideband communication instance comDriver instance fsSpace + instance powerMonitor + instance ina219SysManager + instance ina219SolManager # ---------------------------------------------------------------------- @@ -137,6 +140,7 @@ module ReferenceDeployment { rateGroup1Hz.RateGroupMemberOut[7] -> burnwire.schedIn rateGroup1Hz.RateGroupMemberOut[8] -> antennaDeployer.schedIn rateGroup1Hz.RateGroupMemberOut[9] -> fsSpace.run + rateGroup1Hz.RateGroupMemberOut[10] -> powerMonitor.run } @@ -161,5 +165,15 @@ module ReferenceDeployment { imuManager.magneticFieldGet -> lis2mdlManager.magneticFieldGet imuManager.temperatureGet -> lsm6dsoManager.temperatureGet } + + connections sysPowerMonitor { + powerMonitor.sysVoltageGet -> ina219SysManager.voltageGet + powerMonitor.sysCurrentGet -> ina219SysManager.currentGet + powerMonitor.sysPowerGet -> ina219SysManager.powerGet + powerMonitor.solVoltageGet -> ina219SolManager.voltageGet + powerMonitor.solCurrentGet -> ina219SolManager.currentGet + powerMonitor.solPowerGet -> ina219SolManager.powerGet + } + } } diff --git a/FprimeZephyrReference/project/config/AcConstants.fpp b/FprimeZephyrReference/project/config/AcConstants.fpp new file mode 100644 index 0000000..8eeefb4 --- /dev/null +++ b/FprimeZephyrReference/project/config/AcConstants.fpp @@ -0,0 +1,70 @@ +# ====================================================================== +# AcConstants.fpp +# F Prime configuration constants +# ====================================================================== + +@ Number of rate group member output ports for ActiveRateGroup +constant ActiveRateGroupOutputPorts = 15 + +@ Number of rate group member output ports for PassiveRateGroup +constant PassiveRateGroupOutputPorts = 10 + +@ Used to drive rate groups +constant RateGroupDriverRateGroupPorts = 3 + +@ Used for command and registration ports +constant CmdDispatcherComponentCommandPorts = 30 + +@ Used for uplink/sequencer buffer/response ports +constant CmdDispatcherSequencePorts = 5 + +@ Used for dispatching sequences to command sequencers +constant SeqDispatcherSequencerPorts = 2 + +@ Used for sizing the command splitter input arrays +constant CmdSplitterPorts = CmdDispatcherSequencePorts + +@ Number of static memory allocations +constant StaticMemoryAllocations = 4 + +@ Used to ping active components +constant HealthPingPorts = 25 + +@ Used for broadcasting completed file downlinks +constant FileDownCompletePorts = 1 + +@ Used for number of Fw::Com type ports supported by Svc::ComQueue +constant ComQueueComPorts = 2 + +@ Used for number of Fw::Buffer type ports supported by Svc::ComQueue +constant ComQueueBufferPorts = 1 + +@ Used for maximum number of connected buffer repeater consumers +constant BufferRepeaterOutputPorts = 10 + +@ Size of port array for DpManager +constant DpManagerNumPorts = 5 + +@ Size of processing port array for DpWriter +constant DpWriterNumProcPorts = 5 + +@ The size of a file name string +constant FileNameStringSize = 200 + +@ The size of an assert text string +constant FwAssertTextSize = 256 + +@ The size of a file name in an AssertFatalAdapter event +@ Note: File names in assertion failures are also truncated by +@ the constants FW_ASSERT_TEXT_SIZE and FW_LOG_STRING_MAX_SIZE, set +@ in FpConfig.h. +constant AssertFatalAdapterEventFileSize = FileNameStringSize + +# ---------------------------------------------------------------------- +# Hub connections. Connections on all deployments should mirror these settings. +# ---------------------------------------------------------------------- + +constant GenericHubInputPorts = 10 +constant GenericHubOutputPorts = 10 +constant GenericHubInputBuffers = 10 +constant GenericHubOutputBuffers = 10 diff --git a/FprimeZephyrReference/project/config/CMakeLists.txt b/FprimeZephyrReference/project/config/CMakeLists.txt index cf115d7..0e62ab4 100644 --- a/FprimeZephyrReference/project/config/CMakeLists.txt +++ b/FprimeZephyrReference/project/config/CMakeLists.txt @@ -5,6 +5,7 @@ #### register_fprime_config( CONFIGURATION_OVERRIDES + "${CMAKE_CURRENT_LIST_DIR}/AcConstants.fpp" "${CMAKE_CURRENT_LIST_DIR}/CdhCoreConfig.fpp" "${CMAKE_CURRENT_LIST_DIR}/CdhCoreTlmConfig.fpp" "${CMAKE_CURRENT_LIST_DIR}/CdhCoreFatalHandlerConfig.fpp" diff --git a/FprimeZephyrReference/project/config/TlmPacketizerCfg.hpp b/FprimeZephyrReference/project/config/TlmPacketizerCfg.hpp index 3c11895..9bbbda0 100644 --- a/FprimeZephyrReference/project/config/TlmPacketizerCfg.hpp +++ b/FprimeZephyrReference/project/config/TlmPacketizerCfg.hpp @@ -16,7 +16,7 @@ #include namespace Svc { -static const FwChanIdType MAX_PACKETIZER_PACKETS = 8; +static const FwChanIdType MAX_PACKETIZER_PACKETS = 10; static const FwChanIdType TLMPACKETIZER_NUM_TLM_HASH_SLOTS = 15; // !< Number of slots in the hash table. // Works best when set to about twice the number of components producing telemetry diff --git a/FprimeZephyrReference/test/int/power_monitor_test.py b/FprimeZephyrReference/test/int/power_monitor_test.py new file mode 100644 index 0000000..495ee55 --- /dev/null +++ b/FprimeZephyrReference/test/int/power_monitor_test.py @@ -0,0 +1,63 @@ +""" +power_monitor_test.py: + +Integration tests for the Power Monitor component. +""" + +from datetime import datetime + +import pytest +from common import proves_send_and_assert_command +from fprime.common.models.serialize.time_type import TimeType +from fprime_gds.common.data_types.ch_data import ChData +from fprime_gds.common.testing_fw.api import IntegrationTestAPI + +ina219SysManager = "ReferenceDeployment.ina219SysManager" +ina219SolManager = "ReferenceDeployment.ina219SolManager" + + +@pytest.fixture(autouse=True) +def send_packet(fprime_test_api: IntegrationTestAPI, start_gds): + """Fixture to send the power manager packet before each test""" + proves_send_and_assert_command( + fprime_test_api, + "CdhCore.tlmSend.SEND_PKT", + ["9"], + ) + + +def test_01_power_manager_telemetry(fprime_test_api: IntegrationTestAPI, start_gds): + """Test that we can get Acceleration telemetry""" + start: TimeType = TimeType().set_datetime(datetime.now()) + sys_voltage: ChData = fprime_test_api.assert_telemetry( + f"{ina219SysManager}.Voltage", start=start, timeout=65 + ) + sys_current: ChData = fprime_test_api.assert_telemetry( + f"{ina219SysManager}.Current", start=start, timeout=65 + ) + _: ChData = fprime_test_api.assert_telemetry( + f"{ina219SysManager}.Power", start=start, timeout=65 + ) + sol_voltage: ChData = fprime_test_api.assert_telemetry( + f"{ina219SolManager}.Voltage", start=start, timeout=65 + ) + sol_current: ChData = fprime_test_api.assert_telemetry( + f"{ina219SolManager}.Current", start=start, timeout=65 + ) + _: ChData = fprime_test_api.assert_telemetry( + f"{ina219SolManager}.Power", start=start, timeout=65 + ) + + sys_voltage_reading: dict[float] = sys_voltage.get_val() + sys_current_reading: dict[float] = sys_current.get_val() + # sys_power_reading: dict[float] = sys_power.get_val() + sol_voltage_reading: dict[float] = sol_voltage.get_val() + sol_current_reading: dict[float] = sol_current.get_val() + # sol_power_reading: dict[float] = sol_power.get_val() + + assert sys_voltage_reading != 0, "Acceleration reading should be non-zero" + assert sys_current_reading != 0, "Acceleration reading should be non-zero" + # assert sys_power_reading != 0, "Acceleration reading should be non-zero" + assert sol_voltage_reading != 0, "Acceleration reading should be non-zero" + assert sol_current_reading != 0, "Acceleration reading should be non-zero" + # assert sol_power_reading != 0, "Acceleration reading should be non-zero" diff --git a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5-pinctrl.dtsi b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5-pinctrl.dtsi index 34fd8f3..48167dd 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5-pinctrl.dtsi +++ b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5-pinctrl.dtsi @@ -21,6 +21,12 @@ input-enable; }; }; + i2c0_default: i2c0_default { + group1 { + pinmux = , ; + input-enable; + }; + }; i2c1_default: i2c1_default { group1 { pinmux = , ; diff --git a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi index 11db77d..9eaeb2c 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi +++ b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi @@ -135,6 +135,37 @@ zephyr_udc0: &usbd { }; }; +&i2c0 { + status = "okay"; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + clock-frequency = <100000>; + + ina219Sys: ina219Sys@40 { + compatible = "ti,ina219"; + reg = <0x40>; + brng = <0>; + pg = <0>; + badc = <12>; + sadc = <12>; + shunt-milliohm = <2>; + lsb-microamp = <61>; + label = "INA219 sys"; + }; + ina219Sol: ina219Sol@41 { + compatible = "ti,ina219"; + reg = <0x41>; + brng = <0>; + pg = <0>; + badc = <12>; + sadc = <12>; + shunt-milliohm = <2>; + lsb-microamp = <61>; + label = "INA219 sol"; + }; +}; + + &i2c1 { status = "okay"; pinctrl-0 = <&i2c1_default>; @@ -159,11 +190,4 @@ zephyr_udc0: &usbd { backup-switch-mode = "direct"; label = "RV3028"; }; - ina219: ina219@40 { - compatible = "ti,ina219"; - reg = <0x40>; - shunt-milliohm = <2>; - lsb-microamp = <100>; - label = "INA219"; - }; };