STM32G474 ADC input readings

Discussions and support about ChibiOS/RT, the free embedded RTOS.
User avatar
Roberto Geografo
Posts: 7
Joined: Mon Aug 09, 2021 2:09 pm
Location: Bristol
Has thanked: 1 time

STM32G474 ADC input readings

Postby Roberto Geografo » Mon Aug 09, 2021 3:11 pm

Hi,

I am a new user of ChibiOS and this is my first post here. So, hopefully, I am doing this correctly. If not, please let me know.

I am using a STM32G474VET6 and the ChibiOS version is 20.3.3.

Here is the shell info output:

ch> info
Kernel: 6.1.3
Compiler: GCC 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]
Architecture: ARMv7E-M
Core Variant: Cortex-M4F
Port Info: Advanced kernel mode
Platform: STM32G4 Hi-resolution Line
Board: STMicroelectronics STM32 Nucleo64-G474RE
Build time: Aug 9 2021 - 15:00:57


I created a code to read 2 ADC inputs from ADCD3. The code is the following:

Code: Select all

#include <array>
#include "PowerSensing.hh"
#include "chprintf.h"

#define PORTE_ADC1  ADCD1
#define PORTE_ADC3  ADCD3

namespace EmbeddedToolsN
{
    const adc_channels_num_t adc_grp_num_channels = 2;
    const uint16_t adc_grp1_buf_depth  = 1;
    adcsample_t samples1[adc_grp_num_channels * adc_grp1_buf_depth];

    static void adcerrorcallback(ADCDriver *adcp, adcerror_t err) {
        (void)adcp;
        (void)err;
    }

    extern const ADCConversionGroup porte_adcgrpcfg2;
    const ADCConversionGroup porte_adcgrpcfg2 = {
            .circular       = false,
            .num_channels   = adc_grp_num_channels,
            .end_cb         = NULL,
            .error_cb       = adcerrorcallback,
            .cfgr           = 0U,
            .cfgr2          = 0U,
            .tr1            = ADC_TR_DISABLED,
            .tr2            = ADC_TR_DISABLED,
            .tr3            = ADC_TR_DISABLED,
            .awd2cr         = 0U,
            .awd3cr         = 0U,
            .smpr           =  {
                    ADC_SMPR2_SMP_AN15(ADC_SMPR_SMP_247P5),
                    ADC_SMPR2_SMP_AN14(ADC_SMPR_SMP_247P5)
                    },
            .sqr            = {
                    ADC_SQR1_SQ1_N(ADC_CHANNEL_IN15)|
                    ADC_SQR1_SQ2_N(ADC_CHANNEL_IN14),
            }
    };
   
    const ADCConfig porte_adccfg1 = {
            .difsel = 0U // ADC inputs are single-ended
    };

    //! Setup ADCs
    // This method starts ADCs and samples reference voltage
    // and internal temperature
    bool PowerSensing::setup() {
        adcAcquireBus(&PORTE_ADC3);
        adcStart(&PORTE_ADC3, &porte_adccfg1);
        adcSTM32EnableVREF(&PORTE_ADC3);
        adcSTM32EnableTS(&PORTE_ADC1);
        adcReleaseBus(&PORTE_ADC3);

        return true;
    }

    //! Get some raw adc readings.
    void rawADCRead(int &r0,int &r1)
    {
        adcAcquireBus(&PORTE_ADC3);
        /* Performing a one-shot conversion on input channels.*/
        adcConvert(&PORTE_ADC3, &porte_adcgrpcfg2, samples1, adc_grp1_buf_depth);
        cacheBufferInvalidate(samples1, sizeof(samples1) / sizeof(adcsample_t));
        adcReleaseBus(&PORTE_ADC3);

        r0 = samples1[0];
        r1 = samples1[1];
    }
}


When I read r0 and r1 I get the following:

Code: Select all

ADC Values  134  72
ADC Values  1  71
ADC Values  0  72
ADC Values  0  72
ADC Values  0  71


The first reading (134 and 72) are the expected values.

Then it seems that the first ADC input gets set to some other input as it automatically goes to 0/1. This occurs with whatever ADC3 input I try to read.

One thing I noticed is that if I change the code to have the first desired input twice in the sequence:

Code: Select all

#include <array>
#include "PowerSensing.hh"
#include "chprintf.h"

#define PORTE_ADC1  ADCD1
#define PORTE_ADC3  ADCD3

namespace EmbeddedToolsN
{
    const adc_channels_num_t adc_grp_num_channels = 3;
    const uint16_t adc_grp1_buf_depth  = 1;
    adcsample_t samples1[adc_grp_num_channels * adc_grp1_buf_depth];

    static void adcerrorcallback(ADCDriver *adcp, adcerror_t err) {
        (void)adcp;
        (void)err;
    }

