Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

SAR using PSoC 5LP

wwfeldman

Advanced Member level 4
Joined
Jan 25, 2019
Messages
1,111
Helped
232
Reputation
463
Reaction score
299
Trophy points
83
Activity points
8,654
I am using VDAC8 and ADC_SAR to convert analog to digital and back, in KIT059, PSoC5LP.
A for loop assigns the digital value to the DtoA, whose output is buffered by an op amp follower.
The output is fed back into another buffering opamp and then to an A to D converter, ADC_SAR.

1717008884908.png


the program:
Code:
#include "project.h"
#include "stdio.h"
#include "string.h"
#include "math.h"

uint8    i, ii, j, jj, k, kk;             //index variables
uint8    temp = 0, startflag = 0;         //0 = wait 1 = start

//declare linear regression varibles
uint8    n = 0;
double   x, y = 0;
double   xsum, ysum = 0;
double   xy, xysum = 0;
double   x2, x2sum = 0;
double   num, den, slope, intercept;
double   zero = 0;
double   kkk;

char8 res[16u];

double   value, fracpart, intpart ;    //value is real, frac is fractional part, decim is whole number part
uint8    intfrac, intdecim, decim, frac;

// function:
void lma_clear_display(void)
{
    //clear dispaly
    for(j = 0; j<=3; j++)
    {
        LCD_Position(j,0);
        LCD_PrintString("                    ");
    }
}  //end clear display for(j = 0; j<=3; j++)
  

// function:
void lma_print_real(double value)
{
    intpart = (int) value;
    fracpart = (value - intpart)*1000;
    LCD_PrintNumber(intpart);
    LCD_PrintString(".");
    if(fracpart < 10) LCD_PrintString("0");
    if(fracpart < 100) LCD_PrintString("0");
    //if(fracpart < 1000) LCD_PrintString("0");
    //if(fracpart < 10000) LCD_PrintString("0");
    LCD_PrintNumber(fracpart);

}  //end lma_print_real

