Author Topic: ADC calculations  (Read 1427 times)

0 Members and 1 Guest are viewing this topic.

Offline gnifTopic starter

  • Administrator
  • *****
  • Posts: 1716
  • Country: au
  • Views and opinions are my own
    • AMD
ADC calculations
« on: May 30, 2020, 05:35:24 am »
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: [Select]
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;

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: [Select]
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
« Last Edit: May 30, 2020, 06:06:31 am by gnif »
 

Offline Kleinstein

  • Super Contributor
  • ***
  • Posts: 15157
  • Country: de
Re: ADC calculations
« Reply #1 on: May 30, 2020, 07:44:29 am »
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.
 

Offline Vovk_Z

  • Super Contributor
  • ***
  • Posts: 1478
  • Country: ua
Re: ADC calculations
« Reply #2 on: May 30, 2020, 07:58:33 am »
Have you checked all Ref voltages?
 

Offline gnifTopic starter

  • Administrator
  • *****
  • Posts: 1716
  • Country: au
  • Views and opinions are my own
    • AMD
Re: ADC calculations
« Reply #3 on: May 30, 2020, 07:22:24 pm »
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: [Select]
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
« Last Edit: May 30, 2020, 10:20:50 pm by gnif »
 

Offline Vovk_Z

  • Super Contributor
  • ***
  • Posts: 1478
  • Country: ua
Re: ADC calculations
« Reply #4 on: May 30, 2020, 09:24:41 pm »
It has to have a calibration procedure I think.
 

Offline gnifTopic starter

  • Administrator
  • *****
  • Posts: 1716
  • Country: au
  • Views and opinions are my own
    • AMD
Re: ADC calculations
« Reply #5 on: May 30, 2020, 10:25:16 pm »
It has to have a calibration procedure I think.

It's not calibration related, the STM32's ADC has a calibration that is done prior, and the 5V reference is providing 5.0001v with 1ppm/°C accuracy. This question is how to correctly calculate the current flow based on all known factors.
The only part of the design that is calibration related is the resistor divider networks used to scale the voltages, and has been accounted for.
 

Offline gnifTopic starter

  • Administrator
  • *****
  • Posts: 1716
  • Country: au
  • Views and opinions are my own
    • AMD
Re: ADC calculations
« Reply #6 on: June 04, 2020, 11:00:17 pm »
Just a follow up on this, I was still going about things completely wrong, the VREFINT voltage is to be used in a different manner entirely.

Code: [Select]
volts = sample * 1200 / vrefint
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 7198
  • Country: fi
    • My home page and email address
Re: ADC calculations
« Reply #7 on: June 05, 2020, 10:19:38 am »
When working this stuff out, I like to model the measurements first, with error sources.  In your case, if you let the ADC do its internal calibration every now and then, the datasheet claims your total error is at most two units in least significant position, i.e. ±2/4096 ≃ ±0.04884%, so it is pretty safe to assume the ADC itself is linear without offset.  Also, the ST datasheet says that the ADC unit is VREF/4096 (page 77, ideal sample size).

So, the ADC reading is
    ADC = 4096 × V / VREF
where V is the voltage being measured.  The internal voltage reference can have 3% error. (Nominal 1.20 V, but can vary between 1.16 V and 1.24 V;  0.04 V / 1.20 V ≃ 3.33%).  So, I wouldn't use the internal reference for anything if I can avoid it.   But, if you use the external 2.5V reference, you can only measure 0 - 2.5V.  (VFQFPN and LQFP packages don't even have an external VREF pin, it is internally connected to VDDA.)

The transducer output according to its datasheet is
    VOUT = VREF ± 0.625 [V] × I / IREF
where I is the current being measured.  The 0.625 [V] means 0.625 volts, and is characteristic for the transducer, and does not depend on the reference voltage.

Which samples use which reference voltage?

Personally, I would have used two voltage dividers from the 5V precision source: one at 3.2V or so (assuming your power supply is greater than that), and one at 2.0V or so (since this transducer doesn't like smaller reference voltages).  The 3.2V would be wired directly to the VREF+ pin (so VREF), and you'd measure the actual voltage using a good voltmeter for calibration purposes.  The 2.0V would go to the transducer (so VIREF), and optionally to a free analog pin so you can measure it at run time; any variation (outside ±2, per datasheet) in it indicates something is seriously wrong.

Then, if the sign of the current I indicates the direction of the current flow, the ADC reading would then be
    ADCI = 4096 × VOUT / VREF = 4096 × VIREF / VREF + 2560 [V] × I / (IREF × VREF)
and the estimate for the current (from solving the above for I) would be
    I = (ADCI VREF - 4096 × VIREF) × IREF / 2560 [V]

The resolution would be around 10 mA, but accuracy would depend on how precisely you know or measure the voltage references.  I'd probably use integer arithmetic for this, with currents in milliamps and voltages in millivolts.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf