Electronics > Projects, Designs, and Technical Stuff
ADC calculations
gnif:
Unfortunately, I never did well in math at school and as such, this is a field I struggle with so please bear with me as I know what I am asking is likely very simple math to work out.
I am building a device that uses a current transducer to meter power generated by my solar system, and how much has been stored, etc. I am using a STM32F103C8T which contains a 12-bit ADC and will sample up to 16 channels (iirc). One of the features of this device is that it will let you sample the internal vref so that you can use it to correct for sampling errors due to drift, etc.
As I am looking for good accuracy I have used MAX6350 (I had a few floating around) as a precision 5V reference and using two 1K resistors divided it down to 2.5V for the current transducer's vref. This improved the output of the transducer considerably even though I am doing a less than perfect divide by 2 (yes, I should get a MAX6325). To be able to adjust for error I have also fed this 2.5V reference into the ADC.
The current transducer is a LSTR 15-NP configured for two loops at a nominal 7.5A.
So, I have three analog inputs to the mcu:
1) Current Transducer Output (CH_CUR)
2) Current Transducer VREF (CH_CREF)
3) Battery voltage which I am dropping 48V via two zeners and then using another divider network to scale the remainder to the 3.3V ADC input. (CH_VOL)
So in software, I have four samples per sampling, the fourth being the STM32's ADC reference (CH_VREF). At the moment what I have done is the following although I question its correctness.
--- Code: ---const float vref = (4095.0f * 1200.0f) / samples[CH_VREF];
const float cref = samples[CH_CREF] * (vref / 2047.5f);
const float c = (samples[CH_CUR] * (cref / 4095.0f) - (cref / 2.0f)) * (7500.0f / (3125.0f - 2500.0f));
const float v = samples[CH_VOL] * (10725.0f / 4095.0f) + 47757.0f;
--- End code ---
Does this look correct, or am I missing something here? While the results are close to my DC clamp meter, it's still about 500mA off on average.
Edit: Forgot to add, here is a sample of the raw samples when there is zero current flow.
--- Code: ---VREF CREF CUR VOL
1515 3141 2024 1376
1515 3141 2022 1402
1513 3142 2021 1439
1514 3143 2023 1360
1514 3141 2023 1366
1514 3142 2021 1450
1514 3141 2021 1372
1514 3142 2024 1374
1514 3142 2022 1347
1515 3140 2023 1414
1515 3141 2022 1441
1515 3141 2023 1351
--- End code ---
Kleinstein:
The formulas are at least very confusing and overly complicated to the point I can't really understand them. With so many constants inside chances are high there is a mistake included.
The current transducer ouputs the result relative the the V_ref signal. So there is no need for a very accurate V_ref for the transducer. This is more like a virtual ground. An accurate V_ref may be needed with for the ADC.
Ideally one would use ADC in the µC in a differential mode: one side the the transducer V_ref and the other side to the output.
When using the ADC signals as described one would get the current as:
I = ADCref/ G /4095 * (CH_Cur - CH_Ref)
Here ADref is the ref voltage to the ADC (e.g. 3.3 V) and G = 41.6 mV/A from the transducer data sheet.
Using only negative currents one could set the ADC ref. to some 2.5 V from an external ref. Chip. and the Ref_input for the transducer to a slightly smaller fraction (like 98%) so that at zero the ADC would read near maximum and lower when the current goes down.
Vovk_Z:
Have you checked all Ref voltages?
gnif:
Thanks guys, yes I have checked the ref voltages and @Kleinstein has steered me in the correct direction. Here is what I have come up with now
Expected current out = 2.5v as there is zero flow
Optimal VREF = 4095*1200/3300 = 1489.1
Actual VREF Sample = 1515
Error = 1515-1489.1 = -25.9
Current Ref Sample = 3141
Current Out Sample = 2024
Adjusted Ref Sample = 3141 + -25.9 = 3115.10
Adjusted Out Sample = 2024 + -25.9 = 1998.10
So remembering that `current out` is scaled through a resistor divider network (1.8k / 3.8k), cref is also scaled (1k / 1k), and the current transducer sensitivity is 41.6mV/A but is running with two transformer loops.
vref = 1200*4095*1515 = 3.243v
current ref = 3300/4095*3115.10*2 = 5.020v
current out = (vref/cref)*(3300/4095*cur)
current out = (3.243/5.020)*(3300/4095*2024) = 2.492v
current out err = 2.5 - 2.492 = 7.61mv
across a bunch of samples the error average is 9.81mV
adjusted current out = 2.492v + 9.81mV = 2.502V
I = (2.502V - 2.5V) / (0.0416*2) = 0.05A
Across a bunch of samples here is the resulting spread:
--- Code: ---Raw Samples Adjusted Samples Converted to Voltages Output
VREF ERR CREF CUR CREF CUR VREF CREF CUR ERR CUR A
1515 -25.90 3141 2024 3115.10 1998.10 3243.56 5020.67 2492.39 7.61 2502.21 0.05
1515 -25.90 3141 2022 3115.10 1996.10 3243.56 5020.67 2489.90 10.10 2499.71 -0.01
1513 -23.90 3142 2021 3118.10 1995.10 3247.85 5025.51 2487.76 12.24 2497.57 -0.06
1514 -24.90 3143 2023 3118.10 1997.10 3245.71 5025.51 2491.90 8.10 2501.71 0.04
1514 -24.90 3141 2023 3116.10 1997.10 3245.71 5022.29 2490.30 9.70 2500.11 0.00
1514 -24.90 3142 2021 3117.10 1995.10 3245.71 5023.90 2488.61 11.39 2498.42 -0.04
1514 -24.90 3141 2021 3116.10 1995.10 3245.71 5022.29 2487.81 12.19 2497.62 -0.06
1514 -24.90 3142 2024 3117.10 1998.10 3245.71 5023.90 2492.35 7.65 2502.16 0.05
1514 -24.90 3142 2022 3117.10 1996.10 3245.71 5023.90 2489.85 10.15 2499.66 -0.01
1515 -25.90 3140 2023 3114.10 1997.10 3243.56 5019.06 2490.35 9.65 2500.16 0.00
1515 -25.90 3141 2022 3115.10 1996.10 3243.56 5020.67 2489.90 10.10 2499.71 -0.01
1515 -25.90 3141 2023 3115.10 1997.10 3243.56 5020.67 2491.15 8.85 2500.96 0.02
--- End code ---
Vovk_Z:
It has to have a calibration procedure I think.
Navigation
[0] Message Index
[#] Next page
Go to full version