implemented alternating GPIO SA Deployment
All checks were successful
EIVE/eive-obsw/pipeline/pr-develop This commit looks good

This commit is contained in:
Robin Müller 2022-10-13 17:34:33 +02:00
parent d97e0a1a6a
commit 773747dd54
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
4 changed files with 152 additions and 75 deletions

View File

@ -36,8 +36,10 @@ static constexpr uint32_t MAX_FILENAME_SIZE = 50;
static constexpr uint32_t SA_DEPL_INIT_BUFFER_SECS = 120; static constexpr uint32_t SA_DEPL_INIT_BUFFER_SECS = 120;
// Burn time for autonomous deployment // Burn time for autonomous deployment
static constexpr uint32_t SA_DEPL_BURN_TIME_SECS = 90; static constexpr uint32_t SA_DEPL_BURN_TIME_SECS = 180;
static constexpr uint32_t SA_DEPL_WAIT_TIME_SECS = 45 * 60; static constexpr uint32_t SA_DEPL_WAIT_TIME_SECS = 45 * 60;
// HW constraints (current limit) mean that the GPIO channels need to be switched on in alternation
static constexpr uint32_t SA_DEPL_CHANNEL_ALTERNATION_INTERVAL_SECS = 5;
// Maximum allowed burn time allowed by the software. // Maximum allowed burn time allowed by the software.
static constexpr uint32_t SA_DEPL_MAX_BURN_TIME = 120; static constexpr uint32_t SA_DEPL_MAX_BURN_TIME = 120;

View File

