9 Replies Latest reply on Jan 10, 2019 1:07 PM by reinier_3537311

    Forbidden values in ADC output


      When I use averaging in the ADC_SAR it seems that certain blocks of values are output very rarely or not at all.  I tested this by measuring the ADC output with a gradually increasing voltage.  Without averaging, all values between 0..2047 seem to be valid results.  When I average 16 samples with fixed resolution, there are sudden jumps of around 40 counts.  A histogram of ADC readings shows that the values come in groups of 64 of about 24 on 40 off.   When I average 16 samples with accumulation, expecting all values between 0..32767 to be valid, I get jumps of about 650 in the plot of counts, and the histogram shows groups of 1024 of about 384 on 640 off. 


      Looking more closely at 16 samples averaged with fixed accumulation, I notice that the 32s bit and the 4s bit don't flip like I expect them to.  For example, 795+1=832 in binary is 0011 0001 1011 + 1 = 0011 0100 0000. 


      This is the code I'm using to obtain measurements:

          int16 _getADC(void) {

              int16 val;





              val = ADC_GetResult16(0);


              if (val < 0) val = 0;


              return val;



      I'm using PSoC 4 with ADC_SAR v2.40.  Single-ended with Vss (hence the limitation to positive values). 


      Why does averaging make the output behave so strangely? 

        • 1. Re: Forbidden values in ADC output



          To understand what is happening, can you please provide information?

          1. What is the step size by which input voltage is being varied?

          2. How fast input is being varied?

          3. What is the reference voltage of ADC set to?

          4. How frequently the function is being called to start the ADC conversion?


          If you can also provide the project, it would be helpful.



          • 2. Re: Forbidden values in ADC output

            Sure -


            1. Unfortunately I don't have a way to vary the voltage systematically for this test (or if it's possible to do using the debugger I don't know how), so I'm slowly increasing the stimulus to the sensor that's being read from (nearly) nothing to saturation. 
            2. The sensor is being taken from (nearly) no stimulus to saturation over the course of a minute or two.

            3. The External Vref is set to 2.000V with negative input Vss

            4. The firmware samples at 20Hz, but in fact every 1/20s it calls ADC_Wakeup(), _getADC() three times in succession, then ADC_Sleep().  (The data I've provided is the third reading at every 1/20s interval).  I've tried adding a 10us delay between _getADC() calls and also calling _getADC() only once but that doesn't solve the problem.


            Unfortunately I won't be able to provide the project.


            thank you, and let me know if I can provide any other information to help solve the problem!



            • 3. Re: Forbidden values in ADC output



              It is interesting that the jump is more or less close to 40 counts that corresponds to ~40mV.


              I am suspecting following two things-

              1. Between the two cases (with and without averaging), timing is one of the differences. How is the data being captured? Is it possible that the data is not read at some regular intervals? Can you add a timestamp (something like counter) to each sample?

              2. Sensor response, though unlikely as it worked in the case of without averaging. Can you disconnect the sensor and feed the voltage to the ADC input directly? What is the input voltage step size?



              • 4. Re: Forbidden values in ADC output



                The firmware runs a loop which starts a timer, takes a measurement, prints it to console, then waits until the timer hits 50000 (for 20Hz sampling).  I've rerun the experiment and included a timestamp with each measurement, and attached it here.  Unfortunately it only has second resolution, but there are neatly 20 samples per second so I don't think timing is the issue.


                Also unfortunately it's not straightforward to hook my test board up to a controlled voltage source.  But as you say I don't think there's a problem with the sensor.


                What's most striking to me is that the blocks of allowed values (with few exceptions) are 64*k+1 .. 64*k + 16+8+4+2, with k=0, 1, 2...  See the histogram where I've drawn red and green dotted lines at these boundaries.




                The issue also becomes apparent when I plot the binary representation of the ADC output: the 32s bit doesn't flip when I expect it to.




                All in all to me it looks like the summation in the ADC Sequencer isn't working as expected.  Is there any reason this can happen?  I don't think I'm pushing the system too much - only one channel, not sampling too fast, etc.



                • 5. Re: Forbidden values in ADC output



                  Jump in the counts can happen if the trim value (SAR_ANA_TRIM register) is not proper. Can you please read following two registers? You can read it in debugging mode; please put a breakpoint in the function getADC().


                  1. SAR_ANA_TRIM (address: 0x401A0F00)

                  2. SAR_DFT_CTRL(address: 0x401A0030)


                  I guess, you are using PSoC 4200 device. Am I correct?


                  I have also attached a project which you can test it out on your board. You might have to change few things in the project such as pins and the component for communicating the output.



                  • 6. Re: Forbidden values in ADC output

                    Hi Rajiv,


                    I've recently been able to come back to investigating this issue, and I'm still no closer to understanding what's going on.


                    My recent tests have used 32x averaging with the Accumulate averaging mode.  I'm using a PSoC 4200BL series device, and I found those registers at 0x403axxxx:

                    1. SAR_ANA_TRIM (0x403a0f00): 0x00000012

                    2. SAR_DFT_CTRL (0x403a0030): 0xa0000002


                    I've attached a number of recent tests that show the strange behavior very clearly.  These tests involve a light sensor pointed outside during sunrise, i.e. a very gradually increasing sensor voltage.  The project samples the ADC at a sampling rate of 79Hz, and in fact runs _getADC() (see original post) 3 times for each sample.  I save the 3rd sample, and that's the measurement you see in the first column of the attached .csv files.


                    I've also included the binary representation of the measurements.  If you plot these bitwise you can get a better sense of the strange behavior (see attached example of capture 08)  In particular, bit 9 doesn't flip as expected.  In fact bits 12..10 behave more like I expect bits 11..9 to behave (or conversely bits 8..0 look like they should be upshifted to 9..1).  I've stared at these bits for days but have not managed to figure out what the rhyme or reason is in the bit flips.


                    I noticed that the ADC getResult16() method actually peeks at a 32bit register and takes the low 16 bits.  I also took a look at the upper 32 bits for any clues.  I saw values of 0x8000, 0xa000, 0xe000.   Does this make sense, or should they never change?


                    I'm working on a version of our project that you'll be able to run, but maybe in the meantime can you have a look at these samples and see if you can make anything of it?



                    • 7. Re: Forbidden values in ADC output



                      I also ran a simple test.

                      I wrote a program to measure ADC and print out as int.


                      I connected a funcgen I programmed with FRDM-KL25Z years ago

                      and let it generate a sin wave of 3.0V pp 50Hz.

                      funcgen - Yet another implementation of wave function gen... | Mbed https://os.mbed.com/users/Rhyme/code/funcgen/


                      Then let my cygwin program to count each bits 1's and 0's.


                      The result was


                      $ ./bitcount < adc_log_16avg_1812071724.txt

                      bit 00: 000328 : 000299

                      bit 01: 000316 : 000311

                      bit 02: 000318 : 000309

                      bit 03: 000321 : 000306

                      bit 04: 000284 : 000343

                      bit 05: 000308 : 000319

                      bit 06: 000262 : 000365

                      bit 07: 000264 : 000363

                      bit 08: 000255 : 000372

                      bit 09: 000269 : 000358

                      bit 10: 000281 : 000346

                      bit 11: 000000 : 000627



                      It seems that except bit 11(MSB) all other bits are reasonably flipping.

                      So I would suspect...

                      (0) My ADC configuration is different from yours

                      (1) The output of the sensor actually the bit 9 may be hardly flipping

                      (2) There may be a problem with the internal ADC of your MCU


                      My project for CY8CKIT-044 and the bitcount.c of cygwin64 are attached.



                      • 8. Re: Forbidden values in ADC output

                        Hi Reinier,


                        I am just recalling one issue I had seen couple of years back (which was subsequently fixed in the SAR ADC component version v2_50) which is quite similar. Can you please check the component version in your case?



                        • 9. Re: Forbidden values in ADC output

                          Hi Rajiv,

                          I am using the ADC SAR SEQ P4 component v2.50, and programming my device with PSoC Creator 4.2.