50/60 Hz signals and ADC sampling frequency - Page 1
Forum section: electronics / general

author: Red_Micro
author_rank: Regular Contributor
timestamp: September 01, 2020, 03:26:41 am
content: I'm trying to find the RMS of sine wave during the first cycle, but I have some questions as for the sampling frequency.Let's say I choose a sampling frequency of 1 kHz. That's one sample per millisecond. For a 50 Hz signal: 20 ms/1 ms = 20 samples per cycle. For a 60 Hz signal: 16.67 ms/ 1 ms = 17 samples per cycleBut my system won't know if it's a 50 Hz or 60 Hz signal to adjust the number of samples, so is there a way to capture both frequencies with a common number of samples and sampling frequency? My application is to measure only earth leakage current. No intention to find power.

author: ataradov
author_rank: Super Contributor
timestamp: September 01, 2020, 04:05:14 am
content: It is obviously impossible. It it not about the sample rate, but about the time you need to wait for the samples to be captured. And that depends on the frequency.The best you can do is collect a number of cycles necessary for the longest period and then check if you actually got the shorter one. So on the first cycle you will have to collect more samples that necessary in 60 Hz case. For the second cycle you can adjust.Or if you are processing samples in real-time, then just wait until the period is reached.

author: MasterT
author_rank: Frequent Contributor
timestamp: September 01, 2020, 04:14:21 am
content: Measure 100 msec period, 10 Hz. Than both 50&60 Hz lined up with 5 & 6 cycles of sinewave

author: ataradov
author_rank: Super Contributor
timestamp: September 01, 2020, 04:15:58 am
content: But you still need to collect different number of cycles. And the request is "to capture both frequencies with a common number of samples and sampling frequency".

author: MasterT
author_rank: Frequent Contributor
timestamp: September 01, 2020, 12:30:55 pm
content: Quote from: ataradov on September 01, 2020, 04:15:58 am? Common number of samples = 100, sampl. freq. is the same = 1 kHz. Different number of sinewave cycles has no effect on RMS value.

author: Red_Micro
author_rank: Regular Contributor
timestamp: September 01, 2020, 04:32:35 pm
content: Thank for the answers above. One last question... The ADC will be running all the time, but I wouldn't want to trigger the RMS calculation if there's no the AC signal, otherwise the RMS will be the DC offset. Is it good to say that if any of the samples is greater than DC offset, then do RMS calculation after the 100 samples are taken?

author: ebastler
author_rank: Super Contributor
timestamp: September 01, 2020, 04:46:29 pm
content: Quote from: Red_Micro on September 01, 2020, 04:32:35 pmWhy don't you measure the DC average all the time (as a sliding average or an average over the above-mentioned 100 ms), subtract that from the stream of samples to obtain its AC component, and perform the RMS calculation on the AC component only?Looking at individual samples for a yes/no decision is not a great solution, since it will be very sensitive to noise. In your exampe, there willalwaysbe individual sample values greater than the DC offset (and others smaller than the offset), due to noise on the samples.

author: MasterT
author_rank: Frequent Contributor
timestamp: September 01, 2020, 04:50:08 pm
content: Quote from: Red_Micro on September 01, 2020, 04:32:35 pmGreater OR lower. To find out you have to subtract DC offset and compare abs() to pre-set threshold value. Though I'd calculate rms all the time, small uCPU like atmega328 have no issue to spend 1-5% of clock cycles doing math.

author: Red_Micro
author_rank: Regular Contributor
timestamp: September 01, 2020, 07:51:16 pm
content: Quote from: MasterT on September 01, 2020, 04:14:21 amI'm not too experienced on this topic so I'm wondering if waiting 5 & 6 cycles to get RMS is quick enough for my application. Ideally I wanted to get RMS in the first 1/2/3 cycles, but I don't think it is possible as the frequencies don't line up. The closest alignment I find is with the 100 ms period for a fixed sampling frequency approach.