int main(void)
{       
    //initialize display
    LCD_Start();

    CyGlobalIntEnable; /* Enable global interrupts. */
    
    lma_clear_display();
    LCD_Position(0,0);
    LCD_PrintString("initialize          ");
    CyDelay(500);

    //initialize variables
    n = 0;
    x = 0;
    y = 0;
    xy = 0;
    x2 = 0;
    xsum = 0;
    ysum = 0;
    xysum = 0;
    x2sum = 0;
    zero = 0;
  
    //set op amps, A2D, and D2A   
    OpAmp_grn_in_Start();
    OpAmp_wht_out_Start();
 
    D2A_Vout_Start();
    D2A_Vout_SetSpeed(D2A_Vout_HIGHSPEED);
    D2A_Vout_SetRange(D2A_Vout_RANGE_4V);
  
    lma_clear_display();
    LCD_Position(0,0);
    LCD_PrintString("D to A started      ");
    CyDelay(500);

    A2D_wht_pot_Start();
    A2D_wht_pot_SetPower(A2D_wht_pot__MEDPOWER);
    A2D_wht_pot_SetResolution(A2D_wht_pot__BITS_8);
    A2D_wht_pot_StartConvert();
  
    A2D_grn_snsr_Start();
    A2D_grn_snsr_SetPower(A2D_grn_snsr__MEDPOWER);
    A2D_grn_snsr_SetResolution(A2D_grn_snsr__BITS_8);
    A2D_grn_snsr_StartConvert();
  
    //step through output voltages from 0.75 to 3.23 V
    //digital range 47 to 202 or 0.75 V to 3.32 V
    //increment +1 yields 156 data points
    //increment +5 yields 32 data points
  
    lma_clear_display();
    LCD_Position(0,0);
    LCD_PrintString("for loop            ");
    CyDelay(500);

    for(k = 47; k<=202; k = k + 5)
    {
        D2A_Vout_SetValue(k);
        CyDelay(500); 

        //get pot value
        A2D_wht_pot_StartConvert();
        //wait for end of conversion
        do
            {temp = A2D_wht_pot_IsEndConversion(A2D_wht_pot_RETURN_STATUS);}
        while (temp == 0);
        CyDelay(200);
        x = A2D_wht_pot_CountsTo_Volts(A2D_wht_pot_GetResult8());
      
        //get sensor value
        A2D_grn_snsr_StartConvert();
        //CyDelay(200);
        //wait for end of conversion
         do
            {temp = A2D_grn_snsr_IsEndConversion(A2D_grn_snsr_RETURN_STATUS);}
        while (temp == 0);
        CyDelay(200);
      
        lma_clear_display();
        LCD_Position(0,0);
        LCD_PrintString("convert finished    ");
        CyDelay(500);
        y = A2D_grn_snsr_CountsTo_Volts(A2D_grn_snsr_GetResult8());
              
        //linear regression calculations
        n = n + 1;
        xsum = xsum + x;
        ysum = ysum + y;
        xysum = xysum + (x * y);
        x2sum = x2sum + (x * x);
      
        lma_clear_display();
        LCD_Position(0,0);
        LCD_PrintString("k = ");
        LCD_PrintNumber(k);
        LCD_PrintString("  ");       
        lma_print_real((double) (k * 4.08/255.0));
      
        LCD_Position(1,0);
        LCD_PrintString("x = ");
        lma_print_real((double) x);;

        LCD_Position(2,0);
        LCD_PrintString("y = ");
        lma_print_real((double) y);
  
        CyDelay(10000);
        
    } //end for(k = 47; k<=202; k = k + 5)
  
    //find slope and intercept
    num = n * xysum - xsum * ysum;
    den = n * x2sum - (xsum * xsum);
    slope = num/den;
  
    num = ysum * x2sum - xsum * xysum;
    intercept = num/den;
    zero = (-1 * intercept / slope) - 2.5 ;
  
    //display results
    lma_clear_display();
    LCD_Position(0,0);
    LCD_PrintString("sensor data         ");
    LCD_Position(1,0);
    LCD_PrintString("slope = ");
    lma_print_real(slope);
    LCD_Position(2,0);
    LCD_PrintString("int = ");
    lma_print_real(intercept);
    LCD_Position(3,0);
    LCD_PrintString("zero = ");
    lma_print_real(zero);
  
    CyDelay(5000); //5 second pause
 
} //end of main
/* END OF FILE */

the pinouts for the op-amps were assigned by PSoC Creator

the input range of the SAR AtoD is Vssa to Vdda (single ended)
the reference is thus forced to internal and the reference is 2.5 V

This is the observed results - - left column is the d to a theoretical value, which agrees with meter measurement thereof,
the right column is a to d output as seen on the LCD:

0.752 0.840
0.832 0.938
0.912 1.016
0.992 1.113
1.072 1.191
1.152 1.289
1.232 1.387
1.312 1.465
1.392 1.543
1.472 1.641
1.552 1.719
1.632 1.816
1.712 1.895
1.792 1.992
1.872 2.070
1.952 2.168
2.032 2.246
2.112 2.344
2.192 2.422
2.272 0
2.352 0
2.432 0
2.512 0
2.592 0
2.672 0
2.752 0
2.832 0
2.912 0
2.992 0
3.072 0
3.152 0
3.232 0

this is the graph of the data, without the the SAR produced 0s

1717009224523.png


the question is - what happened to the SAT output when it went above about 2.5 V?
why did it go to zero?
what did i miss/do wrong?
 
Last edited by a moderator:
Look at the guts of all the linear amps & comparators, for
an obvious common mode input range / single pin voltage
contraint which might then steer the search logic off into
the weeds, if nonmonotonicity appears (and once pegged,
supply ripple alone could do that).
 
Post the project archive so we can take a look. Use archive complete
when you do.

As an aside when you post code use the code tags menu item, it maintains the
indenting/format. Menu item is </>

The OpAmps are RRIO.

