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.
PS: Where in Germany are you located? I live near Bremen
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.
@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!
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.
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.
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?
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!
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:
- 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.
- Increase the ADC resolution to 20-bits.
- Decrease the effective ADC vref to slightly higher than R_shunt * maximum_current_expected.
- 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...
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.
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,