ADC Application
응답
16. 9. 20 오전 11:26

Dear XDK community,

the user Peter Yang reached the XDK support via email and asked some questions about how to implement an own application including the ADC.
To give all of you the advantage to benefit of his questions, I am going to answer them here.

 

Question 1:  In PTD_portDriver_ph.h file:

/** ADC input pin of AKU340 sensor */

#define PTD_PORT_AKU340_ADC_OUT         gpioPortD

#define PTD_PIN_AKU340_ADC_OUT          4

 
I do not know what the two numbers are and need your help to clarify:

According to https://www.silabs.com/Support%20Documents/TechnicalDocs/EFM32GG390.pdf Page 7:

2.1.31 General Purpose Input/Output (GPIO) In the EFM32GG390, there are 86 General Purpose Input/Output (GPIO) pins, which are divided into ports with up to 16 pins each. These pins can individually be configured as either an output or input.

My guess is that these two numbers are used to identify  one GPIO pin (port D and Pin 4), am I right?  I guess AKU340 is somehow connected with this GPIO pin.

You are correct, the peripherals like the sensors including the akustic sensor are connected to the EFM32GG390 microcontroller via general purpose pins. This certain pin connects the akustic sensor to the EFM32GG390.

 

Question 2: how to map a specific GPIO pin (eg., Port D and Pin 4) to a ADC channel?  Where can I find such information?

According to https://www.silabs.com/Support%20Documents/TechnicalDocs/EFM32GG390.pdf, page 6: 2.1.25 Analog to Digital Converter (ADC):

The ADC is a Successive Approximation Register (SAR) architecture, with a resolution of up to 12 bits at up to one million samples per second. The integrated input mux can select inputs from 8 external pins and 6 internal signals

I cannot find any C program code, which specifies a ADC channel for a specific GPIO pin (eg., port D and Pin 4). I think I miss something, please help on this.

Currently there are only four pins available to use the ADC on the extension bus. Two of this pins are the ADC channels 5 and 6. Further there are two GPIO pins that can be configured for own applications, e.g ADC. Unfortunately there is only code available in the xdk community that reads  data from the ADC channel 5 and 6 pins. The thread can be found here.

 

Question 3: I hope there is a design document about XDK and give some introduction about GPIO pin, XDK gateway and ADC, because they are very basic for embedded system developers but not for other software developers.

Unfortunately there is only documentation about GPIO pin, XDK gateway and ADC in the general information guide and in the mentioned thread in project exchange of the XDK community available. But I will add this to our improvement list.

I hope this brings some clarify.

Kind regards,
Franjo

0 (0 투표)
RE: ADC Application
응답
16. 9. 20 오전 10:05 as a reply to Franjo Stjepandic.

Hi Stjepandic,

 

thank you to post my questions here. After some discovery, I have better understanding about device.

 

I have following program which may be able to used for sampling (for both battey monitoring and other sensor like acoustic). But if someone can provide detail design document about the XDK, it will be helpful.

 

Especially, if someone can explain the effect of different sampling rate, it will be helpful.

 

/* module includes ********************************************************** */

/* system header files */
#include "BCDS_Basics.h"
#include "BCDS_WlanConnect.h"
#include "BCDS_NetworkConfig.h"
#include "PAL_initialize_ih.h"
#include "PAL_socketMonitor_ih.h"
#include <Serval_HttpClient.h>
#include <Serval_Network.h>

/* additional interface header files */
#include "stdio.h"
#include "FreeRTOS.h"
#include "timers.h"

#include "em_cmu.h"
#include "ADC_ih.h"
#include "XdkGpioConfig.h"
#include "PTD_portDriver_ph.h"
#include "PTD_portDriver_ih.h"
#include "ADC_ih.h"                 /* added for ADC */

/* own header files */
#include "AcousticDetectApp.h"

/* constant definitions ***************************************************** */
#define PAL_IP_ADDRESS_SIZE UINT8_C(15) /*< Maximum size of the ip address */

/* local variables ********************************************************** */
ADC_Init_TypeDef adc0_init_conf = ADC_INIT_DEFAULT;
ADC_InitSingle_TypeDef adc0_singleinit_conf = ADC_INITSINGLE_DEFAULT;

static uint8_t current_sample = 0;
static uint32_t sample_buffer[50];

/* global variables ********************************************************* */
static xTimerHandle connectTimerHandle; /**< variable to store timer handle*/
Ip_Address_T destAddr = UINT32_C(0);/*< variable to store the Ip address of the server */
char url_ptr[MAX_URL_SIZE];
uint32_t sum;


/* inline functions ********************************************************* */

/* local functions ********************************************************** */
 
uint32_t sound_level_calc(uint32_t mic_sample) {
    uint8_t i = 0;

    sample_buffer[current_sample] = mic_sample * mic_sample;
    current_sample = (current_sample + 1) % 50;

    for (i = 0, sum = 0; i < 50; i++) {
        sum += sample_buffer[i];
    }

    return sum;
}

void Read_ADC(xTimerHandle pxTimer) {
    (void) (pxTimer);
    uint32_t ADC_read_value;
    ADC_singleAcq_t ADC_acquire_one = { ADC0, adc0_singleinit_conf,
            adcSingleInpCh4, 0UL };  // adcSingleInpCh7 for battery monitoring

    ADC_singleAcq_tp ADC_acquire_one_p = &ADC_acquire_one;
    ADC_pollSingleData(ADC_acquire_one_p);
    ADC_read_value = ADC_scaleAdcValue(ADC_acquire_one_p);
    uint32_t v = sound_level_calc(ADC_read_value);
    if (current_sample == 0) {
        printf("PD4 = %ld \n\r", (long int) (v));
    }
}

