SAR ADC does not work as expected

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
RuGl_1600761
Employee
Employee
25 replies posted 25 sign-ins 10 replies posted

I use CY8C4247AZI-L485 internal reference (1uF at P1.7) free running 2 channels avarage 4(accululate). Voltage range on the analog pins is 0...1V.

Is there a pssibility to grab results when ever I like  without using an interrupt. Having ADC free running sequencing and averaging in background. I could not find an example in free running mode and the datasheet does not tell much about free running mode and what capabilities I have. The block diagramm on page 26 show the structure of ADC block. It seems that every thing is done automatically and the avaraged results will always be avalibale in result regitser... so I can access asynchrounously access .... doing so the result I get is not as expected... please advice how to handle, thanks.

 

rgl
0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

 

I'm glad that you have already solved the problem.

 

Like you, I could not find how to correctly read the result of free running mode,

so I assumed that the ADC_GetResult16() can be called any time.

I used CY8CKIT-044 for testing, but program won't be much different from your hardware (I hope).

 

I tried both "free running mode" and "hardware trigger mode"

as I usually prefer the later, so that I can have control over "when" to trigger

and (probably) save some power by not converting ADC when I don't need the result.

 

(1) Free running mode

Schematic 

005_freerunning_schematic.JPG

ADC Config

003-freerunning_config.JPG

Pins

007-freerun-pins.JPG

Tera Term log 

Note: I used an external POT to play with the input voltage

001-Freerunning-log.JPG

main.c

#include "project.h"
#include "stdio.h"

#define STR_BUF_LEN 64
char str[STR_BUF_LEN+1] ;
void print(char *str)
{
    UART_UartPutString(str) ;
}

void init_hardware(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    
    ADC_Start() ;
    ADC_StartConvert() ;
    
    UART_Start() ;
    print("\x1b[2J\x1b[;H") ;
    snprintf(str, STR_BUF_LEN, "ADC Freerunning Test ") ;
    print(str) ;
    snprintf(str, STR_BUF_LEN, "(%s %s)\n\r", __DATE__, __TIME__) ;
    print(str) ;
}

int16_t measure(void)
{
    int16_t raw_count ;
    int16_t mV ;
    
    raw_count = ADC_GetResult16(0) ;
    mV = ADC_CountsTo_mVolts(0, raw_count) ;
    
    return( mV ) ;
}

int main(void)
{
    int16_t mV ;
    
    init_hardware() ;

    for(;;) {
        mV = measure() ;
        snprintf(str, STR_BUF_LEN, "%d mV\n\r", mV) ;
        print(str) ;
        
        CyDelay(1000) ;
    }
}

As far as I tested, ADC seems to be working OK.

 

(2) hardware trigger mode

I could trigger it from software, too.

Schematic

006-triggered_schematic.JPG

ADC Config

004-hw-triggered.JPG

Pins

008-trigger-mode-pins.JPG

Tera Term log

002-Triggered-log.JPG

main.c

#include "project.h"
#include "stdio.h"

#define STR_BUF_LEN 64
char str[STR_BUF_LEN+1] ;
void print(char *str)
{
    UART_UartPutString(str) ;
}

void init_hardware(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    
    ADC_Start() ;
//    ADC_StartConvert() ;
    
    UART_Start() ;
    print("\x1b[2J\x1b[;H") ;
    snprintf(str, STR_BUF_LEN, "ADC Triggered Test ") ;
    print(str) ;
    snprintf(str, STR_BUF_LEN, "(%s %s)\n\r", __DATE__, __TIME__) ;
    print(str) ;
}

int16_t measure(void)
{
    int16_t raw_count ;
    int16_t mV ;
    
    ADC_StartConvert() ;
    ADC_IsEndConversion(ADC_WAIT_FOR_RESULT) ;
    raw_count = ADC_GetResult16(0) ;
    mV = ADC_CountsTo_mVolts(0, raw_count) ;
    
    return( mV ) ;
}