author: ebastler
author_rank: Super Contributor
timestamp: September 01, 2020, 08:11:08 pm
content: Quote from: Red_Micro on September 01, 2020, 07:51:16 pmSince you have not told us what you application is, we can't tell you either. ;-)QuoteSure, 100 ms is the smallest common multiple of the two periods (20 ms and 16.66 ms), so there is no shorter sampling window which is compatible with both frequencies. What you could do is a sliding RMS calculation which lets you update your putput or display more frequently:Always do your RMS calculations over a window of 100 ms length, and retain those 100 sample values. Every X ms (where X is between 1 and 99), forget the oldest X samples, append X new samples, and calculate the RMS over the new set of 100 samples.That way, you can get display which updates more frequently than 10 times per second. But it will always show an RMS value which represents the average over the past 100 ms, hence will respond to fast changes of the input with a gradual change of the output, which lags behind a bit.In practice, it's best to chose an X which is a divider of 100, say 10 or 20, and pre-calculate the sum and the sum of squares for each chunk of X samples. Then you don't have to do the whole 100 calculations every time, and don't have to actually store the 100 values. Just store the averages for, say, 5 sub-windows of 20 samples each, and manage these in the "forget the oldest, append a new one" scheme described above.

author: Red_Micro
author_rank: Regular Contributor
timestamp: September 01, 2020, 08:30:45 pm
content: Quote from: ebastler on September 01, 2020, 08:11:08 pmYes, in my first post I said it is an earth leakage current detection. The reason to do RMS is because I don't expect perfect sine wave.Another thing is that I may use DMA with circular array, perhaps that's another way of doing it.

author: ebastler
author_rank: Super Contributor
timestamp: September 01, 2020, 08:43:40 pm
content: Quote from: Red_Micro on September 01, 2020, 08:30:45 pmSure, you mentioned earth leakage detection. But how fast do you need to detect it? Is it meant to trigger some automated response, and if so, what are the sensitivity and timing specs?DMA with a circular array would just be the mechanism to get the data into memory, right? (It may be a good mechanism, or it may be overkill. At 1 kHz sampling frequency, an interrupt handler to get the ADC data should be perfectly adequate.) But using DMA does not change anything regarding the time window required for meaningful processing of the samples, as discussed in this thread.

author: Red_Micro
author_rank: Regular Contributor
timestamp: September 01, 2020, 10:27:12 pm
content: Quote from: ebastler on September 01, 2020, 08:43:40 pmTo give some background, previously there was a circuit which used peak detection of the earth leakage AC current to release a solenoid. The tripping time delay could be adjusted from 0 to say 5 seconds. The "0" will be "the quickest" time the system is able to trip. Some systems translates this zero to about 20-30 milliseconds.Back to my post, I didn't opt for peak detection because of the nuisance tripping, and the signal is not perfect sine. That's why I wanted to try with RMS to get "more reliable" data at the expense of slower response time, of course. Ideally I would want to detect the current as quick as possible and that happens only during the first cycle of the signal. But as I will do RMS, and sample for 100 ms, I will wait 5/6 cycles to send the tripping signal. I will do fast RMS, so I expect the micro not to spend much time on it and release the solenoid in much less than 40 ms.

author: NorthGuy
author_rank: Super Contributor
timestamp: September 01, 2020, 11:43:33 pm
content: Quote from: Red_Micro on September 01, 2020, 10:27:12 pmWhy do you need RMS? Detect the peak. Wait for 3 successive values above (or below) certain threshold, and trip.If you wait 100 ms measuring, then calculation, then solenoid lag - 150 ms. Less than 50 ms if you detect the peak.

author: Red_Micro
author_rank: Regular Contributor
timestamp: September 02, 2020, 12:05:01 am
content: Quote from: NorthGuy on September 01, 2020, 11:43:33 pmPeak detection is more prone to false tripping. I think the three successive values you suggest is to improve that, right?

author: NorthGuy
author_rank: Super Contributor
timestamp: September 02, 2020, 01:21:09 am
content: Quote from: Red_Micro on September 02, 2020, 12:05:01 amOf course. Can be five. If you have some sort of test machine, you can find out what frequency, level, and number of samples produce the best results based on what your criteria are.

