fixed merge conflict and copied max13865 code

This commit is contained in:
2021-03-05 12:57:42 +01:00
parent 93636426b6
commit b75eef7c51
163 changed files with 1207 additions and 16912 deletions

View File

@ -10,8 +10,6 @@ target_sources(${TARGET_NAME} PUBLIC
PDU1Handler.cpp
PDU2Handler.cpp
ACUHandler.cpp
HeaterHandler.cpp
SolarArrayDeploymentHandler.cpp
SyrlinksHkHandler.cpp
)

View File

@ -1,355 +0,0 @@
#include <mission/devices/HeaterHandler.h>
#include <fsfwconfig/devices/powerSwitcherList.h>
#include <fsfw/ipc/QueueFactory.h>
#include <devices/gpioIds.h>
HeaterHandler::HeaterHandler(object_id_t setObjectId_, object_id_t gpioDriverId_,
CookieIF * gpioCookie_, object_id_t mainLineSwitcherObjectId_, uint8_t mainLineSwitch_) :
SystemObject(setObjectId_), gpioDriverId(gpioDriverId_), gpioCookie(gpioCookie_), mainLineSwitcherObjectId(
mainLineSwitcherObjectId_), mainLineSwitch(mainLineSwitch_), actionHelper(this,
nullptr) {
commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize,
MessageQueueMessage::MAX_MESSAGE_SIZE);
}
HeaterHandler::~HeaterHandler() {
}
ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) {
if (operationCode == DeviceHandlerIF::PERFORM_OPERATION) {
readCommandQueue();
handleActiveCommands();
return RETURN_OK;
}
return RETURN_OK;
}
ReturnValue_t HeaterHandler::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
result = initializeHeaterMap();
if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
gpioInterface = objectManager->get<GpioIF>(gpioDriverId);
if (gpioInterface == nullptr) {
sif::error << "HeaterHandler::initialize: Invalid Gpio interface." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
result = gpioInterface->initialize(gpioCookie);
if (result != RETURN_OK) {
sif::error << "HeaterHandler::initialize: Failed to initialize Gpio interface" << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (IPCStore == nullptr) {
sif::error << "HeaterHandler::initialize: IPC store not set up in factory." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
if(mainLineSwitcherObjectId != objects::NO_OBJECT) {
mainLineSwitcher = objectManager->get<PowerSwitchIF>(mainLineSwitcherObjectId);
if (mainLineSwitcher == nullptr) {
sif::error << "HeaterHandler::initialize: Main line switcher failed to fetch object"
<< "from object ID." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
}
result = actionHelper.initialize(commandQueue);
if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
return RETURN_OK;
}
ReturnValue_t HeaterHandler::initializeHeaterMap(){
HeaterCommandInfo_t heaterCommandInfo;
for(switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) {
std::pair status = heaterMap.emplace(switchNr, heaterCommandInfo);
if (status.second == false) {
sif::error << "HeaterHandler::initializeHeaterMap: Failed to initialize heater map"
<< std::endl;
return RETURN_FAILED;
}
}
return RETURN_OK;
}
void HeaterHandler::setInitialSwitchStates() {
for (switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) {
switchStates[switchNr] = OFF;
}
}
void HeaterHandler::readCommandQueue() {
CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result != RETURN_OK) {
return;
}
result = actionHelper.handleActionMessage(&command);
if (result == RETURN_OK) {
return;
}
}
ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
ReturnValue_t result;
if (actionId != SWITCH_HEATER) {
result = COMMAND_NOT_SUPPORTED;
} else {
switchNr_t switchNr = *data;
HeaterMapIter heaterMapIter = heaterMap.find(switchNr);
if (heaterMapIter != heaterMap.end()) {
if (heaterMapIter->second.active) {
return COMMAND_ALREADY_WAITING;
}
heaterMapIter->second.action = *(data + 1);
heaterMapIter->second.active = true;
heaterMapIter->second.replyQueue = commandedBy;
}
else {
sif::error << "HeaterHandler::executeAction: Invalid switchNr" << std::endl;
return INVALID_SWITCH_NR;
}
result = RETURN_OK;
}
return result;
}
void HeaterHandler::sendSwitchCommand(uint8_t switchNr,
ReturnValue_t onOff) const {
ReturnValue_t result;
store_address_t storeAddress;
uint8_t commandData[2];
switch(onOff) {
case PowerSwitchIF::SWITCH_ON:
commandData[0] = switchNr;
commandData[1] = SET_SWITCH_ON;
break;
case PowerSwitchIF::SWITCH_OFF:
commandData[0] = switchNr;
commandData[1] = SET_SWITCH_OFF;
break;
default:
sif::error << "HeaterHandler::sendSwitchCommand: Invalid switch request"
<< std::endl;
break;
}
result = IPCStore->addData(&storeAddress, commandData, sizeof(commandData));
if (result == RETURN_OK) {
CommandMessage message;
ActionMessage::setCommand(&message, SWITCH_HEATER, storeAddress);
/* Send heater command to own command queue */
result = commandQueue->sendMessage(commandQueue->getId(), &message, 0);
if (result != RETURN_OK) {
sif::debug << "HeaterHandler::sendSwitchCommand: Failed to send switch"
<< "message" << std::endl;
}
}
}
void HeaterHandler::handleActiveCommands(){
HeaterMapIter heaterMapIter = heaterMap.begin();
for (; heaterMapIter != heaterMap.end(); heaterMapIter++) {
if (heaterMapIter->second.active) {
switch(heaterMapIter->second.action) {
case SET_SWITCH_ON:
handleSwitchOnCommand(heaterMapIter);
break;
case SET_SWITCH_OFF:
handleSwitchOffCommand(heaterMapIter);
break;
default:
sif::error << "HeaterHandler::handleActiveCommands: Invalid action commanded"
<< std::endl;
break;
}
}
}
}
void HeaterHandler::handleSwitchOnCommand(HeaterMapIter heaterMapIter) {
ReturnValue_t result = RETURN_OK;
switchNr_t switchNr;
/* Check if command waits for main switch being set on and whether the timeout has expired */
if (heaterMapIter->second.waitMainSwitchOn
&& heaterMapIter->second.mainSwitchCountdown.hasTimedOut()) {
//TODO - This requires the initiation of an FDIR procedure
triggerEvent(MAIN_SWITCH_TIMEOUT);
sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout"
<< std::endl;
heaterMapIter->second.active = false;
heaterMapIter->second.waitMainSwitchOn = false;
if (heaterMapIter->second.replyQueue != commandQueue->getId()) {
actionHelper.finish(heaterMapIter->second.replyQueue, heaterMapIter->second.action,
MAIN_SWITCH_SET_TIMEOUT );
}
return;
}
switchNr = heaterMapIter->first;
/* Check state of main line switch */
ReturnValue_t mainSwitchState = mainLineSwitcher->getSwitchState(mainLineSwitch);
if (mainSwitchState == PowerSwitchIF::SWITCH_ON) {
if (!checkSwitchState(switchNr)) {
gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr);
result = gpioInterface->pullHigh(gpioId);
if (result != RETURN_OK) {
sif::error << "HeaterHandler::handleSwitchOnCommand: Failed to pull gpio with id "
<< gpioId << " high" << std::endl;
triggerEvent(GPIO_PULL_HIGH_FAILED, result);
}
else {
switchStates[switchNr] = ON;
}
}
else {
triggerEvent(SWITCH_ALREADY_ON, switchNr);
}
/* There is no need to send action finish replies if the sender was the
* HeaterHandler itself. */
if (heaterMapIter->second.replyQueue != commandQueue->getId()) {
actionHelper.finish(heaterMapIter->second.replyQueue,
heaterMapIter->second.action, result);
}
heaterMapIter->second.active = false;
heaterMapIter->second.waitMainSwitchOn = false;
}
else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF
&& heaterMapIter->second.waitMainSwitchOn) {
/* Just waiting for the main switch being set on */
return;
}
else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF) {
mainLineSwitcher->sendSwitchCommand(mainLineSwitch,
PowerSwitchIF::SWITCH_ON);
heaterMapIter->second.mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
heaterMapIter->second.waitMainSwitchOn = true;
}
else {
sif::debug << "HeaterHandler::handleActiveCommands: Failed to get state of"
<< " main line switch" << std::endl;
if (heaterMapIter->second.replyQueue != commandQueue->getId()) {
actionHelper.finish(heaterMapIter->second.replyQueue,
heaterMapIter->second.action, mainSwitchState);
}
heaterMapIter->second.active = false;
}
}
void HeaterHandler::handleSwitchOffCommand(HeaterMapIter heaterMapIter) {
ReturnValue_t result = RETURN_OK;
switchNr_t switchNr = heaterMapIter->first;
/* Check whether switch is already off */
if (checkSwitchState(switchNr)) {
gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr);
result = gpioInterface->pullLow(gpioId);
if (result != RETURN_OK) {
sif::error << "HeaterHandler::handleSwitchOffCommand: Failed to pull gpio with id"
<< gpioId << " low" << std::endl;
triggerEvent(GPIO_PULL_LOW_FAILED, result);
}
else {
switchStates[switchNr] = OFF;
/* When all switches are off, also main line switch will be turned off */
if (allSwitchesOff()) {
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
}
}
}
else {
sif::info << "HeaterHandler::handleSwitchOffCommand: Switch already off" << std::endl;
triggerEvent(SWITCH_ALREADY_OFF, switchNr);
}
if (heaterMapIter->second.replyQueue != NO_COMMANDER) {
actionHelper.finish(heaterMapIter->second.replyQueue,
heaterMapIter->second.action, result);
}
heaterMapIter->second.active = false;
}
bool HeaterHandler::checkSwitchState(int switchNr) {
return switchStates[switchNr];
}
bool HeaterHandler::allSwitchesOff() {
bool allSwitchesOrd = false;
/* Or all switches. As soon one switch is on, allSwitchesOrd will be true */
for (switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) {
allSwitchesOrd = allSwitchesOrd || switchStates[switchNr];
}
return !allSwitchesOrd;
}
gpioId_t HeaterHandler::getGpioIdFromSwitchNr(int switchNr) {
gpioId_t gpioId = 0xFFFF;
switch(switchNr) {
case heaterSwitches::HEATER_0:
gpioId = gpioIds::HEATER_0;
break;
case heaterSwitches::HEATER_1:
gpioId = gpioIds::HEATER_1;
break;
case heaterSwitches::HEATER_2:
gpioId = gpioIds::HEATER_2;
break;
case heaterSwitches::HEATER_3:
gpioId = gpioIds::HEATER_3;
break;
case heaterSwitches::HEATER_4:
gpioId = gpioIds::HEATER_4;
break;
case heaterSwitches::HEATER_5:
gpioId = gpioIds::HEATER_5;
break;
case heaterSwitches::HEATER_6:
gpioId = gpioIds::HEATER_6;
break;
case heaterSwitches::HEATER_7:
gpioId = gpioIds::HEATER_7;
break;
default:
sif::error << "HeaterHandler::getGpioIdFromSwitchNr: Unknown heater switch number"
<< std::endl;
break;
}
return gpioId;
}
MessageQueueId_t HeaterHandler::getCommandQueue() const {
return commandQueue->getId();
}
void HeaterHandler::sendFuseOnCommand(uint8_t fuseNr) const {
}
ReturnValue_t HeaterHandler::getSwitchState( uint8_t switchNr ) const {
return 0;
}
ReturnValue_t HeaterHandler::getFuseState( uint8_t fuseNr ) const {
return 0;
}
uint32_t HeaterHandler::getSwitchDelayMs(void) const {
return 0;
}

