David Smart / PowerMeasurement
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PowerMeasurement.h Source File

PowerMeasurement.h

00001 ///
00002 ///
00003 /// 
00004 
00005 #ifndef POWERMEASUREMENT_H
00006 #define POWERMEASUREMENT_H
00007 
00008 #include "mbed.h"
00009 
00010 
00011 /// The PowerMeasurement class is used to take voltage and current measurements and compute power consumption.
00012 /// 
00013 /// This is done as a process that takes some amount of time, as it will sample two inputs over a number of
00014 /// cycles of the AC line input (typically 60 Hz). In order to avoid blocking the CPU any more than necessary
00015 /// it will be processed with a ticker. So, there will be functions to start an acquisition, monitor the
00016 /// acquisition, and extract the results when it is done.
00017 ///
00018 /// The power measurement is performed on virtual channels, which map to real analog inputs. The virtual
00019 /// channels may be direct-wired to the processor analog inputs, or it may be esternally multiplexed.
00020 ///
00021 /// Electrically, the voltage measurements are normalized so the A/C swing is biased to mid-range on the
00022 /// A/D and then peak-to-peak is measured from 0 to FFFF.
00023 ///
00024 /// @code
00025 ///              NumMuxes
00026 ///              +----------+   MuxChannels
00027 /// Input 1   ---|0        a|--------------------------------------+
00028 /// Input 2   ---|1        b|--------------------------------------+
00029 /// Input 3   ---|2        c|--------------------------------------+
00030 /// ...       ---|          |                                      |
00031 /// ...       ---|       inh|------------------------------------+ |
00032 /// ...       ---|          |        AinCount                    | |
00033 /// ...       ---|          |        +--------------+            | |
00034 /// Input 8   ---|7        Y|--------|p15           |            | |
00035 ///              +----------+        |              |  Select    | |
00036 ///                                  |           pxx|------------+ |
00037 ///                             - - -|p16           |              |
00038 ///                                  |              |              |
00039 ///                                  |              |              |
00040 ///                                  |              |  MusBus      |
00041 ///                                  |           pcc|--------------+
00042 ///                                  |           pbb|--------------+
00043 ///                                  |           paa|--------------+
00044 ///  GetVoltage() ------->           |              |
00045 ///                                  +--------------+
00046 ///
00047 /// @endcode
00048 ///
00049 class PowerMeasurement {
00050 public:
00051     /// The callback to get the instantaneous value of the voltage time-synchronous with the current measurement.
00052     ///
00053     /// The called function should return the instantaneous voltage measurement. The value is an unsigned value
00054     /// normalized to the range of 0 to FFFF, with a zero-offset of 32768.
00055     ///
00056     /// If not voltage measurement system is in place, the user may choose not to define this function, in 
00057     /// which case the power measurements cannot be made. The current measurements are still valid, and power
00058     /// can be computed by the users program.
00059     ///
00060     /// @returns a value in the range of 0 to FFFF, biased to the mid-point of 32768 which represents 0.0v.
00061     ///
00062     typedef uint16_t (* GetVoltage_T)(void);
00063     
00064     /// Each raw sample consists of 2 values - the voltage and the current at that moment. The labels 'voltage'
00065     /// and 'current' are somewhat artificial. The 'current' values are gathers from the analog inputs and 
00066     /// multiplexers. The 'voltage' is from an external callback, which in turn might be using one of the 
00067     /// analog inputs, or it might be from an external measurement source.
00068     typedef struct {
00069         uint16_t voltage;               ///< The voltage, in A/D units, which are scaled 0 to FFFF
00070         uint16_t current;               ///< The current, in A/D units, which are scaled 0 to FFFF
00071     } RawPowerData_T;
00072     
00073     #define SAMPLES_PER_CYCLE 100       ///< The number of samples in each cycle
00074     #define CYCLES_PER_SAMPLE 2         ///< The number of cycles in the sample
00075     #define PM_ZERO_OFFSET 32767        ///< Zero-Offset applied to A/D values
00076     #define PM_FULL_SCALE  32767        ///< The full-scale value against the calibration
00077 
00078     /// The constructor for the PowerMeasurement class is used to create various hardware assignments.
00079     ///
00080     /// @param[in] AinList is a pointer to an array of AnalogIn classes
00081     /// @param[in] MuxBus is a pointer to a BusOut that is used to select the external multiplexer channel.
00082     /// @param[in] Select is a pointer to a DigitalOut that is used to enable the external multplexer.
00083     /// @param[in] v_get is the callback used to get the voltage time synchronous with the current measurement.
00084     /// @param[in] AinCount is the count of Analog Inputs to use, from 1 to 6, which maps to p15 thru p20. Default: 6.
00085     /// @param[in] MuxChannels is the count of channels on each external multiplexer. Default: 8.
00086     ///
00087     PowerMeasurement(AnalogIn * AinList, BusOut * MuxBus = NULL, DigitalOut * Select = NULL, 
00088         GetVoltage_T callback = NULL, int AinCount = 6, int MuxChannels = 8);
00089 
00090     /// The destructor.
00091     ~PowerMeasurement();
00092 
00093     /// Define the frequency of the line voltage, which in turn defines the sample-rate.
00094     ///
00095     /// Based on this line frequency, the sample-rate for the measurement is set to achieve
00096     /// 'SAMPLES_PER_CYCLE' samples per cycle, and 'CYCLES_PER_SAMPLE' cycles.
00097     /// 
00098     /// @param[in] Hz sets the line frequency.
00099     ///
00100     void frequency(float _Hz);
00101 
00102     /// Define the measuremenbt interval, as an alternative to setting the frequency.
00103     ///
00104     /// Instead of defining the measurement interval by specifying the line frequency, the period
00105     /// can be directly set.
00106     ///
00107     /// @param uSec is the number of microseconds between samples.
00108     /// 
00109     void period_us(uint32_t uSec);
00110 
00111     /// Set the analog input to current calibration value for a channel.
00112     ///
00113     /// Each analog input channel can be configured for the current sensor used on that channel.
00114     /// If the channel has a 30 A current sensor, that channel should be set to 30.0f.
00115     /// If the user calibrates the sensor more precisely, an improved calibration factor (e.g. 31.1)
00116     /// can be defined.
00117     ///
00118     /// The calibration is based on the full-scale reading from the A/D. As the A/D is a normalized
00119     /// uint16_t value, and biased to approximately mid-supply, the full scale range is then
00120     /// 1/2 of the total range, or approximately 32767. Component tolerances, of the voltage 
00121     /// reference, the mid-supply divider, and the current sensing component can affect this.
00122     ///
00123     /// @param[in] channel defines the channel to calibrate.
00124     /// @param[in] fullScaleCurrentCalibration is the calibration factor representing the full-scale current.
00125     /// @returns true if the value is accepted.
00126     /// @returns false if the channel was incorrect.
00127     ///
00128     bool SetFullScaleCurrent(int channel, float fullScaleCurrentCalibration);
00129 
00130     /// Set the voltage value representing the full scale measurement.
00131     ///
00132     /// The GetVoltage callback is expecting a uint16_t as the return value. When configured for a 
00133     /// 120V circuit, which measures approximately 170v peak, the fullScaleVoltageCalibration value 
00134     /// would be 170.0f.
00135     /// 
00136     /// The calibration is based on the full-scale reading from the A/D. As the A/D is a normalized
00137     /// uint16_t value, and biased to approximately mid-supply, the full scale range is then
00138     /// 1/2 of the total range, or approximately 32767. Component tolerances, of the voltage 
00139     /// reference, the mid-supply divider, and the current sensing component can affect this.
00140     ///
00141     /// @param[in] fullScaleVoltageCalibration is the full-scale voltage value.
00142     /// @returns true if the value is accepted, which it will be.
00143     /// 
00144     bool SetFullScaleVoltage(float fullScaleVoltageCalibration);
00145 
00146     /// Starts a measurement on the specified channel.
00147     ///
00148     /// This starts the measurement on a specified channel. The subsystem will then configure
00149     /// the external multiplexer and a/d sampling to gather the the samples.
00150     ///
00151     /// The actual sampling of the data can be either synchronous, or asynchonous, based on a
00152     /// #define value.
00153     ///
00154     /// @param[in] channel defines the channel to measure. This is in the range of 0 to N-1, where N is 
00155     ///         AinCount * MuxChannels.
00156     /// @returns true if the measurement can be started (in async mode), or if the measurement is complete
00157     ///         when operating in synchonous mode.
00158     /// @returns false if the measurement cannot be started - likely because of an incorrect channel 
00159     ///         selection.
00160     ///
00161     bool StartMeasurement(int channel);
00162 
00163     /// Determines if the conversion is complete and the results are readable.
00164     ///
00165     /// When operating in the asynchronous mode, this API can be used to detect when the conversion
00166     /// is complete.
00167     ///
00168     /// @returns true if the measurement is complete (or if no measurement is in process).
00169     /// @returns false if the measurement is in process.
00170     ///
00171     bool readable();
00172 
00173     /// Get the rms current measurement.
00174     ///
00175     /// This retrieves the rms current measurement for the channel which just completed measurement.
00176     ///
00177     /// @returns the rm current measurement.
00178     ///
00179     float GetRMSCurrent();
00180 
00181     /// Get the rms voltage measurement.
00182     ///
00183     /// This retrieves the rms voltage measurement for the channel which just completed measurement.
00184     ///
00185     /// @note This is only valid if the user supplied GetVoltage() function was provided.
00186     ///
00187     /// @returns the rms voltage measurement.
00188     ///
00189     float GetRMSVoltage();
00190 
00191     /// Get the real power measurement.
00192     ///
00193     /// This retrieves the real power measurement for the channel which just completed measurement.
00194     /// This is the average of the instantaneous power.
00195     ///
00196     /// @note This is only valid if the user supplied GetVoltage() function was provided.
00197     ///
00198     /// @returns the real power measurement.
00199     ///
00200     float GetRealPower();
00201 
00202     /// Get the apparent power measurement.
00203     ///
00204     /// This retrieves the apparent power measurement for the channel which just completed measurement.
00205     ///
00206     /// @note This is only valid if the user supplied GetVoltage() function was provided.
00207     ///
00208     /// @returns the apparent power measurement.
00209     ///
00210     float GetApparentPower();
00211 
00212     /// Get the power factor
00213     ///
00214     /// @note This is only valid if the user supplied GetVoltage() function was provided.
00215     ///
00216     /// @returns the power factor measurement.
00217     ///
00218     float GetPowerFactor();
00219 
00220     /// Get the peak current measurement values from the recent sample.
00221     ///
00222     /// @note if either parameter is null, that data will not be provided.
00223     ///
00224     /// @param[inout] negPeak is a pointer to the negative going peak current measured.
00225     /// @param[inout] posPeak is a pointer to the positive going peak current measured.
00226     /// @returns true if a measurement was completed and the data was updated.
00227     /// @returns false if a measurement has not started or is in process.
00228     ///
00229     bool GetPeakCurrent(float * negPeak, float * posPeak);
00230 
00231     /// Get the raw sample data for a given sample number.
00232     ///
00233     /// If a measurement is complete, or has at least proceeded beyond the desired
00234     /// sample, then pass that raw data to the calling function.
00235     ///
00236     /// @param[in] sample is the sample number of interest, ranging from 0 to N-1.
00237     /// @param[inout] rawsample is a pointer to where the specified sample will be written.
00238     /// @returns true if the sample was available for the calling function.
00239     /// @returns false if the same was not available.
00240     ///
00241     bool GetRawSample(int sample, RawPowerData_T * rawsample);
00242 
00243     /// Get the count of raw samples that are being taken,
00244     ///
00245     /// @returns count of samples that are taken.
00246     ///
00247     int GetRawSampleCount(void);
00248 
00249 private:
00250 
00251     void TakeSample(void);          ///< Ticker callback to take a sample
00252     BusOut * MuxBus;                ///< pointer to the bus used to modify the multiplexer.
00253     DigitalOut * Select;            ///< pointer to the pin used to enable the multiplexer.
00254     GetVoltage_T * GetVoltage;      ///< pointer to the GetVoltage callback.
00255     int AinCount;                   ///< count of direct A/D channels.
00256     int NumMuxes;                   ///< count of the number of multiplexers.
00257     int MuxChannels;                ///< count of the number of channels per multiplexer.
00258     
00259     AnalogIn * AinList;             ///< This defines the list of AnalogInputs
00260     int a2dChannel;                 ///< the AnalogIn channel number to sample
00261     uint32_t uSecInterval;          ///< time in uSec between each sample
00262     int totalChannels;              ///< total number of input channels
00263     Ticker sampleTimer;             ///< Timer to schedule the a/d sample.    
00264     volatile bool inProcess;                 ///< indicates when a sample is in process.
00265     volatile bool isComplete;                ///< indicates when conversion is complete.
00266     RawPowerData_T * rawSamples;    ///< points to an array of raw a/d value samples.
00267     volatile int sampleNum;                  ///< keeps track of the current sample in process.
00268     float * fullScaleCurrent;       ///< pointer to an array sized based on total number of channels.
00269     float fullScaleVoltage;         ///< the full scale voltage calibration setting.
00270 };
00271 
00272 
00273 
00274 
00275 #endif // POWERMEASUREMENT_H