STM32F030C6 ADC RMS Voltage Measurement Inconsistency After Reset - Page 1
Forum section: electronics / general

author: Shubham
author_rank: Contributor
timestamp: October 10, 2024, 11:55:48 am
content: Hello everyone,I am working on a project using the STM32F030C6https://www.st.com/en/microcontrollers-microprocessors/stm32f030c6.htmlmicrocontroller to measure mains RMS voltage. The voltage divider output is connected to the ADC (channel 0 pin), and I am taking 800 samples at a 125µs interval to calculate the RMS value.The issue I am facing is that after restarting the microcontroller, the ADC readings seem to deviate, which impacts the accuracy and precision of the RMS voltage calculation. Here's what I have tried so far:1) ADC Calibration: I perform ADC calibration on power-up in my code.2)Increased ADC Sampling Time: I changed the ADC sampling time from 1.5 cycles to 71.5 cycles, but this did not resolve the issue.Despite these steps, the problem persists. My question is:1) Could this issue be related to my schematic?2) What other potential causes or troubleshooting steps should I consider for stabilizing the ADC values?Thank you for any insights or suggestions!Schematic:

author: radiolistener
author_rank: Super Contributor
timestamp: October 10, 2024, 01:03:43 pm
content: I suggest you first debug ADC with a DC measurement, not RMS.Then when it will works as expected, you can debug RMS code.

author: Shubham
author_rank: Contributor
timestamp: October 11, 2024, 10:18:43 am
content: I am sure my code is correct. I am guessing the problem is with the schematic. May be very high input impedance to the adc pin is causing this issue.

author: tom66
author_rank: Super Contributor
timestamp: October 11, 2024, 12:01:02 pm
content: The 100nF cap should help with the sampling current, however it's possible if you sample the pin too often you are drawing too much current on the input.I second the suggestion to test with DC, but do so if possible with similar 510kohm ladder in series. For instance if you put 30VDC on the input what do you read pre and post reset. That may give you an idea.You can measure the DC voltage at the ADC pin and see what changes after reset, if anything.Also mains voltage is typically measured from L to N, assuming your MCU is grounded if you are debugging it with a PC, you will get a less accurate reading as current flows down N and causes an offset relative to PE. I am not familiar with India's electrical infrastructure but if it is anything like UK/Europe then PE and N are tied together closely at the building power entrance but then are distinct points.

author: Dave
author_rank: Super Contributor
timestamp: October 11, 2024, 07:52:23 pm
content: Fill a large buffer in RAM with ADC samples, pause on a breakpoint and extract the data from there. Then process the data on your computer to confirm you're sampling what you expect to be sampling.

author: thm_w
author_rank: Super Contributor
timestamp: October 11, 2024, 09:48:03 pm
content: Measure with a scope first. I don't understand the purpose of the 10k/10k divider to 3.3V. Are you trying to AC couple the signal?https://electronics.stackexchange.com/questions/244667/how-to-measure-mains-ac-voltage-with-an-adc-from-a-microcontrollerhttps://www.eevblog.com/forum/beginners/ac-voltage-measurement-with-a-microcontroller/https://www.electro-tech-online.com/threads/measuring-ac-voltages-using-mcu.117073/

author: tom66
author_rank: Super Contributor
timestamp: October 11, 2024, 10:22:41 pm
content: Quote from: thm_w on October 11, 2024, 09:48:03 pmThe 10k-10k resistor divider biases the ADC pin to 1.65V. This is then drawn either side of this voltage by the AC signal. Since there's effectively 5kohm impedance to ground (3.3V is close enough to ground in this case) it forms roughly a 500:1 voltage divider but with the centre point at 1.65V. You should see between 2.3V and 1.0V at the ADC pin, assuming 230VAC mains.I have used this circuit before and it works fine for measuring mains voltage, though you have to be careful with the layout to make sure the resistors aren't overstressed or at risk of breaking down because there's nothing between the MCU pin and mains otherwise. At a previous job, a guy loaded all of our boards with a 1k resistor instead of 1Mohm. As soon as the boards were tested the PIC had a hole blown right in it!

