Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: NaturalTinyShell_ice libmDot-12Sept mbed-rtos mbed
Fork of ICE by
src/ConfigurationHandler/Controls/FailsafeControl.cpp
- Committer:
- jmarkel44
- Date:
- 2016-10-24
- Revision:
- 260:fe726583ba1d
- Parent:
- 253:ae850c19cf81
- Child:
- 261:4e9a588c938e
File content as of revision 260:fe726583ba1d:
/****************************************************************************** * * File: CompositeControl.cpp * Desciption: ICE Composite Control Class implementation * *****************************************************************************/ #include "FailsafeControl.h" #include "cJSON.h" #include "mDot.h" #include "global.h" #include "ModbusMasterApi.h" #include <string> #include <iostream> #include <iomanip> extern mDot *GLOBAL_mdot; // // method: load // description: load a composite control // // @param none // @return none // bool FailsafeControl::load(std::string _controlFile) { controlFile = _controlFile; // open and read from the control file mDot::mdot_file file = GLOBAL_mdot->openUserFile(controlFile.c_str(), mDot::FM_RDONLY); if ( file.fd < 0 ) { logError("%s: failed to open %s\n", __func__, controlFile.c_str()); return false; } // read the data into a buffer char dataBuf[MAX_FILE_SIZE]; int bytes_read = GLOBAL_mdot->readUserFile(file, (void *)dataBuf, sizeof(dataBuf)); if ( bytes_read != sizeof(dataBuf) ) { logError("%s: failed to read %d bytes from %s", __func__, sizeof(dataBuf), controlFile.c_str()); // caller should destroy the object return false; } // close the file GLOBAL_mdot->closeUserFile(file); // parse the data cJSON * root = cJSON_Parse(dataBuf); id = cJSON_GetObjectItem(root, "id")->valuestring; priority = atoi(cJSON_GetObjectItem(root, "priority")->valuestring); input = cJSON_GetObjectItem(root, "input")->valuestring; output = cJSON_GetObjectItem(root, "output")->valuestring; hfs_data.value = atof(cJSON_GetObjectItem(root, "hfsValue")->valuestring); hfs_data.dutyCycle = atoi(cJSON_GetObjectItem(root, "hfsDutyCycle")->valuestring); hfs_data.interval = atoi(cJSON_GetObjectItem(root, "hfsInterval")->valuestring); lfs_data.value = atof(cJSON_GetObjectItem(root, "lfsValue")->valuestring); lfs_data.dutyCycle = atoi(cJSON_GetObjectItem(root, "lfsDutyCycle")->valuestring); lfs_data.interval = atoi(cJSON_GetObjectItem(root, "lfsInterval")->valuestring); return true; } // // method: start // description: start the failsafe control // // @param none // @return none // void FailsafeControl::start(void) { currentState = STATE_START; } // // method: update // description: update the faisafe control using the FSM // // @param none // @return none // void FailsafeControl::update(void) { switch (this->currentState) { case STATE_INIT: // do nothing - must be invoked break; case STATE_START: // control has been started, do some checking if ( this->aboveHighFailsafe() ) { this->currentState = STATE_CONTROL_HFS_ON; } else if ( this->belowLowFailsafe() ) { this->currentState = STATE_CONTROL_LFS_ON; } else { this->currentState = STATE_CONTROL_OFF; } break; case STATE_CONTROL_OFF: // control is acting normal, within bounds if ( this->aboveHighFailsafe() ) { this->currentState = STATE_CONTROL_HFS_ON; } else if ( this->belowLowFailsafe() ) { this->currentState = STATE_CONTROL_LFS_ON; } else { // do nothing } break; case STATE_CONTROL_LFS_ON: // control is in low-failsafe with duty cycle ON if ( !this->belowLowFailsafe() ) { this->currentState = STATE_CONTROL_OFF; } else if ( this->dutyOnExpired() ) { this->currentState = STATE_CONTROL_LFS_OFF; } else { // do nothing } break; case STATE_CONTROL_LFS_OFF: // control is in low-failsafe with duty cycle OFF if ( !this->belowLowFailsafe() ) { this->currentState = STATE_CONTROL_OFF; } else if ( this->dutyOffExpired() ) { this->currentState = STATE_CONTROL_LFS_ON; } else { // do nothing } break; case STATE_CONTROL_HFS_ON: // control is in high-failsafe with duty cycle ON if ( !this->aboveHighFailsafe() ) { this->currentState = STATE_CONTROL_OFF; } else if ( this->dutyOnExpired() ) { this->currentState = STATE_CONTROL_HFS_OFF; } else { // do nothing } break; case STATE_CONTROL_HFS_OFF: // control is in high-failsafe with cuty cycle OFF if ( !this->aboveHighFailsafe() ) { this->currentState = STATE_CONTROL_OFF; } else if ( this->dutyOffExpired() ) { this->currentState = STATE_CONTROL_LFS_ON; } else { // do nothing } break; default: break; } } bool FailsafeControl::belowLowFailsafe(void) { // read the modbus input ModbusValue value; ModbusMasterReadRegister(input, &value); #if 0 if ( value.errflag ) { logError("%s: error reading %s:", __func__, input); return false; } #endif return ( value.value <= lfs_data.value ); } bool FailsafeControl::aboveHighFailsafe(void) { // read the modbus input ModbusValue value; ModbusMasterReadRegister(input, &value); // TODO: check the error flag #if 0 if ( value.errflag ) { logError("%s: error reading %s:", __func__, input); return false; } #endif return ( value.value >= hfs_data.value ); } bool FailsafeControl::dutyOnExpired() { return false; } bool FailsafeControl::dutyOffExpired() { return false; } // // method: sendMailToOutput // description: send mail to the output task // // @param io_tag -> input/output tag // @param action -> ON, OFF, UNREGISTER // @return none // void FailsafeControl::sendMailToOutput(OutputAction action) { logInfo("%s: failsafe control attempting to send action %d\n", __func__, action); OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); memset(output_mail, 0, sizeof(OutputControlMsg_t)); output_mail->action = action; output_mail->controlType = CONTROL_FAILSAFE; output_mail->priority = this->priority; strncpy(output_mail->input_tag, this->input.c_str(), sizeof(output_mail->input_tag)-1); strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); OutputMasterMailBox.put(output_mail); } // // method: unregisterControl // description: unregister this control with the output task // // @param none // @return none // void FailsafeControl::unregisterControl(void) { logInfo("%s: %s attempting to unregister %s\n", __func__, controlFile.c_str()); OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); memset(output_mail, 0, sizeof(OutputControlMsg_t)); output_mail->action = ACTION_CONTROL_UNREGISTER; output_mail->controlType = CONTROL_FAILSAFE; output_mail->priority = this->priority; strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); OutputMasterMailBox.put(output_mail); } // // method: display // description: display the pertinents // // @param none // @return none // void FailsafeControl::display(void) { const char *mapper[] = { "INIT", "START", "CONTROL_OFF", "LFS_ON", "LFS_OFF", "HFS_ON", "HFS_OFF", "invalid" }; printf("\r\n"); std::cout << left << setw(10) << setfill(' ') << "failsafe: "; std::cout << left << setw(40) << setfill(' ') << controlFile; std::cout << left << setw(20) << setfill(' ') << id; std::cout << left << setw(6) << setfill(' ') << priority; std::cout << left << setw(20) << setfill(' ') << input; std::cout << left << setw(20) << setfill(' ') << output; std::cout << left << setw(16) << setfill(' ') << mapper[currentState]; std::cout << left << setw(12) << setfill(' ') << "lfs-> " << lfs_data.value << ":" << lfs_data.dutyCycle << ":" << lfs_data.interval; std::cout << right << setw(12) << setfill(' ') << "hfs-> " << hfs_data.value << ":" << hfs_data.dutyCycle << ":" << hfs_data.interval; std::cout.flush(); }