Minor update to improve documentation and add missing functions.
PowerMeasurement.cpp@2:7f6a39ec5c01, 2016-10-17 (annotated)
- Committer:
- WiredHome
- Date:
- Mon Oct 17 11:31:18 2016 +0000
- Revision:
- 2:7f6a39ec5c01
- Parent:
- 1:d99a72afec32
Update docs and add missing functions.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
WiredHome | 0:51c019b83ede | 1 | |
WiredHome | 0:51c019b83ede | 2 | |
WiredHome | 0:51c019b83ede | 3 | |
WiredHome | 0:51c019b83ede | 4 | |
WiredHome | 0:51c019b83ede | 5 | #include "PowerMeasurement.h" |
WiredHome | 0:51c019b83ede | 6 | |
WiredHome | 0:51c019b83ede | 7 | |
WiredHome | 1:d99a72afec32 | 8 | //#define DEBUG "POWR" |
WiredHome | 1:d99a72afec32 | 9 | // ... |
WiredHome | 1:d99a72afec32 | 10 | // INFO("Stuff to show %d", var); // new-line is automatically appended |
WiredHome | 1:d99a72afec32 | 11 | // |
WiredHome | 1:d99a72afec32 | 12 | #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) |
WiredHome | 1:d99a72afec32 | 13 | #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 1:d99a72afec32 | 14 | #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 1:d99a72afec32 | 15 | #define ERR(x, ...) std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 1:d99a72afec32 | 16 | static void HexDump(const char * title, const uint8_t * p, int count) |
WiredHome | 1:d99a72afec32 | 17 | { |
WiredHome | 1:d99a72afec32 | 18 | int i; |
WiredHome | 1:d99a72afec32 | 19 | char buf[100] = "0000: "; |
WiredHome | 0:51c019b83ede | 20 | |
WiredHome | 1:d99a72afec32 | 21 | if (*title) |
WiredHome | 1:d99a72afec32 | 22 | INFO("%s", title); |
WiredHome | 1:d99a72afec32 | 23 | for (i=0; i<count; ) { |
WiredHome | 1:d99a72afec32 | 24 | sprintf(buf + strlen(buf), "%02X ", *(p+i)); |
WiredHome | 1:d99a72afec32 | 25 | if ((++i & 0x0F) == 0x00) { |
WiredHome | 1:d99a72afec32 | 26 | INFO("%s", buf); |
WiredHome | 1:d99a72afec32 | 27 | if (i < count) |
WiredHome | 1:d99a72afec32 | 28 | sprintf(buf, "%04X: ", i); |
WiredHome | 1:d99a72afec32 | 29 | else |
WiredHome | 1:d99a72afec32 | 30 | buf[0] = '\0'; |
WiredHome | 1:d99a72afec32 | 31 | } |
WiredHome | 1:d99a72afec32 | 32 | } |
WiredHome | 1:d99a72afec32 | 33 | if (strlen(buf)) |
WiredHome | 1:d99a72afec32 | 34 | INFO("%s", buf); |
WiredHome | 1:d99a72afec32 | 35 | } |
WiredHome | 1:d99a72afec32 | 36 | #else |
WiredHome | 1:d99a72afec32 | 37 | #define INFO(x, ...) |
WiredHome | 1:d99a72afec32 | 38 | #define WARN(x, ...) |
WiredHome | 1:d99a72afec32 | 39 | #define ERR(x, ...) |
WiredHome | 1:d99a72afec32 | 40 | #define HexDump(a, b, c) |
WiredHome | 1:d99a72afec32 | 41 | #endif |
WiredHome | 1:d99a72afec32 | 42 | |
WiredHome | 1:d99a72afec32 | 43 | DigitalOut mip(LED1); |
WiredHome | 1:d99a72afec32 | 44 | DigitalOut sam(LED2); |
WiredHome | 1:d99a72afec32 | 45 | |
WiredHome | 1:d99a72afec32 | 46 | PowerMeasurement::PowerMeasurement(AnalogIn * _AinList, BusOut * _MuxBus, DigitalOut * _Select, |
WiredHome | 1:d99a72afec32 | 47 | GetVoltage_T _GetVoltage, int _AinCount, int _MuxChannels) { |
WiredHome | 1:d99a72afec32 | 48 | if (_AinList) |
WiredHome | 1:d99a72afec32 | 49 | AinList = _AinList; |
WiredHome | 0:51c019b83ede | 50 | if (_MuxBus) |
WiredHome | 0:51c019b83ede | 51 | MuxBus = _MuxBus; |
WiredHome | 1:d99a72afec32 | 52 | if (_Select) { |
WiredHome | 1:d99a72afec32 | 53 | Select = _Select; |
WiredHome | 0:51c019b83ede | 54 | } |
WiredHome | 0:51c019b83ede | 55 | GetVoltage = &_GetVoltage; |
WiredHome | 0:51c019b83ede | 56 | AinCount = _AinCount; |
WiredHome | 1:d99a72afec32 | 57 | NumMuxes = _AinCount; |
WiredHome | 0:51c019b83ede | 58 | MuxChannels = _MuxChannels; |
WiredHome | 0:51c019b83ede | 59 | |
WiredHome | 0:51c019b83ede | 60 | totalChannels = (NumMuxes > 0) ? AinCount * (NumMuxes * MuxChannels) : AinCount; |
WiredHome | 0:51c019b83ede | 61 | fullScaleCurrent = (float *)malloc(totalChannels * sizeof(float)); |
WiredHome | 0:51c019b83ede | 62 | for (int i=0; i<totalChannels; i++) { |
WiredHome | 0:51c019b83ede | 63 | fullScaleCurrent[i] = 1.0f; |
WiredHome | 0:51c019b83ede | 64 | } |
WiredHome | 0:51c019b83ede | 65 | fullScaleVoltage = 1.0f; |
WiredHome | 0:51c019b83ede | 66 | |
WiredHome | 0:51c019b83ede | 67 | if (AinCount > 0 && AinCount <= 6) { |
WiredHome | 1:d99a72afec32 | 68 | //INFO("Configure for %d A/D inputs", AinCount); |
WiredHome | 0:51c019b83ede | 69 | } |
WiredHome | 0:51c019b83ede | 70 | |
WiredHome | 1:d99a72afec32 | 71 | rawSamples = (RawPowerData_T *)malloc(SAMPLES_PER_CYCLE * CYCLES_PER_SAMPLE * sizeof(RawPowerData_T)); |
WiredHome | 0:51c019b83ede | 72 | sampleNum = 0; |
WiredHome | 1:d99a72afec32 | 73 | |
WiredHome | 1:d99a72afec32 | 74 | frequency(60.0f); // default is pathetically slow, but good for basic testing... |
WiredHome | 1:d99a72afec32 | 75 | |
WiredHome | 0:51c019b83ede | 76 | inProcess = false; |
WiredHome | 0:51c019b83ede | 77 | isComplete = false; |
WiredHome | 0:51c019b83ede | 78 | } |
WiredHome | 0:51c019b83ede | 79 | |
WiredHome | 0:51c019b83ede | 80 | |
WiredHome | 0:51c019b83ede | 81 | /// The destructor. |
WiredHome | 0:51c019b83ede | 82 | PowerMeasurement::~PowerMeasurement() { |
WiredHome | 0:51c019b83ede | 83 | free(fullScaleCurrent); |
WiredHome | 0:51c019b83ede | 84 | } |
WiredHome | 0:51c019b83ede | 85 | |
WiredHome | 0:51c019b83ede | 86 | |
WiredHome | 0:51c019b83ede | 87 | /// Defines the overall frequency of the line voltage. |
WiredHome | 0:51c019b83ede | 88 | /// |
WiredHome | 0:51c019b83ede | 89 | /// Based on this line frequency, the sample-rate for the measurement is set. |
WiredHome | 0:51c019b83ede | 90 | /// |
WiredHome | 0:51c019b83ede | 91 | /// @param[in] Hz sets the line frequency. |
WiredHome | 0:51c019b83ede | 92 | /// |
WiredHome | 0:51c019b83ede | 93 | void PowerMeasurement::frequency(float _Hz) { |
WiredHome | 0:51c019b83ede | 94 | uSecInterval = 1.0e6 / _Hz / SAMPLES_PER_CYCLE; |
WiredHome | 0:51c019b83ede | 95 | } |
WiredHome | 0:51c019b83ede | 96 | |
WiredHome | 0:51c019b83ede | 97 | |
WiredHome | 0:51c019b83ede | 98 | /// Defines the measuremenbt interval. |
WiredHome | 0:51c019b83ede | 99 | /// |
WiredHome | 0:51c019b83ede | 100 | /// Instead of defining the measurement interval by line frequency, the period |
WiredHome | 0:51c019b83ede | 101 | /// can be directly set. |
WiredHome | 0:51c019b83ede | 102 | /// |
WiredHome | 0:51c019b83ede | 103 | /// @param uSec is the number of microseconds between samples. |
WiredHome | 0:51c019b83ede | 104 | /// |
WiredHome | 0:51c019b83ede | 105 | void PowerMeasurement::period_us(uint32_t uSec) { |
WiredHome | 0:51c019b83ede | 106 | uSecInterval = uSec; |
WiredHome | 0:51c019b83ede | 107 | } |
WiredHome | 0:51c019b83ede | 108 | |
WiredHome | 0:51c019b83ede | 109 | |
WiredHome | 0:51c019b83ede | 110 | /// Set the voltage to current calibration value for a channel. |
WiredHome | 0:51c019b83ede | 111 | /// |
WiredHome | 0:51c019b83ede | 112 | /// Each analog input channel can be configured for the current sensor used on that channel. |
WiredHome | 0:51c019b83ede | 113 | /// If the channel has a 30 A current sensor, that channel should be set to 30.0f. |
WiredHome | 0:51c019b83ede | 114 | /// If the user calibrates the sensor more precisely, an improved calibration factor (e.g. 31.1) |
WiredHome | 0:51c019b83ede | 115 | /// can be defined. |
WiredHome | 0:51c019b83ede | 116 | /// |
WiredHome | 0:51c019b83ede | 117 | /// @param[in] channel defines the channel to calibrate. |
WiredHome | 0:51c019b83ede | 118 | /// @param[in] fullScaleCurrent is the calibration factor representing the full-scale current. |
WiredHome | 0:51c019b83ede | 119 | /// @returns true if the value is accepted. |
WiredHome | 0:51c019b83ede | 120 | /// @returns false if the channel was incorrect. |
WiredHome | 0:51c019b83ede | 121 | /// |
WiredHome | 0:51c019b83ede | 122 | bool PowerMeasurement::SetFullScaleCurrent(int channel, float fullScaleCurrentCalibration) { |
WiredHome | 0:51c019b83ede | 123 | if (channel >= 0 && channel < totalChannels) { |
WiredHome | 0:51c019b83ede | 124 | fullScaleCurrent[channel] = fullScaleCurrentCalibration; |
WiredHome | 0:51c019b83ede | 125 | return true; |
WiredHome | 0:51c019b83ede | 126 | } else { |
WiredHome | 0:51c019b83ede | 127 | return false; |
WiredHome | 0:51c019b83ede | 128 | } |
WiredHome | 0:51c019b83ede | 129 | } |
WiredHome | 0:51c019b83ede | 130 | |
WiredHome | 0:51c019b83ede | 131 | |
WiredHome | 0:51c019b83ede | 132 | /// Set the voltage value representing the full scale measurement. |
WiredHome | 0:51c019b83ede | 133 | /// |
WiredHome | 0:51c019b83ede | 134 | /// The GetVoltage callback is based on a uint16_t. This API sets the full scale voltage |
WiredHome | 0:51c019b83ede | 135 | /// representing the value FFFF. Based on an A/C input, biased to the split supply, this |
WiredHome | 0:51c019b83ede | 136 | /// represents an A/D value of 7FFF. When configured for a 120V circuit, which measures |
WiredHome | 0:51c019b83ede | 137 | /// approximately 170v peak, the fullScaleVoltage value would be 170.0f. |
WiredHome | 0:51c019b83ede | 138 | /// |
WiredHome | 0:51c019b83ede | 139 | /// @param[in] fullScaleVoltage is the full-scale voltage value. |
WiredHome | 0:51c019b83ede | 140 | /// @returns true if the value is accepted. |
WiredHome | 0:51c019b83ede | 141 | /// |
WiredHome | 0:51c019b83ede | 142 | bool PowerMeasurement::SetFullScaleVoltage(float fullScaleVoltageCalibration) { |
WiredHome | 0:51c019b83ede | 143 | fullScaleVoltage = fullScaleVoltageCalibration; |
WiredHome | 0:51c019b83ede | 144 | return true; |
WiredHome | 0:51c019b83ede | 145 | } |
WiredHome | 0:51c019b83ede | 146 | |
WiredHome | 0:51c019b83ede | 147 | |
WiredHome | 0:51c019b83ede | 148 | /// Starts a measurement on the specified channel. |
WiredHome | 0:51c019b83ede | 149 | /// |
WiredHome | 0:51c019b83ede | 150 | /// This starts the measurement on a specified channel. |
WiredHome | 0:51c019b83ede | 151 | /// |
WiredHome | 0:51c019b83ede | 152 | /// @param[in] channel defines the channel to measure. This is in the range of 0 to N-1, where N is |
WiredHome | 0:51c019b83ede | 153 | /// AinCount * MuxChannels. |
WiredHome | 0:51c019b83ede | 154 | /// @returns true if the measurement can be started. |
WiredHome | 0:51c019b83ede | 155 | /// @returns false if the measurement cannot be started - likely because of an incorrect channel |
WiredHome | 0:51c019b83ede | 156 | /// selection. |
WiredHome | 0:51c019b83ede | 157 | /// |
WiredHome | 0:51c019b83ede | 158 | bool PowerMeasurement::StartMeasurement(int channel) { |
WiredHome | 0:51c019b83ede | 159 | if (channel >= 0 && channel < totalChannels) { |
WiredHome | 1:d99a72afec32 | 160 | int muxCh; |
WiredHome | 1:d99a72afec32 | 161 | |
WiredHome | 0:51c019b83ede | 162 | inProcess = true; |
WiredHome | 0:51c019b83ede | 163 | isComplete = false; |
WiredHome | 1:d99a72afec32 | 164 | sampleNum = 0; // ready for the first sample |
WiredHome | 0:51c019b83ede | 165 | if (NumMuxes > 0) { |
WiredHome | 1:d99a72afec32 | 166 | muxCh = channel % MuxChannels; |
WiredHome | 1:d99a72afec32 | 167 | a2dChannel = channel / MuxChannels; |
WiredHome | 1:d99a72afec32 | 168 | *MuxBus = muxCh; |
WiredHome | 1:d99a72afec32 | 169 | Select->write(false); |
WiredHome | 0:51c019b83ede | 170 | } else { |
WiredHome | 1:d99a72afec32 | 171 | a2dChannel = channel; |
WiredHome | 0:51c019b83ede | 172 | } |
WiredHome | 1:d99a72afec32 | 173 | INFO("StartMeasurement(%2d) at %d usec, Mux Ch: %d, A/D ch: %d", |
WiredHome | 1:d99a72afec32 | 174 | channel, uSecInterval, (NumMuxes) ? muxCh : 0, a2dChannel); |
WiredHome | 1:d99a72afec32 | 175 | #if 1 |
WiredHome | 1:d99a72afec32 | 176 | // Directly calling the TakeSample works, but StartMeasurement is then is a blocking call |
WiredHome | 1:d99a72afec32 | 177 | while (inProcess) { |
WiredHome | 1:d99a72afec32 | 178 | TakeSample(); |
WiredHome | 1:d99a72afec32 | 179 | wait_us(uSecInterval); // this now has 'slippage' in time, based on TakeSample execution |
WiredHome | 1:d99a72afec32 | 180 | } |
WiredHome | 2:7f6a39ec5c01 | 181 | mip = false; |
WiredHome | 1:d99a72afec32 | 182 | #else |
WiredHome | 1:d99a72afec32 | 183 | // Attaching it to a timer seems not to work, for reasons not yet understood |
WiredHome | 0:51c019b83ede | 184 | sampleTimer.attach_us(this, &PowerMeasurement::TakeSample, uSecInterval); |
WiredHome | 2:7f6a39ec5c01 | 185 | mip = true; |
WiredHome | 1:d99a72afec32 | 186 | #endif |
WiredHome | 0:51c019b83ede | 187 | return true; |
WiredHome | 0:51c019b83ede | 188 | } else { |
WiredHome | 1:d99a72afec32 | 189 | ERR("Cannot StartMeasurement(%d) of %d", channel, totalChannels); |
WiredHome | 1:d99a72afec32 | 190 | mip = false; |
WiredHome | 0:51c019b83ede | 191 | return false; |
WiredHome | 0:51c019b83ede | 192 | } |
WiredHome | 0:51c019b83ede | 193 | } |
WiredHome | 0:51c019b83ede | 194 | |
WiredHome | 0:51c019b83ede | 195 | void PowerMeasurement::TakeSample(void) { |
WiredHome | 1:d99a72afec32 | 196 | rawSamples[sampleNum].current = AinList[a2dChannel].read_u16(); |
WiredHome | 2:7f6a39ec5c01 | 197 | if (GetVoltage) |
WiredHome | 2:7f6a39ec5c01 | 198 | rawSamples[sampleNum].voltage = (*GetVoltage)(); |
WiredHome | 2:7f6a39ec5c01 | 199 | else |
WiredHome | 2:7f6a39ec5c01 | 200 | rawSamples[sampleNum].voltage = 0 + 32768; // bias to mid-point |
WiredHome | 0:51c019b83ede | 201 | sampleNum++; |
WiredHome | 1:d99a72afec32 | 202 | sam = !sam; |
WiredHome | 0:51c019b83ede | 203 | if (sampleNum > (SAMPLES_PER_CYCLE * CYCLES_PER_SAMPLE)) { |
WiredHome | 0:51c019b83ede | 204 | inProcess = false; |
WiredHome | 0:51c019b83ede | 205 | isComplete = true; |
WiredHome | 1:d99a72afec32 | 206 | mip = false; |
WiredHome | 0:51c019b83ede | 207 | } |
WiredHome | 0:51c019b83ede | 208 | } |
WiredHome | 0:51c019b83ede | 209 | |
WiredHome | 0:51c019b83ede | 210 | /// Determines if the conversion is complete and the results are readable. |
WiredHome | 0:51c019b83ede | 211 | /// |
WiredHome | 0:51c019b83ede | 212 | /// @returns true if the measurement is complete (or if no measurement is in process). |
WiredHome | 0:51c019b83ede | 213 | /// @returns false if the measurement is in process. |
WiredHome | 0:51c019b83ede | 214 | /// |
WiredHome | 0:51c019b83ede | 215 | bool PowerMeasurement::readable() { |
WiredHome | 0:51c019b83ede | 216 | return isComplete; |
WiredHome | 0:51c019b83ede | 217 | } |
WiredHome | 0:51c019b83ede | 218 | |
WiredHome | 0:51c019b83ede | 219 | |
WiredHome | 0:51c019b83ede | 220 | /// Get the real power measurement. |
WiredHome | 0:51c019b83ede | 221 | /// |
WiredHome | 0:51c019b83ede | 222 | /// This retrieves the real power measurement for the channel which just completed measurement. |
WiredHome | 0:51c019b83ede | 223 | /// This is the average of the instantaneous power. |
WiredHome | 0:51c019b83ede | 224 | /// |
WiredHome | 0:51c019b83ede | 225 | /// @returns the real power measurement. |
WiredHome | 0:51c019b83ede | 226 | /// |
WiredHome | 0:51c019b83ede | 227 | float PowerMeasurement::GetRealPower() { |
WiredHome | 0:51c019b83ede | 228 | if (isComplete) { |
WiredHome | 0:51c019b83ede | 229 | float sumInstantP = 0.0f; |
WiredHome | 0:51c019b83ede | 230 | |
WiredHome | 0:51c019b83ede | 231 | for (int i=0; i<(SAMPLES_PER_CYCLE * CYCLES_PER_SAMPLE); i++) { |
WiredHome | 0:51c019b83ede | 232 | float voltage = fullScaleVoltage * ((float)rawSamples[i].voltage - PM_ZERO_OFFSET) / PM_FULL_SCALE; |
WiredHome | 1:d99a72afec32 | 233 | float current = fullScaleCurrent[a2dChannel] * ((float)rawSamples[i].current - PM_ZERO_OFFSET) / PM_FULL_SCALE; |
WiredHome | 0:51c019b83ede | 234 | |
WiredHome | 0:51c019b83ede | 235 | sumInstantP += (voltage * current); |
WiredHome | 0:51c019b83ede | 236 | } |
WiredHome | 0:51c019b83ede | 237 | float realP = sumInstantP / (SAMPLES_PER_CYCLE * CYCLES_PER_SAMPLE); |
WiredHome | 0:51c019b83ede | 238 | return realP; |
WiredHome | 0:51c019b83ede | 239 | } else { |
WiredHome | 0:51c019b83ede | 240 | return 0.0f; |
WiredHome | 0:51c019b83ede | 241 | } |
WiredHome | 0:51c019b83ede | 242 | } |
WiredHome | 0:51c019b83ede | 243 | |
WiredHome | 0:51c019b83ede | 244 | |
WiredHome | 0:51c019b83ede | 245 | /// Get the rms voltage measurement. |
WiredHome | 0:51c019b83ede | 246 | /// |
WiredHome | 0:51c019b83ede | 247 | /// This retrieves the rms voltage measurement for the channel which just completed measurement. |
WiredHome | 0:51c019b83ede | 248 | /// |
WiredHome | 0:51c019b83ede | 249 | /// @returns the rms voltage measurement. |
WiredHome | 0:51c019b83ede | 250 | /// |
WiredHome | 0:51c019b83ede | 251 | float PowerMeasurement::GetRMSVoltage() { |
WiredHome | 0:51c019b83ede | 252 | if (isComplete) { |
WiredHome | 0:51c019b83ede | 253 | float sumSquaredV = 0.0f; |
WiredHome | 0:51c019b83ede | 254 | |
WiredHome | 0:51c019b83ede | 255 | for (int i=0; i<(SAMPLES_PER_CYCLE * CYCLES_PER_SAMPLE); i++) { |
WiredHome | 0:51c019b83ede | 256 | float voltage = fullScaleVoltage * ((float)rawSamples[i].voltage - PM_ZERO_OFFSET) / PM_FULL_SCALE; |
WiredHome | 0:51c019b83ede | 257 | |
WiredHome | 0:51c019b83ede | 258 | sumSquaredV += (voltage * voltage); |
WiredHome | 0:51c019b83ede | 259 | } |
WiredHome | 0:51c019b83ede | 260 | float rmsV = sqrt(sumSquaredV / (SAMPLES_PER_CYCLE * CYCLES_PER_SAMPLE)); |
WiredHome | 0:51c019b83ede | 261 | return rmsV; |
WiredHome | 0:51c019b83ede | 262 | } else { |
WiredHome | 0:51c019b83ede | 263 | return 0.0f; |
WiredHome | 0:51c019b83ede | 264 | } |
WiredHome | 0:51c019b83ede | 265 | } |
WiredHome | 0:51c019b83ede | 266 | |
WiredHome | 0:51c019b83ede | 267 | |
WiredHome | 0:51c019b83ede | 268 | /// Get the rms current measurement. |
WiredHome | 0:51c019b83ede | 269 | /// |
WiredHome | 0:51c019b83ede | 270 | /// This retrieves the rms current measurement for the channel which just completed measurement. |
WiredHome | 0:51c019b83ede | 271 | /// |
WiredHome | 0:51c019b83ede | 272 | /// @returns the rm current measurement. |
WiredHome | 0:51c019b83ede | 273 | /// |
WiredHome | 0:51c019b83ede | 274 | float PowerMeasurement::GetRMSCurrent() { |
WiredHome | 0:51c019b83ede | 275 | if (isComplete) { |
WiredHome | 0:51c019b83ede | 276 | float sumSquaredCurrent = 0.0f; |
WiredHome | 0:51c019b83ede | 277 | |
WiredHome | 0:51c019b83ede | 278 | for (int i=0; i<(SAMPLES_PER_CYCLE * CYCLES_PER_SAMPLE); i++) { |
WiredHome | 1:d99a72afec32 | 279 | float current = fullScaleCurrent[a2dChannel] * ((float)rawSamples[i].current - PM_ZERO_OFFSET) / PM_FULL_SCALE; |
WiredHome | 0:51c019b83ede | 280 | |
WiredHome | 0:51c019b83ede | 281 | sumSquaredCurrent += (current * current); |
WiredHome | 0:51c019b83ede | 282 | } |
WiredHome | 0:51c019b83ede | 283 | float meanSqC = sumSquaredCurrent / (SAMPLES_PER_CYCLE * CYCLES_PER_SAMPLE); |
WiredHome | 0:51c019b83ede | 284 | return sqrt(meanSqC); |
WiredHome | 0:51c019b83ede | 285 | } else { |
WiredHome | 0:51c019b83ede | 286 | return 0.0f; |
WiredHome | 0:51c019b83ede | 287 | } |
WiredHome | 0:51c019b83ede | 288 | } |
WiredHome | 0:51c019b83ede | 289 | |
WiredHome | 0:51c019b83ede | 290 | |
WiredHome | 2:7f6a39ec5c01 | 291 | bool PowerMeasurement::GetPeakCurrent(float * negPeak, float * posPeak) |
WiredHome | 2:7f6a39ec5c01 | 292 | { |
WiredHome | 2:7f6a39ec5c01 | 293 | if (isComplete) { |
WiredHome | 2:7f6a39ec5c01 | 294 | for (int i=0; i<(SAMPLES_PER_CYCLE * CYCLES_PER_SAMPLE); i++) { |
WiredHome | 2:7f6a39ec5c01 | 295 | if (i == 0) { |
WiredHome | 2:7f6a39ec5c01 | 296 | if (negPeak) |
WiredHome | 2:7f6a39ec5c01 | 297 | *negPeak = fullScaleCurrent[a2dChannel] * ((float)rawSamples[i].current - PM_ZERO_OFFSET) / PM_FULL_SCALE; |
WiredHome | 2:7f6a39ec5c01 | 298 | if (posPeak) |
WiredHome | 2:7f6a39ec5c01 | 299 | *posPeak = fullScaleCurrent[a2dChannel] * ((float)rawSamples[i].current - PM_ZERO_OFFSET) / PM_FULL_SCALE; |
WiredHome | 2:7f6a39ec5c01 | 300 | } else { |
WiredHome | 2:7f6a39ec5c01 | 301 | float testVal = fullScaleCurrent[a2dChannel] * ((float)rawSamples[i].current - PM_ZERO_OFFSET) / PM_FULL_SCALE; |
WiredHome | 2:7f6a39ec5c01 | 302 | if (negPeak && testVal < *negPeak) |
WiredHome | 2:7f6a39ec5c01 | 303 | *negPeak = testVal; |
WiredHome | 2:7f6a39ec5c01 | 304 | if (posPeak && testVal > *posPeak) |
WiredHome | 2:7f6a39ec5c01 | 305 | *posPeak = testVal; |
WiredHome | 2:7f6a39ec5c01 | 306 | } |
WiredHome | 2:7f6a39ec5c01 | 307 | } |
WiredHome | 2:7f6a39ec5c01 | 308 | return true; |
WiredHome | 2:7f6a39ec5c01 | 309 | } else { |
WiredHome | 2:7f6a39ec5c01 | 310 | return false; |
WiredHome | 2:7f6a39ec5c01 | 311 | } |
WiredHome | 2:7f6a39ec5c01 | 312 | } |
WiredHome | 2:7f6a39ec5c01 | 313 | |
WiredHome | 2:7f6a39ec5c01 | 314 | |
WiredHome | 0:51c019b83ede | 315 | /// Get the apparent power measurement. |
WiredHome | 0:51c019b83ede | 316 | /// |
WiredHome | 0:51c019b83ede | 317 | /// This retrieves the apparent power measurement for the channel which just completed measurement. |
WiredHome | 0:51c019b83ede | 318 | /// |
WiredHome | 0:51c019b83ede | 319 | /// @returns the apparent power measurement. |
WiredHome | 0:51c019b83ede | 320 | /// |
WiredHome | 0:51c019b83ede | 321 | float PowerMeasurement::GetApparentPower() { |
WiredHome | 0:51c019b83ede | 322 | if (isComplete) { |
WiredHome | 0:51c019b83ede | 323 | return GetRMSVoltage() * GetRMSCurrent(); |
WiredHome | 0:51c019b83ede | 324 | } else { |
WiredHome | 0:51c019b83ede | 325 | return 0.0f; |
WiredHome | 0:51c019b83ede | 326 | } |
WiredHome | 0:51c019b83ede | 327 | } |
WiredHome | 0:51c019b83ede | 328 | |
WiredHome | 0:51c019b83ede | 329 | |
WiredHome | 0:51c019b83ede | 330 | float PowerMeasurement::GetPowerFactor() { |
WiredHome | 0:51c019b83ede | 331 | if (isComplete) { |
WiredHome | 0:51c019b83ede | 332 | return GetRealPower() / GetApparentPower(); |
WiredHome | 0:51c019b83ede | 333 | } else { |
WiredHome | 0:51c019b83ede | 334 | return 0.0f; |
WiredHome | 0:51c019b83ede | 335 | } |
WiredHome | 0:51c019b83ede | 336 | } |
WiredHome | 0:51c019b83ede | 337 | |
WiredHome | 1:d99a72afec32 | 338 | |
WiredHome | 1:d99a72afec32 | 339 | bool PowerMeasurement::GetRawSample(int sample, RawPowerData_T * rawsample) { |
WiredHome | 1:d99a72afec32 | 340 | if ((isComplete || (inProcess && sampleNum > sample)) && sample >= 0) { |
WiredHome | 2:7f6a39ec5c01 | 341 | if (rawsample) |
WiredHome | 2:7f6a39ec5c01 | 342 | *rawsample = rawSamples[sample]; |
WiredHome | 1:d99a72afec32 | 343 | return true; |
WiredHome | 1:d99a72afec32 | 344 | } else { |
WiredHome | 1:d99a72afec32 | 345 | return false; |
WiredHome | 1:d99a72afec32 | 346 | } |
WiredHome | 1:d99a72afec32 | 347 | } |
WiredHome | 1:d99a72afec32 | 348 | |
WiredHome | 1:d99a72afec32 | 349 | int PowerMeasurement::GetRawSampleCount(void) { |
WiredHome | 1:d99a72afec32 | 350 | return SAMPLES_PER_CYCLE * CYCLES_PER_SAMPLE; |
WiredHome | 1:d99a72afec32 | 351 | } |
WiredHome | 1:d99a72afec32 | 352 |