author: Kleinstein
author_rank: Super Contributor
timestamp: October 12, 2024, 06:57:25 am
content: The capacitors shown would filter out much of the AC part. The capacitors shown in the schematics should be removed or much smaller (pF range). If higher frequency ( > 10 kHz) performance is critical one may have to add capacitors in parallel to the resistive divider. Good accuracy would than need a trim.

author: radiolistener
author_rank: Super Contributor
timestamp: October 12, 2024, 08:05:56 am
content: Connect known voltage source on the input and record sample recording (with no skips) then extract it to PC and analyze what is going on

author: SteveThackery
author_rank: Super Contributor
timestamp: October 12, 2024, 10:42:06 am
content: What is C1 for? I think you could dump it. Maybe it's charge-up time is causing bad readings until it reaches equilibrium. I would try it without.Also, I don't know what C2 is for. The ADC has its own sample-and-hold circuit.I think all you need are the resistors: then it will be a pure voltage-divider-plus offset, with no phase shifting going on. If you need to absorb noise on the mains, you could either do that in software, or put C2 back in but adjust its value until the noise is sufficiently reduced, rather than guessing at a nice round number.Myself I would do it in software.

author: DavidAlfa
author_rank: Super Contributor
timestamp: October 13, 2024, 02:05:45 am
content: I'd lower or remove the caps too, and buffer the signal using an op-amp so the adc pin sees a much lower impedance.

author: Shubham
author_rank: Contributor
timestamp: October 13, 2024, 06:39:52 am
content: Quote from: tom66 on October 11, 2024, 12:01:02 pmYes, I am sampling the pin quite frequently—800 samples spaced 125µs apart to calculate the RMS value. I’ll test with DC using a similar 510kΩ resistor ladder in series as suggested and measure the voltage before and after reset.For debugging, I’m using a laptop that's isolated from mains. Thanks for pointing out the potential grounding issues; I’ll keep that in mind.

author: Shubham
author_rank: Contributor
timestamp: October 13, 2024, 06:47:19 am
content: Quote from: Dave on October 11, 2024, 07:52:23 pmI’m currently calculating RMS by using totalSamples += (adcRead - dcOffset) * (adcRead - dcOffset); (totalSamples is uint64_t variable) and only perform the final RMS calculation after collecting all 800 samples. Unfortunately, filling a large buffer in RAM isn’t feasible with the STM32F030C6, as it has limited memory, and I also need to scale this approach for 3-phase RMS calculations.

author: Shubham
author_rank: Contributor
timestamp: October 13, 2024, 06:50:53 am
content: Quote from: thm_w on October 11, 2024, 09:48:03 pmI don’t see any distortion on the oscilloscope. The 10k/10k divider to 3.3V is being used to add a DC bias to the signal.

author: Shubham
author_rank: Contributor
timestamp: October 13, 2024, 07:00:39 am
content: Quote from: tom66 on October 11, 2024, 10:22:41 pmYes, you're right. The 10k-10k divider biases the ADC pin to 1.65V, and I’m seeing the expected voltage range at the pin. I’ve been careful with the resistor ratings to avoid any breakdown, but I’m open to suggestions. Do you have any recommendations for improving the schematic or increasing the safety margin for the resistors, especially given the direct connection to mains?In the code, I’m using totalSamples += (adcRead - dcOffset) * (adcRead - dcOffset);, where totalSamples is a uint64_t variable. After gathering 800 samples, I calculate the RMS value. If you have suggestions to optimize this or improve how I handle the ADC input, I’d really appreciate it.Additionally, if you know any reference links for measuring mains voltage or improving ADC performance, that would be very helpful. Lastly, any advice on PCB layout to prevent overstressing components or breakdown would also be great.

author: Shubham
author_rank: Contributor
timestamp: October 13, 2024, 07:06:51 am
content: Quote from: Kleinstein on October 12, 2024, 06:57:25 amI don’t see any reduction in amplitude or distortion on the oscilloscope. The low-pass RC filter’s cutoff frequency is 1591.55 Hz, which is well above the 50 Hz mains signal. However, I’ll try using capacitors in the pF range as suggested and see how it affects the performance.

