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.
ICE-Application/src/ConfigurationHandler/Controls/FailsafeControl.cpp@0:61364762ee0e, 2017-01-24 (annotated)
- Committer:
- jmarkel44
- Date:
- Tue Jan 24 19:05:33 2017 +0000
- Revision:
- 0:61364762ee0e
Port from IAR to Nucleo-F412 board
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| jmarkel44 | 0:61364762ee0e | 1 | /****************************************************************************** |
| jmarkel44 | 0:61364762ee0e | 2 | * |
| jmarkel44 | 0:61364762ee0e | 3 | * File: FailsafeControl.cpp |
| jmarkel44 | 0:61364762ee0e | 4 | * Desciption: ICE Failsafe Control Class implementation |
| jmarkel44 | 0:61364762ee0e | 5 | * |
| jmarkel44 | 0:61364762ee0e | 6 | *****************************************************************************/ |
| jmarkel44 | 0:61364762ee0e | 7 | #include "FailsafeControl.h" |
| jmarkel44 | 0:61364762ee0e | 8 | #include "cJSON.h" |
| jmarkel44 | 0:61364762ee0e | 9 | #include "ICELog.h" |
| jmarkel44 | 0:61364762ee0e | 10 | #include "global.h" |
| jmarkel44 | 0:61364762ee0e | 11 | #include "ModbusMasterApi.h" |
| jmarkel44 | 0:61364762ee0e | 12 | #include "utilities.h" |
| jmarkel44 | 0:61364762ee0e | 13 | #include <string> |
| jmarkel44 | 0:61364762ee0e | 14 | #include <iostream> |
| jmarkel44 | 0:61364762ee0e | 15 | #include <iomanip> |
| jmarkel44 | 0:61364762ee0e | 16 | #include <stdarg.h> |
| jmarkel44 | 0:61364762ee0e | 17 | #include <stdlib.h> |
| jmarkel44 | 0:61364762ee0e | 18 | #include <time.h> |
| jmarkel44 | 0:61364762ee0e | 19 | |
| jmarkel44 | 0:61364762ee0e | 20 | using namespace std; |
| jmarkel44 | 0:61364762ee0e | 21 | |
| jmarkel44 | 0:61364762ee0e | 22 | #ifdef MDOT_ICE |
| jmarkel44 | 0:61364762ee0e | 23 | extern mDot *GLOBAL_mdot; |
| jmarkel44 | 0:61364762ee0e | 24 | #endif |
| jmarkel44 | 0:61364762ee0e | 25 | |
| jmarkel44 | 0:61364762ee0e | 26 | // for debugging - this can be set via the console command: |
| jmarkel44 | 0:61364762ee0e | 27 | // "debug-fs 1 or debug-fs 0 |
| jmarkel44 | 0:61364762ee0e | 28 | bool debugFailsafeControl = false; |
| jmarkel44 | 0:61364762ee0e | 29 | |
| jmarkel44 | 0:61364762ee0e | 30 | static void debug(const char *fmt, ...) |
| jmarkel44 | 0:61364762ee0e | 31 | { |
| jmarkel44 | 0:61364762ee0e | 32 | if ( debugFailsafeControl ) { |
| jmarkel44 | 0:61364762ee0e | 33 | va_list vargs; |
| jmarkel44 | 0:61364762ee0e | 34 | va_start(vargs, fmt); |
| jmarkel44 | 0:61364762ee0e | 35 | vfprintf(stdout, fmt, vargs); |
| jmarkel44 | 0:61364762ee0e | 36 | va_end(vargs); |
| jmarkel44 | 0:61364762ee0e | 37 | } |
| jmarkel44 | 0:61364762ee0e | 38 | } |
| jmarkel44 | 0:61364762ee0e | 39 | |
| jmarkel44 | 0:61364762ee0e | 40 | // |
| jmarkel44 | 0:61364762ee0e | 41 | // method: load |
| jmarkel44 | 0:61364762ee0e | 42 | // description: load a composite control |
| jmarkel44 | 0:61364762ee0e | 43 | // |
| jmarkel44 | 0:61364762ee0e | 44 | // @param none |
| jmarkel44 | 0:61364762ee0e | 45 | // @return none |
| jmarkel44 | 0:61364762ee0e | 46 | // |
| jmarkel44 | 0:61364762ee0e | 47 | bool FailsafeControl::load(std::string _controlFile) |
| jmarkel44 | 0:61364762ee0e | 48 | { |
| jmarkel44 | 0:61364762ee0e | 49 | controlFile = _controlFile; |
| jmarkel44 | 0:61364762ee0e | 50 | |
| jmarkel44 | 0:61364762ee0e | 51 | |
| jmarkel44 | 0:61364762ee0e | 52 | // read the data into a buffer |
| jmarkel44 | 0:61364762ee0e | 53 | char dataBuf[MAX_FILE_SIZE]; |
| jmarkel44 | 0:61364762ee0e | 54 | |
| jmarkel44 | 0:61364762ee0e | 55 | bool rc = GLOBAL_mdot->readUserFile(controlFile.c_str(), (void *)dataBuf, sizeof(dataBuf)); |
| jmarkel44 | 0:61364762ee0e | 56 | if ( rc != true ) { |
| jmarkel44 | 0:61364762ee0e | 57 | logError("%s: failed to read %s", __func__, controlFile.c_str()); |
| jmarkel44 | 0:61364762ee0e | 58 | // caller should destroy the object |
| jmarkel44 | 0:61364762ee0e | 59 | return false; |
| jmarkel44 | 0:61364762ee0e | 60 | } |
| jmarkel44 | 0:61364762ee0e | 61 | |
| jmarkel44 | 0:61364762ee0e | 62 | |
| jmarkel44 | 0:61364762ee0e | 63 | if ( !validateControlData(dataBuf) ) { |
| jmarkel44 | 0:61364762ee0e | 64 | logError("%s: failed to validate control data", __func__); |
| jmarkel44 | 0:61364762ee0e | 65 | return false; |
| jmarkel44 | 0:61364762ee0e | 66 | } |
| jmarkel44 | 0:61364762ee0e | 67 | |
| jmarkel44 | 0:61364762ee0e | 68 | copyControlData(dataBuf); |
| jmarkel44 | 0:61364762ee0e | 69 | |
| jmarkel44 | 0:61364762ee0e | 70 | ModbusValue val; |
| jmarkel44 | 0:61364762ee0e | 71 | // validate the input & output |
| jmarkel44 | 0:61364762ee0e | 72 | if ( ModbusMasterReadRegister(input, &val) == false ) { |
| jmarkel44 | 0:61364762ee0e | 73 | logError("%s failed to find input %s", id.c_str(), input.c_str()); |
| jmarkel44 | 0:61364762ee0e | 74 | return false; |
| jmarkel44 | 0:61364762ee0e | 75 | } |
| jmarkel44 | 0:61364762ee0e | 76 | if ( ModbusMasterReadRegister(output, &val) == false ) { |
| jmarkel44 | 0:61364762ee0e | 77 | logError("%s failed to find output %s", id.c_str(), output.c_str()); |
| jmarkel44 | 0:61364762ee0e | 78 | return false; |
| jmarkel44 | 0:61364762ee0e | 79 | } |
| jmarkel44 | 0:61364762ee0e | 80 | |
| jmarkel44 | 0:61364762ee0e | 81 | isVirtualOutput = Util_isVirtualOutput(output) ? true : false; |
| jmarkel44 | 0:61364762ee0e | 82 | return true; |
| jmarkel44 | 0:61364762ee0e | 83 | } |
| jmarkel44 | 0:61364762ee0e | 84 | // |
| jmarkel44 | 0:61364762ee0e | 85 | // method: validateControlData |
| jmarkel44 | 0:61364762ee0e | 86 | // description: validate the JSON formatted strings for |
| jmarkel44 | 0:61364762ee0e | 87 | // expected tags |
| jmarkel44 | 0:61364762ee0e | 88 | // |
| jmarkel44 | 0:61364762ee0e | 89 | // @param[in] buf -> JSON formatted string |
| jmarkel44 | 0:61364762ee0e | 90 | // @param[out] none |
| jmarkel44 | 0:61364762ee0e | 91 | // @return true if valid; false otherwise |
| jmarkel44 | 0:61364762ee0e | 92 | // |
| jmarkel44 | 0:61364762ee0e | 93 | bool FailsafeControl::validateControlData(const char *buf) |
| jmarkel44 | 0:61364762ee0e | 94 | { |
| jmarkel44 | 0:61364762ee0e | 95 | bool rc = true; |
| jmarkel44 | 0:61364762ee0e | 96 | // parse the data |
| jmarkel44 | 0:61364762ee0e | 97 | cJSON * root = cJSON_Parse(buf); |
| jmarkel44 | 0:61364762ee0e | 98 | |
| jmarkel44 | 0:61364762ee0e | 99 | if ( !cJSON_HasObjectItem(root, "id") || |
| jmarkel44 | 0:61364762ee0e | 100 | !cJSON_HasObjectItem(root, "priority") || |
| jmarkel44 | 0:61364762ee0e | 101 | !cJSON_HasObjectItem(root, "input") || |
| jmarkel44 | 0:61364762ee0e | 102 | !cJSON_HasObjectItem(root, "output") || |
| jmarkel44 | 0:61364762ee0e | 103 | !cJSON_HasObjectItem(root, "hfsValue") || |
| jmarkel44 | 0:61364762ee0e | 104 | !cJSON_HasObjectItem(root, "hfsDutyCycle") || |
| jmarkel44 | 0:61364762ee0e | 105 | !cJSON_HasObjectItem(root, "hfsInterval") || |
| jmarkel44 | 0:61364762ee0e | 106 | !cJSON_HasObjectItem(root, "lfsValue") || |
| jmarkel44 | 0:61364762ee0e | 107 | !cJSON_HasObjectItem(root, "lfsDutyCycle") || |
| jmarkel44 | 0:61364762ee0e | 108 | !cJSON_HasObjectItem(root, "lfsInterval") ) { |
| jmarkel44 | 0:61364762ee0e | 109 | logError("%s: control file is missing expected tags", __func__); |
| jmarkel44 | 0:61364762ee0e | 110 | rc = false; |
| jmarkel44 | 0:61364762ee0e | 111 | } |
| jmarkel44 | 0:61364762ee0e | 112 | |
| jmarkel44 | 0:61364762ee0e | 113 | cJSON_Delete(root); |
| jmarkel44 | 0:61364762ee0e | 114 | return rc; |
| jmarkel44 | 0:61364762ee0e | 115 | } |
| jmarkel44 | 0:61364762ee0e | 116 | |
| jmarkel44 | 0:61364762ee0e | 117 | // |
| jmarkel44 | 0:61364762ee0e | 118 | // method: copyControlData |
| jmarkel44 | 0:61364762ee0e | 119 | // description: copy data from JSON buffer to object |
| jmarkel44 | 0:61364762ee0e | 120 | // |
| jmarkel44 | 0:61364762ee0e | 121 | // @param[in] buf -> JSON formattted string |
| jmarkel44 | 0:61364762ee0e | 122 | // @param[out] none |
| jmarkel44 | 0:61364762ee0e | 123 | // @return none |
| jmarkel44 | 0:61364762ee0e | 124 | // |
| jmarkel44 | 0:61364762ee0e | 125 | void FailsafeControl::copyControlData(const char *buf) |
| jmarkel44 | 0:61364762ee0e | 126 | { |
| jmarkel44 | 0:61364762ee0e | 127 | cJSON *root = cJSON_Parse(buf); |
| jmarkel44 | 0:61364762ee0e | 128 | |
| jmarkel44 | 0:61364762ee0e | 129 | id = cJSON_GetObjectItem(root, "id")->valuestring; |
| jmarkel44 | 0:61364762ee0e | 130 | priority = atoi(cJSON_GetObjectItem(root, "priority")->valuestring); |
| jmarkel44 | 0:61364762ee0e | 131 | input = cJSON_GetObjectItem(root, "input")->valuestring; |
| jmarkel44 | 0:61364762ee0e | 132 | output = cJSON_GetObjectItem(root, "output")->valuestring; |
| jmarkel44 | 0:61364762ee0e | 133 | |
| jmarkel44 | 0:61364762ee0e | 134 | // high failsafe data |
| jmarkel44 | 0:61364762ee0e | 135 | hfs_data.value = atof(cJSON_GetObjectItem(root, "hfsValue")->valuestring); |
| jmarkel44 | 0:61364762ee0e | 136 | hfs_data.dutyCycle = atoi(cJSON_GetObjectItem(root, "hfsDutyCycle")->valuestring); |
| jmarkel44 | 0:61364762ee0e | 137 | hfs_data.interval = atoi(cJSON_GetObjectItem(root, "hfsInterval")->valuestring); |
| jmarkel44 | 0:61364762ee0e | 138 | |
| jmarkel44 | 0:61364762ee0e | 139 | // low failsafe data |
| jmarkel44 | 0:61364762ee0e | 140 | lfs_data.value = atof(cJSON_GetObjectItem(root, "lfsValue")->valuestring); |
| jmarkel44 | 0:61364762ee0e | 141 | lfs_data.dutyCycle = atoi(cJSON_GetObjectItem(root, "lfsDutyCycle")->valuestring); |
| jmarkel44 | 0:61364762ee0e | 142 | lfs_data.interval = atoi(cJSON_GetObjectItem(root, "lfsInterval")->valuestring); |
| jmarkel44 | 0:61364762ee0e | 143 | |
| jmarkel44 | 0:61364762ee0e | 144 | cJSON_Delete(root); |
| jmarkel44 | 0:61364762ee0e | 145 | } |
| jmarkel44 | 0:61364762ee0e | 146 | |
| jmarkel44 | 0:61364762ee0e | 147 | // |
| jmarkel44 | 0:61364762ee0e | 148 | // method: start |
| jmarkel44 | 0:61364762ee0e | 149 | // description: start the failsafe control |
| jmarkel44 | 0:61364762ee0e | 150 | // |
| jmarkel44 | 0:61364762ee0e | 151 | // @param none |
| jmarkel44 | 0:61364762ee0e | 152 | // @return none |
| jmarkel44 | 0:61364762ee0e | 153 | // |
| jmarkel44 | 0:61364762ee0e | 154 | void FailsafeControl::start(void) |
| jmarkel44 | 0:61364762ee0e | 155 | { |
| jmarkel44 | 0:61364762ee0e | 156 | currentState = STATE_START; |
| jmarkel44 | 0:61364762ee0e | 157 | } |
| jmarkel44 | 0:61364762ee0e | 158 | |
| jmarkel44 | 0:61364762ee0e | 159 | // |
| jmarkel44 | 0:61364762ee0e | 160 | // method: update |
| jmarkel44 | 0:61364762ee0e | 161 | // description: update the faisafe control using the FSM |
| jmarkel44 | 0:61364762ee0e | 162 | // |
| jmarkel44 | 0:61364762ee0e | 163 | // @param none |
| jmarkel44 | 0:61364762ee0e | 164 | // @return none |
| jmarkel44 | 0:61364762ee0e | 165 | // |
| jmarkel44 | 0:61364762ee0e | 166 | FailsafeControlError_t FailsafeControl::update(void) |
| jmarkel44 | 0:61364762ee0e | 167 | { |
| jmarkel44 | 0:61364762ee0e | 168 | FailsafeControlError_t rc = FAILSAFE_CONTROL_OK; |
| jmarkel44 | 0:61364762ee0e | 169 | |
| jmarkel44 | 0:61364762ee0e | 170 | switch (this->currentState) { |
| jmarkel44 | 0:61364762ee0e | 171 | case STATE_INIT: |
| jmarkel44 | 0:61364762ee0e | 172 | // do nothing - control must be programatically started |
| jmarkel44 | 0:61364762ee0e | 173 | break; |
| jmarkel44 | 0:61364762ee0e | 174 | case STATE_START: |
| jmarkel44 | 0:61364762ee0e | 175 | // control has programmatically started, do some checking |
| jmarkel44 | 0:61364762ee0e | 176 | if ( this->aboveHighFailsafe() ) { |
| jmarkel44 | 0:61364762ee0e | 177 | if ( hfs_data.dutyCycle) { |
| jmarkel44 | 0:61364762ee0e | 178 | debug("\r%s: [START]->above hfs->[ON_HFS]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 179 | // start high failsafe duty cycle |
| jmarkel44 | 0:61364762ee0e | 180 | this->currentState = STATE_CONTROL_ON_HFS; |
| jmarkel44 | 0:61364762ee0e | 181 | // turn the pump ON for the duty cycle, start the timer |
| jmarkel44 | 0:61364762ee0e | 182 | sendMailToOutput(ACTION_CONTROL_ON); |
| jmarkel44 | 0:61364762ee0e | 183 | this->startHfsDutyTimer(); |
| jmarkel44 | 0:61364762ee0e | 184 | } else { |
| jmarkel44 | 0:61364762ee0e | 185 | // no duty cycle specified, so go into the high-faisafe |
| jmarkel44 | 0:61364762ee0e | 186 | // fixed-off state |
| jmarkel44 | 0:61364762ee0e | 187 | debug("\r%s: [START]->above hfs && !dc->[OFF_HFS]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 188 | this->currentState = STATE_CONTROL_OFF_HFS; |
| jmarkel44 | 0:61364762ee0e | 189 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 0:61364762ee0e | 190 | // no need to start the duty timer |
| jmarkel44 | 0:61364762ee0e | 191 | } |
| jmarkel44 | 0:61364762ee0e | 192 | } else if ( this->belowLowFailsafe() ) { |
| jmarkel44 | 0:61364762ee0e | 193 | debug("\r%s: [START]->below lfs->[ON_LFS]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 194 | // start low failsafe duty cycle |
| jmarkel44 | 0:61364762ee0e | 195 | if ( lfs_data.dutyCycle ) { |
| jmarkel44 | 0:61364762ee0e | 196 | this->currentState = STATE_CONTROL_ON_LFS; |
| jmarkel44 | 0:61364762ee0e | 197 | // turn the pump ON for the duty cycle, start the timer |
| jmarkel44 | 0:61364762ee0e | 198 | sendMailToOutput(ACTION_CONTROL_ON); |
| jmarkel44 | 0:61364762ee0e | 199 | this->startLfsDutyTimer(); |
| jmarkel44 | 0:61364762ee0e | 200 | } else { |
| jmarkel44 | 0:61364762ee0e | 201 | // no duty cycle specified, so go into the low-failsafe |
| jmarkel44 | 0:61364762ee0e | 202 | // fixed off-state |
| jmarkel44 | 0:61364762ee0e | 203 | this->currentState = STATE_CONTROL_OFF_LFS; |
| jmarkel44 | 0:61364762ee0e | 204 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 0:61364762ee0e | 205 | // no need to start the timer |
| jmarkel44 | 0:61364762ee0e | 206 | } |
| jmarkel44 | 0:61364762ee0e | 207 | } else { |
| jmarkel44 | 0:61364762ee0e | 208 | debug("\r%s: [START]->no conditions->[OFF]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 209 | this->currentState = STATE_CONTROL_OFF; |
| jmarkel44 | 0:61364762ee0e | 210 | } |
| jmarkel44 | 0:61364762ee0e | 211 | break; |
| jmarkel44 | 0:61364762ee0e | 212 | case STATE_CONTROL_OFF: |
| jmarkel44 | 0:61364762ee0e | 213 | // control is acting normal, within bounds |
| jmarkel44 | 0:61364762ee0e | 214 | if ( this->aboveHighFailsafe() ) { |
| jmarkel44 | 0:61364762ee0e | 215 | if ( hfs_data.dutyCycle ) { |
| jmarkel44 | 0:61364762ee0e | 216 | debug("\r%s: [OFF]->above hfs->[ON HFS]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 217 | this->currentState = STATE_CONTROL_ON_HFS; |
| jmarkel44 | 0:61364762ee0e | 218 | sendMailToOutput(ACTION_CONTROL_ON); |
| jmarkel44 | 0:61364762ee0e | 219 | this->startHfsDutyTimer(); |
| jmarkel44 | 0:61364762ee0e | 220 | } else { |
| jmarkel44 | 0:61364762ee0e | 221 | debug("\r%s: [OFF]->above hfs && no dc->[OFF HFS]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 222 | this->currentState = STATE_CONTROL_OFF_HFS; |
| jmarkel44 | 0:61364762ee0e | 223 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 0:61364762ee0e | 224 | } |
| jmarkel44 | 0:61364762ee0e | 225 | } else if ( this->belowLowFailsafe() ) { |
| jmarkel44 | 0:61364762ee0e | 226 | // restart the low failsafe duty cycle |
| jmarkel44 | 0:61364762ee0e | 227 | debug("\r%s: [OFF]->below lfs->[ON_LFS]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 228 | if ( lfs_data.dutyCycle ) { |
| jmarkel44 | 0:61364762ee0e | 229 | this->currentState = STATE_CONTROL_ON_LFS; |
| jmarkel44 | 0:61364762ee0e | 230 | sendMailToOutput(ACTION_CONTROL_ON); |
| jmarkel44 | 0:61364762ee0e | 231 | this->startLfsDutyTimer(); |
| jmarkel44 | 0:61364762ee0e | 232 | } else { |
| jmarkel44 | 0:61364762ee0e | 233 | this->currentState = STATE_CONTROL_OFF_LFS; |
| jmarkel44 | 0:61364762ee0e | 234 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 0:61364762ee0e | 235 | } |
| jmarkel44 | 0:61364762ee0e | 236 | } else { |
| jmarkel44 | 0:61364762ee0e | 237 | // do nothing |
| jmarkel44 | 0:61364762ee0e | 238 | } |
| jmarkel44 | 0:61364762ee0e | 239 | break; |
| jmarkel44 | 0:61364762ee0e | 240 | case STATE_CONTROL_ON_LFS: |
| jmarkel44 | 0:61364762ee0e | 241 | // control is in low-failsafe with duty cycle ON |
| jmarkel44 | 0:61364762ee0e | 242 | if ( !this->belowLowFailsafe() ) { |
| jmarkel44 | 0:61364762ee0e | 243 | // input has fallen below the failsafe, so turn off the control |
| jmarkel44 | 0:61364762ee0e | 244 | debug("\r%s: [ON_LFS]->above lfs->[OFF]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 245 | this->currentState = STATE_CONTROL_OFF; |
| jmarkel44 | 0:61364762ee0e | 246 | this->unregisterControl(); |
| jmarkel44 | 0:61364762ee0e | 247 | } else if ( this->dutyOnExpired() ) { |
| jmarkel44 | 0:61364762ee0e | 248 | // duty ON has expired, so let's idle in the OFF-LFS state now |
| jmarkel44 | 0:61364762ee0e | 249 | debug("\r%s: [ON_LFS]->duty on expired->[OFF LFS]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 250 | this->currentState = STATE_CONTROL_OFF_LFS; |
| jmarkel44 | 0:61364762ee0e | 251 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 0:61364762ee0e | 252 | } else { |
| jmarkel44 | 0:61364762ee0e | 253 | // do nothing |
| jmarkel44 | 0:61364762ee0e | 254 | } |
| jmarkel44 | 0:61364762ee0e | 255 | break; |
| jmarkel44 | 0:61364762ee0e | 256 | case STATE_CONTROL_OFF_LFS: |
| jmarkel44 | 0:61364762ee0e | 257 | // control is in low-failsafe with duty cycle OFF |
| jmarkel44 | 0:61364762ee0e | 258 | if ( !this->belowLowFailsafe() ) { |
| jmarkel44 | 0:61364762ee0e | 259 | // no longer in dangerous waters, so transition to OFF |
| jmarkel44 | 0:61364762ee0e | 260 | debug("\r%s: [OFF_LFS]->above lfs->[OFF]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 261 | this->currentState = STATE_CONTROL_OFF; |
| jmarkel44 | 0:61364762ee0e | 262 | this->unregisterControl(); |
| jmarkel44 | 0:61364762ee0e | 263 | } else if ( this->dutyOffExpired() && lfs_data.dutyCycle ) { |
| jmarkel44 | 0:61364762ee0e | 264 | debug("\r%s: [OFF_LFS]->duty OFF exp->[ON_LFS]", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 265 | // turn the PUMP back on and restart the duty timer |
| jmarkel44 | 0:61364762ee0e | 266 | this->currentState = STATE_CONTROL_ON_LFS; |
| jmarkel44 | 0:61364762ee0e | 267 | sendMailToOutput(ACTION_CONTROL_ON); |
| jmarkel44 | 0:61364762ee0e | 268 | this->startLfsDutyTimer(); |
| jmarkel44 | 0:61364762ee0e | 269 | |
| jmarkel44 | 0:61364762ee0e | 270 | } else { |
| jmarkel44 | 0:61364762ee0e | 271 | // do nothing |
| jmarkel44 | 0:61364762ee0e | 272 | } |
| jmarkel44 | 0:61364762ee0e | 273 | break; |
| jmarkel44 | 0:61364762ee0e | 274 | case STATE_CONTROL_ON_HFS: |
| jmarkel44 | 0:61364762ee0e | 275 | // control is in high-failsafe with duty cycle ON |
| jmarkel44 | 0:61364762ee0e | 276 | if ( !this->aboveHighFailsafe() ) { |
| jmarkel44 | 0:61364762ee0e | 277 | debug("\r%s: [ON_HFS]->below hfs->[OFF]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 278 | this->currentState = STATE_CONTROL_OFF; |
| jmarkel44 | 0:61364762ee0e | 279 | this->unregisterControl(); |
| jmarkel44 | 0:61364762ee0e | 280 | } else if ( this->dutyOnExpired() ) { |
| jmarkel44 | 0:61364762ee0e | 281 | debug("\r%s: [ON_HFS]->duty ON expired->[OFF_HFS]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 282 | this->currentState = STATE_CONTROL_OFF_HFS; |
| jmarkel44 | 0:61364762ee0e | 283 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 0:61364762ee0e | 284 | } else { |
| jmarkel44 | 0:61364762ee0e | 285 | // do nothing |
| jmarkel44 | 0:61364762ee0e | 286 | } |
| jmarkel44 | 0:61364762ee0e | 287 | break; |
| jmarkel44 | 0:61364762ee0e | 288 | case STATE_CONTROL_OFF_HFS: |
| jmarkel44 | 0:61364762ee0e | 289 | // control is in high-failsafe with cuty cycle OFF |
| jmarkel44 | 0:61364762ee0e | 290 | if ( !this->aboveHighFailsafe() ) { |
| jmarkel44 | 0:61364762ee0e | 291 | debug("\r%s: [OFF_HFS]->below hfs->[OFF]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 292 | this->currentState = STATE_CONTROL_OFF; |
| jmarkel44 | 0:61364762ee0e | 293 | this->unregisterControl(); |
| jmarkel44 | 0:61364762ee0e | 294 | } else if ( this->dutyOffExpired() && hfs_data.dutyCycle ) { |
| jmarkel44 | 0:61364762ee0e | 295 | debug("\r%s: [OFF_HFS]->duty OFF expired->[ON_HFS]\n", id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 296 | this->currentState = STATE_CONTROL_ON_HFS; |
| jmarkel44 | 0:61364762ee0e | 297 | sendMailToOutput(ACTION_CONTROL_ON); |
| jmarkel44 | 0:61364762ee0e | 298 | this->startHfsDutyTimer(); |
| jmarkel44 | 0:61364762ee0e | 299 | } else { |
| jmarkel44 | 0:61364762ee0e | 300 | // do nothing |
| jmarkel44 | 0:61364762ee0e | 301 | } |
| jmarkel44 | 0:61364762ee0e | 302 | break; |
| jmarkel44 | 0:61364762ee0e | 303 | default: |
| jmarkel44 | 0:61364762ee0e | 304 | logError("%s: unknown state %d", __func__, this->currentState); |
| jmarkel44 | 0:61364762ee0e | 305 | rc = FAILSAFE_CONTROL_UNK_STATE; |
| jmarkel44 | 0:61364762ee0e | 306 | break; |
| jmarkel44 | 0:61364762ee0e | 307 | } |
| jmarkel44 | 0:61364762ee0e | 308 | return rc; |
| jmarkel44 | 0:61364762ee0e | 309 | } |
| jmarkel44 | 0:61364762ee0e | 310 | |
| jmarkel44 | 0:61364762ee0e | 311 | // |
| jmarkel44 | 0:61364762ee0e | 312 | // method: belowFailsafe |
| jmarkel44 | 0:61364762ee0e | 313 | // description: returns true if the input signal is below the |
| jmarkel44 | 0:61364762ee0e | 314 | // failsafe mark |
| jmarkel44 | 0:61364762ee0e | 315 | // |
| jmarkel44 | 0:61364762ee0e | 316 | // @param[in] none |
| jmarkel44 | 0:61364762ee0e | 317 | // @param[out] none |
| jmarkel44 | 0:61364762ee0e | 318 | // @return true if below; false otherwise |
| jmarkel44 | 0:61364762ee0e | 319 | // |
| jmarkel44 | 0:61364762ee0e | 320 | bool FailsafeControl::belowLowFailsafe(void) |
| jmarkel44 | 0:61364762ee0e | 321 | { |
| jmarkel44 | 0:61364762ee0e | 322 | // read the modbus input |
| jmarkel44 | 0:61364762ee0e | 323 | ModbusValue value; |
| jmarkel44 | 0:61364762ee0e | 324 | ModbusMasterReadRegister(input, &value); |
| jmarkel44 | 0:61364762ee0e | 325 | return ( value.value <= lfs_data.value ); |
| jmarkel44 | 0:61364762ee0e | 326 | } |
| jmarkel44 | 0:61364762ee0e | 327 | |
| jmarkel44 | 0:61364762ee0e | 328 | // |
| jmarkel44 | 0:61364762ee0e | 329 | // method: aboveHighFailsafe |
| jmarkel44 | 0:61364762ee0e | 330 | // description: returns true if the input signal is above the |
| jmarkel44 | 0:61364762ee0e | 331 | // failsafe mark |
| jmarkel44 | 0:61364762ee0e | 332 | // |
| jmarkel44 | 0:61364762ee0e | 333 | // @param[in] none |
| jmarkel44 | 0:61364762ee0e | 334 | // @param[out] none |
| jmarkel44 | 0:61364762ee0e | 335 | // @return true if above; false otherwise |
| jmarkel44 | 0:61364762ee0e | 336 | // |
| jmarkel44 | 0:61364762ee0e | 337 | bool FailsafeControl::aboveHighFailsafe(void) |
| jmarkel44 | 0:61364762ee0e | 338 | { |
| jmarkel44 | 0:61364762ee0e | 339 | // read the modbus input |
| jmarkel44 | 0:61364762ee0e | 340 | ModbusValue value; |
| jmarkel44 | 0:61364762ee0e | 341 | ModbusMasterReadRegister(input, &value); |
| jmarkel44 | 0:61364762ee0e | 342 | return ( value.value >= hfs_data.value ); |
| jmarkel44 | 0:61364762ee0e | 343 | } |
| jmarkel44 | 0:61364762ee0e | 344 | |
| jmarkel44 | 0:61364762ee0e | 345 | // |
| jmarkel44 | 0:61364762ee0e | 346 | // method: startHfsDutyTimer |
| jmarkel44 | 0:61364762ee0e | 347 | // description: start the high failsafe duty timer |
| jmarkel44 | 0:61364762ee0e | 348 | // |
| jmarkel44 | 0:61364762ee0e | 349 | // @param none |
| jmarkel44 | 0:61364762ee0e | 350 | // @return none |
| jmarkel44 | 0:61364762ee0e | 351 | // |
| jmarkel44 | 0:61364762ee0e | 352 | void FailsafeControl::startHfsDutyTimer(void) |
| jmarkel44 | 0:61364762ee0e | 353 | { |
| jmarkel44 | 0:61364762ee0e | 354 | unsigned long currentTime = time(NULL); |
| jmarkel44 | 0:61364762ee0e | 355 | unsigned long period = hfs_data.interval * 60; |
| jmarkel44 | 0:61364762ee0e | 356 | |
| jmarkel44 | 0:61364762ee0e | 357 | duty_timer.offTime = currentTime + ((double)period * ((double)hfs_data.dutyCycle/100.0)); |
| jmarkel44 | 0:61364762ee0e | 358 | duty_timer.expirationTime = currentTime + period; |
| jmarkel44 | 0:61364762ee0e | 359 | |
| jmarkel44 | 0:61364762ee0e | 360 | debug("\r%s:%s-> currentTime = %lu\n", __func__, id.c_str(), currentTime); |
| jmarkel44 | 0:61364762ee0e | 361 | debug("\r%s:%s-> off Time = %lu\n", __func__, id.c_str(), duty_timer.offTime); |
| jmarkel44 | 0:61364762ee0e | 362 | debug("\r%s:%s-> expiration = %lu\n", __func__, id.c_str(),duty_timer.expirationTime); |
| jmarkel44 | 0:61364762ee0e | 363 | } |
| jmarkel44 | 0:61364762ee0e | 364 | |
| jmarkel44 | 0:61364762ee0e | 365 | // |
| jmarkel44 | 0:61364762ee0e | 366 | // method: stopHfsDutyTimer |
| jmarkel44 | 0:61364762ee0e | 367 | // description: stop the high failsafe duty timer |
| jmarkel44 | 0:61364762ee0e | 368 | // |
| jmarkel44 | 0:61364762ee0e | 369 | // @param [in] none |
| jmarkel44 | 0:61364762ee0e | 370 | // @param[out] none |
| jmarkel44 | 0:61364762ee0e | 371 | // @return none |
| jmarkel44 | 0:61364762ee0e | 372 | // |
| jmarkel44 | 0:61364762ee0e | 373 | void FailsafeControl::stopHfsDutyTimer(void) |
| jmarkel44 | 0:61364762ee0e | 374 | { |
| jmarkel44 | 0:61364762ee0e | 375 | debug("\r%sL%s-> invoked\n", __func__, id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 376 | memset(&duty_timer, 0, sizeof(duty_timer)); |
| jmarkel44 | 0:61364762ee0e | 377 | } |
| jmarkel44 | 0:61364762ee0e | 378 | |
| jmarkel44 | 0:61364762ee0e | 379 | // |
| jmarkel44 | 0:61364762ee0e | 380 | // method: startLfsDutyTimer |
| jmarkel44 | 0:61364762ee0e | 381 | // descrption: start the low failsafe duty-timer |
| jmarkel44 | 0:61364762ee0e | 382 | // |
| jmarkel44 | 0:61364762ee0e | 383 | // @param[in] none |
| jmarkel44 | 0:61364762ee0e | 384 | // @param[out] none |
| jmarkel44 | 0:61364762ee0e | 385 | // @return none |
| jmarkel44 | 0:61364762ee0e | 386 | // |
| jmarkel44 | 0:61364762ee0e | 387 | void FailsafeControl::startLfsDutyTimer(void) |
| jmarkel44 | 0:61364762ee0e | 388 | { |
| jmarkel44 | 0:61364762ee0e | 389 | unsigned long currentTime = time(NULL); |
| jmarkel44 | 0:61364762ee0e | 390 | unsigned long period = lfs_data.interval * 60; |
| jmarkel44 | 0:61364762ee0e | 391 | |
| jmarkel44 | 0:61364762ee0e | 392 | duty_timer.offTime = currentTime + ((double)period * ((double)lfs_data.dutyCycle/100.0)); |
| jmarkel44 | 0:61364762ee0e | 393 | duty_timer.expirationTime = currentTime + period; |
| jmarkel44 | 0:61364762ee0e | 394 | |
| jmarkel44 | 0:61364762ee0e | 395 | debug("\r%s:%s-> next off time = %lu\n", __func__, id.c_str(), duty_timer.offTime); |
| jmarkel44 | 0:61364762ee0e | 396 | debug("\r%s:%s->expiration time = %lu\n", __func__, id.c_str(), duty_timer.expirationTime); |
| jmarkel44 | 0:61364762ee0e | 397 | } |
| jmarkel44 | 0:61364762ee0e | 398 | |
| jmarkel44 | 0:61364762ee0e | 399 | // |
| jmarkel44 | 0:61364762ee0e | 400 | // method: stopLfsDutyTimer |
| jmarkel44 | 0:61364762ee0e | 401 | // description: stop the low failsafe duty-timer |
| jmarkel44 | 0:61364762ee0e | 402 | // |
| jmarkel44 | 0:61364762ee0e | 403 | // @param none |
| jmarkel44 | 0:61364762ee0e | 404 | // @return none |
| jmarkel44 | 0:61364762ee0e | 405 | // |
| jmarkel44 | 0:61364762ee0e | 406 | void FailsafeControl::stopLfsDutyTimer(void) |
| jmarkel44 | 0:61364762ee0e | 407 | { |
| jmarkel44 | 0:61364762ee0e | 408 | debug("\r%s:5s-> invoked\n", __func__, id.c_str()); |
| jmarkel44 | 0:61364762ee0e | 409 | memset(&duty_timer, 0, sizeof(duty_timer)); |
| jmarkel44 | 0:61364762ee0e | 410 | } |
| jmarkel44 | 0:61364762ee0e | 411 | |
| jmarkel44 | 0:61364762ee0e | 412 | // |
| jmarkel44 | 0:61364762ee0e | 413 | // method: dutyOnExpired |
| jmarkel44 | 0:61364762ee0e | 414 | // description: returns true if ON cycle has expired; false otherwise |
| jmarkel44 | 0:61364762ee0e | 415 | // |
| jmarkel44 | 0:61364762ee0e | 416 | // @param none |
| jmarkel44 | 0:61364762ee0e | 417 | // @return none |
| jmarkel44 | 0:61364762ee0e | 418 | // |
| jmarkel44 | 0:61364762ee0e | 419 | bool FailsafeControl::dutyOnExpired(void) |
| jmarkel44 | 0:61364762ee0e | 420 | { |
| jmarkel44 | 0:61364762ee0e | 421 | return (time(0) >= duty_timer.offTime); |
| jmarkel44 | 0:61364762ee0e | 422 | } |
| jmarkel44 | 0:61364762ee0e | 423 | |
| jmarkel44 | 0:61364762ee0e | 424 | // |
| jmarkel44 | 0:61364762ee0e | 425 | // method: dutyOffExpired |
| jmarkel44 | 0:61364762ee0e | 426 | // description: returns true if OFF cycle has expired; false otherwise |
| jmarkel44 | 0:61364762ee0e | 427 | // |
| jmarkel44 | 0:61364762ee0e | 428 | // @param none |
| jmarkel44 | 0:61364762ee0e | 429 | // @return none |
| jmarkel44 | 0:61364762ee0e | 430 | // |
| jmarkel44 | 0:61364762ee0e | 431 | bool FailsafeControl::dutyOffExpired(void) |
| jmarkel44 | 0:61364762ee0e | 432 | { |
| jmarkel44 | 0:61364762ee0e | 433 | return (duty_timer.expirationTime < time(NULL)); |
| jmarkel44 | 0:61364762ee0e | 434 | } |
| jmarkel44 | 0:61364762ee0e | 435 | |
| jmarkel44 | 0:61364762ee0e | 436 | // |
| jmarkel44 | 0:61364762ee0e | 437 | // method: sendMailToOutput |
| jmarkel44 | 0:61364762ee0e | 438 | // description: send mail to the output task |
| jmarkel44 | 0:61364762ee0e | 439 | // |
| jmarkel44 | 0:61364762ee0e | 440 | // @param io_tag -> input/output tag |
| jmarkel44 | 0:61364762ee0e | 441 | // @param action -> ON, OFF, UNREGISTER |
| jmarkel44 | 0:61364762ee0e | 442 | // @return none |
| jmarkel44 | 0:61364762ee0e | 443 | // |
| jmarkel44 | 0:61364762ee0e | 444 | void FailsafeControl::sendMailToOutput(OutputAction action) |
| jmarkel44 | 0:61364762ee0e | 445 | { |
| jmarkel44 | 0:61364762ee0e | 446 | logInfo("%s: failsafe control %s attempting to send action %d\n", |
| jmarkel44 | 0:61364762ee0e | 447 | __func__, id.c_str(), action); |
| jmarkel44 | 0:61364762ee0e | 448 | |
| jmarkel44 | 0:61364762ee0e | 449 | if ( isVirtualOutput ) { |
| jmarkel44 | 0:61364762ee0e | 450 | debug("%s:%s-> updating the virtual output %s\n", __func__, id.c_str(), output.c_str()); |
| jmarkel44 | 0:61364762ee0e | 451 | ModbusMasterWriteRegister(this->output, |
| jmarkel44 | 0:61364762ee0e | 452 | (action == ACTION_CONTROL_ON) ? 1.0 : 0.0); |
| jmarkel44 | 0:61364762ee0e | 453 | } else { |
| jmarkel44 | 0:61364762ee0e | 454 | OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); |
| jmarkel44 | 0:61364762ee0e | 455 | memset(output_mail, 0, sizeof(OutputControlMsg_t)); |
| jmarkel44 | 0:61364762ee0e | 456 | |
| jmarkel44 | 0:61364762ee0e | 457 | output_mail->action = action; |
| jmarkel44 | 0:61364762ee0e | 458 | output_mail->controlType = CONTROL_FAILSAFE; |
| jmarkel44 | 0:61364762ee0e | 459 | output_mail->priority = this->priority; |
| jmarkel44 | 0:61364762ee0e | 460 | |
| jmarkel44 | 0:61364762ee0e | 461 | strncpy(output_mail->input_tag, this->input.c_str(), sizeof(output_mail->input_tag)-1); |
| jmarkel44 | 0:61364762ee0e | 462 | strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); |
| jmarkel44 | 0:61364762ee0e | 463 | strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); |
| jmarkel44 | 0:61364762ee0e | 464 | |
| jmarkel44 | 0:61364762ee0e | 465 | OutputMasterMailBox.put(output_mail); |
| jmarkel44 | 0:61364762ee0e | 466 | } |
| jmarkel44 | 0:61364762ee0e | 467 | } |
| jmarkel44 | 0:61364762ee0e | 468 | |
| jmarkel44 | 0:61364762ee0e | 469 | |
| jmarkel44 | 0:61364762ee0e | 470 | // |
| jmarkel44 | 0:61364762ee0e | 471 | // method: unregisterControl |
| jmarkel44 | 0:61364762ee0e | 472 | // description: unregister this control with the output task |
| jmarkel44 | 0:61364762ee0e | 473 | // |
| jmarkel44 | 0:61364762ee0e | 474 | // @param none |
| jmarkel44 | 0:61364762ee0e | 475 | // @return none |
| jmarkel44 | 0:61364762ee0e | 476 | // |
| jmarkel44 | 0:61364762ee0e | 477 | void FailsafeControl::unregisterControl(void) |
| jmarkel44 | 0:61364762ee0e | 478 | { |
| jmarkel44 | 0:61364762ee0e | 479 | logInfo("%s: %s attempting to unregister %s\n", |
| jmarkel44 | 0:61364762ee0e | 480 | __func__, id.c_str(), controlFile.c_str()); |
| jmarkel44 | 0:61364762ee0e | 481 | |
| jmarkel44 | 0:61364762ee0e | 482 | if ( isVirtualOutput ) { |
| jmarkel44 | 0:61364762ee0e | 483 | debug("%s: %s attempting to unregister virtual output %s\n", |
| jmarkel44 | 0:61364762ee0e | 484 | __func__, id.c_str(), output.c_str()); |
| jmarkel44 | 0:61364762ee0e | 485 | ModbusMasterWriteRegister(output, 0.0); |
| jmarkel44 | 0:61364762ee0e | 486 | } else { |
| jmarkel44 | 0:61364762ee0e | 487 | OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); |
| jmarkel44 | 0:61364762ee0e | 488 | memset(output_mail, 0, sizeof(OutputControlMsg_t)); |
| jmarkel44 | 0:61364762ee0e | 489 | |
| jmarkel44 | 0:61364762ee0e | 490 | output_mail->action = ACTION_CONTROL_UNREGISTER; |
| jmarkel44 | 0:61364762ee0e | 491 | output_mail->controlType = CONTROL_FAILSAFE; |
| jmarkel44 | 0:61364762ee0e | 492 | output_mail->priority = this->priority; |
| jmarkel44 | 0:61364762ee0e | 493 | strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); |
| jmarkel44 | 0:61364762ee0e | 494 | strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); |
| jmarkel44 | 0:61364762ee0e | 495 | |
| jmarkel44 | 0:61364762ee0e | 496 | OutputMasterMailBox.put(output_mail); |
| jmarkel44 | 0:61364762ee0e | 497 | } |
| jmarkel44 | 0:61364762ee0e | 498 | } |
| jmarkel44 | 0:61364762ee0e | 499 | |
| jmarkel44 | 0:61364762ee0e | 500 | // |
| jmarkel44 | 0:61364762ee0e | 501 | // method: display |
| jmarkel44 | 0:61364762ee0e | 502 | // description: display the pertinents |
| jmarkel44 | 0:61364762ee0e | 503 | // |
| jmarkel44 | 0:61364762ee0e | 504 | // @param none |
| jmarkel44 | 0:61364762ee0e | 505 | // @return none |
| jmarkel44 | 0:61364762ee0e | 506 | // |
| jmarkel44 | 0:61364762ee0e | 507 | void FailsafeControl::display(void) |
| jmarkel44 | 0:61364762ee0e | 508 | { |
| jmarkel44 | 0:61364762ee0e | 509 | const char *mapper[] = { "INIT", |
| jmarkel44 | 0:61364762ee0e | 510 | "START", |
| jmarkel44 | 0:61364762ee0e | 511 | "OFF", |
| jmarkel44 | 0:61364762ee0e | 512 | "ON_LFS", |
| jmarkel44 | 0:61364762ee0e | 513 | "OFF_LFS", |
| jmarkel44 | 0:61364762ee0e | 514 | "ON_HFS", |
| jmarkel44 | 0:61364762ee0e | 515 | "OFF_HFS", |
| jmarkel44 | 0:61364762ee0e | 516 | "SENSOR_ERR", |
| jmarkel44 | 0:61364762ee0e | 517 | "invalid" |
| jmarkel44 | 0:61364762ee0e | 518 | }; |
| jmarkel44 | 0:61364762ee0e | 519 | |
| jmarkel44 | 0:61364762ee0e | 520 | printf("\r\n"); |
| jmarkel44 | 0:61364762ee0e | 521 | std::cout << left << setw(10) << setfill(' ') << "failsafe: "; |
| jmarkel44 | 0:61364762ee0e | 522 | std::cout << left << setw(40) << setfill(' ') << controlFile; |
| jmarkel44 | 0:61364762ee0e | 523 | std::cout << left << setw(20) << setfill(' ') << id; |
| jmarkel44 | 0:61364762ee0e | 524 | std::cout << left << setw(6) << setfill(' ') << priority; |
| jmarkel44 | 0:61364762ee0e | 525 | std::cout << left << setw(20) << setfill(' ') << input; |
| jmarkel44 | 0:61364762ee0e | 526 | std::cout << left << setw(20) << setfill(' ') << output; |
| jmarkel44 | 0:61364762ee0e | 527 | std::cout << left << setw(16) << setfill(' ') << mapper[currentState]; |
| jmarkel44 | 0:61364762ee0e | 528 | std::cout << left << setw(12) << setfill(' ') << "lfs-> " |
| jmarkel44 | 0:61364762ee0e | 529 | << lfs_data.value << ":" << lfs_data.dutyCycle << ":" << lfs_data.interval; |
| jmarkel44 | 0:61364762ee0e | 530 | std::cout << right << setw(12) << setfill(' ') << "hfs-> " |
| jmarkel44 | 0:61364762ee0e | 531 | << hfs_data.value << ":" << hfs_data.dutyCycle << ":" << hfs_data.interval; |
| jmarkel44 | 0:61364762ee0e | 532 | |
| jmarkel44 | 0:61364762ee0e | 533 | std::cout.flush(); |
| jmarkel44 | 0:61364762ee0e | 534 | } |