implemented alternating GPIO SA Deployment
EIVE/eive-obsw/pipeline/pr-develop This commit looks good Details

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;
// 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;
// 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.
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())) {
if (exists(SD_0_DEPL_FILE)) {
// 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
sdcMan.isSdCardUsable(activeSdc.value())) {
if (exists(SD_1_DEPL_FILE)) {
// perform autonomous deployment handling
performAutonomousDepl(sd::SdCard::SLOT_1);
performAutonomousDepl(sd::SdCard::SLOT_1, dryRunStringInFile(SD_1_DEPL_FILE));
}
}
readCommandQueue();
@ -51,7 +51,7 @@ ReturnValue_t SolarArrayDeploymentHandler::performOperation(uint8_t operationCod
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;
auto initFile = [](const char* filename) {
@ -63,21 +63,21 @@ ReturnValue_t SolarArrayDeploymentHandler::performAutonomousDepl(sd::SdCard sdCa
if (not exists(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);
}
} else if (sdCard == sd::SdCard::SLOT_1) {
if (not exists(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);
}
}
return returnvalue::OK;
}
bool SolarArrayDeploymentHandler::autonomousDeplForFile(const char* filename) {
bool SolarArrayDeploymentHandler::autonomousDeplForFile(const char* filename, bool dryRun) {
using namespace std;
ifstream file(filename);
string line;
@ -153,9 +153,8 @@ bool SolarArrayDeploymentHandler::autonomousDeplForFile(const char* filename) {
if (stateSwitch) {
if (deplState == AutonomousDeplState::FIRST_BURN or
deplState == AutonomousDeplState::SECOND_BURN) {
// TODO: Update to be channel specific
// startFsmOn(channel, config::SA_DEPL_BURN_TIME_SECS);
// startFsm(true, true);
// TODO: Update whole procedure to work for both channels
startFsmOn(config::SA_DEPL_BURN_TIME_SECS, dryRun);
} else if (deplState == AutonomousDeplState::WAIT or deplState == AutonomousDeplState::DONE) {
startFsmOff();
// startFsm(false, false);
@ -210,12 +209,20 @@ void SolarArrayDeploymentHandler::handleStateMachine() {
}
}
if (stateMachine == SWITCH_DEPL_GPIOS) {
// This should never fail
deploymentTransistorsOn(fsmInfo.channel);
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()) {
allOff();
stateMachine = WAIT_MAIN_POWER_OFF;
@ -253,7 +260,7 @@ bool SolarArrayDeploymentHandler::checkMainPower(bool onOff) {
return false;
}
bool SolarArrayDeploymentHandler::startFsmOn(DeploymentChannels channel, uint32_t burnCountdown_) {
bool SolarArrayDeploymentHandler::startFsmOn(uint32_t burnCountdown_, bool dryRun) {
if (stateMachine != StateMachine::IDLE) {
return false;
}
@ -261,7 +268,7 @@ bool SolarArrayDeploymentHandler::startFsmOn(DeploymentChannels channel, uint32_
burnCountdown_ = config::SA_DEPL_MAX_BURN_TIME;
}
fsmInfo.onOff = true;
fsmInfo.channel = channel;
fsmInfo.dryRun = dryRun;
fsmInfo.burnCountdown = burnCountdown_;
retryCounter = 0;
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() {
deploymentTransistorsOff(DeploymentChannels::SA_1);
deploymentTransistorsOff(DeploymentChannels::SA_2);
deploymentTransistorsOff();
mainLineSwitcher.sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
mainSwitchCountdown.setTimeout(mainLineSwitcher.getSwitchDelayMs());
}
ReturnValue_t SolarArrayDeploymentHandler::deploymentTransistorsOff(DeploymentChannels channel) {
ReturnValue_t result = returnvalue::FAILED;
if (channel == DeploymentChannels::SA_1) {
result = gpioInterface.pullLow(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_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);
bool SolarArrayDeploymentHandler::dryRunStringInFile(const char* filename) {
std::ifstream ifile(filename);
if (ifile.bad()) {
return false;
}
std::string line;
while (getline(ifile, line)) {
if (line.find("dryrun") != std::string::npos) {
return true;
}
}
return result;
return false;
}
void SolarArrayDeploymentHandler::readCommandQueue() {
@ -377,7 +349,7 @@ ReturnValue_t SolarArrayDeploymentHandler::executeAction(ActionId_t actionId,
if (result != returnvalue::OK) {
return result;
}
if (not startFsmOn(channel, burnCountdown)) {
if (not startFsmOn(burnCountdown, cmd.isDryRun())) {
return HasActionsIF::IS_BUSY;
}
return result;
@ -390,6 +362,100 @@ ReturnValue_t SolarArrayDeploymentHandler::executeAction(ActionId_t actionId,
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 {
return commandQueue->getId();
}

View File

@ -42,10 +42,13 @@ class ManualDeploymentCommand : public SerialLinkedListAdapter<SerializeIF> {
return HasActionsIF::INVALID_PARAMETERS;
}
bool isDryRun() const { return dryRun.entry; }
private:
SerializeElement<uint32_t> burnTime;
// Deployment channel SA1 or SA2
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 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 =
FIRST_BURN_START_TIME + config::SA_DEPL_BURN_TIME_SECS;
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_OFF,
SWITCH_DEPL_GPIOS,
CHANNEL_ON
BURNING
};
struct FsmInfo {
DeploymentChannels channel;
// Not required anymore
// DeploymentChannels channel;
// false if OFF, true is ON
bool onOff;
bool dryRun;
bool alternationDummy = false;
uint32_t burnCountdown = config::SA_DEPL_MAX_BURN_TIME;
};
@ -153,13 +158,14 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
PeriodicOperationDivider opDivider = PeriodicOperationDivider(5);
uint8_t retryCounter = 3;
bool startFsmOn(DeploymentChannels channel, uint32_t burnCountdown);
bool startFsmOn(uint32_t burnCountdown, bool dryRun);
void startFsmOff();
void finishFsm(ReturnValue_t resultForActionHelper);
ReturnValue_t performAutonomousDepl(sd::SdCard sdCard);
bool autonomousDeplForFile(const char* filename);
ReturnValue_t performAutonomousDepl(sd::SdCard sdCard, bool dryRun);
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.
*/
@ -170,6 +176,8 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
*/
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.
* This is necessary to send later the action finish replies.
@ -214,11 +222,12 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
void allOff();
/**
* @brief This functions handles the switching of the solar array deployment transistors.
*/
ReturnValue_t deploymentTransistorsOn(DeploymentChannels channel);
ReturnValue_t deploymentTransistorsOff(DeploymentChannels channel);
ReturnValue_t deploymentTransistorsOff();
ReturnValue_t saGpioAlternation();
ReturnValue_t sa1On();
ReturnValue_t sa1Off();
ReturnValue_t sa2On();
ReturnValue_t sa2Off();
};
#endif /* MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_ */

2
tmtc

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