View File

@ -1,177 +0,0 @@
#ifndef MISSION_DEVICES_HEATERHANDLER_H_
#define MISSION_DEVICES_HEATERHANDLER_H_
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/action/HasActionsIF.h>
#include <fsfw/power/PowerSwitchIF.h>
#include <fsfwconfig/devices/heaterSwitcherList.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/devicehandlers/CookieIF.h>
#include <fsfw/timemanager/Countdown.h>
#include <linux/gpio/GpioIF.h>
#include <unordered_map>
/**
* @brief This class intends the control of heaters.
*
* @author J. Meier
*/
class HeaterHandler: public ExecutableObjectIF,
public PowerSwitchIF,
public SystemObject,
public HasActionsIF {
public:
/** Device command IDs */
static const DeviceCommandId_t SWITCH_HEATER = 0x0;
HeaterHandler(object_id_t setObjectId, object_id_t gpioDriverId, CookieIF * gpioCookie,
object_id_t mainLineSwitcherObjectId, uint8_t mainLineSwitch);
virtual ~HeaterHandler();
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
virtual void sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const override;
virtual void sendFuseOnCommand(uint8_t fuseNr) const override;
/**
* @brief This function will be called from the Heater object to check
* the current switch state.
*/
virtual ReturnValue_t getSwitchState( uint8_t switchNr ) const override;
virtual ReturnValue_t getFuseState( uint8_t fuseNr ) const override;
virtual uint32_t getSwitchDelayMs(void) const override;
virtual MessageQueueId_t getCommandQueue() const override;
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override;
virtual ReturnValue_t initialize() override;
private:
static const uint8_t INTERFACE_ID = CLASS_ID::HEATER_HANDLER;
static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1);
static const ReturnValue_t INIT_FAILED = MAKE_RETURN_CODE(0xA2);
static const ReturnValue_t INVALID_SWITCH_NR = MAKE_RETURN_CODE(0xA3);
static const ReturnValue_t MAIN_SWITCH_SET_TIMEOUT = MAKE_RETURN_CODE(0xA4);
static const ReturnValue_t COMMAND_ALREADY_WAITING = MAKE_RETURN_CODE(0xA5);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HEATER_HANDLER;
static const Event GPIO_PULL_HIGH_FAILED = MAKE_EVENT(0, severity::LOW);
static const Event GPIO_PULL_LOW_FAILED = MAKE_EVENT(1, severity::LOW);
static const Event SWITCH_ALREADY_ON = MAKE_EVENT(2, severity::LOW);
static const Event SWITCH_ALREADY_OFF = MAKE_EVENT(3, severity::LOW);
static const Event MAIN_SWITCH_TIMEOUT = MAKE_EVENT(4, severity::LOW);
static const MessageQueueId_t NO_COMMANDER = 0;
enum SwitchState : bool {
ON = true,
OFF = false
};
/**
* @brief Struct holding information about a heater command to execute.
*
* @param action The action to perform.
* @param replyQueue The queue of the commander to which status replies
* will be sent.
* @param active True if command is waiting for execution, otherwise false.
* @param waitSwitchOn True if the command is waiting for the main switch being set on.
* @param mainSwitchCountdown Sets timeout to wait for main switch being set on.
*/
typedef struct HeaterCommandInfo {
uint8_t action;
MessageQueueId_t replyQueue;
bool active = false;
bool waitMainSwitchOn = false;
Countdown mainSwitchCountdown;
} HeaterCommandInfo_t;
enum SwitchAction {
SET_SWITCH_OFF,
SET_SWITCH_ON
};
using switchNr_t = uint8_t;
using HeaterMap = std::unordered_map<switchNr_t, HeaterCommandInfo_t>;
using HeaterMapIter = HeaterMap::iterator;
HeaterMap heaterMap;
bool switchStates[heaterSwitches::NUMBER_OF_SWITCHES];
/** Size of command queue */
size_t cmdQueueSize = 20;
/**
* The object ID of the GPIO driver which enables and disables the
* heaters.
*/
object_id_t gpioDriverId;
CookieIF * gpioCookie;
GpioIF* gpioInterface;
/** Queue to receive messages from other objects. */
MessageQueueIF* commandQueue = nullptr;
object_id_t mainLineSwitcherObjectId;
/** Switch number of the heater power supply switch */
uint8_t mainLineSwitch;
/**
* Power switcher object which controls the 8V main line of the heater
* logic on the TCS board.
*/
PowerSwitchIF *mainLineSwitcher = nullptr;
ActionHelper actionHelper;
StorageManagerIF *IPCStore = nullptr;
void readCommandQueue();
/**
* @brief Returns the state of a switch (ON - true, or OFF - false).
* @param switchNr The number of the switch to check.
*/
bool checkSwitchState(int switchNr);
/**
* @brief Returns the ID of the GPIO related to a heater identified by the switch number
* which is defined in the heaterSwitches list.
*/
gpioId_t getGpioIdFromSwitchNr(int switchNr);
/**
* @brief This function runs commands waiting for execution.
*/
void handleActiveCommands();
ReturnValue_t initializeHeaterMap();
/**
* @brief Sets all switches to OFF.
*/
void setInitialSwitchStates();
void handleSwitchOnCommand(HeaterMapIter heaterMapIter);
void handleSwitchOffCommand(HeaterMapIter heaterMapIter);
/**
* @brief Checks if all switches are off.
* @return True if all switches are off, otherwise false.
*/
bool allSwitchesOff();
};
#endif /* MISSION_DEVICES_HEATERHANDLER_H_ */