author: Shubham
author_rank: Contributor
timestamp: October 13, 2024, 07:08:09 am
content: Quote from: radiolistener on October 12, 2024, 08:05:56 amOkay, I’ll try connecting a known voltage source to the input and record the samples without skips, then extract and analyze the data on the PC. Thanks for the suggestion!

author: Atlan
author_rank: Frequent Contributor
timestamp: October 13, 2024, 07:08:25 am
content: Rectify it with 1 diode, smooth it with a capacitor, measure the peak value, you don't need 800 samples, form 10. Calculate rms from the peak. As you have it now, you are probably measuring something else and not a sine wave.It would be ideal to connect an oscilloscope and see what the signal is on the adc pin.

author: Shubham
author_rank: Contributor
timestamp: October 13, 2024, 07:16:37 am
content: Quote from: SteveThackery on October 12, 2024, 10:42:06 amC1 is a bypass decoupling capacitor, and both C1 and C2 are there to suppress high-frequency noise. However, I understand your point, and I'll try removing both capacitors and see if it affects the readings.

author: Shubham
author_rank: Contributor
timestamp: October 13, 2024, 07:20:57 am
content: Quote from: DavidAlfa on October 13, 2024, 02:05:45 amI will try removing the capacitors first and see the results. I've been considering using an op-amp as a last option. What do you think about the LMV358 rail-to-rail op-amp?https://www.ti.com/lit/ds/symlink/lmv324.pdf

author: Shubham
author_rank: Contributor
timestamp: October 13, 2024, 07:33:41 am
content: Quote from: Atlan on October 13, 2024, 07:08:25 amI don't want to use the peak-to-RMS calculation method because it won't work with other waveforms, like quasi-sine waves. I'm trying to create a true RMS measurement. I'm confident that I'm measuring RMS since I'm getting the expected results in both simulations and practical tests before resetting the MCU. I will connect the oscilloscope to the ADC pin when the divider output is connected, and I will share a picture of the waveform.

author: Kleinstein
author_rank: Super Contributor
timestamp: October 13, 2024, 08:52:52 am
content: The cross over frequency for the low pass is indeed in the 1.5 kHz range, so should not effect the mains reading too much.For testing I would stay away from mains but use a transformer and a low voltage, like 24 V and use less divider. Adjusting the divider and going to a higher voltage would be only after most testing and SW corrections are done.One issue could be with the way how the offset is handled. If not correct (e.g. due to DC drift) small AC readings would be too high from the extra DC part. One can do a correction of the DC offset even after the summation over some 100 ms: the RMS value without the DC part is sqrt ( sum(V²) - (sum(V)/N)²). Besides the DC part there is also a noise background, that can be an issue for small readings.I point to check is if the µC / ADC actually runs at the expected speed.If the time is not exactly at 100 ms (or the mains frequency is rel. far off) there can be some error depending on the starting phase. Ideally one would start about 1/8 of a period off a zero crossing and thus around 70% of the peak voltage, so that the missing or added part would still be close to the correct RMS value.A possible problem can be a digital input at the µC that is floating. This can cause extra variations in the supply current.The LMV358 has a limited input voltage range. One would have to use it with a little gain (e.g. inverting amplifier or active divider), not just as a buffer.As a buffer a RR OP-amp like MCP6001 would be more suitable, though with some input cross over that can add some error. Most RR OP-amps have this issue, though to different degree.

author: SteveThackery
author_rank: Super Contributor
timestamp: October 13, 2024, 09:33:45 am
content: Quote from: Shubham on October 13, 2024, 07:06:51 amYou are right - I should have done that calculation myself before commenting.A simple question - in your software, are you waiting until C1 is charged up before making your measurements?

author: iMo
author_rank: Super Contributor
timestamp: October 13, 2024, 11:22:07 am
content: FYI - LTspice is your friend..