Note when you dbl click the component and set the config, you do not have to repeat this in code
unless code needs to change component operation, ranges, speed, etcc. This eliminates tedious
coding......

Also Creator will auto assign pins, but keep in mind you can generally assign pins as needed.
Note however there are preferred analog pin assignments, because of internal routing resistance,
in case currents are being routed, as in IDAC routing. There is an ohmmeter tool to help when you
deviate from preferred analog routes (mainly port 0 for analog) so you can determine if there might be
a route that might contribute to error in a significant way.

What is the "SAT" output you refer to ?


Regards, Dana.
 
Last edited:
SAT is a typo - should be SAR.

I am aware that creator auto assigns pins.

i'm thinking the issue is in the SAR - since the opamps are RR as you said, and that the
output of the D to A matches the meter.

thank you
 

Attachments

  • A2D D2A Test.cyprj.Archive01.zip
    2.2 MB · Views: 28
SARs configed like this :

1717075509864.png


What sample rate you running SAR at ?

What specific pins did the auto assign for SAR inputs result in assignments ?

Not sure if this is affecting results :

1717076934579.png


Like when you flip the MSB of DAC and then start SAR while DAC still settling .......although I would think the SAR has
a S/H on its input.

I just checked architecture manual and it does not have a S/H.........if that turns into an issue could always use one of the
onchip S/Hs and code to time sequence.....however I looked at Cypress forum and no one seems to be affected this way,
eg. your issue.


Regards, Dana.
 
Last edited:
there is a 500 ms delay after setting the D to A, >> 3 us, so the analog ouptu should be settled

Vout_white is connected to P0(0), OpAmp2.Vout
Vin_green is connected to P3(3), OpAmp3.Vplus

the SAR is software triggered and has a "wait until complete" loop thereafter
so the sample rate likely doesn't matter.

according to PSoC® 5LP: CY8C58LP Family Datasheet:
page 93 (94 per acrobat reader),
Vref is 1.025 V max, so SAR can only get to 2.05 V
the SAR section does not have a spec on Vref.

i found nothing that indicated the reference was 2.5V
apparently the SAR is good to 2 * Vref, but not good to Vdd
 
Maybe I am missing something but second entry seems to give full
analog range (to VDDA) from SAR datasheet :

1717107030212.png


SAR input range :

1717108880871.png



Note the DAC is limited to only 4.096V max output.


Regards, Dana.
 
Last edited:
that's the problem.
i used the second entry
i used two separate KIt059s
i tried the sigma delta a to d - same result, no data after about 2.5 V
the sigma delta has an entry supposedly from Vss to 6*Vref, where Vref = 1.??V, so it tops out at 6V
same result - once the input hits about 2.5 V, the A to D output is 0

the D to A works, the A to D does not

and i only need about 0.7V to about 3.5V, so the D to A topping out at 4V is not a problem
 
I will do a setup this weekend in lieu of your not posting project to see if I get
the same result. You could also post at Infineon.com, but they wont go very
far on issue w/o project to examine.


Regards, Dana.
--- Updated ---

1717151058050.png


If you are selected to first entry in configurator wizard (dbl click component) your range is 0 - 2 x 1.024V
using internal reference.

Note this ref selection is only setup in wizard, no API to change it.


Regards, Dana.

My apologies, I see you are selected to correct Vref, your prior statements. Seems this is tied
to ext Vref is being invoked. You want internal Vref selected in wizard.
 
Last edited:
My thoughts are ;
The output is the input minus the reference and is in 2s compliment.

Thus differential inputs are +/- Vref or single-ended = 0 to 2*Vref.

Also to check for non-linearity and Vref - gnd noise, generate a triangle ramp or sine sweep to the ADC and send to DAC and compare analog In-Out vs In using XY mode on a scope.

If it's > 1 bit error, you have a problem.
 
Last edited:
The DNL and INL errors, the OpAmp offsets, the VDAC G error as well as
offsets all produce >> 1 LSB error. The test I ran in post #11 seems to work
just fine. I redid it as well at 12 bits, same results, albeit more accurate.

