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.
Diff: ICE-Application/src/ConfigurationHandler/Controls/SetpointControl.cpp
- Revision:
- 2:02cb20446785
- Parent:
- 1:b2e90cda7a5a
--- a/ICE-Application/src/ConfigurationHandler/Controls/SetpointControl.cpp Tue Jan 24 19:06:45 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,369 +0,0 @@ -/****************************************************************************** -* -* File: SetpointControl.cpp -* Desciption: ICE Setpoint Control class implementation -* -*****************************************************************************/ -#include "SetpointControl.h" -#include "ICELog.h" -#include "cJSON.h" -#include "ModbusMasterApi.h" -#include "global.h" -#include "utilities.h" -#include <string> -#include <iostream> -#include <iomanip> -#include <stdarg.h> -#include <stdlib.h> - -// for debugging - this can be set via the console command: -// "debug-sp 1 or debug-sp 0 -bool debugSetpointControl = false; - -static void debug(const char *fmt, ...) -{ - if ( debugSetpointControl ) { - va_list vargs; - va_start(vargs, fmt); - vfprintf(stdout, fmt, vargs); - va_end(vargs); - } -} - -#ifdef MDOT_ICE -extern mDot *GLOBAL_mdot; -#endif - -// -// method: load -// description: open the configuration file and assign data to the -// setpoint control object -// -// @param controlFile -> name of the control file -// @return true if data is assigned; false on error -// -bool SetpointControl::load(std::string _controlFile) -{ - controlFile = _controlFile; - - char dataBuf[MAX_FILE_SIZE]; - - // read the control data - bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf)); - if ( rc != true ) { - logError("%s: failed to read %s", __func__, controlFile.c_str()); - // caller should destroy the object - return false; - } - - // validate control data - if ( !validateControlData(dataBuf) ) { - logError("%s: failed to validate control data", __func__); - return false; - } - - // copy control data - copyControlData(dataBuf); - - ModbusValue val; - // validate the input & output - if ( ModbusMasterReadRegister(input, &val) == false ) { - logError("%s failed to find the input %s", id.c_str(), input.c_str()); - return false; - } - if ( ModbusMasterReadRegister(output, &val) == false ) { - logError("%s failed to find output %s", id.c_str(), output.c_str()); - return false; - } - - isVirtualOutput = Util_isVirtualOutput(output) ? true : false; - return true; -} - -// -// method: validateControlData -// description: validate JSON formatted string -// -bool SetpointControl::validateControlData(const char *buf) -{ - bool rc = true; - cJSON * root = cJSON_Parse(buf); - - if ( !cJSON_HasObjectItem(root, "id") || - !cJSON_HasObjectItem(root, "priority") || - !cJSON_HasObjectItem(root, "input") || - !cJSON_HasObjectItem(root, "output") || - !cJSON_HasObjectItem(root, "setpoint") || - !cJSON_HasObjectItem(root, "prodfact") || - !cJSON_HasObjectItem(root, "actingDir") || - !cJSON_HasObjectItem(root, "tol") ) { - logError("Setpoint control is missing expected tags\n"); - rc = false; - } - - cJSON_Delete(root); - return rc; -} - -// -// method: copyControlData -// description: copy JSON formatted data -// -void SetpointControl::copyControlData(const char *buf) -{ - cJSON * root = cJSON_Parse(buf); - - 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; - setpoint = atof(cJSON_GetObjectItem(root,"setpoint")->valuestring); - productFactor = atof(cJSON_GetObjectItem(root, "prodfact")->valuestring); - actingDir = atoi(cJSON_GetObjectItem(root, "actingDir")->valuestring); - tolerance = atof(cJSON_GetObjectItem(root, "tol")->valuestring); - - cJSON_Delete(root); -} - -// -// method: start -// description: start the setpoint control -// -// @param none -// @return none -// -void SetpointControl::start(void) -{ - // this is the initial state; what else needs to be done?? - this->currentState = STATE_STARTUP; -} - -// -// method: -// description: based on the state of the control, check for -// under limit and over limit values, adjust the -// state accordingly -// -// @param none -// @return none -// -SetpointControlError_t SetpointControl::update(void) -{ - SetpointControlError_t rc = SETPOINT_CONTROL_OK; - - switch (this->currentState) { - case STATE_INIT: - // do nothing - break; - case STATE_STARTUP: - if ( this->underLimit() ) { - // start the feed right away - this->startFeed(); - this->currentState = STATE_CONTROL_ON; - debug("\r%s: [START]->under limit->[ON]\n", id.c_str()); - } else { - this->currentState = STATE_CONTROL_OFF; - this->stopFeed(); - debug("\r%s: [START]->!under limit->[OFF]\n", id.c_str()); - } - break; - case STATE_CONTROL_ON: - if ( this->overLimit() ) { - // stop the feed - this->stopFeed(); - this->currentState = STATE_CONTROL_OFF; - debug("\r%s: [ON]->over limit->[OFF]\n", id.c_str()); - } else { - // do nothing - } - break; - case STATE_CONTROL_OFF: - if ( this->underLimit() ) { - // start the feed - this->startFeed(); - this->currentState = STATE_CONTROL_ON; - debug("\r%s: [OFF]->under limit->[ON]\n", id.c_str()); - } else { - // do nothing - } - break; - default: - rc = SETPOINT_CONTROL_UNK_STATE; - break; - } - return rc; -} - -// -// method: overLimit -// description: (see @return) -// -// @param none -// @return true if product is over the upper limit for normal mode -// or under the limit for reverse mode; false otherwise -// -bool SetpointControl::overLimit(void) -{ - ModbusValue value; - ModbusMasterReadRegister( input, &value ); - float flimit; - - if ( !actingDir ) { - flimit = setpoint + tolerance; - return (value.value >= flimit); - } else { - flimit = setpoint - tolerance; - return (value.value <= flimit); - } -} - -// -// method: underLimit -// description: (see @return) -// -// @param none -// @return true if product is under lower limit for normal mode or -// over the upper limit for reverse mode; false otherwise -// -bool SetpointControl::underLimit(void) -{ - ModbusValue value; - ModbusMasterReadRegister( input, &value ); - float flimit; - - if ( !actingDir ) { - flimit = setpoint - tolerance; - return (value.value <= flimit); - } else { - flimit = setpoint + tolerance; - return (value.value >= flimit); - } -} - -// -// method: startFeed() -// description: send ON indication to Output Master for this control's -// relay -// -// @param none -// @return none -// -void SetpointControl::startFeed(void) -{ - logInfo("%s: %s attempting to start feed on relay %s\n", - __func__, controlFile.c_str(), output.c_str()); - - if ( isVirtualOutput ) { - ModbusMasterWriteRegister(output, 1.0); - } else { - OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); - memset(output_mail, 0, sizeof(OutputControlMsg_t)); - - output_mail->action = ACTION_CONTROL_ON; - output_mail->controlType = CONTROL_SETPOINT; - 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); - output_mail->priority = this->priority; - strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); - OutputMasterMailBox.put(output_mail); - } -} - -// -// method: stopFeed -// description: send OFF indication to Output Master for this control's -// relay -// -// @param none -// @return none -// -void SetpointControl::stopFeed(void) -{ - logInfo("%s: %s attempting to stop feed on relay %s\n", - __func__, controlFile.c_str(), output.c_str()); - - if ( isVirtualOutput ) { - ModbusMasterWriteRegister(output, 0.0); - } else { - OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); - memset(output_mail, 0, sizeof(OutputControlMsg_t)); - - output_mail->action = ACTION_CONTROL_OFF; - output_mail->controlType = CONTROL_SETPOINT; - 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); - output_mail->priority = this->priority; - strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); - OutputMasterMailBox.put(output_mail); - } -} - -// -// method: unregisterControl -// description: send OFF indication to Output Master for this control's -// relay -// -// @param none -// @return none -// -void SetpointControl::unregisterControl(void) -{ - logInfo("%s: %s attempting to unregister %s\n", - __func__, id.c_str(), controlFile.c_str()); - - if ( isVirtualOutput ) { - ModbusMasterWriteRegister(output, 0.0); - } else { - OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); - memset(output_mail, 0, sizeof(OutputControlMsg_t)); - - output_mail->action = ACTION_CONTROL_UNREGISTER; - output_mail->controlType = CONTROL_MANUAL; - 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 control's information -// -// @param none -// @return none -// -void SetpointControl::display(void) -{ - // NOTE: this mapping must be 1:1 with "State" enumeration in SetpointControl.h - std::string mapper[] = { "INIT", - "STARTUP", - "CONTROL_OFF", - "CONTROL_ON", - "CONTROL_DISABLE", - "CONTROL_PAUSE", - "CONTROL_MAX" - }; - - - ModbusValue inputValue; - ModbusMasterReadRegister(input, &inputValue); - - printf("\r\n"); - std::cout << std::left << std::setw(10) << std::setfill(' ') << "setpoint: "; - std::cout << std::left << std::setw(40) << std::setfill(' ') << controlFile; - std::cout << std::left << std::setw(20) << std::setfill(' ') << id; - std::cout << std::left << std::setw(6) << std::setfill(' ') << priority; - std::cout << std::left << std::setw(20) << std::setfill(' ') << input; - std::cout << std::left << std::setw(20) << std::setfill(' ') << output; - std::cout << std::left << std::setw(8) << std::setfill(' ') << setpoint; - std::cout << std::left << std::setw(12) << std::setfill(' ') << (actingDir ? "direct" : "indirect"); - std::cout << std::left << std::setw(16) << std::setfill(' ') << mapper[currentState]; - std::cout << std::right << std::setw(8) << std::setfill(' ') << setpoint + tolerance << " <- "; - std::cout << std::left << std::setw(8) << std::setfill(' ') << inputValue.value << " -> "; - std::cout << std::left << std::setw(8) << std::setfill(' ') << setpoint - tolerance; - //std::cout << left << setw(10) << setfill(' ') << highFailsafe << " : " << lowFailsafe; - - std::cout.flush(); -} \ No newline at end of file