View File

@ -0,0 +1,357 @@
#include <bitset>
#include <cmath>
#include "Max31865PT100Handler.h"
Max31865PT1000Handler::Max31865PT1000Handler(object_id_t objectId,
object_id_t comIF, CookieIF *comCookie, uint8_t switchId):
DeviceHandlerBase(objectId, comIF, comCookie), switchId(switchId),
sensorDataset(this), sensorDatasetSid(sensorDataset.getSid()) {
#if OBSW_VERBOSE_LEVEL >= 1
debugDivider = new PeriodicOperationDivider(10);
#endif
}
Max31865PT1000Handler::~Max31865PT1000Handler() {
}
void Max31865PT1000Handler::doStartUp() {
if(internalState == InternalState::NONE) {
internalState = InternalState::WARMUP;
Clock::getUptime(&startTime);
}
if(internalState == InternalState::WARMUP) {
dur_millis_t timeNow = 0;
Clock::getUptime(&timeNow);
if(timeNow - startTime >= 100) {
internalState = InternalState::CONFIGURE;
}
}
if(internalState == InternalState::CONFIGURE) {
if(commandExecuted) {
internalState = InternalState::REQUEST_CONFIG;
commandExecuted = false;
}
}
if(internalState == InternalState::REQUEST_CONFIG) {
if (commandExecuted) {
setMode(MODE_ON);
setMode(MODE_NORMAL);
commandExecuted = false;
internalState = InternalState::RUNNING;
}
}
}
void Max31865PT1000Handler::doShutDown() {
commandExecuted = false;
setMode(MODE_OFF);
}
ReturnValue_t Max31865PT1000Handler::buildNormalDeviceCommand(
DeviceCommandId_t *id) {
if(internalState == InternalState::RUNNING) {
*id = TSensorDefinitions::REQUEST_RTD;
return buildCommandFromCommand(*id, nullptr, 0);
}
else if(internalState == InternalState::REQUEST_FAULT_BYTE) {
*id = TSensorDefinitions::REQUEST_FAULT_BYTE;
return buildCommandFromCommand(*id, nullptr, 0);
}
else {
return DeviceHandlerBase::NOTHING_TO_SEND;
}
}
ReturnValue_t Max31865PT1000Handler::buildTransitionDeviceCommand(
DeviceCommandId_t *id) {
switch(internalState) {
case(InternalState::NONE):
case(InternalState::WARMUP):
case(InternalState::RUNNING):
return DeviceHandlerBase::NOTHING_TO_SEND;
case(InternalState::CONFIGURE): {
*id = TSensorDefinitions::CONFIG_CMD;
uint8_t config[1] = {DEFAULT_CONFIG};
return buildCommandFromCommand(*id, config, 1);
}
case(InternalState::REQUEST_CONFIG): {
*id = TSensorDefinitions::REQUEST_CONFIG;
return buildCommandFromCommand(*id, nullptr, 0);
}
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Max31865PT1000Handler: Invalid internal state" << std::endl;
#else
sif::printError("Max31865PT1000Handler: Invalid internal state\n");
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t Max31865PT1000Handler::buildCommandFromCommand(
DeviceCommandId_t deviceCommand, const uint8_t *commandData,
size_t commandDataLen) {
switch(deviceCommand) {
case(TSensorDefinitions::CONFIG_CMD) : {
commandBuffer[0] = static_cast<uint8_t>(TSensorDefinitions::CONFIG_CMD);
if(commandDataLen == 1) {
commandBuffer[1] = commandData[0];
DeviceHandlerBase::rawPacketLen = 2;
DeviceHandlerBase::rawPacket = commandBuffer.data();
return HasReturnvaluesIF::RETURN_OK;
}
else {
return DeviceHandlerIF::NO_COMMAND_DATA;
}
}
case(TSensorDefinitions::REQUEST_CONFIG): {
commandBuffer[0] = 0x00; // dummy byte
commandBuffer[1] = static_cast<uint8_t>(
TSensorDefinitions::REQUEST_CONFIG);
DeviceHandlerBase::rawPacketLen = 2;
DeviceHandlerBase::rawPacket = commandBuffer.data();
return HasReturnvaluesIF::RETURN_OK;
}
case(TSensorDefinitions::REQUEST_RTD): {
commandBuffer[0] = static_cast<uint8_t>(
TSensorDefinitions::REQUEST_RTD);
// two dummy bytes
commandBuffer[1] = 0x00;
commandBuffer[2] = 0x00;
DeviceHandlerBase::rawPacketLen = 3;
DeviceHandlerBase::rawPacket = commandBuffer.data();
return HasReturnvaluesIF::RETURN_OK;
}
case(TSensorDefinitions::REQUEST_FAULT_BYTE): {
commandBuffer[0] = static_cast<uint8_t>(
TSensorDefinitions::REQUEST_FAULT_BYTE);
commandBuffer[1] = 0x00;
DeviceHandlerBase::rawPacketLen = 2;
DeviceHandlerBase::rawPacket = commandBuffer.data();
return HasReturnvaluesIF::RETURN_OK;
}
default:
//Unknown DeviceCommand
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
}
void Max31865PT1000Handler::fillCommandAndReplyMap() {
insertInCommandAndReplyMap(TSensorDefinitions::CONFIG_CMD, 3);
insertInCommandAndReplyMap(TSensorDefinitions::REQUEST_CONFIG, 3);
insertInCommandAndReplyMap(TSensorDefinitions::REQUEST_RTD, 3,
&sensorDataset);
insertInCommandAndReplyMap(TSensorDefinitions::REQUEST_FAULT_BYTE, 3);
}
ReturnValue_t Max31865PT1000Handler::scanForReply(const uint8_t *start,
size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) {
size_t rtdReplySize = 3;
size_t configReplySize = 2;
if(remainingSize == rtdReplySize and
internalState == InternalState::RUNNING) {
*foundId = TSensorDefinitions::REQUEST_RTD;
*foundLen = rtdReplySize;
}
if(remainingSize == configReplySize) {
if(internalState == InternalState::CONFIGURE) {
commandExecuted = true;
*foundLen = configReplySize;
*foundId = TSensorDefinitions::CONFIG_CMD;
}
else if(internalState == InternalState::REQUEST_FAULT_BYTE) {
*foundId = TSensorDefinitions::REQUEST_FAULT_BYTE;
*foundLen = 2;
internalState = InternalState::RUNNING;
}
else {
*foundId = TSensorDefinitions::REQUEST_CONFIG;
*foundLen = configReplySize;
}
}
return RETURN_OK;
}
ReturnValue_t Max31865PT1000Handler::interpretDeviceReply(
DeviceCommandId_t id, const uint8_t *packet) {
switch(id) {
case(TSensorDefinitions::REQUEST_CONFIG): {
if(packet[1] != DEFAULT_CONFIG) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
// it propably would be better if we at least try one restart..
sif::error << "Max31865PT1000Handler: Invalid configuration reply!" << std::endl;
#else
sif::printError("Max31865PT1000Handler: Invalid configuration reply!\n");
#endif
return HasReturnvaluesIF::RETURN_OK;
}
// set to true for invalid configs too for now.
if(internalState == InternalState::REQUEST_CONFIG) {
commandExecuted = true;
}
else if(internalState == InternalState::RUNNING) {
// we should propably generate a telemetry with the config byte
// as payload here.
}
break;
}
case(TSensorDefinitions::REQUEST_RTD): {
// first bit of LSB reply byte is the fault bit
uint8_t faultBit = packet[2] & 0b0000'0001;
if(faultBit == 1) {
// Maybe we should attempt to restart it?
if(faultByte == 0) {
internalState = InternalState::REQUEST_FAULT_BYTE;
}
}
// RTD value consists of last seven bits of the LSB reply byte and
// the MSB reply byte
uint16_t adcCode = ((packet[1] << 8) | packet[2]) >> 1;
// do something with rtd value, will propably be stored in
// dataset.
float rtdValue = adcCode * RTD_RREF_PT1000 / INT16_MAX;
// calculate approximation
float approxTemp = adcCode / 32.0 - 256.0;
#if OBSW_VERBOSE_LEVEL >= 1
if(debugDivider->checkAndIncrement()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Max31865PT1000Handler::interpretDeviceReply: Measured "
<< "resistance is " << rtdValue << " Ohms." << std::endl;
sif::info << "Approximated temperature is " << approxTemp << " <20>C"
<< std::endl;
#else
sif::printInfo("Max31865PT1000Handler::interpretDeviceReply: Measured resistance is %f"
" Ohms.\n", rtdValue);
sif::printInfo("Approximated temperature is %f C\n", approxTemp);
#endif
sensorDataset.setChanged(true);
}
#endif
ReturnValue_t result = sensorDataset.read();
if(result != HasReturnvaluesIF::RETURN_OK) {
// Configuration error
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Max31865PT1000Handler::interpretDeviceReply: Error reading dataset!"
<< std::endl;
#else
sif::printDebug("Max31865PT1000Handler::interpretDeviceReply: Error reading dataset!\n");
#endif
return result;
}
if(not sensorDataset.isValid()) {
sensorDataset.temperatureCelcius.setValid(true);
}
sensorDataset.temperatureCelcius = approxTemp;
result = sensorDataset.commit();
if(result != HasReturnvaluesIF::RETURN_OK) {
// Configuration error
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Max31865PT1000Handler::interpretDeviceReply: "
"Error commiting dataset!" << std::endl;
#else
sif::printDebug("Max31865PT1000Handler::interpretDeviceReply: "
"Error commiting dataset!\n");
#endif
return result;
}
break;
}
case(TSensorDefinitions::REQUEST_FAULT_BYTE): {
faultByte = packet[1];
#if OBSW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Max31865PT1000Handler::interpretDeviceReply: Fault byte"
" is: 0b" << std::bitset<8>(faultByte) << std::endl;
#else
sif::printInfo("Max31865PT1000Handler::interpretDeviceReply: Fault byte"
" is: 0b" BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(faultByte));
#endif
#endif
ReturnValue_t result = sensorDataset.read();
if(result != HasReturnvaluesIF::RETURN_OK) {
// Configuration error
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Max31865PT1000Handler::interpretDeviceReply: "
"Error reading dataset!" << std::endl;
#else
sif::printDebug("Max31865PT1000Handler::interpretDeviceReply: "
"Error reading dataset!\n");
#endif
return result;
}
sensorDataset.errorByte.setValid(true);
sensorDataset.errorByte = faultByte;
if(faultByte != 0) {
sensorDataset.temperatureCelcius.setValid(false);
}
result = sensorDataset.commit();
if(result != HasReturnvaluesIF::RETURN_OK) {
// Configuration error
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Max31865PT1000Handler::interpretDeviceReply: "
"Error commiting dataset!" << std::endl;
#else
sif::printDebug("Max31865PT1000Handler::interpretDeviceReply: "
"Error commiting dataset!\n");
#endif
return result;
}
break;
}
default:
break;
}
return HasReturnvaluesIF::RETURN_OK;
}
void Max31865PT1000Handler::debugInterface(uint8_t positionTracker,
object_id_t objectId, uint32_t parameter) {
}
uint32_t Max31865PT1000Handler::getTransitionDelayMs(
Mode_t modeFrom, Mode_t modeTo) {
return 5000;
}
ReturnValue_t Max31865PT1000Handler::getSwitches(
const uint8_t **switches, uint8_t *numberOfSwitches) {
return DeviceHandlerBase::NO_SWITCH;
}
void Max31865PT1000Handler::doTransition(Mode_t modeFrom,
Submode_t subModeFrom) {
DeviceHandlerBase::doTransition(modeFrom, subModeFrom);
}
ReturnValue_t Max31865PT1000Handler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
localDataPoolMap.emplace(TSensorDefinitions::PoolIds::TEMPERATURE_C,
new PoolEntry<float>({0}, 1, true));
localDataPoolMap.emplace(TSensorDefinitions::PoolIds::FAULT_BYTE,
new PoolEntry<uint8_t>({0}));
poolManager.subscribeForPeriodicPacket(sensorDatasetSid,
false, 4.0, false);
return HasReturnvaluesIF::RETURN_OK;
}
void Max31865PT1000Handler::modeChanged() {
internalState = InternalState::NONE;
}

View File

@ -0,0 +1,104 @@
#ifndef MISSION_DEVICES_MAX31865PT100HANDLER_H_
#define MISSION_DEVICES_MAX31865PT100HANDLER_H_
#include "devicedefinitions/ThermalSensorPacket.h"
#include <OBSWConfig.h>
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include <array>
#include <cstdint>
/**
* @brief Device Handler for the thermal sensors
* @details
* Documentation of devices:
* MAX31865 RTD converter:
* https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf
* Pt1000 platinum resistance thermometers OMEGA F2020-1000-1/3B:
* https://br.omega.com/omegaFiles/temperature/pdf/F1500_F2000_F4000.pdf
*
* The thermal sensor values are measured using the MAX31865 RTD converter IC
* which creates digital values from the measured resistance of the Pt1000
* devices which can be read with the SPI interface.
* Refer to the SOURCE system schematic for the exact setup and number
* of devices.
*
* @author R. Mueller
* @ingroup devices
*/
class Max31865PT1000Handler: public DeviceHandlerBase {
public:
Max31865PT1000Handler(object_id_t objectId, object_id_t comIF,
CookieIF * comCookie, uint8_t switchId);
virtual~ Max31865PT1000Handler();
// Configuration in 8 digit code:
// 1. 1 for V_BIAS enabled, 0 for disabled
// 2. 1 for Auto-conversion, 0 for off
// 3. 1 for 1-shot enabled, 0 for disabled
// 4. 1 for 3-wire disabled, 0 for disabled
// 5./6. Fault detection: 00 for no action, 01 for automatic delay, 1
// 0 for run fault detection with manual delay,
// 11 for finish fault detection with manual delay
// 7. Fault status: 1 for auto-clear, 0 for auto-clear off
// 8. 1 for 50 Hz filter, 0 for 60 Hz filter (noise rejection filter)
static constexpr uint8_t DEFAULT_CONFIG = 0b11000001;
static constexpr float RTD_RREF_PT1000 = 4000.0; //!< Ohm
static constexpr float RTD_RESISTANCE0_PT1000 = 1000.0; //!< Ohm
protected:
/* DeviceHandlerBase abstract function implementation */
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t * commandData, size_t commandDataLen) override;
void fillCommandAndReplyMap() override;
ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize,
DeviceCommandId_t *foundId, size_t *foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t getSwitches(const uint8_t **switches,
uint8_t *numberOfSwitches) override;
void doTransition(Mode_t modeFrom, Submode_t subModeFrom) override;
void debugInterface(uint8_t positionTracker = 0,
object_id_t objectId = 0, uint32_t parameter = 0) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
void modeChanged() override;
private:
const uint8_t switchId;
enum class InternalState {
NONE,
WARMUP,
CONFIGURE,
REQUEST_CONFIG,
RUNNING,
REQUEST_FAULT_BYTE
};
InternalState internalState = InternalState::NONE;
bool commandExecuted = false;
dur_millis_t startTime = 0;
uint8_t faultByte = 0;
std::array<uint8_t, 3> commandBuffer { 0 };
TSensorDefinitions::ThermalSensorDataset sensorDataset;
sid_t sensorDatasetSid;
#if OBSW_VERBOSE_LEVEL >= 1
PeriodicOperationDivider* debugDivider;
#endif
};
#endif /* MISSION_DEVICES_MAX31865PT100HANDLER_H_ */

