I am writing a software for a small 8-bit microcontroller in C. Part of the code is to read the ADC value of a current transformer (ZCT), and then calculate the RMS value. T
Since your sum-of-squares value acc_load_current does not vary very much between iterations, its square root will be almost constant. A Newton-Raphson sqrt() function normally converges in only a few iterations. By using one iteration per step, the computation is smeared out.
static double one_step_newton_raphson_sqrt(double val, double hint)
{
double probe;
if (hint <= 0) return val /2;
probe = val / hint;
return (probe+hint) /2;
}
static double acc_load_current = 0.0; // accumulator = (I1*I1 + I2*I2 + ... + In*In)
static double rms_current = 1.0;
float adc_value, inst_current;
double tmp_rms_current;
// Calculate the real instantanous value from the ADC reading
inst_current = (adc_value/1024)*2.5; // 10bit ADC, Voltage ref. 2.5V, so formula is: x=(adc/1024)*2.5V
// Update the RMS value with the new instananous value:
// Substract 1 sample from the accumulator (sample size is 512, so divide accumulator by 512 and substract it from the accumulator)
acc_load_current -= (acc_load_current / 512);
inst_current *= inst_current; // square the instantanous current
acc_load_current += inst_current; // Add it to the accumulator
tmp_rms_current = (acc_load_current / 512);
rms_current = one_step_newton_raphson_sqrt(tmp_rms_current, rms_current); // Polish RMS value
// Now the is the APPROXIMATE RMS current
Notes:
float to double (which is normal on a general purpose machine/desktop) If double is very expensive on your microcomputer you could change them back.static, because I did not know if the code was from a function or from a loop.static to force it to be inlined. If the compiler does not inline static functions, you should inline it manually.