public void Measure(int wavelengths, int timeout) { int crossCount = 0; //Used to measure number of times threshold is crossed. int numberOfSamples = 0; //This is now incremented //------------------------------------------------------------------------------------------------------------------------- // 1) Waits for the waveform to be close to 'zero' (500 adc) part in sin curve. //------------------------------------------------------------------------------------------------------------------------- bool st = false; //an indicator to exit the while loop while (st == false && crossCount < 1000) //the while loop... { startVoltage = AnalogRead(voltageInput); //using the voltage waveform if ((startVoltage < 550) && (startVoltage > 440)) { st = true; //check its within range } crossCount++; } if (crossCount >= 1000) { Debug.Print("ERROR:Could not detect zero signal level. Last value=" + startVoltage.ToString()); return; } crossCount = 0; //------------------------------------------------------------------------------------------------------------------------- // 2) Main measurment loop //------------------------------------------------------------------------------------------------------------------------- int start = DateTime.Now.Millisecond; //millis()-start makes sure it doesnt get stuck in the loop if there is an error. while ((crossCount < wavelengths) && ((DateTime.Now.Millisecond - start) < timeout)) { numberOfSamples++; //Count number of times looped. lastSampleVoltage = sampleVoltage; //Used for digital high pass filter lastSampleCurrent = sampleCurrent; //Used for digital high pass filter lastFilteredVoltage = filteredVoltage; //Used for offset removal lastFilteredCurrent = filteredCurrent; //Used for offset removal // A) Read in raw voltage and current samples sampleVoltage = AnalogRead(voltageInput); //Read in raw voltage signal sampleCurrent = AnalogRead(currentInput); //Read in raw current signal // B) Apply digital high pass filters to remove 2.5V DC offset (centered on 0V). filteredVoltage = 0.996 * (lastFilteredVoltage + sampleVoltage - lastSampleVoltage); filteredCurrent = 0.996 * (lastFilteredCurrent + sampleCurrent - lastSampleCurrent); // C) Root-mean-square method voltage squaredVoltage = filteredVoltage * filteredVoltage; //1) square voltage values voltageSum += squaredVoltage; //2) sum // D) Root-mean-square method current squaredCurrent = filteredCurrent * filteredCurrent; //1) square current values currentSum += squaredCurrent; //2) sum // E) Phase calibration phaseShiftedVoltage = lastFilteredVoltage + calibrationPhase * (filteredVoltage - lastFilteredVoltage); // F) Instantaneous power calc instantaneousPower = phaseShiftedVoltage * filteredCurrent; //Instantaneous Power powerSum += instantaneousPower; //Sum // G) Find the number of times the voltage has crossed the initial voltage // - every 2 crosses we will have sampled 1 wavelength // - so this method allows us to sample an integer number of wavelengths which increases accuracy lastVoltageCross = checkVoltageCross; if (sampleVoltage > startVoltage) { checkVoltageCross = true; } else { checkVoltageCross = false; } if (numberOfSamples == 1) { lastVoltageCross = checkVoltageCross; } if (lastVoltageCross != checkVoltageCross) { crossCount++; } } // 3) Post loop calculations //Calculation of the root of the mean of the voltage and current squared (rms) //Calibration coeficients applied. RMSVoltage = calibrationVoltage * SquaredRoot(voltageSum / numberOfSamples); RMSCurrent = calibrationCurrent * SquaredRoot(currentSum / numberOfSamples); //Calculation power values RealPower = calibrationVoltage * calibrationCurrent * powerSum / numberOfSamples; ApparentPower = RMSVoltage * RMSCurrent; PowerFactor = RealPower / ApparentPower; // kwh increment calculation // 1) find out how much time there has been since the last measurement of power lwhtime = whtime; whtime = DateTime.Now.Ticks; whInc = RealPower * ((whtime - lwhtime) / 3600000.0); //Reset accumulators voltageSum = 0; currentSum = 0; powerSum = 0; //-------------------------------------------------------------------------------------- Debug.Print("rmsVoltage = " + RMSVoltage.ToString() + " rmsCurrent = " + RMSCurrent.ToString() + " apparentPower = " + ApparentPower.ToString() + " PowerFactor = " + PowerFactor.ToString() + " Wh = " + whInc.ToString()); }