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@284:cc72206ea8e0, 2016-10-28 (annotated)
- Committer:
- jinu
- Date:
- Fri Oct 28 18:44:12 2016 +0000
- Revision:
- 284:cc72206ea8e0
- Parent:
- 276:851554207c77
modified for live data testing
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| jmarkel44 | 250:1cd8ec63e9e9 | 1 | /****************************************************************************** |
| jmarkel44 | 250:1cd8ec63e9e9 | 2 | * |
| jmarkel44 | 250:1cd8ec63e9e9 | 3 | * File: CompositeControl.cpp |
| jmarkel44 | 250:1cd8ec63e9e9 | 4 | * Desciption: ICE Composite Control Class implementation |
| jmarkel44 | 250:1cd8ec63e9e9 | 5 | * |
| jmarkel44 | 250:1cd8ec63e9e9 | 6 | *****************************************************************************/ |
| jmarkel44 | 250:1cd8ec63e9e9 | 7 | #include "FailsafeControl.h" |
| jmarkel44 | 250:1cd8ec63e9e9 | 8 | #include "cJSON.h" |
| jmarkel44 | 250:1cd8ec63e9e9 | 9 | #include "mDot.h" |
| jmarkel44 | 250:1cd8ec63e9e9 | 10 | #include "global.h" |
| jmarkel44 | 252:3c9863f951b7 | 11 | #include "ModbusMasterApi.h" |
| jmarkel44 | 250:1cd8ec63e9e9 | 12 | #include <string> |
| jmarkel44 | 250:1cd8ec63e9e9 | 13 | #include <iostream> |
| jmarkel44 | 250:1cd8ec63e9e9 | 14 | #include <iomanip> |
| jmarkel44 | 250:1cd8ec63e9e9 | 15 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 16 | extern mDot *GLOBAL_mdot; |
| jmarkel44 | 250:1cd8ec63e9e9 | 17 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 18 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 19 | // method: load |
| jmarkel44 | 250:1cd8ec63e9e9 | 20 | // description: load a composite control |
| jmarkel44 | 250:1cd8ec63e9e9 | 21 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 22 | // @param none |
| jmarkel44 | 250:1cd8ec63e9e9 | 23 | // @return none |
| jmarkel44 | 250:1cd8ec63e9e9 | 24 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 25 | bool FailsafeControl::load(std::string _controlFile) |
| jmarkel44 | 250:1cd8ec63e9e9 | 26 | { |
| jmarkel44 | 250:1cd8ec63e9e9 | 27 | controlFile = _controlFile; |
| jmarkel44 | 250:1cd8ec63e9e9 | 28 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 29 | // open and read from the control file |
| jmarkel44 | 250:1cd8ec63e9e9 | 30 | mDot::mdot_file file = GLOBAL_mdot->openUserFile(controlFile.c_str(), mDot::FM_RDONLY); |
| jmarkel44 | 250:1cd8ec63e9e9 | 31 | if ( file.fd < 0 ) { |
| jmarkel44 | 250:1cd8ec63e9e9 | 32 | logError("%s: failed to open %s\n", __func__, controlFile.c_str()); |
| jmarkel44 | 250:1cd8ec63e9e9 | 33 | return false; |
| jmarkel44 | 250:1cd8ec63e9e9 | 34 | } |
| jmarkel44 | 250:1cd8ec63e9e9 | 35 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 36 | // read the data into a buffer |
| jmarkel44 | 250:1cd8ec63e9e9 | 37 | char dataBuf[MAX_FILE_SIZE]; |
| jmarkel44 | 250:1cd8ec63e9e9 | 38 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 39 | int bytes_read = GLOBAL_mdot->readUserFile(file, (void *)dataBuf, sizeof(dataBuf)); |
| jmarkel44 | 250:1cd8ec63e9e9 | 40 | if ( bytes_read != sizeof(dataBuf) ) { |
| jmarkel44 | 250:1cd8ec63e9e9 | 41 | logError("%s: failed to read %d bytes from %s", __func__, sizeof(dataBuf), controlFile.c_str()); |
| jmarkel44 | 250:1cd8ec63e9e9 | 42 | // caller should destroy the object |
| jmarkel44 | 250:1cd8ec63e9e9 | 43 | return false; |
| jmarkel44 | 250:1cd8ec63e9e9 | 44 | } |
| jmarkel44 | 250:1cd8ec63e9e9 | 45 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 46 | // close the file |
| jmarkel44 | 250:1cd8ec63e9e9 | 47 | GLOBAL_mdot->closeUserFile(file); |
| jmarkel44 | 250:1cd8ec63e9e9 | 48 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 49 | // parse the data |
| jmarkel44 | 250:1cd8ec63e9e9 | 50 | cJSON * root = cJSON_Parse(dataBuf); |
| jmarkel44 | 250:1cd8ec63e9e9 | 51 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 52 | id = cJSON_GetObjectItem(root, "id")->valuestring; |
| jmarkel44 | 250:1cd8ec63e9e9 | 53 | priority = atoi(cJSON_GetObjectItem(root, "priority")->valuestring); |
| jmarkel44 | 250:1cd8ec63e9e9 | 54 | input = cJSON_GetObjectItem(root, "input")->valuestring; |
| jmarkel44 | 250:1cd8ec63e9e9 | 55 | output = cJSON_GetObjectItem(root, "output")->valuestring; |
| jmarkel44 | 250:1cd8ec63e9e9 | 56 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 57 | hfs_data.value = atof(cJSON_GetObjectItem(root, "hfsValue")->valuestring); |
| jmarkel44 | 250:1cd8ec63e9e9 | 58 | hfs_data.dutyCycle = atoi(cJSON_GetObjectItem(root, "hfsDutyCycle")->valuestring); |
| jmarkel44 | 250:1cd8ec63e9e9 | 59 | hfs_data.interval = atoi(cJSON_GetObjectItem(root, "hfsInterval")->valuestring); |
| jmarkel44 | 250:1cd8ec63e9e9 | 60 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 61 | lfs_data.value = atof(cJSON_GetObjectItem(root, "lfsValue")->valuestring); |
| jmarkel44 | 250:1cd8ec63e9e9 | 62 | lfs_data.dutyCycle = atoi(cJSON_GetObjectItem(root, "lfsDutyCycle")->valuestring); |
| jmarkel44 | 250:1cd8ec63e9e9 | 63 | lfs_data.interval = atoi(cJSON_GetObjectItem(root, "lfsInterval")->valuestring); |
| jmarkel44 | 276:851554207c77 | 64 | |
| jmarkel44 | 276:851554207c77 | 65 | cJSON_Delete(root); |
| jmarkel44 | 250:1cd8ec63e9e9 | 66 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 67 | return true; |
| jmarkel44 | 250:1cd8ec63e9e9 | 68 | } |
| jmarkel44 | 250:1cd8ec63e9e9 | 69 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 70 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 71 | // method: start |
| jmarkel44 | 250:1cd8ec63e9e9 | 72 | // description: start the failsafe control |
| jmarkel44 | 250:1cd8ec63e9e9 | 73 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 74 | // @param none |
| jmarkel44 | 250:1cd8ec63e9e9 | 75 | // @return none |
| jmarkel44 | 250:1cd8ec63e9e9 | 76 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 77 | void FailsafeControl::start(void) |
| jmarkel44 | 250:1cd8ec63e9e9 | 78 | { |
| jmarkel44 | 250:1cd8ec63e9e9 | 79 | currentState = STATE_START; |
| jmarkel44 | 250:1cd8ec63e9e9 | 80 | } |
| jmarkel44 | 250:1cd8ec63e9e9 | 81 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 82 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 83 | // method: update |
| jmarkel44 | 252:3c9863f951b7 | 84 | // description: update the faisafe control using the FSM |
| jmarkel44 | 250:1cd8ec63e9e9 | 85 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 86 | // @param none |
| jmarkel44 | 250:1cd8ec63e9e9 | 87 | // @return none |
| jmarkel44 | 250:1cd8ec63e9e9 | 88 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 89 | void FailsafeControl::update(void) |
| jmarkel44 | 250:1cd8ec63e9e9 | 90 | { |
| jmarkel44 | 260:fe726583ba1d | 91 | switch (this->currentState) { |
| jmarkel44 | 250:1cd8ec63e9e9 | 92 | case STATE_INIT: |
| jmarkel44 | 261:4e9a588c938e | 93 | // do nothing - control must be started |
| jmarkel44 | 250:1cd8ec63e9e9 | 94 | break; |
| jmarkel44 | 250:1cd8ec63e9e9 | 95 | case STATE_START: |
| jmarkel44 | 260:fe726583ba1d | 96 | // control has been started, do some checking |
| jmarkel44 | 269:97243a7f56ba | 97 | if ( this->sensorError() ) { |
| jmarkel44 | 269:97243a7f56ba | 98 | this->currentState = STATE_CONTROL_SENSOR_ERROR; |
| jmarkel44 | 269:97243a7f56ba | 99 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 269:97243a7f56ba | 100 | } else if ( this->aboveHighFailsafe() ) { |
| jmarkel44 | 262:696cd48bb04a | 101 | // start high failsafe duty cycle |
| jmarkel44 | 269:97243a7f56ba | 102 | this->currentState = STATE_CONTROL_ON_HFS; |
| jmarkel44 | 262:696cd48bb04a | 103 | sendMailToOutput(ACTION_CONTROL_ON); |
| jmarkel44 | 261:4e9a588c938e | 104 | this->startHfsDutyTimer(); |
| jmarkel44 | 262:696cd48bb04a | 105 | } else if ( this->belowLowFailsafe() ) { |
| jmarkel44 | 262:696cd48bb04a | 106 | // start low failsafe duty cycle |
| jmarkel44 | 269:97243a7f56ba | 107 | this->currentState = STATE_CONTROL_ON_LFS; |
| jmarkel44 | 262:696cd48bb04a | 108 | sendMailToOutput(ACTION_CONTROL_ON); |
| jmarkel44 | 262:696cd48bb04a | 109 | this->startLfsDutyTimer(); |
| jmarkel44 | 262:696cd48bb04a | 110 | } else { |
| jmarkel44 | 260:fe726583ba1d | 111 | this->currentState = STATE_CONTROL_OFF; |
| jmarkel44 | 252:3c9863f951b7 | 112 | } |
| jmarkel44 | 252:3c9863f951b7 | 113 | break; |
| jmarkel44 | 250:1cd8ec63e9e9 | 114 | case STATE_CONTROL_OFF: |
| jmarkel44 | 260:fe726583ba1d | 115 | // control is acting normal, within bounds |
| jmarkel44 | 269:97243a7f56ba | 116 | if ( this->sensorError() ) { |
| jmarkel44 | 269:97243a7f56ba | 117 | this->currentState = STATE_CONTROL_SENSOR_ERROR; |
| jmarkel44 | 269:97243a7f56ba | 118 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 269:97243a7f56ba | 119 | } else if ( this->aboveHighFailsafe() ) { |
| jmarkel44 | 262:696cd48bb04a | 120 | // restart the high failsafe duty cycle |
| jmarkel44 | 269:97243a7f56ba | 121 | this->currentState = STATE_CONTROL_ON_HFS; |
| jmarkel44 | 262:696cd48bb04a | 122 | sendMailToOutput(ACTION_CONTROL_ON); |
| jmarkel44 | 262:696cd48bb04a | 123 | this->startHfsDutyTimer(); |
| jmarkel44 | 252:3c9863f951b7 | 124 | } else if ( this->belowLowFailsafe() ) { |
| jmarkel44 | 262:696cd48bb04a | 125 | // restart the low failsafe duty cycle |
| jmarkel44 | 269:97243a7f56ba | 126 | this->currentState = STATE_CONTROL_ON_LFS; |
| jmarkel44 | 262:696cd48bb04a | 127 | sendMailToOutput(ACTION_CONTROL_ON); |
| jmarkel44 | 262:696cd48bb04a | 128 | this->startLfsDutyTimer(); |
| jmarkel44 | 252:3c9863f951b7 | 129 | } else { |
| jmarkel44 | 252:3c9863f951b7 | 130 | // do nothing |
| jmarkel44 | 252:3c9863f951b7 | 131 | } |
| jmarkel44 | 252:3c9863f951b7 | 132 | break; |
| jmarkel44 | 269:97243a7f56ba | 133 | case STATE_CONTROL_ON_LFS: |
| jmarkel44 | 260:fe726583ba1d | 134 | // control is in low-failsafe with duty cycle ON |
| jmarkel44 | 269:97243a7f56ba | 135 | if ( this->sensorError() ) { |
| jmarkel44 | 269:97243a7f56ba | 136 | this->currentState = STATE_CONTROL_SENSOR_ERROR; |
| jmarkel44 | 269:97243a7f56ba | 137 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 269:97243a7f56ba | 138 | } else if ( !this->belowLowFailsafe() ) { |
| jmarkel44 | 260:fe726583ba1d | 139 | this->currentState = STATE_CONTROL_OFF; |
| jmarkel44 | 262:696cd48bb04a | 140 | this->unregisterControl(); |
| jmarkel44 | 260:fe726583ba1d | 141 | } else if ( this->dutyOnExpired() ) { |
| jmarkel44 | 269:97243a7f56ba | 142 | this->currentState = STATE_CONTROL_OFF_LFS; |
| jmarkel44 | 262:696cd48bb04a | 143 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 252:3c9863f951b7 | 144 | } else { |
| jmarkel44 | 260:fe726583ba1d | 145 | // do nothing |
| jmarkel44 | 252:3c9863f951b7 | 146 | } |
| jmarkel44 | 252:3c9863f951b7 | 147 | break; |
| jmarkel44 | 269:97243a7f56ba | 148 | case STATE_CONTROL_OFF_LFS: |
| jmarkel44 | 260:fe726583ba1d | 149 | // control is in low-failsafe with duty cycle OFF |
| jmarkel44 | 269:97243a7f56ba | 150 | if ( this->sensorError() ) { |
| jmarkel44 | 269:97243a7f56ba | 151 | this->currentState = STATE_CONTROL_SENSOR_ERROR; |
| jmarkel44 | 269:97243a7f56ba | 152 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 269:97243a7f56ba | 153 | } else if ( !this->belowLowFailsafe() ) { |
| jmarkel44 | 260:fe726583ba1d | 154 | this->currentState = STATE_CONTROL_OFF; |
| jmarkel44 | 262:696cd48bb04a | 155 | this->unregisterControl(); |
| jmarkel44 | 260:fe726583ba1d | 156 | } else if ( this->dutyOffExpired() ) { |
| jmarkel44 | 269:97243a7f56ba | 157 | this->currentState = STATE_CONTROL_ON_LFS; |
| jmarkel44 | 262:696cd48bb04a | 158 | this->startLfsDutyTimer(); |
| jmarkel44 | 252:3c9863f951b7 | 159 | } else { |
| jmarkel44 | 260:fe726583ba1d | 160 | // do nothing |
| jmarkel44 | 252:3c9863f951b7 | 161 | } |
| jmarkel44 | 252:3c9863f951b7 | 162 | break; |
| jmarkel44 | 269:97243a7f56ba | 163 | case STATE_CONTROL_ON_HFS: |
| jmarkel44 | 260:fe726583ba1d | 164 | // control is in high-failsafe with duty cycle ON |
| jmarkel44 | 269:97243a7f56ba | 165 | if ( this->sensorError() ) { |
| jmarkel44 | 269:97243a7f56ba | 166 | this->currentState = STATE_CONTROL_SENSOR_ERROR; |
| jmarkel44 | 269:97243a7f56ba | 167 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 269:97243a7f56ba | 168 | } else if ( !this->aboveHighFailsafe() ) { |
| jmarkel44 | 260:fe726583ba1d | 169 | this->currentState = STATE_CONTROL_OFF; |
| jmarkel44 | 262:696cd48bb04a | 170 | this->unregisterControl(); |
| jmarkel44 | 260:fe726583ba1d | 171 | } else if ( this->dutyOnExpired() ) { |
| jmarkel44 | 269:97243a7f56ba | 172 | this->currentState = STATE_CONTROL_OFF_HFS; |
| jmarkel44 | 262:696cd48bb04a | 173 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 260:fe726583ba1d | 174 | } else { |
| jmarkel44 | 260:fe726583ba1d | 175 | // do nothing |
| jmarkel44 | 252:3c9863f951b7 | 176 | } |
| jmarkel44 | 252:3c9863f951b7 | 177 | break; |
| jmarkel44 | 269:97243a7f56ba | 178 | case STATE_CONTROL_OFF_HFS: |
| jmarkel44 | 260:fe726583ba1d | 179 | // control is in high-failsafe with cuty cycle OFF |
| jmarkel44 | 269:97243a7f56ba | 180 | if ( this->sensorError() ) { |
| jmarkel44 | 269:97243a7f56ba | 181 | this->currentState = STATE_CONTROL_SENSOR_ERROR; |
| jmarkel44 | 269:97243a7f56ba | 182 | sendMailToOutput(ACTION_CONTROL_OFF); |
| jmarkel44 | 269:97243a7f56ba | 183 | } else if ( !this->aboveHighFailsafe() ) { |
| jmarkel44 | 260:fe726583ba1d | 184 | this->currentState = STATE_CONTROL_OFF; |
| jmarkel44 | 262:696cd48bb04a | 185 | this->unregisterControl(); |
| jmarkel44 | 260:fe726583ba1d | 186 | } else if ( this->dutyOffExpired() ) { |
| jmarkel44 | 269:97243a7f56ba | 187 | this->currentState = STATE_CONTROL_ON_LFS; |
| jmarkel44 | 262:696cd48bb04a | 188 | sendMailToOutput(ACTION_CONTROL_ON); |
| jmarkel44 | 262:696cd48bb04a | 189 | this->startLfsDutyTimer(); |
| jmarkel44 | 261:4e9a588c938e | 190 | } else { |
| jmarkel44 | 260:fe726583ba1d | 191 | // do nothing |
| jmarkel44 | 252:3c9863f951b7 | 192 | } |
| jmarkel44 | 252:3c9863f951b7 | 193 | break; |
| jmarkel44 | 269:97243a7f56ba | 194 | case STATE_CONTROL_SENSOR_ERROR: |
| jmarkel44 | 269:97243a7f56ba | 195 | if ( !this->sensorError() ) { |
| jmarkel44 | 269:97243a7f56ba | 196 | this->currentState = STATE_CONTROL_OFF; |
| jmarkel44 | 273:0373b2a15f8a | 197 | this->unregisterControl(); |
| jmarkel44 | 269:97243a7f56ba | 198 | } else { |
| jmarkel44 | 269:97243a7f56ba | 199 | // do nothing |
| jmarkel44 | 269:97243a7f56ba | 200 | } |
| jmarkel44 | 269:97243a7f56ba | 201 | break; |
| jmarkel44 | 250:1cd8ec63e9e9 | 202 | default: |
| jmarkel44 | 250:1cd8ec63e9e9 | 203 | break; |
| jmarkel44 | 250:1cd8ec63e9e9 | 204 | } |
| jmarkel44 | 250:1cd8ec63e9e9 | 205 | } |
| jmarkel44 | 250:1cd8ec63e9e9 | 206 | |
| jmarkel44 | 252:3c9863f951b7 | 207 | bool FailsafeControl::belowLowFailsafe(void) |
| jmarkel44 | 252:3c9863f951b7 | 208 | { |
| jmarkel44 | 252:3c9863f951b7 | 209 | // read the modbus input |
| jmarkel44 | 252:3c9863f951b7 | 210 | ModbusValue value; |
| jmarkel44 | 252:3c9863f951b7 | 211 | ModbusMasterReadRegister(input, &value); |
| jmarkel44 | 252:3c9863f951b7 | 212 | #if 0 |
| jmarkel44 | 252:3c9863f951b7 | 213 | if ( value.errflag ) { |
| jmarkel44 | 252:3c9863f951b7 | 214 | logError("%s: error reading %s:", __func__, input); |
| jmarkel44 | 252:3c9863f951b7 | 215 | return false; |
| jmarkel44 | 252:3c9863f951b7 | 216 | } |
| jmarkel44 | 252:3c9863f951b7 | 217 | #endif |
| jmarkel44 | 252:3c9863f951b7 | 218 | return ( value.value <= lfs_data.value ); |
| jmarkel44 | 252:3c9863f951b7 | 219 | } |
| jmarkel44 | 252:3c9863f951b7 | 220 | |
| jmarkel44 | 252:3c9863f951b7 | 221 | bool FailsafeControl::aboveHighFailsafe(void) |
| jmarkel44 | 252:3c9863f951b7 | 222 | { |
| jmarkel44 | 252:3c9863f951b7 | 223 | // read the modbus input |
| jmarkel44 | 252:3c9863f951b7 | 224 | ModbusValue value; |
| jmarkel44 | 252:3c9863f951b7 | 225 | ModbusMasterReadRegister(input, &value); |
| jmarkel44 | 252:3c9863f951b7 | 226 | // TODO: check the error flag |
| jmarkel44 | 252:3c9863f951b7 | 227 | #if 0 |
| jmarkel44 | 252:3c9863f951b7 | 228 | if ( value.errflag ) { |
| jmarkel44 | 252:3c9863f951b7 | 229 | logError("%s: error reading %s:", __func__, input); |
| jmarkel44 | 252:3c9863f951b7 | 230 | return false; |
| jmarkel44 | 252:3c9863f951b7 | 231 | } |
| jmarkel44 | 252:3c9863f951b7 | 232 | #endif |
| jmarkel44 | 252:3c9863f951b7 | 233 | return ( value.value >= hfs_data.value ); |
| jmarkel44 | 252:3c9863f951b7 | 234 | } |
| jmarkel44 | 252:3c9863f951b7 | 235 | |
| jmarkel44 | 261:4e9a588c938e | 236 | // |
| jmarkel44 | 261:4e9a588c938e | 237 | // method: startHfsDutyTimer |
| jmarkel44 | 261:4e9a588c938e | 238 | // description: start the high failsafe duty timer |
| jmarkel44 | 261:4e9a588c938e | 239 | // |
| jmarkel44 | 261:4e9a588c938e | 240 | // @param none |
| jmarkel44 | 261:4e9a588c938e | 241 | // @return none |
| jmarkel44 | 261:4e9a588c938e | 242 | // |
| jmarkel44 | 261:4e9a588c938e | 243 | void FailsafeControl::startHfsDutyTimer(void) |
| jmarkel44 | 252:3c9863f951b7 | 244 | { |
| jmarkel44 | 261:4e9a588c938e | 245 | unsigned long currentTime = time(NULL); |
| jmarkel44 | 261:4e9a588c938e | 246 | unsigned long period = hfs_data.interval * 60; |
| jmarkel44 | 261:4e9a588c938e | 247 | |
| jmarkel44 | 261:4e9a588c938e | 248 | duty_timer.offTime = currentTime + ((double)period * ((double)hfs_data.dutyCycle/100.0)); |
| jmarkel44 | 261:4e9a588c938e | 249 | duty_timer.expirationTime = currentTime + period; |
| jmarkel44 | 262:696cd48bb04a | 250 | |
| jmarkel44 | 261:4e9a588c938e | 251 | printf("\r%s: currentTime = %lu\n", __func__, currentTime); |
| jmarkel44 | 261:4e9a588c938e | 252 | printf("\r%s: off Time = %lu\n", __func__, duty_timer.offTime); |
| jmarkel44 | 261:4e9a588c938e | 253 | printf("\r%s: expiration = %lu\n", __func__, duty_timer.expirationTime); |
| jmarkel44 | 261:4e9a588c938e | 254 | } |
| jmarkel44 | 261:4e9a588c938e | 255 | |
| jmarkel44 | 261:4e9a588c938e | 256 | // |
| jmarkel44 | 261:4e9a588c938e | 257 | // method: stopHfsDutyTimer |
| jmarkel44 | 261:4e9a588c938e | 258 | // description: stop the high failsafe duty timer |
| jmarkel44 | 261:4e9a588c938e | 259 | // |
| jmarkel44 | 261:4e9a588c938e | 260 | // @param none |
| jmarkel44 | 261:4e9a588c938e | 261 | // @return none |
| jmarkel44 | 261:4e9a588c938e | 262 | // |
| jmarkel44 | 261:4e9a588c938e | 263 | void FailsafeControl::stopHfsDutyTimer(void) |
| jmarkel44 | 261:4e9a588c938e | 264 | { |
| jmarkel44 | 261:4e9a588c938e | 265 | printf("\r%s invoked\n", __func__); |
| jmarkel44 | 261:4e9a588c938e | 266 | memset(&duty_timer, 0, sizeof(duty_timer)); |
| jmarkel44 | 252:3c9863f951b7 | 267 | } |
| jmarkel44 | 252:3c9863f951b7 | 268 | |
| jmarkel44 | 261:4e9a588c938e | 269 | // |
| jmarkel44 | 261:4e9a588c938e | 270 | // method: startLfsDutyTimer |
| jmarkel44 | 261:4e9a588c938e | 271 | // descrption: start the low failsafe duty-timer |
| jmarkel44 | 261:4e9a588c938e | 272 | // |
| jmarkel44 | 261:4e9a588c938e | 273 | // @param none |
| jmarkel44 | 261:4e9a588c938e | 274 | // @return none |
| jmarkel44 | 261:4e9a588c938e | 275 | // |
| jmarkel44 | 261:4e9a588c938e | 276 | void FailsafeControl::startLfsDutyTimer(void) |
| jmarkel44 | 261:4e9a588c938e | 277 | { |
| jmarkel44 | 261:4e9a588c938e | 278 | unsigned long currentTime = time(NULL); |
| jmarkel44 | 261:4e9a588c938e | 279 | unsigned long period = lfs_data.interval * 60; |
| jmarkel44 | 261:4e9a588c938e | 280 | |
| jmarkel44 | 261:4e9a588c938e | 281 | duty_timer.offTime = (double)period * ((double)lfs_data.dutyCycle/100.0); |
| jmarkel44 | 261:4e9a588c938e | 282 | duty_timer.expirationTime = currentTime + period; |
| jmarkel44 | 261:4e9a588c938e | 283 | } |
| jmarkel44 | 261:4e9a588c938e | 284 | |
| jmarkel44 | 261:4e9a588c938e | 285 | // |
| jmarkel44 | 261:4e9a588c938e | 286 | // method: stopLfsDutyTimer |
| jmarkel44 | 261:4e9a588c938e | 287 | // description: stop the low failsafe duty-timer |
| jmarkel44 | 261:4e9a588c938e | 288 | // |
| jmarkel44 | 261:4e9a588c938e | 289 | // @param none |
| jmarkel44 | 261:4e9a588c938e | 290 | // @return none |
| jmarkel44 | 261:4e9a588c938e | 291 | // |
| jmarkel44 | 261:4e9a588c938e | 292 | void FailsafeControl::stopLfsDutyTimer(void) |
| jmarkel44 | 252:3c9863f951b7 | 293 | { |
| jmarkel44 | 262:696cd48bb04a | 294 | printf("\r%s invoked\n", __func__); |
| jmarkel44 | 262:696cd48bb04a | 295 | memset(&duty_timer, 0, sizeof(duty_timer)); |
| jmarkel44 | 261:4e9a588c938e | 296 | } |
| jmarkel44 | 261:4e9a588c938e | 297 | |
| jmarkel44 | 261:4e9a588c938e | 298 | // |
| jmarkel44 | 261:4e9a588c938e | 299 | // method: dutyOnExpired |
| jmarkel44 | 261:4e9a588c938e | 300 | // description: returns true if ON cycle has expired; false otherwise |
| jmarkel44 | 261:4e9a588c938e | 301 | // |
| jmarkel44 | 261:4e9a588c938e | 302 | // @param none |
| jmarkel44 | 261:4e9a588c938e | 303 | // @return none |
| jmarkel44 | 261:4e9a588c938e | 304 | // |
| jmarkel44 | 261:4e9a588c938e | 305 | bool FailsafeControl::dutyOnExpired(void) |
| jmarkel44 | 261:4e9a588c938e | 306 | { |
| jmarkel44 | 261:4e9a588c938e | 307 | return (duty_timer.offTime < time(NULL)); |
| jmarkel44 | 261:4e9a588c938e | 308 | } |
| jmarkel44 | 261:4e9a588c938e | 309 | |
| jmarkel44 | 261:4e9a588c938e | 310 | // |
| jmarkel44 | 261:4e9a588c938e | 311 | // method: dutyOffExpired |
| jmarkel44 | 261:4e9a588c938e | 312 | // description: returns true if OFF cycle has expired; false otherwise |
| jmarkel44 | 261:4e9a588c938e | 313 | // |
| jmarkel44 | 261:4e9a588c938e | 314 | // @param none |
| jmarkel44 | 261:4e9a588c938e | 315 | // @return none |
| jmarkel44 | 261:4e9a588c938e | 316 | // |
| jmarkel44 | 261:4e9a588c938e | 317 | bool FailsafeControl::dutyOffExpired(void) |
| jmarkel44 | 261:4e9a588c938e | 318 | { |
| jmarkel44 | 262:696cd48bb04a | 319 | return (duty_timer.expirationTime < time(NULL)); |
| jmarkel44 | 252:3c9863f951b7 | 320 | } |
| jmarkel44 | 252:3c9863f951b7 | 321 | |
| jmarkel44 | 252:3c9863f951b7 | 322 | // |
| jmarkel44 | 260:fe726583ba1d | 323 | // method: sendMailToOutput |
| jmarkel44 | 252:3c9863f951b7 | 324 | // description: send mail to the output task |
| jmarkel44 | 252:3c9863f951b7 | 325 | // |
| jmarkel44 | 252:3c9863f951b7 | 326 | // @param io_tag -> input/output tag |
| jmarkel44 | 252:3c9863f951b7 | 327 | // @param action -> ON, OFF, UNREGISTER |
| jmarkel44 | 252:3c9863f951b7 | 328 | // @return none |
| jmarkel44 | 252:3c9863f951b7 | 329 | // |
| jmarkel44 | 260:fe726583ba1d | 330 | void FailsafeControl::sendMailToOutput(OutputAction action) |
| jmarkel44 | 252:3c9863f951b7 | 331 | { |
| jmarkel44 | 252:3c9863f951b7 | 332 | logInfo("%s: failsafe control attempting to send action %d\n", |
| jmarkel44 | 252:3c9863f951b7 | 333 | __func__, action); |
| jmarkel44 | 252:3c9863f951b7 | 334 | |
| jmarkel44 | 252:3c9863f951b7 | 335 | OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); |
| jmarkel44 | 252:3c9863f951b7 | 336 | memset(output_mail, 0, sizeof(OutputControlMsg_t)); |
| jmarkel44 | 252:3c9863f951b7 | 337 | |
| jmarkel44 | 252:3c9863f951b7 | 338 | output_mail->action = action; |
| jmarkel44 | 252:3c9863f951b7 | 339 | output_mail->controlType = CONTROL_FAILSAFE; |
| jmarkel44 | 252:3c9863f951b7 | 340 | output_mail->priority = this->priority; |
| jmarkel44 | 252:3c9863f951b7 | 341 | |
| jmarkel44 | 252:3c9863f951b7 | 342 | strncpy(output_mail->input_tag, this->input.c_str(), sizeof(output_mail->input_tag)-1); |
| jmarkel44 | 252:3c9863f951b7 | 343 | strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); |
| jmarkel44 | 252:3c9863f951b7 | 344 | strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); |
| jmarkel44 | 252:3c9863f951b7 | 345 | |
| jmarkel44 | 252:3c9863f951b7 | 346 | OutputMasterMailBox.put(output_mail); |
| jmarkel44 | 252:3c9863f951b7 | 347 | } |
| jmarkel44 | 252:3c9863f951b7 | 348 | |
| jmarkel44 | 269:97243a7f56ba | 349 | // |
| jmarkel44 | 269:97243a7f56ba | 350 | // method: sensorError |
| jmarkel44 | 269:97243a7f56ba | 351 | // description: return true if a sensor's error flag it set |
| jmarkel44 | 269:97243a7f56ba | 352 | // |
| jmarkel44 | 269:97243a7f56ba | 353 | // @param[in] none |
| jmarkel44 | 269:97243a7f56ba | 354 | // @param[out] none |
| jmarkel44 | 269:97243a7f56ba | 355 | // @return true if sensor error |
| jmarkel44 | 269:97243a7f56ba | 356 | // |
| jmarkel44 | 269:97243a7f56ba | 357 | bool FailsafeControl::sensorError(void) |
| jmarkel44 | 269:97243a7f56ba | 358 | { |
| jmarkel44 | 269:97243a7f56ba | 359 | ModbusValue value; |
| jmarkel44 | 269:97243a7f56ba | 360 | ModbusMasterReadRegister(input, &value); |
| jmarkel44 | 273:0373b2a15f8a | 361 | |
| jmarkel44 | 269:97243a7f56ba | 362 | if ( value.errflag ) { |
| jmarkel44 | 269:97243a7f56ba | 363 | logInfo("%s: %s is in error\n", __func__, input.c_str()); |
| jmarkel44 | 269:97243a7f56ba | 364 | return true; |
| jmarkel44 | 269:97243a7f56ba | 365 | } |
| jmarkel44 | 269:97243a7f56ba | 366 | return false; |
| jmarkel44 | 269:97243a7f56ba | 367 | } |
| jmarkel44 | 269:97243a7f56ba | 368 | |
| jmarkel44 | 252:3c9863f951b7 | 369 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 370 | // |
| jmarkel44 | 260:fe726583ba1d | 371 | // method: unregisterControl |
| jmarkel44 | 260:fe726583ba1d | 372 | // description: unregister this control with the output task |
| jmarkel44 | 260:fe726583ba1d | 373 | // |
| jmarkel44 | 260:fe726583ba1d | 374 | // @param none |
| jmarkel44 | 260:fe726583ba1d | 375 | // @return none |
| jmarkel44 | 260:fe726583ba1d | 376 | // |
| jmarkel44 | 260:fe726583ba1d | 377 | void FailsafeControl::unregisterControl(void) |
| jmarkel44 | 260:fe726583ba1d | 378 | { |
| jmarkel44 | 260:fe726583ba1d | 379 | logInfo("%s: %s attempting to unregister %s\n", |
| jmarkel44 | 260:fe726583ba1d | 380 | __func__, controlFile.c_str()); |
| jmarkel44 | 260:fe726583ba1d | 381 | |
| jmarkel44 | 260:fe726583ba1d | 382 | OutputControlMsg_t *output_mail = OutputMasterMailBox.alloc(); |
| jmarkel44 | 260:fe726583ba1d | 383 | memset(output_mail, 0, sizeof(OutputControlMsg_t)); |
| jmarkel44 | 260:fe726583ba1d | 384 | |
| jmarkel44 | 260:fe726583ba1d | 385 | output_mail->action = ACTION_CONTROL_UNREGISTER; |
| jmarkel44 | 260:fe726583ba1d | 386 | output_mail->controlType = CONTROL_FAILSAFE; |
| jmarkel44 | 260:fe726583ba1d | 387 | output_mail->priority = this->priority; |
| jmarkel44 | 260:fe726583ba1d | 388 | strncpy(output_mail->output_tag, this->output.c_str(), sizeof(output_mail->output_tag)-1); |
| jmarkel44 | 260:fe726583ba1d | 389 | strncpy(output_mail->id, this->id.c_str(), sizeof(output_mail->id)-1); |
| jmarkel44 | 260:fe726583ba1d | 390 | |
| jmarkel44 | 260:fe726583ba1d | 391 | OutputMasterMailBox.put(output_mail); |
| jmarkel44 | 260:fe726583ba1d | 392 | } |
| jmarkel44 | 260:fe726583ba1d | 393 | |
| jmarkel44 | 260:fe726583ba1d | 394 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 395 | // method: display |
| jmarkel44 | 250:1cd8ec63e9e9 | 396 | // description: display the pertinents |
| jmarkel44 | 250:1cd8ec63e9e9 | 397 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 398 | // @param none |
| jmarkel44 | 250:1cd8ec63e9e9 | 399 | // @return none |
| jmarkel44 | 250:1cd8ec63e9e9 | 400 | // |
| jmarkel44 | 250:1cd8ec63e9e9 | 401 | void FailsafeControl::display(void) |
| jmarkel44 | 250:1cd8ec63e9e9 | 402 | { |
| jmarkel44 | 250:1cd8ec63e9e9 | 403 | const char *mapper[] = { "INIT", |
| jmarkel44 | 250:1cd8ec63e9e9 | 404 | "START", |
| jmarkel44 | 269:97243a7f56ba | 405 | "OFF", |
| jmarkel44 | 269:97243a7f56ba | 406 | "ON_LFS", |
| jmarkel44 | 269:97243a7f56ba | 407 | "OFF_LFS", |
| jmarkel44 | 269:97243a7f56ba | 408 | "ON_HFS", |
| jmarkel44 | 269:97243a7f56ba | 409 | "OFF_HFS", |
| jmarkel44 | 269:97243a7f56ba | 410 | "SENSOR_ERR", |
| jmarkel44 | 250:1cd8ec63e9e9 | 411 | "invalid" |
| jmarkel44 | 250:1cd8ec63e9e9 | 412 | }; |
| jmarkel44 | 250:1cd8ec63e9e9 | 413 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 414 | printf("\r\n"); |
| jmarkel44 | 250:1cd8ec63e9e9 | 415 | std::cout << left << setw(10) << setfill(' ') << "failsafe: "; |
| jmarkel44 | 253:ae850c19cf81 | 416 | std::cout << left << setw(40) << setfill(' ') << controlFile; |
| jmarkel44 | 250:1cd8ec63e9e9 | 417 | std::cout << left << setw(20) << setfill(' ') << id; |
| jmarkel44 | 250:1cd8ec63e9e9 | 418 | std::cout << left << setw(6) << setfill(' ') << priority; |
| jmarkel44 | 250:1cd8ec63e9e9 | 419 | std::cout << left << setw(20) << setfill(' ') << input; |
| jmarkel44 | 250:1cd8ec63e9e9 | 420 | std::cout << left << setw(20) << setfill(' ') << output; |
| jmarkel44 | 250:1cd8ec63e9e9 | 421 | std::cout << left << setw(16) << setfill(' ') << mapper[currentState]; |
| jmarkel44 | 252:3c9863f951b7 | 422 | std::cout << left << setw(12) << setfill(' ') << "lfs-> " |
| jmarkel44 | 252:3c9863f951b7 | 423 | << lfs_data.value << ":" << lfs_data.dutyCycle << ":" << lfs_data.interval; |
| jmarkel44 | 252:3c9863f951b7 | 424 | std::cout << right << setw(12) << setfill(' ') << "hfs-> " |
| jmarkel44 | 252:3c9863f951b7 | 425 | << hfs_data.value << ":" << hfs_data.dutyCycle << ":" << hfs_data.interval; |
| jmarkel44 | 250:1cd8ec63e9e9 | 426 | |
| jmarkel44 | 250:1cd8ec63e9e9 | 427 | std::cout.flush(); |
| jmarkel44 | 252:3c9863f951b7 | 428 | } |