The problem is OP wrong Vref setting .....
 
the archived files are in post 4 and here

i re-did the SAR as you have them - output still 0 as in data list of post 1
--- Updated ---

i removed most of the extras
used a trim pot as the input
compared DMM measurement of input with SAR display of output

1717428364960.png


linear until reach 2.48 V on SAR
then all data yields 0
does not look like noise, linearity, monotonic-ness
looks like Vout is limited to 2.48 V - anything that causes a larger output yields 0 .
seems to imply that the input range is Vss to Vdd/2

same result if use a battery or USB power.
 

Attachments

  • A2D D2A Test.cyprj.Archive01.zip
    2.2 MB · Views: 21
  • A2D D2A Test_pot.cyprj.Archive01.zip
    2 MB · Views: 23
Last edited:
Here is a test of DelSig as ref testing the SAR and DAC outputs.

Debug, I have two breakpoints set. one after the SAR tests, one after
DAC tests.

Hover cursor over code structures, SARResults and VDACResults, right click,
and add watch, in subroutines below main()

Then you can look at each test and see its good to VDAC max out of 4.096 volts.

Debug compile of course....


Regards, Dana.
--- Updated ---

the archived files are in post 4 and here

i re-did the SAR as you have them - output still 0 as in data list of post 1
--- Updated ---

i removed most of the extras
used a trim pot as the input
compared DMM measurement of input with SAR display of output

View attachment 191231

linear until reach 2.48 V on SAR
then all data yields 0
does not look like noise, linearity, monotonic-ness
looks like Vout is limited to 2.48 V - anything that causes a larger output yields 0 .
seems to imply that the input range is Vss to Vdd/2

same result if use a battery or USB power.

The easiest way to send a project is as an archive from the file menu, do it as "archive complete".


Regards, Dana.
--- Updated ---

Almost forgot, turn off code optimization in project build settings, otherwise
it eliminates variables never used.

1717429524155.png



Regards, Dana.
--- Updated ---

One other comment. I run a interrupt on the DelSig and run it in continuous mode. It has
capability to do single shot conversions, but knowing the internals of a DelSig and its various
internals; buffers, I feel, short of a glaring "DO NOT DO THIS" notification in specs, that
flushing these analog "cache" processes is second best to just running the DelSig in
continuous mode.


Regards, Dana.
 

Attachments

  • SARtest.cywrk.Archive01.zip
    2.3 MB · Views: 23
Last edited:
In your SAR sample you have :

x = SAR1_CountsTo_Volts( SAR1_GetResult8());
Should be :

x = SAR1_CountsTo_Volts( (int16) SAR1_GetResult8());

Correct that.


Regards, Dana.

PS : I just filed a case at Infineon, I too cannot get the SAR to read VSSA to VDDA.
I get in debugger -Vref to + Vref (- 2.5 to + 2.5). For kicks added a 2.5V offset to
result, and still same results, eg. I think that the counts to volts api in 8 bit mode may
have a bug.

Note my example seems to work because I did it as 12 bit.

Regards, Dana.
 
Last edited:
Take a look at this (which is working in 8 bit mode) :



Regards, Dana.
 
I moded MotooTanaka 's project and added a DAC to supply source
for SAR measurement.

Open up a terminal session, 115K baud, to watch the SAR output.

Note I moded project, as a test, to change

count = SAR_1_GetResult.16() ;

to

count = SAR_1_GetResult8() ;

And project repeated limit problem of 2.5V max, so reported to infineon to
look at.


Regards, Dana.
 

Attachments

  • adc_test_240604-000.cywrk.Archive01.zip
    1.7 MB · Views: 20
Last edited:
i did some testing
i think the error is in the SAR API GetReults8
using an 8 bit SAR with GetResult8 gives the bad data after about 2.5 V
using an 8 bit SAR with GetResult16 works past 2.5 V
 
Hi,

for debugging purposes you definitely should watch the raw data given by the GetResult function.

Klaus
 

LaTeX Commands Quick-Menu:

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top