View File

@ -1,6 +1,6 @@
#include "PDU1Handler.h"
#include <mission/devices/devicedefinitions/GomSpacePackets.h>
#include <fsfwconfig/OBSWConfig.h>
#include <OBSWConfig.h>
PDU1Handler::PDU1Handler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) :
GomspaceDeviceHandler(objectId, comIF, comCookie, PDU::MAX_CONFIGTABLE_ADDRESS,

View File

@ -1,197 +0,0 @@
#include <mission/devices/SolarArrayDeploymentHandler.h>
#include <fsfwconfig/devices/powerSwitcherList.h>
#include <fsfw/ipc/QueueFactory.h>
#include <devices/gpioIds.h>
SolarArrayDeploymentHandler::SolarArrayDeploymentHandler(object_id_t setObjectId_,
object_id_t gpioDriverId_, CookieIF * gpioCookie_, object_id_t mainLineSwitcherObjectId_,
uint8_t mainLineSwitch_, gpioId_t deplSA1, gpioId_t deplSA2, uint32_t burnTimeMs) :
SystemObject(setObjectId_), gpioDriverId(gpioDriverId_), gpioCookie(gpioCookie_), mainLineSwitcherObjectId(
mainLineSwitcherObjectId_), mainLineSwitch(mainLineSwitch_), deplSA1(deplSA1), deplSA2(
deplSA2), burnTimeMs(burnTimeMs), actionHelper(this, nullptr) {
commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize,
MessageQueueMessage::MAX_MESSAGE_SIZE);
}
SolarArrayDeploymentHandler::~SolarArrayDeploymentHandler() {
}
ReturnValue_t SolarArrayDeploymentHandler::performOperation(uint8_t operationCode) {
if (operationCode == DeviceHandlerIF::PERFORM_OPERATION) {
handleStateMachine();
return RETURN_OK;
}
return RETURN_OK;
}
ReturnValue_t SolarArrayDeploymentHandler::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
gpioInterface = objectManager->get<GpioIF>(gpioDriverId);
if (gpioInterface == nullptr) {
sif::error << "SolarArrayDeploymentHandler::initialize: Invalid Gpio interface."
<< std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
result = gpioInterface->initialize(gpioCookie);
if (result != RETURN_OK) {
sif::error << "SolarArrayDeploymentHandler::initialize: Failed to initialize Gpio interface"
<< std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
if (mainLineSwitcherObjectId != objects::NO_OBJECT) {
mainLineSwitcher = objectManager->get<PowerSwitchIF>(mainLineSwitcherObjectId);
if (mainLineSwitcher == nullptr) {
sif::error
<< "SolarArrayDeploymentHandler::initialize: Main line switcher failed to fetch object"
<< "from object ID." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
}
result = actionHelper.initialize(commandQueue);
if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
return RETURN_OK;
}
void SolarArrayDeploymentHandler::handleStateMachine() {
switch (stateMachine) {
case WAIT_ON_DELOYMENT_COMMAND:
readCommandQueue();
break;
case SWITCH_8V_ON:
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_ON);
mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
stateMachine = WAIT_ON_8V_SWITCH;
break;
case WAIT_ON_8V_SWITCH:
performWaitOn8VActions();
break;
case SWITCH_DEPL_GPIOS:
switchDeploymentTransistors();
break;
case WAIT_ON_DEPLOYMENT_FINISH:
handleDeploymentFinish();
break;
case WAIT_FOR_MAIN_SWITCH_OFF:
if (mainLineSwitcher->getSwitchState(mainLineSwitch) == PowerSwitchIF::SWITCH_OFF) {
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
} else if (mainSwitchCountdown.hasTimedOut()) {
triggerEvent(MAIN_SWITCH_OFF_TIMEOUT);
sif::error << "SolarArrayDeploymentHandler::handleStateMachine: Failed to switch main"
<< " switch off" << std::endl;
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
}
break;
default:
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Invalid state" << std::endl;
break;
}
}
void SolarArrayDeploymentHandler::performWaitOn8VActions() {
if (mainLineSwitcher->getSwitchState(mainLineSwitch) == PowerSwitchIF::SWITCH_ON) {
stateMachine = SWITCH_DEPL_GPIOS;
} else {
if (mainSwitchCountdown.hasTimedOut()) {
triggerEvent(MAIN_SWITCH_ON_TIMEOUT);
actionHelper.finish(rememberCommanderId, DEPLOY_SOLAR_ARRAYS,
MAIN_SWITCH_TIMEOUT_FAILURE);
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
}
}
}
void SolarArrayDeploymentHandler::switchDeploymentTransistors() {
ReturnValue_t result = RETURN_OK;
result = gpioInterface->pullHigh(deplSA1);
if (result != RETURN_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 reinitiating
* the deployment sequence. */
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
triggerEvent(DEPL_SA1_GPIO_SWTICH_ON_FAILED);
actionHelper.finish(rememberCommanderId, DEPLOY_SOLAR_ARRAYS,
SWITCHING_DEPL_SA2_FAILED);
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
}
result = gpioInterface->pullHigh(deplSA2);
if (result != RETURN_OK) {
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 2 high " << std::endl;
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
triggerEvent(DEPL_SA2_GPIO_SWTICH_ON_FAILED);
actionHelper.finish(rememberCommanderId, DEPLOY_SOLAR_ARRAYS,
SWITCHING_DEPL_SA2_FAILED);
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
}
deploymentCountdown.setTimeout(burnTimeMs);
stateMachine = WAIT_ON_DEPLOYMENT_FINISH;
}
void SolarArrayDeploymentHandler::handleDeploymentFinish() {
ReturnValue_t result = RETURN_OK;
if (deploymentCountdown.hasTimedOut()) {
actionHelper.finish(rememberCommanderId, DEPLOY_SOLAR_ARRAYS, RETURN_OK);
result = gpioInterface->pullLow(deplSA1);
if (result != RETURN_OK) {
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 1 low " << std::endl;
}
result = gpioInterface->pullLow(deplSA2);
if (result != RETURN_OK) {
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
" array deployment switch 2 low " << std::endl;
}
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
stateMachine = WAIT_FOR_MAIN_SWITCH_OFF;
}
}
void SolarArrayDeploymentHandler::readCommandQueue() {
CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result != RETURN_OK) {
return;
}
result = actionHelper.handleActionMessage(&command);
if (result == RETURN_OK) {
return;
}
}
ReturnValue_t SolarArrayDeploymentHandler::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
ReturnValue_t result;
if (stateMachine != WAIT_ON_DELOYMENT_COMMAND) {
sif::error << "SolarArrayDeploymentHandler::executeAction: Received command while not in"
<< "waiting-on-command-state" << std::endl;
return DEPLOYMENT_ALREADY_EXECUTING;
}
if (actionId != DEPLOY_SOLAR_ARRAYS) {
sif::error << "SolarArrayDeploymentHandler::executeAction: Received invalid command"
<< std::endl;
result = COMMAND_NOT_SUPPORTED;
} else {
stateMachine = SWITCH_8V_ON;
rememberCommanderId = commandedBy;
result = RETURN_OK;
}
return result;
}
MessageQueueId_t SolarArrayDeploymentHandler::getCommandQueue() const {
return commandQueue->getId();
}

