Shunt resistance current measurement - PSoC 5 LP

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
JaGe_4104756
Level 1
Level 1

Hello everybody,

First, I wanted to say that I am new here and therefore I do not know if I have placed the topic in the right place (may then be moved by the admin).

So I'm not only new here in the community, but also freshly come into contact with the PSoC 5LP.

Nonetheless, I've ventured into programming with tutorials and Cypress test codes.

Now to the project:

I have a laboratory photovoltaic string consisting of 10 modules and 10 bypass diodes (U_oc = 5V and I_sc = 100mA). In the circuit there is a shunt resistor with 0.006 ohms and a consumer with 100 ohms and downstream green LED. About the voltage drop at the shunt I would like to calculate the current. I would like to have the issue displayed on HTerm.

The program and the output works. Unfortunately, the values ​​given give me problems.

The attached picture shows my output in the red box without pin assignment, here should normally stand for both 0mV. And in the green box, the values ​​that the measurement gives me, but the program does not jump to the output of Ush2.

Even if I do not use the lab string, but VDD and GND from the PSoC, then a current of about 25mA should flow. Accordingly, I should have a voltage drop of about 0.15mV. Since the voltage drop is very low, since my resolution is not right?

Actually, it is a simple voltage drop measurement, but I can not explain how the output values ​​come about.

I hope you can help me.



Thank you very much and sunny greetings from germany

jg.vs


19.05.29-HTherm Ausgabe_markiert-JG.jpg19.05.31-Schematic Ausgabe-JG.JPG

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.

jg.vs,

Let me see if I understand your needs correctly.  You want an increase in resolution and you want the results in floating point.

Increased resolution: Easy!   How much improvement do you need? (mV/ADC_count)

There are multiple ways to increase the resolution.

  • Increase the value of R_shunt.  If your design can tolerate a larger voltage drop across the shunt, this is the first improvement you should do.  Pro: Increasing the voltage drop helps to detect very small currents better because they less closer to the noise floor of measurements.  Con: A higher value of R_shunt will limit the maximum circuit current.
  • Increase the ADC resolution.  Your design uses an 8-bit DelSig.  With the Vref set to 1.024V you are limited to 8mV per ADC count.  SARs are capable of being configured for 12-bits.  With Vref = 1.024V and differential mode (effective 11-bits per polarity) you can improve your resolution to (1.024V/(1<<11)  =  1.024/2048 = ) 0.5mV.
    If you use the DeltaSigma ADC you can set it to 20-bits.  With Vref = 1.024V and differential mode (effective 19-bits per polarity) you can improve your resolution to (1.024V/(1<<19)  =  1.024/524288 = ) 0.002mV.
  • Decrease the Vref.  With the DeltaSigma ADC, you can assign Vref, Vref/2,  Vref/4, Vref/8 and lastly Vref/16.   Selecting a a lower value of effective Vref into the ADC will improve the resolution.  You're new V/ADC_count = (Vref/n)(1-(ADC_bits - 1)).  Generally use this as a second-to-last resort.
  • Increase the DeltaSigma ADC buffer gain.  Normally set to 1.  Generally use this as a last resort.

My advice is to:

  1. increase R_shunt to the largest value your design can tolerate. You use 100 ohms for a LED current limiter.  Get rid of R_shunt and place your differential Ush across R_LED.   You lower your BOM count and the current will be the same and your V across R_LED will be significantly above your noise floor.
  2. Increase the ADC resolution to 20-bits.
  3. Decrease the effective ADC vref to slightly higher than R_shunt * maximum_current_expected.
  4. If needed, increase the Buffer gain.

Please remember the lower the mV/ADC_count the closer you are to the noise floor.  This means to read very low current values, you might see thermal and cosmic noise as well as noise from other sources on your own PCB.  To minimize this effect, you would need to make multiple readings and average the result.

Floating-point number conversion: Easy!

You will need to make the following simple changes to your Project\Build settings...

pastedImage_1.png

and to your Project\[Project name] Resources\System...

You will need to be careful with your floating point math in your SW.  For example your code stated:

#define RSH     0.006      //6mOhm

...

