PSOC 4 ADC Formula - What is it?

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

cross mob
EyGe_3183606
Level 4
Level 4
25 replies posted 10 sign-ins 10 replies posted

Hello,

We are developing a project using PSOC 4 (BLE 4.2) and we have are using the SAR ADC module.

We are developing a medical device that requires FDA level documentation.

As part of the requirements of the documentation that we need to prepare is to describe the formula used to convert the raw data from the SAR ADC to voltage.

Unfortunately, we could not find any Cypress documentation that describes how the conversion is made.

We can only rely on the source code, and we don't understand it. We need to write a formula. Could you perhaps provide a formula?

Here is the source code (generated by Cypress PSOC Creator 4.1):

/*******************************************************************************

* Function Name: ADC_SAR_Seq_1_GetResult16

********************************************************************************

*

* Summary:

*  Gets the data available in the SAR DATA register.

*

* Parameters:

*  chan: The ADC channel in which to return the result. The first channel

*  is 0 and the injection channel if enabled is the number of valid channels.

*

* Return:

*  Returns converted data as a signed 16-bit integer

*

*******************************************************************************/

int16 ADC_SAR_Seq_1_GetResult16(uint32 chan)

{

    uint32 result;

    /* Halt CPU in debug mode if channel is out of valid range */

    CYASSERT(chan < ADC_SAR_Seq_1_TOTAL_CHANNELS_NUM);

    if(chan < ADC_SAR_Seq_1_SEQUENCED_CHANNELS_NUM)

    {

        result = CY_GET_REG32((reg32 *)(ADC_SAR_Seq_1_SAR_CHAN_RESULT_IND + (uint32)(chan << 2u))) &

                ADC_SAR_Seq_1_RESULT_MASK;

    }

    else

    {

        #if(ADC_SAR_Seq_1_INJ_CHANNEL_ENABLED)

            result = ADC_SAR_Seq_1_SAR_INJ_RESULT_REG & ADC_SAR_Seq_1_RESULT_MASK;

        #else

            result = 0u;

        #endif /* ADC_SAR_Seq_1_INJ_CHANNEL_ENABLED */

    }

    return ( (int16)result );

}

And the second function used is:

/*******************************************************************************

    * Function Name: ADC_SAR_Seq_1_CountsTo_mVolts

    ********************************************************************************

    *

    * Summary:

    *  This function converts ADC counts to mVolts

    *  This function is not available when left data format justification selected.

    *

    * Parameters:

    *  chan: The ADC channel number.

    *  adcCounts: Result from the ADC conversion

    *

    * Return:

    *  Results in mVolts

    *

    * Global variables:

    *  ADC_SAR_Seq_1_countsPer10Volt:  used to convert ADC counts to mVolts.

    *  ADC_SAR_Seq_1_Offset:  Used as the offset while converting ADC counts

    *   to mVolts.

    *

    *******************************************************************************/

    int16 ADC_SAR_Seq_1_CountsTo_mVolts(uint32 chan, int16 adcCounts)

    {

        int16 mVolts;

        /* Halt CPU in debug mode if channel is out of valid range */

        CYASSERT(chan < ADC_SAR_Seq_1_TOTAL_CHANNELS_NUM);

        /* Divide the adcCount when accumulate averaging mode selected */

        #if(ADC_SAR_Seq_1_DEFAULT_AVG_MODE == ADC_SAR_Seq_1__ACCUMULATE)

            if((ADC_SAR_Seq_1_channelsConfig[chan] & ADC_SAR_Seq_1_AVERAGING_EN) != 0u)

            {

                adcCounts /= ADC_SAR_Seq_1_DEFAULT_AVG_SAMPLES_DIV;

            }

        #endif /* ADC_SAR_Seq_1_DEFAULT_AVG_MODE == ADC_SAR_Seq_1__ACCUMULATE */

        /* Subtract ADC offset */

        adcCounts -= ADC_SAR_Seq_1_offset[chan];

        mVolts = (int16)((((int32)adcCounts * ADC_SAR_Seq_1_10MV_COUNTS) + ( (adcCounts > 0) ?

                 (ADC_SAR_Seq_1_countsPer10Volt[chan] / 2) : (-(ADC_SAR_Seq_1_countsPer10Volt[chan] / 2)) ))

                 / ADC_SAR_Seq_1_countsPer10Volt[chan]);

        return( mVolts );

    }

