SAMD21 adc_sync_set_inputs(..) Macros

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi 

 

I'm a bit confused about the definitions for the positive and negative mux inputs on my SAMD21 ADC.  I have 8 inputs into the ADC and I want to configure each one individually. It looks to me like the positive mux inputs are 0-7 but I don't know the value for negative mux value which I want to set as Internal ground.

 

Based on google results, I have tried this:

 

adc_sync_set_inputs(&ADC_0, 0, 0x18, 0) // Input 0

adc_sync_set_inputs(&ADC_0, 1, 0x18, 1) // Input 1

adc_sync_set_inputs(&ADC_0, 2, 0x18, 2) // Input 2

 

but this does not work for me. Any clues on what I'm doing wrong?

 

thanks for your help

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can only have one input setting active at any one time (with a SAMD21), another way to put that is that it has only one channel. This is visible in the implementation where the channel argument is unused:

/**..
 * \brief Set channels input sources
 */
void _adc_sync_set_inputs(struct _adc_sync_device *const device, const adc_pos_input_t pos_input,
                          const adc_neg_input_t neg_input, const uint8_t channel)
{
	(void)channel;

	hri_adc_write_INPUTCTRL_MUXPOS_bf(device->hw, pos_input);
	hri_adc_write_INPUTCTRL_MUXNEG_bf(device->hw, neg_input);
}

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lajon wrote:

You can only have one input setting active at any one time (with a SAMD21), another way to put that is that it has only one channel. This is visible in the implementation where the channel argument is unused:

 

I'm ok with that. When I tried to setup 8 channels via Atmel Start dashboard I was getting wrong conversion values. But when I use them one at a time the conversion values are correct.. This is what I plan to do:

    adc_sync_enable_channel(&ADC_0, 0);

    adc_sync_set_inputs(&ADC_0, 0, 0x18, 0);
    adc_sync_read_channel(&ADC_0, 0, &buf[0], 2);
    adc_sync_disable_channel(&ADC_0, 0);

 

    adc_sync_enable_channel(&ADC_0, 1);
    adc_sync_set_inputs(&ADC_0, 1, 0x18, 1);
    adc_sync_read_channel(&ADC_0, 1, &buf[2], 2);
    adc_sync_disable_channel(&ADC_0, 1);

I'm unable to figure out the MACROS to use for positive mux input and Internal ground.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So I got that part of the code working. The only issue is that my converted value is correct only once in 16 readings. That is weird.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hallo YogiWannabe!

 

I suspect that your chip's ADC is set to read 16 input values in atmel start, thus the ADC's internal circular buffer's size is also 16 values long, but that you are only reading one ADC value into your own array with adc_sync_read_channel(&ADC_0, 0, adc_read_buffer, 2), thus only on the 16th read do you get correct values.

 

Have a look at the attached atmel studio project, particularly in main.c 

 

lines 220-251 - my own explanation

lines 282-293 - variable setup

lines 322-342 - actually retrieving the adc values into my own variables

 

Also look at the ADC setup in Atmel Start, how I set up the reading of 9 consecutive inputs.

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm unable to figure out the MACROS to use for positive mux input and Internal ground : look in :  Projects\Light sensor\Light sensor\Config\hpl_adc_config.h

 

adc_sync_set_inputs(&ADC_0, 0x02, 0x19, 0);//AIN02 with IO ground

 

// <o> Positive Mux Input Selection
// <0x00=>ADC AIN0 pin
// <0x01=>ADC AIN1 pin
// <0x02=>ADC AIN2 pin
// <0x03=>ADC AIN3 pin
// <0x04=>ADC AIN4 pin
// <0x05=>ADC AIN5 pin
// <0x06=>ADC AIN6 pin
// <0x07=>ADC AIN7 pin
// <0x08=>ADC AIN8 pin
// <0x09=>ADC AIN9 pin
// <0x0A=>ADC AIN10 pin
// <0x0B=>ADC AIN11 pin
// <0x0C=>ADC AIN12 pin
// <0x0D=>ADC AIN13 pin
// <0x0E=>ADC AIN14 pin
// <0x0F=>ADC AIN15 pin
// <0x10=>ADC AIN16 pin
// <0x11=>ADC AIN17 pin
// <0x12=>ADC AIN18 pin
// <0x13=>ADC AIN19 pin
// <0x18=>Temperature reference
// <0x19=>Bandgap voltage
// <0x1A=>1/4 scaled core supply
// <0x1B=>1/4 scaled I/O supply
// <0x1C=>DAC output
// <i> These bits define the Mux selection for the positive ADC input. (MUXPOS)
// <id> adc_pinmux_positive
#ifndef CONF_ADC_0_MUXPOS
#define CONF_ADC_0_MUXPOS 0x2
#endif