current_pv = ush/RSH/corr;    //  This code has issues.  1) You are mixing integers with float values.  You can't be guaranteed how the compiler handles conversions.

                                                //      2) If using integer math, always perform your multiplications first before divisions.  In integer math, divisions WILL truncate.

I've attached a update to my last project update with the floating point changes you're looking for.

Additionally I've made the following changes:

  • R_shunt eliminated.
  • R_LED is the new R_shunt.  Maximum measurable current = 20.48mA
  • ADC to 20-bits.  Sampling rate = 183 SPS
  • ADCvref = 2.048V (=Vref*2).  This should maximize resolution and keep most if it above the noise floor.  Your new ADC Voltage resolution = 4uV/ADC_count.  ADC current resolution = (4uV/100)/ADC_count = 0.04uA/ADC_count.
  • sprintf() to snprintf().  snprintf() is the ANSI safe function.  It protects against string buffer overruns.

Try it out.

Len

Len
"Engineering is an Art. The Art of Compromise."

View solution in original post

0 Likes
10 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Welcome in the fascinating world of PSoCs!

Assuming you have got a common GND for your cell aray and the PSoC5.

The size of your TransmitBuffer is with 16 bytes quite too small. Use something like 80 and the sram will not be clobbered by a long output line.

Bob

PS: Where in Germany are you located? I live near Bremen

0 Likes

Hi,

I agree with Bob.

Additionally, use snprintf() instead of sprintf().  The 'n' uses an additional argument of the size if the buffer

[ie.  snprintf(buffer, sizeof(buffer), args ...)].

This is a 'C' safe function because it prevents buffer overruns because the size argument is tested against the string being formatted.

The other issue appears to be that the large value you are displaying '4294967288' is actually a unsigned 32 bit version of the signed 32-bit version of the number returned by your line 92 in main():  ush1 = ADC_DelSig_1_CountsTo_mVolts(ADC_DelSig_1_Read32());

Change your declaration of uint32 ush1;  to int16 ush1.  This will cause '4294967288' to become -8.  Remember you are using the ADC in differential mode.  You appear to have a small negative polarity current on your R_shunt.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
JaGe_4104756
Level 1
Level 1

hello everybody,

@bob: Thank you for the nice welcome and your answer. I currently live near Ausgburg
@len: Also thank you for your detailed description

Since I am really a beginner in programming and especially with PSoC, I would be very happy to receive detailed explanations at the beginning.

I have now modified my program so that my output has been described as len. Now I always get both values ​​(Ush1 and Ush2).

Now my other questions:

1. I would like to spend only positive values. so that my output is starting from zero. How can I write my code so that the negative values ​​are not displayed?

2. Currently (03.06.2019 10:35) I have at a voltage of U = 5V a current with about 7.52 mA. Therefore, my voltage drop should be 0.04512mV. How should I change my code to match my output?

a) my output is currently either 0 or -8.
b) I want ush1 = 0 and ush2 = 0 if I did not connect to the PSoC.
c) If I measure my voltage drop, ush1 should be about 5000,00000 mV
and ush2 is about 4999,95488 mV, here again is 0 or -8 the output.