author: Kleinstein
author_rank: Super Contributor
timestamp: October 13, 2024, 12:17:47 pm
content: 1.7 V RMS may be just a little too much for the 3.3 V supply range.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: October 13, 2024, 01:49:11 pm
content: C2 is probably useful. Your voltage divider has a relative high output impedance, and this reduces the accuracy of the ADC. A capacitor on the ADC input that is many times bigger then the capacitance of the ADC input itself provides a low impedance to the mostly capacitive input of the ADC. One of the uC manufacturers made an application note for this. (I think it was Atmel, but I'm not sure).Quote from: Kleinstein on October 13, 2024, 12:17:47 pmPossibly. Outputting and plotting the raw adc vaules in a graph will clearly show any saturation effects.Starting with DC measurements is always a first start to see if your sampling frontend and ADC code does something that looks plausible. Circuits like this look deceptively simple, but all the parts have to be dimensioned right relative to each other for it to work well. Calculations on the ADC values hides all details of the sampling input. A good way to verify is to write a little oscilloscope function (including triggering, possibly on a low voltage channel only) Then verify whether your ADC frontend works by sampling some data both with a decent oscilloscope and with your gadget, and then compare the data. Probably easiest on your PC, but you may be able to upload the raw ADC values to your scope to a "reference channel". Also do this with badly distorted signals (high crest factor) and verify your ADC can capture the waveform properly.

author: iMo
author_rank: Super Contributor
timestamp: October 13, 2024, 02:09:02 pm
content: Quote from: Kleinstein on October 13, 2024, 12:17:47 pmYep, you have to subtract the DC=1.65V (or the "average" in the previous v1 graph)..

author: Shubham
author_rank: Contributor
timestamp: October 16, 2024, 02:41:58 pm
content: I connected my oscilloscope to the ADC pin my observation was that, when the mains power is clean (not noisy), the RMS readings are consistent and accurate, even after restarting the microcontroller.However, when the mains power becomes noisy, I notice a significant impact on both the accuracy and precision of the RMS voltage calculation.Could this be related to my schematic, or should I focus on modifying my code? I'd appreciate any suggestions on how to mitigate this problem.

author: thm_w
author_rank: Super Contributor
timestamp: October 16, 2024, 10:38:23 pm
content: Quote from: Shubham on October 16, 2024, 02:41:58 pmIt can be filtered in code or hardware. Usually easiest is to start with hardware.Maybe increase the capacitance of the filter and see if that has a direct effect on the noise spikes.

author: Kleinstein
author_rank: Super Contributor
timestamp: October 17, 2024, 07:44:13 am
content: The easier filtering is with software - just use slightly faster sampling, so that the existing RC filtering is more effective as anti aliasing filter. More readings also get better averaging over ADC errors.The main issue I see with the accuracy is when the reading window is not exactly an integer number of periods. It should still not be a large error. With 100 ms and thus 5 or 6 periods a frequency error of 1% could result in uncertainty of some 1/5 %. Starting at a point with some 70% of the peak values could reduce this error quite a bit compared to a random start. One could also do additional digital filtering with a few points with reduced weight at the start and end, so get a more soft start / stop and this way get less sensitive to the exact start phase.If there is noise superimposed to the waveform, this does add to the RMS values - that is normal. The noise is part of the AC signal and thus needs to be included. Different meters may have a different bandwidth and may for this reason get different results. Especially the RMS result from the scope with a much higher BW can be a bit higher.A little more care is needed for relatively small readings. Here the noise of the ADC itself should be subtracted from the squared values. This way one should be able to also get OK readings at rather small amplitudes, like 1% of the range or even less. With significant background noise it is normal that also the RMS readings may get a bit more noisy - that is natural as noise is usually random and scattering amplitude.

author: iMo
author_rank: Super Contributor
timestamp: October 17, 2024, 08:42:42 am
content: You may also try with a "median" filter in sw. Pretty good for filtering out the "outliers" (your noise spikes)..

author: Jeroen3
author_rank: Super Contributor
timestamp: October 17, 2024, 10:34:11 am
content: What is your samplerate?What high-pass filter are you using?How wide of a window are your using, or are you phase locking the sampling to the base frequency?