View File

@ -1,158 +0,0 @@
#ifndef MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_
#define MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <fsfw/action/HasActionsIF.h>
#include <fsfw/power/PowerSwitchIF.h>
#include <fsfw/devicehandlers/CookieIF.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/timemanager/Countdown.h>
#include <linux/gpio/GpioIF.h>
#include <unordered_map>
/**
* @brief This class is used to control the solar array deployment.
*
* @author J. Meier
*/
class SolarArrayDeploymentHandler: public ExecutableObjectIF,
public SystemObject,
public HasReturnvaluesIF,
public HasActionsIF {
public:
static const DeviceCommandId_t DEPLOY_SOLAR_ARRAYS = 0x5;
/**
* @brief constructor
*
* @param setObjectId The object id of the SolarArrayDeploymentHandler.
* @param gpioDriverId The id of the gpio com if.
* @param gpioCookie GpioCookie holding information about the gpios used to switch the
* transistors.
* @param mainLineSwitcherObjectId The object id of the object responsible for switching
* the 8V power source. This is normally the PCDU.
* @param mainLineSwitch The id of the main line switch. This is defined in
* powerSwitcherList.h.
* @param deplSA1 gpioId of the GPIO controlling the deployment 1 transistor.
* @param deplSA2 gpioId of the GPIO controlling the deployment 2 transistor.
* @param burnTimeMs Time duration the power will be applied to the burn wires.
*/
SolarArrayDeploymentHandler(object_id_t setObjectId, object_id_t gpioDriverId,
CookieIF * gpioCookie, object_id_t mainLineSwitcherObjectId, uint8_t mainLineSwitch,
gpioId_t deplSA1, gpioId_t deplSA2, uint32_t burnTimeMs);
virtual ~SolarArrayDeploymentHandler();
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
virtual MessageQueueId_t getCommandQueue() const override;
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override;
virtual ReturnValue_t initialize() override;
private:
static const uint8_t INTERFACE_ID = CLASS_ID::SA_DEPL_HANDLER;
static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA0);
static const ReturnValue_t DEPLOYMENT_ALREADY_EXECUTING = MAKE_RETURN_CODE(0xA1);
static const ReturnValue_t MAIN_SWITCH_TIMEOUT_FAILURE = MAKE_RETURN_CODE(0xA2);
static const ReturnValue_t SWITCHING_DEPL_SA1_FAILED = MAKE_RETURN_CODE(0xA3);
static const ReturnValue_t SWITCHING_DEPL_SA2_FAILED = MAKE_RETURN_CODE(0xA4);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SA_DEPL_HANDLER;
static const Event MAIN_SWITCH_ON_TIMEOUT = MAKE_EVENT(0, severity::LOW);
static const Event MAIN_SWITCH_OFF_TIMEOUT = MAKE_EVENT(1, severity::LOW);
static const Event DEPLOYMENT_FAILED = MAKE_EVENT(2, severity::HIGH);
static const Event DEPL_SA1_GPIO_SWTICH_ON_FAILED = MAKE_EVENT(3, severity::HIGH);
static const Event DEPL_SA2_GPIO_SWTICH_ON_FAILED = MAKE_EVENT(4, severity::HIGH);
enum StateMachine {
WAIT_ON_DELOYMENT_COMMAND,
SWITCH_8V_ON,
WAIT_ON_8V_SWITCH,
SWITCH_DEPL_GPIOS,
WAIT_ON_DEPLOYMENT_FINISH,
WAIT_FOR_MAIN_SWITCH_OFF
};
StateMachine stateMachine = WAIT_ON_DELOYMENT_COMMAND;
/**
* This countdown is used to check if the PCDU sets the 8V line on in the intended time.
*/
Countdown mainSwitchCountdown;
/**
* This countdown is used to wait for the burn wire being successful cut.
*/
Countdown deploymentCountdown;
/**
* 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.
*/
MessageQueueId_t rememberCommanderId = 0;
/** Size of command queue */
size_t cmdQueueSize = 20;
/** The object ID of the GPIO driver which switches the deployment transistors */
object_id_t gpioDriverId;
CookieIF * gpioCookie;
/** Object id of the object responsible to switch the 8V power input. Typically the PCDU. */
object_id_t mainLineSwitcherObjectId;
/** Switch number of the 8V power switch */
uint8_t mainLineSwitch;
gpioId_t deplSA1;
gpioId_t deplSA2;
GpioIF* gpioInterface;
/** Time duration switches are active to cut the burn wire */
uint32_t burnTimeMs;
/** Queue to receive messages from other objects. */
MessageQueueIF* commandQueue = nullptr;
/**
* After initialization this pointer will hold the reference to the main line switcher object.
*/
PowerSwitchIF *mainLineSwitcher = nullptr;
ActionHelper actionHelper;
void readCommandQueue();
/**
* @brief This function performs actions dependent on the current state.
*/
void handleStateMachine();
/**
* @brief This function polls the 8V switch state and changes the state machine when the
* switch has been enabled.
*/
void performWaitOn8VActions();
/**
* @brief This functions handles the switching of the solar array deployment transistors.
*/
void switchDeploymentTransistors();
/**
* @brief This function performs actions to finish the deployment. Essentially switches
* are turned of after the burn time has expired.
*/
void handleDeploymentFinish();
};
#endif /* MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_ */