Can you help me? I already despair the whole weekend :-(.

Thanks for your support!

greetings
jg.vs

19.06.03-HTherm Ausgabe nach ersten umstellung-JG.JPG

0 Likes

To have your program checked or changed best will be to upload the project here. To do so, use

Creator->File->Create Workspace Bundle (minimal)

and attach the resulting file.

Bob

0 Likes
lock attach
Attachments are accessible only for community members.

Thanks bob!

Here it comes

0 Likes
lock attach
Attachments are accessible only for community members.

jg.vs,

I'm glad we can help.

I downloaded your project.  Here's a few comments.

Here is the major source of the problems you are seeing:

You show in main() that you are making two readings.  One for Ush_1 and the other for Ush_2.  This is totally unnecessary.  The ADC configuration you are using is in differential mode.  This means it reads both Ush_1 and Ush_2 simultaneously and the result is the difference (Ush_1 - Ush_2).  This is the preferred way to measure current across a resistor since both the voltage nodes are read at the same time.  You could switch to single-ended mode in the ADC (which I wouldn't advise) and make two readings.  Differential mode is preferred here.

Because you are reading the same (Ush_1-Ush_2) reading twice and subtracting it you are effectively subtracting two identical readings which will be zero.  The reason your readings are at or near zero (-8mV) is that your two readings are done with a slight delay in time, this may cause the second reading to be off by probably one ADC count due to your Vdd source fluctuating or circuit noise.

The ADC resolution you have chosen is 8 bit.  The ADC is set to differential mode with a 1.024V Vref.  This means your results will be 7 bits from 0 to 1.204V and 7 bits for 0 to -1.024V.  In effect, each ADC count equals 8mV (1.024V/128 ADC counts).

I've attached a modified version of your application.  I've gotten rid of the 'b' command.  Type 'c' and the single ADC reading and current computation occurs.  This should eliminated the need to put in SW logic to remove negative value readings.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
JaGe_4104756
Level 1
Level 1

Hello,
many thanks for your response.

Exactly, the voltage drop between Ush1 and Ush2 is so minimal that it goes to zero. My wish would have been that I read the two values ​​only for security and then gladly as a floating-point number.

The voltage drop can only be in the range of 0.00mV  =< Ush =< 0.24mV.

Therefore, I need an exact resolution of the values, so that I can also determine my "small" current.

With the code changed by you, I currently only get the output 0mA, even if I make the power supply with VDD from the PSoC.

Since my lab photovoltaic string and VDD have the same voltage, I can compare both supplies well with each other.

I've been working on the resolution setting since yesterday and I'm not getting any further. Can you or the community help me to output the value as a floating-point number?

Example output:
Ush = 0.399991 mV
Ipv = 6.645551 mA

If that works, then I'll take a big step in my project.

Thank you in advance!

0 Likes
lock attach
Attachments are accessible only for community members.

jg.vs,

Let me see if I understand your needs correctly.  You want an increase in resolution and you want the results in floating point.

Increased resolution: Easy!   How much improvement do you need? (mV/ADC_count)

There are multiple ways to increase the resolution.

  • Increase the value of R_shunt.  If your design can tolerate a larger voltage drop across the shunt, this is the first improvement you should do.  Pro: Increasing the voltage drop helps to detect very small currents better because they less closer to the noise floor of measurements.  Con: A higher value of R_shunt will limit the maximum circuit current.
  • Increase the ADC resolution.  Your design uses an 8-bit DelSig.  With the Vref set to 1.024V you are limited to 8mV per ADC count.  SARs are capable of being configured for 12-bits.  With Vref = 1.024V and differential mode (effective 11-bits per polarity) you can improve your resolution to (1.024V/(1<<11)  =  1.024/2048 = ) 0.5mV.
    If you use the DeltaSigma ADC you can set it to 20-bits.  With Vref = 1.024V and differential mode (effective 19-bits per polarity) you can improve your resolution to (1.024V/(1<<19)  =  1.024/524288 = ) 0.002mV.
  • Decrease the Vref.  With the DeltaSigma ADC, you can assign Vref, Vref/2,  Vref/4, Vref/8 and lastly Vref/16.   Selecting a a lower value of effective Vref into the ADC will improve the resolution.  You're new V/ADC_count = (Vref/n)(1-(ADC_bits - 1)).  Generally use this as a second-to-last resort.
  • Increase the DeltaSigma ADC buffer gain.  Normally set to 1.  Generally use this as a last resort.

My advice is to:

  1. increase R_shunt to the largest value your design can tolerate. You use 100 ohms for a LED current limiter.  Get rid of R_shunt and place your differential Ush across R_LED.   You lower your BOM count and the current will be the same and your V across R_LED will be significantly above your noise floor.
  2. Increase the ADC resolution to 20-bits.
  3. Decrease the effective ADC vref to slightly higher than R_shunt * maximum_current_expected.
  4. If needed, increase the Buffer gain.

Please remember the lower the mV/ADC_count the closer you are to the noise floor.  This means to read very low current values, you might see thermal and cosmic noise as well as noise from other sources on your own PCB.  To minimize this effect, you would need to make multiple readings and average the result.

Floating-point number conversion: Easy!

You will need to make the following simple changes to your Project\Build settings...

pastedImage_1.png

and to your Project\[Project name] Resources\System...

You will need to be careful with your floating point math in your SW.  For example your code stated:

#define RSH     0.006      //6mOhm

...

current_pv = ush/RSH/corr;    //  This code has issues.  1) You are mixing integers with float values.  You can't be guaranteed how the compiler handles conversions.

                                                //      2) If using integer math, always perform your multiplications first before divisions.  In integer math, divisions WILL truncate.

I've attached a update to my last project update with the floating point changes you're looking for.

Additionally I've made the following changes:

  • R_shunt eliminated.
  • R_LED is the new R_shunt.  Maximum measurable current = 20.48mA
  • ADC to 20-bits.  Sampling rate = 183 SPS
  • ADCvref = 2.048V (=Vref*2).  This should maximize resolution and keep most if it above the noise floor.  Your new ADC Voltage resolution = 4uV/ADC_count.  ADC current resolution = (4uV/100)/ADC_count = 0.04uA/ADC_count.
  • sprintf() to snprintf().  snprintf() is the ANSI safe function.  It protects against string buffer overruns.

Try it out.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
lock attach
Attachments are accessible only for community members.
JaGe_4104756
Level 1
Level 1

Hello everybody,

I thank len for the editing of my program :-)!

I have now further programmed and unfortunately can not fix this one error.

Since I also check the voltage drop with a digital voltmeter, I can always say very well whether the output values ​​fit into something.

I have changed the program so that I can output the current value and an average over 10 measurements. As a small addition, an LED flashes during averaging.

So now for the problems:

1. If I do my measurement on the photovoltaic test string, then I have the phenomenon that the value (positive) fits but then continues to rise (much too high) and then becomes negative and negative (negative maximum and again different). (Picture 1 and 2)

When measuring with const VDD, the correct value is permanently output. (Picture 3)

So only the power supply of PV was changed fluctuating after irradiation on VDD equal constant.

2. Since I expect a current over 20,48mA I changed the input range of the ADC. From Range +/- 2.048V (-Input +/- 2 * Vref) to +/- 6.144V (-Input +/- 6 * Vref). Is that permissible?

My other plans:

3. Currently I have my values ​​displayed in HTerm. For the future it is planned that my PSoC measures and outputs an average value every 5 minutes. the output should be in a time-current characteristic (diagram) and as an additional value the values ​​should also be saved in an Excel (csv).

For me it would be interesting to see how I can create a diagram and a csv for my current program.

Thank you for your support and slowly but surely I will be a bit safer in dealing with the programming.

Bye for now,
jg.vs

19.06.11.-HTerm Ausgabe 1-PV negativ und postiv-JG.JPG

19.06.11.-HTerm Ausgabe 2-PV herunterlaufen negativ-JG.JPG

19.06.11.-HTerm Ausgabe 3-5V const-JG.JPG

0 Likes
lock attach
Attachments are accessible only for community members.
JaGe_4104756
Level 1
Level 1

Hello and sunny greetings from Germany :-)!

The following problem exists:

1. When reading the voltage at the shunt resistor I can observe when outputting that the AD converter reaches a maximum and overflows.


2. The AD converter operates with an input range +/- 1.024V (-Input +/- Vref) and the reference voltage internally with 1.024V

3. I have a voltage range at the shunt resistor 0 mV < Ush < 927.6 mV. Over an output I let in addition the calculated current spend (max 15.45 mA).


4. As an example, I have attached the picture below.
Here it can be seen that the voltage drop rises up to approx. 61 mV (= 1mA), then overflows and the values are counted up again starting from 0 mV. So I can not read my stream exactly.


5. When changing the input range and reference voltage, only the time of overflow can be shifted.
Example: With the setting Input Range +/- 6.144 (-Input +/- 6 * Vref) and the reference voltage internally with 1.024 V receive an overflow will occur at about 0.360mV (= 6mA).

I hope you can help me.

19.06.28-Überlauf_markiert-JG.jpg

19.06.30-Scematic-JG.JPG

Have a nice day
jg.vs

0 Likes