int main(void)
{
    int16_t mV ;
    
    init_hardware() ;

    for(;;) {
        mV = measure() ;
        snprintf(str, STR_BUF_LEN, "%d mV\n\r", mV) ;
        print(str) ;
        
        CyDelay(1000) ;
    }
}

So both seemed running OK.

moto

 

View solution in original post

2 Replies
RuGl_1600761
Employee
Employee
25 replies posted 25 sign-ins 10 replies posted

I found the issue. It is now working. Anyhow the description how to use free runnung mode could be added in data sheet; even a pice of code would be vey helpful to avoid try and error !

rgl
0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

 

I'm glad that you have already solved the problem.

 

Like you, I could not find how to correctly read the result of free running mode,

so I assumed that the ADC_GetResult16() can be called any time.

I used CY8CKIT-044 for testing, but program won't be much different from your hardware (I hope).

 

I tried both "free running mode" and "hardware trigger mode"

as I usually prefer the later, so that I can have control over "when" to trigger

and (probably) save some power by not converting ADC when I don't need the result.

 

(1) Free running mode

Schematic 

005_freerunning_schematic.JPG

ADC Config

003-freerunning_config.JPG

Pins

007-freerun-pins.JPG

Tera Term log 

Note: I used an external POT to play with the input voltage

001-Freerunning-log.JPG

main.c

#include "project.h"
#include "stdio.h"

#define STR_BUF_LEN 64
char str[STR_BUF_LEN+1] ;
void print(char *str)
{
    UART_UartPutString(str) ;
}

void init_hardware(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    
    ADC_Start() ;
    ADC_StartConvert() ;
    
    UART_Start() ;
    print("\x1b[2J\x1b[;H") ;
    snprintf(str, STR_BUF_LEN, "ADC Freerunning Test ") ;
    print(str) ;
    snprintf(str, STR_BUF_LEN, "(%s %s)\n\r", __DATE__, __TIME__) ;
    print(str) ;
}

int16_t measure(void)
{
    int16_t raw_count ;
    int16_t mV ;
    
    raw_count = ADC_GetResult16(0) ;
    mV = ADC_CountsTo_mVolts(0, raw_count) ;
    
    return( mV ) ;
}

int main(void)
{
    int16_t mV ;
    
    init_hardware() ;

    for(;;) {
        mV = measure() ;
        snprintf(str, STR_BUF_LEN, "%d mV\n\r", mV) ;
        print(str) ;
        
        CyDelay(1000) ;
    }
}

As far as I tested, ADC seems to be working OK.

 

(2) hardware trigger mode

I could trigger it from software, too.

Schematic

006-triggered_schematic.JPG

ADC Config

004-hw-triggered.JPG

Pins

008-trigger-mode-pins.JPG

Tera Term log

002-Triggered-log.JPG

main.c

#include "project.h"
#include "stdio.h"

#define STR_BUF_LEN 64
char str[STR_BUF_LEN+1] ;
void print(char *str)
{
    UART_UartPutString(str) ;
}

void init_hardware(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    
    ADC_Start() ;
//    ADC_StartConvert() ;
    
    UART_Start() ;
    print("\x1b[2J\x1b[;H") ;
    snprintf(str, STR_BUF_LEN, "ADC Triggered Test ") ;
    print(str) ;
    snprintf(str, STR_BUF_LEN, "(%s %s)\n\r", __DATE__, __TIME__) ;
    print(str) ;
}

int16_t measure(void)
{
    int16_t raw_count ;
    int16_t mV ;
    
    ADC_StartConvert() ;
    ADC_IsEndConversion(ADC_WAIT_FOR_RESULT) ;
    raw_count = ADC_GetResult16(0) ;
    mV = ADC_CountsTo_mVolts(0, raw_count) ;
    
    return( mV ) ;
}

int main(void)
{
    int16_t mV ;
    
    init_hardware() ;

    for(;;) {
        mV = measure() ;
        snprintf(str, STR_BUF_LEN, "%d mV\n\r", mV) ;
        print(str) ;
        
        CyDelay(1000) ;
    }
}

So both seemed running OK.

moto