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
Advanced Member level 4
Joined
Jan 25, 2019
Messages
1,116
Helped
232
Reputation
463
Reaction score
301
Trophy points
83
Activity points
8,742
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:
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

Agree, I have reported this to Infineon.

Post # 18 gives a working example when using GetResult16()


Regards, Dana.
 
Last edited:

LaTeX Commands Quick-Menu:

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top