@ -37,13 +37,13 @@ ReturnValue_t SolarArrayDeploymentHandler::performOperation(uint8_t operationCod
sdcMan.isSdCardUsable(activeSdc.value())) { sdcMan.isSdCardUsable(activeSdc.value())) {
if (exists(SD_0_DEPL_FILE)) { if (exists(SD_0_DEPL_FILE)) {
// perform autonomous deployment handling // perform autonomous deployment handling
performAutonomousDepl(sd::SdCard::SLOT_0); performAutonomousDepl(sd::SdCard::SLOT_0, dryRunStringInFile(SD_0_DEPL_FILE));
} }
} else if (activeSdc and activeSdc.value() == sd::SdCard::SLOT_1 and } else if (activeSdc and activeSdc.value() == sd::SdCard::SLOT_1 and
sdcMan.isSdCardUsable(activeSdc.value())) { sdcMan.isSdCardUsable(activeSdc.value())) {
if (exists(SD_1_DEPL_FILE)) { if (exists(SD_1_DEPL_FILE)) {
// perform autonomous deployment handling // perform autonomous deployment handling
performAutonomousDepl(sd::SdCard::SLOT_1); performAutonomousDepl(sd::SdCard::SLOT_1, dryRunStringInFile(SD_1_DEPL_FILE));
} }
} }
readCommandQueue(); readCommandQueue();
@ -51,7 +51,7 @@ ReturnValue_t SolarArrayDeploymentHandler::performOperation(uint8_t operationCod
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t SolarArrayDeploymentHandler::performAutonomousDepl(sd::SdCard sdCard) { ReturnValue_t SolarArrayDeploymentHandler::performAutonomousDepl(sd::SdCard sdCard, bool dryRun) {
using namespace std::filesystem; using namespace std::filesystem;
using namespace std; using namespace std;
auto initFile = [](const char* filename) { auto initFile = [](const char* filename) {
@ -63,21 +63,21 @@ ReturnValue_t SolarArrayDeploymentHandler::performAutonomousDepl(sd::SdCard sdCa
if (not exists(SD_0_DEPLY_INFO)) { if (not exists(SD_0_DEPLY_INFO)) {
initFile(SD_0_DEPLY_INFO); initFile(SD_0_DEPLY_INFO);
} }
if (not autonomousDeplForFile(SD_0_DEPLY_INFO)) { if (not autonomousDeplForFile(SD_0_DEPLY_INFO, dryRun)) {
initFile(SD_0_DEPLY_INFO); initFile(SD_0_DEPLY_INFO);
} }
} else if (sdCard == sd::SdCard::SLOT_1) { } else if (sdCard == sd::SdCard::SLOT_1) {
if (not exists(SD_1_DEPLY_INFO)) { if (not exists(SD_1_DEPLY_INFO)) {
initFile(SD_1_DEPLY_INFO); initFile(SD_1_DEPLY_INFO);
} }
if (not autonomousDeplForFile(SD_1_DEPLY_INFO)) { if (not autonomousDeplForFile(SD_1_DEPLY_INFO, dryRun)) {
initFile(SD_1_DEPLY_INFO); initFile(SD_1_DEPLY_INFO);
} }
} }
return returnvalue::OK; return returnvalue::OK;
} }
bool SolarArrayDeploymentHandler::autonomousDeplForFile(const char* filename) { bool SolarArrayDeploymentHandler::autonomousDeplForFile(const char* filename, bool dryRun) {
using namespace std; using namespace std;
ifstream file(filename); ifstream file(filename);
string line; string line;
@ -153,9 +153,8 @@ bool SolarArrayDeploymentHandler::autonomousDeplForFile(const char* filename) {
if (stateSwitch) { if (stateSwitch) {
if (deplState == AutonomousDeplState::FIRST_BURN or if (deplState == AutonomousDeplState::FIRST_BURN or
deplState == AutonomousDeplState::SECOND_BURN) { deplState == AutonomousDeplState::SECOND_BURN) {
// TODO: Update to be channel specific // TODO: Update whole procedure to work for both channels
// startFsmOn(channel, config::SA_DEPL_BURN_TIME_SECS); startFsmOn(config::SA_DEPL_BURN_TIME_SECS, dryRun);
// startFsm(true, true);
} else if (deplState == AutonomousDeplState::WAIT or deplState == AutonomousDeplState::DONE) { } else if (deplState == AutonomousDeplState::WAIT or deplState == AutonomousDeplState::DONE) {
startFsmOff(); startFsmOff();
// startFsm(false, false); // startFsm(false, false);
@ -210,12 +209,20 @@ void SolarArrayDeploymentHandler::handleStateMachine() {
} }
} }
if (stateMachine == SWITCH_DEPL_GPIOS) { if (stateMachine == SWITCH_DEPL_GPIOS) {
// This should never fail
deploymentTransistorsOn(fsmInfo.channel);
burnCountdown.setTimeout(fsmInfo.burnCountdown); burnCountdown.setTimeout(fsmInfo.burnCountdown);
stateMachine = CHANNEL_ON; // This should never fail
if (not fsmInfo.dryRun) {
channelAlternationCd.resetTimer();
sa2Off();
sa1On();
fsmInfo.alternationDummy = true;
}
stateMachine = BURNING;
} }
if (stateMachine == CHANNEL_ON) { if (stateMachine == BURNING) {
if (not fsmInfo.dryRun) {
saGpioAlternation();
}
if (burnCountdown.hasTimedOut()) { if (burnCountdown.hasTimedOut()) {
allOff(); allOff();
stateMachine = WAIT_MAIN_POWER_OFF; stateMachine = WAIT_MAIN_POWER_OFF;
@ -253,7 +260,7 @@ bool SolarArrayDeploymentHandler::checkMainPower(bool onOff) {
return false; return false;
} }
bool SolarArrayDeploymentHandler::startFsmOn(DeploymentChannels channel, uint32_t burnCountdown_) { bool SolarArrayDeploymentHandler::startFsmOn(uint32_t burnCountdown_, bool dryRun) {
if (stateMachine != StateMachine::IDLE) { if (stateMachine != StateMachine::IDLE) {
return false; return false;
} }
@ -261,7 +268,7 @@ bool SolarArrayDeploymentHandler::startFsmOn(DeploymentChannels channel, uint32_
burnCountdown_ = config::SA_DEPL_MAX_BURN_TIME; burnCountdown_ = config::SA_DEPL_MAX_BURN_TIME;
} }
fsmInfo.onOff = true; fsmInfo.onOff = true;
fsmInfo.channel = channel; fsmInfo.dryRun = dryRun;
fsmInfo.burnCountdown = burnCountdown_; fsmInfo.burnCountdown = burnCountdown_;
retryCounter = 0; retryCounter = 0;
return true; return true;
@ -290,59 +297,24 @@ void SolarArrayDeploymentHandler::finishFsm(ReturnValue_t resultForActionHelper)
} }
} }
ReturnValue_t SolarArrayDeploymentHandler::deploymentTransistorsOn(DeploymentChannels channel) {
ReturnValue_t result = returnvalue::FAILED;
if (channel == DeploymentChannels::SA_1) {
result = gpioInterface.pullHigh(deplSA1);
if (result != returnvalue::OK) {
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 1 high "
<< std::endl;
// If gpio switch high failed, state machine is reset to wait for a command re-initiating
// the deployment sequence.
triggerEvent(DEPL_SA1_GPIO_SWTICH_ON_FAILED);
}
} else if (channel == DeploymentChannels::SA_2) {
result = gpioInterface.pullHigh(deplSA2);
if (result != returnvalue::OK) {
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 2 high "
<< std::endl;
triggerEvent(DEPL_SA2_GPIO_SWTICH_ON_FAILED);
}
}
return result;
}
void SolarArrayDeploymentHandler::allOff() { void SolarArrayDeploymentHandler::allOff() {
deploymentTransistorsOff(DeploymentChannels::SA_1); deploymentTransistorsOff();
deploymentTransistorsOff(DeploymentChannels::SA_2);
mainLineSwitcher.sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF); mainLineSwitcher.sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
mainSwitchCountdown.setTimeout(mainLineSwitcher.getSwitchDelayMs()); mainSwitchCountdown.setTimeout(mainLineSwitcher.getSwitchDelayMs());
} }
ReturnValue_t SolarArrayDeploymentHandler::deploymentTransistorsOff(DeploymentChannels channel) { bool SolarArrayDeploymentHandler::dryRunStringInFile(const char* filename) {
ReturnValue_t result = returnvalue::FAILED; std::ifstream ifile(filename);
if (channel == DeploymentChannels::SA_1) { if (ifile.bad()) {
result = gpioInterface.pullLow(deplSA1); return false;
if (result != returnvalue::OK) { }
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar" std::string line;
" array deployment switch 1 high " while (getline(ifile, line)) {
<< std::endl; if (line.find("dryrun") != std::string::npos) {
// If gpio switch high failed, state machine is reset to wait for a command re-initiating return true;
// the deployment sequence.
triggerEvent(DEPL_SA1_GPIO_SWTICH_OFF_FAILED);
}
} else if (channel == DeploymentChannels::SA_2) {
result = gpioInterface.pullLow(deplSA2);
if (result != returnvalue::OK) {
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 2 high "
<< std::endl;
triggerEvent(DEPL_SA2_GPIO_SWTICH_OFF_FAILED);
} }
} }
return result; return false;
} }
void SolarArrayDeploymentHandler::readCommandQueue() { void SolarArrayDeploymentHandler::readCommandQueue() {
@ -377,7 +349,7 @@ ReturnValue_t SolarArrayDeploymentHandler::executeAction(ActionId_t actionId,
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
if (not startFsmOn(channel, burnCountdown)) { if (not startFsmOn(burnCountdown, cmd.isDryRun())) {
return HasActionsIF::IS_BUSY; return HasActionsIF::IS_BUSY;
} }
return result; return result;
@ -390,6 +362,100 @@ ReturnValue_t SolarArrayDeploymentHandler::executeAction(ActionId_t actionId,
return result; return result;
} }
ReturnValue_t SolarArrayDeploymentHandler::saGpioAlternation() {
ReturnValue_t status = returnvalue::OK;
ReturnValue_t result;
if (channelAlternationCd.hasTimedOut()) {
if (fsmInfo.alternationDummy) {
result = sa1Off();
if (result != returnvalue::OK) {
status = result;
}
result = sa2On();
if (result != returnvalue::OK) {
status = result;
}
} else {
result = sa1On();
if (result != returnvalue::OK) {
status = result;
}
result = sa2Off();
if (result != returnvalue::OK) {
status = result;
}
}
fsmInfo.alternationDummy = not fsmInfo.alternationDummy;
channelAlternationCd.resetTimer();
}
return status;
}
ReturnValue_t SolarArrayDeploymentHandler::deploymentTransistorsOff() {
ReturnValue_t status = returnvalue::OK;
ReturnValue_t result = sa1Off();
if (result != returnvalue::OK) {
status = result;
}
result = sa2Off();
if (result != returnvalue::OK) {
status = result;
}
return status;
}
ReturnValue_t SolarArrayDeploymentHandler::sa1On() {
ReturnValue_t result = gpioInterface.pullHigh(deplSA1);
if (result != returnvalue::OK) {
sif::warning << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 1 high"
<< std::endl;
// If gpio switch high failed, state machine is reset to wait for a command re-initiating
// the deployment sequence.
triggerEvent(DEPL_SA1_GPIO_SWTICH_ON_FAILED);
}
return result;
}
ReturnValue_t SolarArrayDeploymentHandler::sa1Off() {
ReturnValue_t result = gpioInterface.pullLow(deplSA1);
if (result != returnvalue::OK) {
sif::warning << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 1 low"
<< std::endl;
// If gpio switch high failed, state machine is reset to wait for a command re-initiating
// the deployment sequence.
triggerEvent(DEPL_SA1_GPIO_SWTICH_OFF_FAILED);
}
return result;
}
ReturnValue_t SolarArrayDeploymentHandler::sa2On() {
ReturnValue_t result = gpioInterface.pullHigh(deplSA2);
if (result != returnvalue::OK) {
sif::warning << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 2 high"
<< std::endl;
// If gpio switch high failed, state machine is reset to wait for a command re-initiating
// the deployment sequence.
triggerEvent(DEPL_SA2_GPIO_SWTICH_ON_FAILED);
}
return result;
}
ReturnValue_t SolarArrayDeploymentHandler::sa2Off() {
ReturnValue_t result = gpioInterface.pullLow(deplSA2);
if (result != returnvalue::OK) {
sif::warning << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 2 low"
<< std::endl;
// If gpio switch high failed, state machine is reset to wait for a command re-initiating
// the deployment sequence.
triggerEvent(DEPL_SA2_GPIO_SWTICH_OFF_FAILED);
}
return result;
}
MessageQueueId_t SolarArrayDeploymentHandler::getCommandQueue() const { MessageQueueId_t SolarArrayDeploymentHandler::getCommandQueue() const {
return commandQueue->getId(); return commandQueue->getId();
} }

View File

@ -42,10 +42,13 @@ class ManualDeploymentCommand : public SerialLinkedListAdapter<SerializeIF> {
return HasActionsIF::INVALID_PARAMETERS; return HasActionsIF::INVALID_PARAMETERS;
} }
bool isDryRun() const { return dryRun.entry; }
private: private:
SerializeElement<uint32_t> burnTime; SerializeElement<uint32_t> burnTime;
// Deployment channel SA1 or SA2 // Deployment channel SA1 or SA2
SerializeElement<uint8_t> channel; SerializeElement<uint8_t> channel;
SerializeElement<uint8_t> dryRun;
}; };
/** /**
@ -61,7 +64,7 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
static constexpr DeviceCommandId_t DEPLOY_SOLAR_ARRAYS_MANUALLY = 0x05; static constexpr DeviceCommandId_t DEPLOY_SOLAR_ARRAYS_MANUALLY = 0x05;
static constexpr DeviceCommandId_t SWITCH_OFF_DEPLOYMENT = 0x06; static constexpr DeviceCommandId_t SWITCH_OFF_DEPLOYMENT = 0x06;
static constexpr uint32_t FIRST_BURN_START_TIME = config::SA_DEPL_BURN_TIME_SECS; static constexpr uint32_t FIRST_BURN_START_TIME = config::SA_DEPL_INIT_BUFFER_SECS;
static constexpr uint32_t FIRST_BURN_END_TIME = static constexpr uint32_t FIRST_BURN_END_TIME =
FIRST_BURN_START_TIME + config::SA_DEPL_BURN_TIME_SECS; FIRST_BURN_START_TIME + config::SA_DEPL_BURN_TIME_SECS;
static constexpr uint32_t WAIT_START_TIME = FIRST_BURN_END_TIME; static constexpr uint32_t WAIT_START_TIME = FIRST_BURN_END_TIME;
@ -118,14 +121,16 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
WAIT_MAIN_POWER_ON, WAIT_MAIN_POWER_ON,
WAIT_MAIN_POWER_OFF, WAIT_MAIN_POWER_OFF,
SWITCH_DEPL_GPIOS, SWITCH_DEPL_GPIOS,
CHANNEL_ON BURNING
}; };
struct FsmInfo { struct FsmInfo {
DeploymentChannels channel; // Not required anymore
// DeploymentChannels channel;
// false if OFF, true is ON // false if OFF, true is ON
bool onOff; bool onOff;
bool dryRun; bool dryRun;
bool alternationDummy = false;
uint32_t burnCountdown = config::SA_DEPL_MAX_BURN_TIME; uint32_t burnCountdown = config::SA_DEPL_MAX_BURN_TIME;
}; };
@ -153,13 +158,14 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
PeriodicOperationDivider opDivider = PeriodicOperationDivider(5); PeriodicOperationDivider opDivider = PeriodicOperationDivider(5);
uint8_t retryCounter = 3; uint8_t retryCounter = 3;
bool startFsmOn(DeploymentChannels channel, uint32_t burnCountdown); bool startFsmOn(uint32_t burnCountdown, bool dryRun);
void startFsmOff(); void startFsmOff();
void finishFsm(ReturnValue_t resultForActionHelper); void finishFsm(ReturnValue_t resultForActionHelper);
ReturnValue_t performAutonomousDepl(sd::SdCard sdCard); ReturnValue_t performAutonomousDepl(sd::SdCard sdCard, bool dryRun);
bool autonomousDeplForFile(const char* filename); bool dryRunStringInFile(const char* filename);
bool autonomousDeplForFile(const char* filename, bool dryRun);
/** /**
* This countdown is used to check if the PCDU sets the 8V line on in the intended time. * This countdown is used to check if the PCDU sets the 8V line on in the intended time.
*/ */
@ -170,6 +176,8 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
*/ */
Countdown burnCountdown; Countdown burnCountdown;
Countdown channelAlternationCd = Countdown(config::SA_DEPL_CHANNEL_ALTERNATION_INTERVAL_SECS);
/** /**
* The message queue id of the component commanding an action will be stored in this variable. * The message queue id of the component commanding an action will be stored in this variable.
* This is necessary to send later the action finish replies. * This is necessary to send later the action finish replies.
@ -214,11 +222,12 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
void allOff(); void allOff();
/** ReturnValue_t deploymentTransistorsOff();
* @brief This functions handles the switching of the solar array deployment transistors. ReturnValue_t saGpioAlternation();
*/ ReturnValue_t sa1On();
ReturnValue_t deploymentTransistorsOn(DeploymentChannels channel); ReturnValue_t sa1Off();
ReturnValue_t deploymentTransistorsOff(DeploymentChannels channel); ReturnValue_t sa2On();
ReturnValue_t sa2Off();
}; };
#endif /* MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_ */ #endif /* MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_ */

2
tmtc

@ -1 +1 @@
Subproject commit 4c3f5f28256be0dbfc5b46ea87f8f484c93a9996 Subproject commit 50abe69f261b7d2a3345d86bd7042514ff845fd3