// EO-1 Reference Model v1.0: the electrical power subsystem only, in SysML v2 textual notation. // EO-1 Reference Model v1.0 by Holarch, Angry Pixie Electronics LLC (https://holarch.app/reference-models/eo-1/) // is licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0): // https://creativecommons.org/licenses/by/4.0/. You may share and adapt it for any purpose, also commercially, // if you give appropriate credit ("Holarch, Angry Pixie Electronics LLC"), link to the license and say if you // made changes. EO-1 is a fictional spacecraft; names, people and results in the model are invented. The license // covers the model files only, not the Holarch software. package CubeSatEPS { doc /* The electrical power system (EPS) of the EO-1 CubeSat: solar arrays, a battery pack and a power distribution unit that feed the payload camera and the S-band transmitter. */ private import ScalarValues::*; private import ISQ::*; private import SI::*; // ---- Ports and interfaces ---- port def DCPowerPort { out attribute voltage : ElectricPotentialValue; out attribute current : ElectricCurrentValue; } port def BusPowerPort { out attribute voltage : ElectricPotentialValue; out attribute powerLimit : PowerValue; } interface def BusLink { end source : BusPowerPort; end load : ~BusPowerPort; } // ---- Components ---- part def SolarArray { attribute mass : MassValue; attribute cellArea : AreaValue; attribute cellEfficiency : Real; attribute peakPower : PowerValue; attribute pathEfficiency : Real; port arrayOut : DCPowerPort; } part def BatteryPack { attribute mass : MassValue; attribute capacity : EnergyValue; port cellsOut : DCPowerPort; } part def PowerDistributionUnit { attribute mass : MassValue; attribute busVoltage : ElectricPotentialValue; port arrayIn : ~DCPowerPort; port batteryIn : ~DCPowerPort; port busOut : BusPowerPort; } part def PayloadCamera { attribute powerDraw : PowerValue; port powerIn : ~BusPowerPort; } part def SBandTransmitter { attribute powerDraw : PowerValue; port powerIn : ~BusPowerPort; } // ---- Calculations ---- calc def OrbitAverage { doc /* Orbit-average array output (EQ-1.3): peak power times the sunlit fraction times the power path efficiency. */ in peakPower : PowerValue; in sunlitFraction : Real; in pathEfficiency : Real; return : PowerValue = peakPower * sunlitFraction * pathEfficiency; } // ---- The assembly ---- part def ElectricalPowerSystem { part solarArrays : SolarArray { attribute redefines mass = 0.45 [kg]; attribute redefines cellArea = 0.2 [m^2]; attribute redefines cellEfficiency = 0.295; attribute redefines peakPower = 75.4 [W]; attribute redefines pathEfficiency = 0.6; } part battery : BatteryPack { attribute redefines mass = 0.62 [kg]; attribute redefines capacity = 77 [W*h]; } part pdu : PowerDistributionUnit { attribute redefines mass = 0.28 [kg]; attribute redefines busVoltage = 12 [V]; } port bus : BusPowerPort; connect solarArrays.arrayOut to pdu.arrayIn; connect battery.cellsOut to pdu.batteryIn; bind bus = pdu.busOut; attribute sunlitFraction : Real = 0.62; attribute eclipseEnergy : EnergyValue = 18.5 [W*h]; attribute orbitAveragePower : PowerValue = OrbitAverage(solarArrays.peakPower, sunlitFraction, solarArrays.pathEfficiency); attribute depthOfDischarge : Real = eclipseEnergy / battery.capacity; attribute totalMass : MassValue = solarArrays.mass + battery.mass + pdu.mass; } part def Spacecraft { part eps : ElectricalPowerSystem; part camera : PayloadCamera { attribute redefines powerDraw = 6.2 [W]; } part transmitter : SBandTransmitter { attribute redefines powerDraw = 3.4 [W]; } interface payloadPower : BusLink connect eps.bus to camera.powerIn; interface radioPower : BusLink connect eps.bus to transmitter.powerIn; } // ---- Behavior ---- item def Sunlight; item def ArrayPower; item def ChargePower; item def DischargePower; item def BusPower; action def ConvertSunlight { in item sun : Sunlight; out item power : ArrayPower; } action def ChargeBattery { in item power : ArrayPower; out item charge : ChargePower; } action def StoreEnergy { in item charge : ChargePower; out item discharge : DischargePower; } action def SupplyBus { in item discharge : DischargePower; out item bus : BusPower; } action def RunPowerCycle { doc /* One orbit: about 59 minutes of sunlight, then a 36 minute eclipse. */ action collect : ConvertSunlight; action charge : ChargeBattery; action store : StoreEnergy; action supply : SupplyBus; flow collect.power to charge.power; flow charge.charge to store.charge; flow store.discharge to supply.discharge; first start then collect; first collect then charge; first charge then store; first store then supply; first supply then done; } part eo1 : Spacecraft { part redefines eps { perform action powerCycle : RunPowerCycle; part redefines solarArrays { perform powerCycle.collect; } part redefines battery { perform powerCycle.store; } part redefines pdu { perform powerCycle.charge; perform powerCycle.supply; } } } } package CubeSatEPSRequirements { doc /* Electrical power requirements of EO-1 (section 3) and how one of them is verified. */ private import CubeSatEPS::*; private import ScalarValues::*; private import ISQ::*; private import SI::*; requirement def <'3.1'> OrbitAveragePower { doc /* The solar arrays shall generate at least 28 W orbit-average power at end of life. */ subject eps : ElectricalPowerSystem; attribute required : PowerValue; require constraint { eps.orbitAveragePower >= required } } requirement def <'3.2'> BatteryCapacity { doc /* The battery shall store at least 77 Wh at beginning of life. */ subject eps : ElectricalPowerSystem; attribute minimum : EnergyValue; require constraint { eps.battery.capacity >= minimum } } requirement def <'3.3'> DepthOfDischarge { doc /* The EPS shall limit battery depth of discharge to 30% per orbit. */ subject eps : ElectricalPowerSystem; attribute limit : Real; require constraint { eps.depthOfDischarge <= limit } } requirement powerSpec { doc /* The electrical power requirements EO-1 is built to. */ subject eps : ElectricalPowerSystem; requirement orbitAveragePower : OrbitAveragePower { attribute redefines required = 28 [W]; } requirement batteryCapacity : BatteryCapacity { attribute redefines minimum = 77 [W*h]; } requirement depthOfDischarge : DepthOfDischarge { attribute redefines limit = 0.3; } } satisfy powerSpec by eo1.eps; verification def <'TC-07'> BatteryCapacityTest { doc /* Discharge the pack at C/2 from full charge in a thermal chamber at 20 degrees C and measure the energy delivered. */ subject eps : ElectricalPowerSystem; objective { verify powerSpec.batteryCapacity; } return verdict : Boolean = eps.battery.capacity >= powerSpec.batteryCapacity.minimum; } verification batteryTest : BatteryCapacityTest { subject eps = eo1.eps; } } package CubeSatEPSViews { doc /* Views of the EO-1 power system. Each view selects part of the model; the layout belongs to the tool. */ private import CubeSatEPS::*; private import CubeSatEPSRequirements::*; private import StandardViewDefinitions::*; // The EPS parts, their ports and connections. view epsConnections : InterconnectionView { expose CubeSatEPS::ElectricalPowerSystem; } // One orbit: the sunlit steps, the eclipse steps and the power that flows between them. view powerCycleFlow : ActionFlowView { expose CubeSatEPS::RunPowerCycle; } // The requirements with what satisfies and verifies them. view requirementTree : GeneralView { filter @SysML::RequirementDefinition or @SysML::RequirementUsage or @SysML::SatisfyRequirementUsage; expose CubeSatEPSRequirements::**; } }