Chapter II. Software.
Part 1. Sampling.
Specific of this project compare to VU meter, is necessity to sample two analog inputs simultaneously. I have a blog, where 4 ! analog inputs processed, only with Arduino – Leonardo. This time UNO, but it’s almost the same. Take one channel sample, than switch input multiplexer, take another and so on. Here is the subroutine:
int16_t adc_value = ADC - adc_Offst;
static int16_t last_smpl = 0;
if ( smpl_Nmbr < SAMPL_P )
if( smpl_Nmbr & 0x01 )
ADMUX = 0xC5; // Voltage, pin AN5
v_s[smpl_Nmbr >>1] = (last_smpl + adc_value) / 2; //Linear Interpolation
last_smpl = adc_value;
ADMUX = 0xC4; // Current 3, pin AN4
c_s[smpl_Nmbr >>1] = adc_value;
Another things, related exclusively to Power (Energy) Meter, is phase. It has to be the same for both channels, and as Arduino has only one ADC, it requires some efforts. I choose linear interpolation method, as the easiest one. Other option would be phase rotation after FFT processing, which is also quite simple, but not so as with interpolation. The main duty of the sampling subroutine, is to fill up two data arrays, 64 samples each, 128 samples overall. Sampling goes synchronously, read more in the Power Quality Meter blog for details. Frequency = 60 x 128 = 7680 Hz. Or 3840 Hz per channel. According to the Whittaker-Kotel’nikov-Shannon (WKS) sampling theorem it’s well enough up to 1920 Hz of the analog input signal. Calculating in other directing, 64 – bins FFT outputs 32 bins of results, in other words provides 32 harmonics content, and 32 x 60 = 1920. I read somewhere, that for power metering up to 20-th harmonics must be included, so I’m covering more than standard says.
I noticed, that switching input multiplexer of Arduino UNO, ADC occasionally swapped samples. To solve an issue, I increase default ADC preselector frequency 125 kHz up to 250 kHz in setup().
Part 2. Voltage, Current and Phase.
Sampling flows in background, Real-Time. Each interrupt request at digital pin 2 ( coming from comparator LM311 – look on previous blog-page ) initiates copy procedure of the captured samples from two arrays to another set of two arrays for FFT calculation. To simplify debugging, I assign also two imaginary arrays, even for practical use only one would be sufficient. If memory is an essence in your application, you may eliminate one of them. Interrupt sets a flag “data ready” for main program – loop. In foreground procedure, conveyor belt consists of next stages:
- Calculation Real and Imaginary (Quadrature) part for Voltage;
- - // – same for Current samples;
- Accumulate values for over 32 cycles on main frequency (60 Hz);
- Calculate precise Magnitude and Phase for Voltage;
- Calculate “estimated” magnitude for Current, and set PGA Gain;
- Do precise calculation for Current channel, (subtracting interference, use appropriate gain coefficients);
- Calculate Power usage Power = Voltage x Current (Real);
- Accumulate Energy summing up Power divided by 1000 (kWatts).
Now, I would go step by step.
1. Why FFT for Voltage channel, you may ask. If sampling is synchronous process, than calculation of the phase is also not required – it’s defined by threshold voltage of the comparator. First of all, FFT is very efficient High Pass Filter, which is must be implemented in Voltage channel anyway, to suppress DC voltage offset instability and ADC internal non-linearity / inaccuracy. At step 3 – accumulation, bin – 0 (DC) is not summed. I already explained this here. Secondly, I draw a Current Phase Indicator ( extended Power Factor -90 +90 degree ), and I need Voltage Phase data in order to draw this correctly. Electrical grid Voltage has distorted waveform, and it may be shocking or looks like a paradox, but calculating phase of the 32 harmonics sum, phase is never what it’s originally defined by comparator, and there is no way to trim it to “0″. Voltage shape is never exact in each period. It fluctuates. If there was HPF you would not even know, that each harmonics has unique phase, and only FFT could provide crystal clear picture of this phenomenon. Moreover, averaging data for 32 periods, phase “offset” grows up. ( It’s statistic / math, sure you can find nice tutorial on google. -); . Because of this, Current passing via pure resistive load, always has exactly the same phase “runaway” as Voltage has, and must be subtracted.
2. Ordinary, sum up squares of the 31 bins real and imaginary part, and accumulate. Sign extraction for extended Power Factor indicator based on bin, as major player in Current Magnitude. May be not accurate assumption for highly distorted waveform (for example, with thyristor power regulator). I’m still searching right approach. It would be much easier to show data in 0 – 90 range, but there would not be any difference in capacitive and inductive load, what I want to be visible.
3. Why accumulate? To save on hardware. I did not explain in hardware section, why I choose ~x10 amplification gain per each of two stages, now it is right time. 10 bit arduino ADC could get only 55 dB dynamic range ( 9 bit plus sign, 9 X 6.02 + 1.76 = 55.something ). To have 1% (40 dB) accuracy, stages can’t be spaced more than 15 dB. And if I want 52 dB dynamic range ( 500 : 1, according to standard ), at least 4 amplification steps are required. “Oversampling” data over 32 cycles, more than 2 bits of resolution are additionally obtained, and 11 x 6.02 + 1.76 = 68.almost, providing about 28 dB allowance for spacing, and just 2 cascades of PGA would be enough to cover 52 dB. Gain per stage could be set as high as x25 (28 dB). I pick up x10 and x100 in my “proto-type”, simply to relax on hardware, assembly, wiring, on-board routing etc. You can scale up gain in x20 and x400. One more hardware – software issue, is GLCD library, which in default configuration occupies 5 analog inputs. So I changed config file, moving 3 pins to the other side UNO board, shifting whole pack up from 4 – 11 to 6 – 13 digital pins, and assigning 3 – 5 (digital) to 3 wires that were on analog pins. Doing this way, I have PGA two control lines on AN2 and AN3, Current analog input on AN4, and Voltage on AN5.
Be careful, change LCD wiring and test different config file running test GLCD application before you wire up Power (Energy) Meter to your Arduino!!!.
4, 5 & 6 – below, in Calibration section.
7. Active Power calculated, P = V x I – (Real). The problem, I do not have right equipment to do calibration precisely. In my initial design, I was considering to build two identical boards for voltage and current sensors, so that they would provide precisely match in phase outputs. But as you know, I changed my design, due to unplanned issue with limited optocoupler interference immunity, and now there is small phase offset between two channels. Current signal is passing more filtering / amplification stages, and it’s not surprising that phase is drifted off. Luckily, not much, approximately 0.05 – 0.15 degree, but I can’t be 100% sure, as my heater I used for testing has build-in electrical motor (inductive load , about -45 degree – watch video clip below ). I will do more tests, and if they confirm noticeable phase offset, I would up-date software with phase rotation subroutine, which would allow to make tiny phase adjustment. Or, as I mention in “sampling” paragraph, may be linear approximation with different proportion would be easier approach.
8. Just for estimation. To get “normalized” value, correct timing would be necessary, as in this design all timing / frequency grid varying with electrical main 60 Hz.
Part 3. Calibration.
If you successfully ( and safely ! shock hazard ) build all circuits from hardware blog-page, than you are ready to start calibration. In short, this is not “for beginning” project, and I’m not going to teach how to do calibration of the electrical equipment here. You should already know this.
Minimum good DMM with AC current measurement capability required, and a few loads ranging from 200 mA up to 15 A. Use resistive loads, for example, soldering iron, incandescent bulb (100 – 200 W), heater (1 – 2 kW). Set 0.5V voltage offset on analog pins 4 and 5 trimming two 50k pots on main (LCD) board. If you do have an oscilloscope, check peak-to-peak value on input AN5 received from Voltage sensor Board. 600 – 900 mV would be o’k, If not, use your DMM with a capacitor for DC decoupling. Approximately same DC offset 0.5V should be on input 2 of the comparator, adjust using 1k pot. When comparator runs stable pulses at the output, everything else could be adjusted via arduino serial monitor. There are “x” and “f” commands. One prints out raw data pull, another – process data.
4. Printing out process data via “f” on serial monitor, look for Voltage Magnitude and Voltage Phase two lines. Adjusting comparator’s pot, bring phase as close to “0″ as possible. I have around 1.5 degree “phase runaway”, but it would depends on THD of specific electrical network. Next, divide real Voltage value measured with DMM by Magnitude value received on serial monitor. You get scaling coefficient. Square it up (^2) and substitute in this section:
volt_Real *= 0.002566241; // Calibration coeff. Voltage = ( Real Value / volt_Magn ) ^ 2 !!!
volt_Imag *= 0.002566241; //
Reload sketch, and see how accurate voltage readings you get.
5 & 6. Following the same procedure for current channel, you need to get 3 coefficients. Start with high current – minimum PGA amplification settings. You may comment out this section of the code:
ampr_Magn = sqrt(ampr_Real + ampr_Imag);
if((ampr_Magn < 200) && (ampr_Gain < 3)) ampr_Gain++;
if((ampr_Magn > 2400) && (ampr_Gain > 1)) ampr_Gain--;
and use “manual” switching of the PGA – there are two CLI commands “u” – up and “d” – down, that I implemented to simplify debugging. High current should be easiest part, as interference practically doesn’t exist when nothing connected to “load”.
What I want to light up, is a method of fighting electrical interference I “invented” working on this project. When PGA is set to high amplification mode (~ 360) essentially it’s picking up surrounding electrical EMI. There are would be bunch of reasons, starting from amateur routing traces on the Current sensor board ( It’s about me, I have no clue how to design this stuff ), or inputs terminal placed too close to high voltage network, bad grounding, not shielded cables, etc. etc. As long as EMI readings stable, you would need to confirm this by printing out “f” – process data array many times, when PGA is in high gain mode and nothing connected as a load, it’s a piece of cake to subtract this EMI magnitude directly from squared sum of the Real and Imaginary Current values !!! Doesn’t matter how strong this interference, and what phase it has. In my tests, I see capacitive “phantom” load ( obviously coming somewhere at the input stage of the amplifier ) approximately 8 – 12 mA. Press a button – “s” and arduino would do “zero” settings for you ! Of course, this procedure has to be done after installation, as EMI would change depends on location. Here you are, after zero is set, Power Meter should be good to measure down to 1 mA !!!
Issue with EMI little bit complicate calibration procedure, especially on middle range. You would need to calculate two more coefficients, that scaling down EMI at medium and low gain. Because EMI estimated at high gain settings (PGA-3) first, it has to be divided by ratio ( PGA3 / PGA2 ), and ( PGA3 / PGA1 ), consequently.
I remember, there were black and red painted lines on rotating disk surface of the mechanical power meter installed in our house. When I was a kid, I like to watch on this marks, slowly passing left to right. It moved faster, when my mother did an ironing. I just can’t resist to add this mark animation to the project !
Enjoy the show, Video on youtube would follows shortly. Done.
LCD config file. Download
Arduino Uno sketch. Download