author: David Hess
author_rank: Super Contributor
timestamp: September 02, 2020, 05:34:04 am
content: Quote from: Red_Micro on September 01, 2020, 07:51:16 pmMaking an integrated measurement over 100 milliseconds is a common method when high rejection of other signals is required and the source can be 50 or 60 Hz but if a shorter measurement time is required, then some multimeters lock to the 50 or 60 Hz source and adjust their measurement time appropriately.I think the fastest measurement would be to phase lock to the source so that the phase of every sample is known, then a single measurement not at a zero crossing will reveal the current amplitude. In practice this might mean phase locking and taking a measurement at each peak so every 10 or 8.33 milliseconds, or maybe every 45, 30, or 15 degrees.

author: voltsandjolts
author_rank: Unknown
timestamp: September 02, 2020, 10:50:20 am
content: What hardware are you using to safely couple the mains AC signal into your ADC?

author: Red_Micro
author_rank: Regular Contributor
timestamp: September 02, 2020, 12:08:56 pm
content: Quote from: voltsandjolts on September 02, 2020, 10:50:20 amI'm using a CT, a burden and an opamp.

author: radiolistener
author_rank: Super Contributor
timestamp: September 04, 2020, 03:34:00 pm
content: Quote from: Red_Micro on September 01, 2020, 07:51:16 pmfor what bandwidth you're want to calculate RMS voltage?Usually RMS voltmeter for mains needs about 20-200 kHz bandwidth.ADC bandwidth is a half of sample rate frequency. In order to reduce aliases ADC bandwidth needs to be about 3 times wider than anti-alias filter cut-off.In order to get flat response, anti-alias filter on the ADC input also should be about 3 times wider than your measurement bandwidth.So, if you want 20 kHz measurement bandwidth, then you're needs about 20*3=60 kHz anti-alias filter cut-off on the ADC input. And ADC bandwidth about 60*3=180 kHz. It means you will need ADC sample rate 180*2 = 360 kHz.Also you will need to apply low pass filter in digital domain with sharp slope and flat response for your measurement within 20 kHz bandwidth.

author: David Hess
author_rank: Super Contributor
timestamp: September 04, 2020, 07:25:39 pm
content: Quote from: radiolistener on September 04, 2020, 03:34:00 pmBut the bandwidth of an RMS voltmeter has nothing to do with the settling time, which can vary depending on signal level.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: September 04, 2020, 08:44:18 pm
content: Why choose a 1kHz sample frequency?I.e:50*60 = 3000Or: if you use a 3kHz sample frequency and take a bunch of samples then you have a buffer to do some math.1). First estimate some average DC offset.2). Count the number of samples between the zero crossings.3). For a 50Hz signal, use 60 samples from the buffer to calculate the RMS value.4). For a 60Hz signal, use 50 samples from the buffer to calculate the RMS value.This can also be done with a 1.5kHz sample rate, or a another frequency which is a common multiple of those mains frequencies.There is also a sneaky thing about the period of the signal.As you probably know, you have to use a number of full cycles to accurately calculate the RMS value.But mains frequency varies a bit, and your sample frequency is probably also not syncrhonised with the mains frequency.For simplicity sake, assume an uncertainty of 1 sample, so you either have one sample too many, or one sample too less, but you do not know which.If you calculate the RMS from positive zero crossing to positive zero crossing, then the erroneous last sample is close to zero, which has a relative big influence on the calculated RMS result.Similar if you sample from top to top. The erroneous sample will be near the mains peak value, and also has a noticeable influence on the result.If you however estimate a phase shift of 60 degrees, then the instantaneous voltage at the start and at the end of your sample interval is close to the RMS value, and it (almost) cancels out with the RMS averaging of the samples!