View File

@ -0,0 +1,60 @@
#ifndef MISSION_DEVICES_DEVICEPACKETS_THERMALSENSORPACKET_H_
#define MISSION_DEVICES_DEVICEPACKETS_THERMALSENSORPACKET_H_
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfwconfig/objects/systemObjectList.h>
namespace TSensorDefinitions {
enum ObjIds: object_id_t {
TEST_HKB_HANDLER = objects::SPI_Test_PT1000,
SYRLINKS_HANDLER = objects::PT1000_Syrlinks_DEC1_O1,
MGT_1_HANDLER = objects::PT1000_MGT1_DEC2,
PLOC_HANDLER = objects::PT1000_PLOC_DEC4,
MESHCAM_HANDLER = objects::PT1000_Camera_DEC1_O2
};
enum PoolIds: lp_id_t {
TEMPERATURE_C,
FAULT_BYTE
};
static constexpr DeviceCommandId_t CONFIG_CMD = 0x80;
static constexpr DeviceCommandId_t REQUEST_CONFIG = 0x00;
static constexpr DeviceCommandId_t REQUEST_RTD = 0x01;
static constexpr DeviceCommandId_t REQUEST_FAULT_BYTE = 0x07;
static constexpr uint32_t THERMAL_SENSOR_SET_ID = REQUEST_RTD;
class ThermalSensorDataset:
public StaticLocalDataSet<sizeof(float) + sizeof(uint8_t)> {
public:
/**
* Constructor used by owner and data creators like device handlers.
* @param owner
* @param setId
*/
ThermalSensorDataset(HasLocalDataPoolIF* owner):
StaticLocalDataSet(owner, THERMAL_SENSOR_SET_ID) {
}
/**
* Constructor used by data users like controllers.
* @param sid
*/
ThermalSensorDataset(object_id_t objectId):
StaticLocalDataSet(sid_t(objectId, THERMAL_SENSOR_SET_ID)) {
}
lp_var_t<float> temperatureCelcius = lp_var_t<float>(sid.objectId,
PoolIds::TEMPERATURE_C, this);
lp_var_t<uint8_t> errorByte = lp_var_t<uint8_t>(sid.objectId,
PoolIds::FAULT_BYTE, this);
};
}
#endif /* MISSION_DEVICES_DEVICEPACKETS_THERMALSENSORPACKET_H_ */