Thanks,

David

0 Likes
1 Solution
Vasanth
Moderator
Moderator
Moderator
250 sign-ins 500 solutions authored First question asked

Hello David,

The first part of the API, ADC_SAR_Seq_1_GetResult16() just returns the count value corresponding to the channel. The API resolves the channel number to the right register address to get the result. There is no calculation happening there.

The ADC counts to mV converts the count value into voltage. Normally the count value of the ADC is multiplied with its resolution for this calculation. But PSoC API provides a gain correction mechanism inside its APIs, so in case external voltage reference is used or when calibration is required with a known input.

ADC_SetGain() Sets the ADC gain in counts per 10 volt for the voltage conversion functions. This value is set by default by the reference and input range settings. It should only be used to further calibrate the ADC with a known input or if an external reference is used. Affects the ADC_CountsTo_uVolts, ADC_CountsTo_mVolts

and ADC_CountsTo_Volts functions by supplying the correct conversion between ADC counts and voltage.

Voltage equivalent = count_value * resolution

                                 = count_value * resolution * 1000 (in mV scale)

ADC_SAR_Seq_1_countsPer10Volt is the parameter set by the ADC_SetGain() API.

ADC_SAR_Seq_1_countsPer10Volt = 10 V/ resolution

ADC_SAR_Seq_1_10MV_COUNTS = 10000 ( it is10V x 1000 as the API is converts to mV)

Now ADC_SAR_Seq_1_10MV_COUNTS/ADC_SAR_Seq_1_countsPer10Volt = resolution x 1000

Applying this in the first equation,

Voltage equivalent = count_value* ADC_SAR_Seq_1_10MV_COUNTS/ADC_SAR_Seq_1_countsPer10Volt

Now at the end there is  rounding off in this equation ( half way rounding scheme). The idea of this rounding mechanism is that, if you wan to find A/B, you will find the division (A+ (B/2))/B for rounding of the value to the rail or floor. The same is done in the equation by adding the half of ADC_SAR_Seq_1_countsPer10Volt to the equation, which is the denominator part. Whether to add or subract this value is decided based on whether the count value is positive or negative.

I hope this clarifies your doubt.

Best Regards,
VRS

View solution in original post

1 Reply
Vasanth
Moderator
Moderator
Moderator
250 sign-ins 500 solutions authored First question asked

Hello David,

The first part of the API, ADC_SAR_Seq_1_GetResult16() just returns the count value corresponding to the channel. The API resolves the channel number to the right register address to get the result. There is no calculation happening there.

The ADC counts to mV converts the count value into voltage. Normally the count value of the ADC is multiplied with its resolution for this calculation. But PSoC API provides a gain correction mechanism inside its APIs, so in case external voltage reference is used or when calibration is required with a known input.

ADC_SetGain() Sets the ADC gain in counts per 10 volt for the voltage conversion functions. This value is set by default by the reference and input range settings. It should only be used to further calibrate the ADC with a known input or if an external reference is used. Affects the ADC_CountsTo_uVolts, ADC_CountsTo_mVolts

and ADC_CountsTo_Volts functions by supplying the correct conversion between ADC counts and voltage.

Voltage equivalent = count_value * resolution

                                 = count_value * resolution * 1000 (in mV scale)

ADC_SAR_Seq_1_countsPer10Volt is the parameter set by the ADC_SetGain() API.

ADC_SAR_Seq_1_countsPer10Volt = 10 V/ resolution

ADC_SAR_Seq_1_10MV_COUNTS = 10000 ( it is10V x 1000 as the API is converts to mV)

Now ADC_SAR_Seq_1_10MV_COUNTS/ADC_SAR_Seq_1_countsPer10Volt = resolution x 1000

Applying this in the first equation,

Voltage equivalent = count_value* ADC_SAR_Seq_1_10MV_COUNTS/ADC_SAR_Seq_1_countsPer10Volt

Now at the end there is  rounding off in this equation ( half way rounding scheme). The idea of this rounding mechanism is that, if you wan to find A/B, you will find the division (A+ (B/2))/B for rounding of the value to the rail or floor. The same is done in the equation by adding the half of ADC_SAR_Seq_1_countsPer10Volt to the equation, which is the denominator part. Whether to add or subract this value is decided based on whether the count value is positive or negative.

I hope this clarifies your doubt.

Best Regards,
VRS