author: jesuscf
author_rank: Frequent Contributor
timestamp: September 06, 2020, 04:10:48 am
content: This rings a bell. I think I did something like what the OP wants back in 2003. Disclaimer: I may be wrong though about what it is required. Anyhow, here it goes. Assuming you can do a bit of math in the processor your are using this is one way of doing it; assume you have a nice sine wave on top of a nice DC as described by this equation:\$v(t)=V_{DC}+\sqrt{2}V_{RMS}cos(2{\pi}ft+\theta)\$Take three samples spaced by some time 'h' so that the samples fit inside one period of the wave you are trying to process, and construct this system of equations:\$\begin{cases}v(t)=V_{DC}+\sqrt{2}V_{RMS}cos(2{\pi}ft+\theta)\\v(t-h)=V_{DC}+\sqrt{2}V_{RMS}cos(2{\pi}f(t-h)+\theta)\\v(t-2h)=V_{DC}+\sqrt{2}V_{RMS}cos(2{\pi}f(t-2h)+\theta)\end{cases}\$In my case I knew 'f', and wanted the DC component, the RMS component, and the phase angle, which I obtained algebraically! I think it should be possible, by adding another sample and corresponding equation, to calculate the frequency, DC, RMS, and phase. May not be possible (or difficult) algebraically, but the newton-raphson method should be capable of handling it. If I remember correctly, this technique is described in a paper by Makino and Miki related to protective relays in electric power systems.

author: hamster_nz
author_rank: Super Contributor
timestamp: September 06, 2020, 06:27:43 am
content: A couple of observations....If you know what the average is, you only need to sample for 50ms (2.5 cycles of the 50 Hz, 3 cycles of the 60 Hz), to have a common period (look at a graph of V*V if unsure why this is)Also, if you record the total power of the signal and average voltage (i.e. y*y and y), then to calculate power power you can subtract the DC component from the total power, giving the AC power. The RMS voltage of the AC is the sqrt() of the the AC power. That way you don't need to know the average signal while you are sampling them, or have to make two passes of the data (one to get the average, one to get the RMS from the data minus the average)

author: Kleinstein
author_rank: Super Contributor
timestamp: September 06, 2020, 10:08:51 am
content: There is no need to have the sample rate in such a way to get an integer number of readings per period. It only helps if the total integration time is a multiple of full periods. If one does not have access to the mains frequency, one could try to get the frequency from the measured values.To reduce the error from not having the right length one can use a soft end and start, so have a few values at the ends with reduced weight, a little like used with the FFT windowing function.One may not need an aliasing filter - one could even intentionally leave it out and do some "random" dithering on the sampling times to get closer to random sampling. This way one could rise the effective BW from 1/2 the sampling rate to 1 over 2 * sampling time.Many DMMs have a BW in the 20-200 kHz range, but this does not mean one needs this to measure mains frequency. A limited BW means less noise and can even be an advantage for weak signals.