    extern const ADCConversionGroup porte_adcgrpcfg2;
    const ADCConversionGroup porte_adcgrpcfg2 = {
            .circular       = false,
            .num_channels   = adc_grp_num_channels,
            .end_cb         = NULL,
            .error_cb       = adcerrorcallback,
            .cfgr           = 0U,
            .cfgr2          = 0U,
            .tr1            = ADC_TR_DISABLED,
            .tr2            = ADC_TR_DISABLED,
            .tr3            = ADC_TR_DISABLED,
            .awd2cr         = 0U,
            .awd3cr         = 0U,
            .smpr           =  {
                    ADC_SMPR2_SMP_AN15(ADC_SMPR_SMP_247P5),
                    ADC_SMPR2_SMP_AN14(ADC_SMPR_SMP_247P5)
                    },
            .sqr            = {
                    ADC_SQR1_SQ1_N(ADC_CHANNEL_IN15)|
                    ADC_SQR1_SQ2_N(ADC_CHANNEL_IN15)|
                    ADC_SQR1_SQ3_N(ADC_CHANNEL_IN14),
            }
    };


    const ADCConfig porte_adccfg1 = {
            .difsel = 0U // ADC inputs are single-ended
    };

    //! Setup ADCs
    // This method starts ADCs and samples reference voltage
    // and internal temperature
    bool PowerSensing::setup() {
        adcAcquireBus(&PORTE_ADC3);
        adcStart(&PORTE_ADC3, &porte_adccfg1);
        adcSTM32EnableVREF(&PORTE_ADC3);
        adcSTM32EnableTS(&PORTE_ADC1);
        adcReleaseBus(&PORTE_ADC3);

        return true;
    }

    //! Get some raw adc readings.
    void rawADCRead(int &r0,int &r1,int &r2)
    {
        adcAcquireBus(&PORTE_ADC3);
        /* Performing a one-shot conversion on input channels.*/
        adcConvert(&PORTE_ADC3, &porte_adcgrpcfg2, samples1, adc_grp1_buf_depth);
        cacheBufferInvalidate(samples1, sizeof(samples1) / sizeof(adcsample_t));
        adcReleaseBus(&PORTE_ADC3);

        r0 = samples1[0];
        r1 = samples1[1];
        r2 = samples1[2];
    }
}


I get the following results:

Code: Select all

ADC Values  134  135 72
ADC Values  0  134 71
ADC Values  0  135 72
ADC Values  0  134 71
ADC Values  0  134 71
ADC Values  0  134 71
ADC Values  0  135 71
ADC Values  1  135 71


This time the r0 is still set to something else after the first conversion, however, r1 and r2 are the desired ADC inputs readings.

For completion, below you can find the method I use to output those readings on the serial interface:

Code: Select all

static void cmd_readADC(BaseSequentialStream *chp, int argc, char *argv[])
{
    (void)argc;
    (void)argv;

    while (chnGetTimeout((BaseChannel*)chp,TIME_IMMEDIATE) == STM_TIMEOUT) {

        chThdSleepMilliseconds(500);

        int r0 = 0,r1 = 0,r2 = 0;
        EmbeddedToolsN::rawADCRead(r0,r1,r2);
        chprintf(chp, "ADC Values  %d  %d %d \r\n",r0,r1,r2);
    }
}


What am I doing incorrectly?

Thanks for your help. Let me know if further info is required.

Best,

Rob
Best,

Rob

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32G474 ADC input readings

Postby Giovanni » Mon Aug 09, 2021 6:11 pm

Hi,

I cannot test right now but probably you just need to add CONT to CFGR when depth is greater than one or the ADC stops after the 1st conversion.

Giovanni

User avatar
Roberto Geografo
Posts: 7
Joined: Mon Aug 09, 2021 2:09 pm
Location: Bristol
Has thanked: 1 time

Re: STM32G474 ADC input readings

Postby Roberto Geografo » Mon Aug 09, 2021 9:12 pm

Hi,

I tried to add CONT to CFGR as follows, but I got the same result.

However, I have adc_grp1_buf_depth set to 1.

Code: Select all

const ADCConversionGroup porte_adcgrpcfg2 = {
            .circular       = false,
            .num_channels   = adc_grp_num_channels,
            .end_cb         = NULL,
            .error_cb       = adcerrorcallback,
            .cfgr           = ADC_CFGR_CONT,
            .cfgr2          = 0U,
            .tr1            = ADC_TR_DISABLED,
            .tr2            = ADC_TR_DISABLED,
            .tr3            = ADC_TR_DISABLED,
            .awd2cr         = 0U,
            .awd3cr         = 0U,
            .smpr           =  {
                    ADC_SMPR2_SMP_AN15(ADC_SMPR_SMP_247P5),
                    ADC_SMPR2_SMP_AN14(ADC_SMPR_SMP_247P5)
                    },
            .sqr            = {
                    ADC_SQR1_SQ1_N(ADC_CHANNEL_IN15)|
                    ADC_SQR1_SQ2_N(ADC_CHANNEL_IN14),
            }
    };
Best,

Rob


Return to “ChibiOS/RT”

Who is online

Users browsing this forum: No registered users and 9 guests