// <o> Negative Mux Input Selection
// <0x00=>ADC AIN0 pin
// <0x01=>ADC AIN1 pin
// <0x02=>ADC AIN2 pin
// <0x03=>ADC AIN3 pin
// <0x04=>ADC AIN4 pin
// <0x05=>ADC AIN5 pin
// <0x06=>ADC AIN6 pin
// <0x07=>ADC AIN7 pin
// <0x18=>Internal ground
// <0x19=>I/O ground
// <i> These bits define the Mux selection for the negative ADC input. (MUXNEG)
// <id> adc_pinmux_negative
#ifndef CONF_ADC_0_MUXNEG
#define CONF_ADC_0_MUXNEG 0x19
#endif

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi ,

 

We are using SAMd51 ADC. We want to change the positive input mux at run time. Because in atmel start, we are able to configure only one channel as positive inpuyt mux. We are using 6 ADC channels ( 3 in ADC 0 and 3 in ADC1). We have checked the datasheet and provided valid arguments to set_inputs () as like below, 

 

adc_async_set_inputs(&ADC_0,0x03 ,0x18 ,0); 

 

0x04 - Using Atmel start, I have selected the positive mux source as AIN4 pin and confirmed that we are able to read the conversions. 

 

Next, I need to configure the positive input source as AIN 3. So I used 0x03 and 0x18 for internal ground and should be able to read conversion. Likewise, I need to do the same for all 6 channels(one by one channel sampling). 

 

Also, i have checked in google and some FAQ, and found that we can do only one channel active at a time for SAMD21. Is it same for SAMd51 also?

 

Could you please help me for this one by one sampling?

 

 

Jana8153

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So I used 0x03 and 0x18 for internal ground and should be able to read conversion.

Your are not really saying what the problem is.

This main works fine for me 

int main(void)
{
    atmel_start_init();

    adc_sync_enable_channel(&ADC_0, 0);
    const uint8_t inputs[4] = { 3, 4, 5, 6};
    uint16_t values[4];
    while (1) {
        for(size_t i = 0; i < sizeof(inputs); ++i) {
            adc_sync_set_inputs(&ADC_0, inputs[i], 0x18, 0);
            adc_sync_read_channel(&ADC_0, 0, (uint8_t*)&values[i], 2);
        }
    }
}

/Lars

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lajon wrote:

So I used 0x03 and 0x18 for internal ground and should be able to read conversion.

Your are not really saying what the problem is.

This main works fine for me 

int main(void)
{
    atmel_start_init();

    adc_sync_enable_channel(&ADC_0, 0);
    const uint8_t inputs[4] = { 3, 4, 5, 6};
    uint16_t values[4];
    while (1) {
        for(size_t i = 0; i < sizeof(inputs); ++i) {
            adc_sync_set_inputs(&ADC_0, inputs[i], 0x18, 0);
            adc_sync_read_channel(&ADC_0, 0, (uint8_t*)&values[i], 2);
        }
    }
}

/Lars

 

My problem is, I need to change the positive mux input runtime ( 6 channels i have). Also, out of 6 channels 3 in ADC0 and 3 in ADC 1.

 

using hri_adc_write_INPUTCTRL_reg(ADC0,0X1802) API, i able to read 3 channels of ADC 0. But in the same way, I am unable to read ADC 1.

 

Is it possible to read ADC0 and ADC 1 channels simultaneously?

Jana8153

Last Edited: Wed. Jan 2, 2019 - 04:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ADC1 works for me, I just added a 2nd loop.

int main(void)
{
    atmel_start_init();
    
    adc_sync_enable_channel(&ADC_0, 0);
    adc_sync_enable_channel(&ADC_1, 0);
    const uint8_t inputs0[3] = { 4, 5, 6};
    uint16_t values0[3];
    const uint8_t inputs1[2] = { 0, 1};
    uint16_t values1[2];
    while (1) {
        for(size_t i = 0; i < sizeof(inputs0); ++i) {
            adc_sync_set_inputs(&ADC_0, inputs0[i], 0x18, 0);
            adc_sync_read_channel(&ADC_0, 0, (uint8_t*)&values0[i], 2);
        }
        for(size_t i = 0; i < sizeof(inputs1); ++i) {
            adc_sync_set_inputs(&ADC_1, inputs1[i], 0x18, 0);
            adc_sync_read_channel(&ADC_1, 0, (uint8_t*)&values1[i], 2);
        }		
    }
}

But if there really is need to have both ADC converting at the same time then you would have to use the async driver.

/Lars