author: hamster_nz
author_rank: Super Contributor
timestamp: September 06, 2020, 11:12:53 am
content: I know it doesn't meet your needs to find out the AC value in 1/50th or 1/60th of a second - this needs 1/10th.However, here's what I was indirectly ranting about...The update when you get a new sample is very simple:Code:static void include_new_sample(uint16_t new_data) {// Remove the oldest samplerunning_total -= data;running_squared_total -= data*data;// Add the new samplerunning_total += new_data;running_squared_total += new_data*new_data;// Store the new data for when we remove itdata = new_data;// Update the indexindex = (index == N_POINTS-1) ? 0 : index+1;}Extracting the DC and AC RMS values is pretty simple too, (but only if you can use floating point, with integers only it will be a bit more tricky):Code:static void output_results(void) {double avg, total_power, dc_power, ac_power, ac_rms;avg = running_total/(double)(N_POINTS);total_power = running_squared_total/((double)(N_POINTS));dc_power = avg*avg;ac_power = total_power - dc_power;ac_rms = sqrt(ac_power);printf("%4i: Average is %6.2f, dc power is %9.1f, ac power is %8.1f, ac_rms %6.2f\n",sample_no, avg, dc_power, ac_power, ac_rms);}Here's the full test, in case you want to play with it. Note that it will of course take 100 samples to 'ramp up', and is using unsigned int values:Code:#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <math.h>#include <time.h>#define N_POINTS 100static uint16_t data;static uint16_t index;static uint32_t running_total;static uint32_t running_squared_total;static uint32_t sample_no = 0;static void include_new_sample(uint16_t new_data) {// Remove the oldest samplerunning_total -= data;running_squared_total -= data*data;// Add the new samplerunning_total += new_data;running_squared_total += new_data*new_data;// Store the new data for when we remove itdata = new_data;// Update the indexindex = (index == N_POINTS-1) ? 0 : index+1;}static void output_results(void) {double avg, total_power, dc_power, ac_power, ac_rms;avg = running_total/(double)(N_POINTS);total_power = running_squared_total/((double)(N_POINTS));dc_power = avg*avg;ac_power = total_power - dc_power;ac_rms = sqrt(ac_power);printf("%4i: Average is %6.2f, dc power is %9.1f, ac power is %8.1f, ac_rms %6.2f\n",sample_no, avg, dc_power, ac_power, ac_rms);}uint16_t get_sample(int waveform) {uint16_t new_val = 0;switch(waveform) {case 1: // Random of +/- 50, DC of 100 , RMS of about 30new_val = rand()/(RAND_MAX/100)-50 + 100;break;case 2: // Sine of 20 samples (50Hz at 1kS/s), 70.7 units RMS, DC 200new_val = sin(2.0*M_PI * sample_no/20)*100 + 200;break;case 3: // Sine of 16.6 samples (60Hz @ 1kS/s) 70.7 units RMS DC 512new_val = sin(2.0*M_PI * sample_no/16.66)*100 + 512;break;default:new_val = 0;break;}sample_no++;return new_val;}int main(int argc, char *argv[]) {srand(time(NULL)); // Just in case we use rand()for(int i = 0; i < 1000; i++) {include_new_sample(get_sample(3));// Results only every 10 samplesif(i %10 == 0) output_results();}}

author: NorthGuy
author_rank: Super Contributor
timestamp: September 06, 2020, 03:57:58 pm
content: If someone uses the device in a place powered by a generator, the frequency may vary. Nominally, generator is 60 Hz, but as the load on the generator changes and the generator tries to adjust, the frequency may vary between 50 and 70 Hz, or even wider.

author: David Hess
author_rank: Super Contributor
timestamp: September 07, 2020, 04:35:07 am
content: Quote from: NorthGuy on September 06, 2020, 03:57:58 pmHigher performance designs phase lock a local oscillator to the line frequency to provide a clean phase reference. Today of course this is all done in the digital domain.

author: Red_Micro
author_rank: Regular Contributor
timestamp: September 07, 2020, 03:55:54 pm
content: I also found this code that is attached that claims to calculate RMS using Walsh Functions. The author said it was tested on an Atmega328P. Anyways, Walsh Functions is a totally different monster for me so it would take a while for me to understand it. I think that code is only for 60 Hz. Not sure if it even works. Maybe someone can have a look and provide feedback.Source of the code:https://www.avrfreaks.net/forum/adc-calculating-rms-dc-biased-signal

author: hamster_nz
author_rank: Super Contributor
timestamp: September 08, 2020, 09:59:20 pm
content: Quote from: Red_Micro on September 07, 2020, 03:55:54 pmHad a look at the math behind this. It's much like a single FFT bin at f/4, but with a tiny twist to make the math cleaner.- Take four samples 90 degrees apart (so will need different samples for different frequencies- Multiply samples by sin() and cos(), but at 45, 135, 225, 315 degrees (e.g. 0.707, 0.707, -0.707, -0.707 for sin()) rather than the usual 0,90,180,270 degrees.- However, these are pre-scaled by the 1/(RMS of a sine wave), which is 0.707, making the coefficients (1,1,-1,-1) fir sin() and (1, -1, -1, 1) for cos(). This turns the mults into just adds and subtracts.- Then compute the magnitude of the resulting vectorSo the code ends up being the relatively simple:Code:CAL = x0 - x1 - x2 + x3SAL = x0 + x1 - x2 - x2RMS = sqrt(CAL*CAL + SAL*SAL)Pretty cute.

author: Red_Micro
author_rank: Regular Contributor
timestamp: September 08, 2020, 11:36:18 pm
content: Quote from: hamster_nz on September 08, 2020, 09:59:20 pmMakes sense. It looks like it works good only for 60 Hz not for 50 Hz.

author: hamster_nz
author_rank: Super Contributor
timestamp: September 08, 2020, 11:58:33 pm
content: Quote from: Red_Micro on September 08, 2020, 11:36:18 pm... and most likely only if you have tightly band-passed the signal to the target frequency before sampling.