5 Replies Latest reply on Jul 10, 2018 5:12 AM by rajiv.vasanth.badiger

    Forbidden values in ADC output

    reinier_3537311

      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;

             

              ADC_StartConvert();

              ADC_IsEndConversion(ADC_WAIT_FOR_RESULT);

              ADC_StopConvert();

              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
          rajiv.vasanth.badiger

          Hi,

           

          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.

           

          -Rajiv

          • 2. Re: Forbidden values in ADC output
            reinier_3537311

            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!

             

            -Reinier.

            • 3. Re: Forbidden values in ADC output
              rajiv.vasanth.badiger

              Reinier,

               

              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?

               

              -Rajiv

              • 4. Re: Forbidden values in ADC output
                reinier_3537311

                Rajiv,

                 

                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.

                 

                adc_16sa_fixed_hist_groups.png

                 

                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.

                 

                adc_16sa_fixed_binary.png

                 

                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.

                 

                thanks,
                Reinier.

                • 5. Re: Forbidden values in ADC output
                  rajiv.vasanth.badiger

                  Reinier,

                   

                  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.

                   

                  -Rajiv