/**
 * @brief Configure the ADC to scan multiple channels;
 *        Initialize and Start a time to scan the ADC
 */
void setupApp(void) {
    adc0_init_conf.warmUpMode = adcWarmupKeepADCWarm;

    adc0_singleinit_conf.prsSel = adcPRSSELCh0;
    adc0_singleinit_conf.reference = adcRef2V5;
    adc0_singleinit_conf.input = adcSingleInpCh4;  // adcSingleInpCh7 for battery monitoring

    PTD_pinOutSet(PTD_PORT_AKU340_VDD, PTD_PIN_AKU340_VDD);  //battery monitoring does not need this line

    ADC_node_t ADC_node_one = { ADC0, cmuClock_ADC0, 1000, ADC_INIT_DEFAULT };
    ADC_node_tp ADC_node_one_p = &ADC_node_one;
    ADC_init(ADC_node_one_p);

    /*Task for reading the ADC*/
    xTimerHandle timer_read_adc = xTimerCreate((const char *) "Reading ADC",
    ONESECONDDELAY, TIMER_AUTORELOAD_ON, NULL, Read_ADC);

    xTimerStart(timer_read_adc, TIMERBLOCKTIME);

}

/* global functions ********************************************************* */

/**
 * @brief This is a template function where the user can write his custom application.
 *
 */

void appInitSystem(xTimerHandle xTimer) {
    (void) (xTimer);
    setupApp();
}
/** ************************************************************************* */

0 (0 투표)
RE: ADC Application
응답
16. 9. 20 오후 1:05 as a reply to yuexiang yang.

Hello Yuexiang,

thank you for sharing your code with the XDK community. You can find an abstract block diagram of the XDK in the general information guide on page 10. A more detailed schematic is unfortunately not available. Further I will contact an other XDK community member who has worked with the ADC and gathered some experience with it. Maybe he is willing to share some code with us.

Lets take a look at the sampling rate of the ADC: The sampling rate configures the frequency in Hz in which analog measurements like external sensorvalues are read and digitized by the ADC.

I hope this could help you.

Kind regards,
Franjo

0 (0 투표)
RE: ADC Application
응답
16. 9. 21 오전 2:06 as a reply to yuexiang yang.

According to EFM32GG Reference Manual, 

28.3.1 Clock Selection
The ADC has an internal prescaler (PRESC bits in ADCn_CTRL) which can divide the peripheral clock
(HFPERCLK) by any factor between 1 and 128. Note that the resulting ADC_CLK should not be set to
a higher frequency than 13 MHz and not lower than 32 kHz.

I need to change to

    ADC_node_t ADC_node_one = { ADC0, cmuClock_ADC0, 32000, ADC_INIT_DEFAULT };

 

 

0 (0 투표)
RE: ADC Application
응답
16. 9. 21 오전 3:01 as a reply to yuexiang yang.

it seems that I cannot edit my previous post and only can reply a new post.

I need to add another line:    adc0_singleinit_conf.acqTime = adcAcqTime16;
 

EFM32GG Reference Manual, section 28.3.2 Conversions
A conversion consists of two phases. The input is sampled in the acquisition phase before it is converted
to digital representation during the approximation phase. The acquisition time can be configured
independently for scan and single conversions (see Section 28.3.7 (p. 694) ) by setting AT in
ADCn_SINGLECTRL/ADCn_SCANCTRL. The acquisition times can be set to any integer power of 2
from 1 to 256 ADC_CLK cycles.
Note
For high impedance sources the acquisition time should be adjusted to allow enough time
for the internal sample capacitor to fully charge.
The minimum acquisition time for the
internal temperature sensor and Vdd/3 is given in the electrical characteristics for the device.

0 (0 투표)
RE: ADC Application
응답
16. 9. 23 오후 1:21 as a reply to yuexiang yang.

Hello Yuexiang,

it seems you made a more detailed research into the functionality of the ADC. Your manual descriptions and my reply are both correct. In other words, the sampling rate discribes the time interval in which the ADC samples and digitizes the analog value.

Please note that the sampling rate of the ADC works different then the sampling rate of the other sensors on the XDK.

The EFM32GG manual description snippets you posted explain how the ADC works. I will explain to you how the presccaling with the according the acquisition time is working.

The functionality of the ADC can be imagined as two parts. One part does the sampling of the analog value and holds it until the value is converted. The other part does the digitization of the analog value into the digital value. This complete time interval of reading, holding and digitizing is defined by the ADC sample frequency. This frequency is set by a prescaled clock frequency. The EFM32GG provides a bunch of clocks that can be used for peripherals like the ADC. Here you initialize the desired ADC frequency with a prescaled default ADC clock. What you also mentioned is you have to be aware of how you choose the ADC frequency. The holding of the analog input voltage has a minimum time period to be fully charged. This time can be configured with the parameter acquisition time and it restricts the choice of a certain frequency.

In case of the ADC interface of the XDK you don't need to make explizit definition of all adc necessary parameters. There are enough default values that should be o.k. for your application.

I hope this could help you.

Kind regards,
Franjo

0 (0 투표)