Multiple Channel input for ADC on Atmel SAM D20

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

I know that the input pin scan of the ADC works correctly if all the input pins are all simultaneously and the pins aren't skipped.
I also know a lot of folks have asked this question before but there doesn't seem to be any solutions provided. 

 

What if the inputs aren't continuous ? Unfortunately the H/W engineers decided to just use the pins in a random fashion. 

Obviously they didn't know about the pin scan function provided. 
How can I configure and initialize the ADC with the pins below and using ASF?  

/* Configure analog pins */
	struct system_pinmux_config config;
	system_pinmux_get_config_defaults(&config);

	/* Analog functions are all on MUX setting B */
	config.input_pull   = SYSTEM_PINMUX_PIN_PULL_NONE;
	config.mux_position = 1;

	system_pinmux_pin_set_config(PIN_PA02, &config);
	system_pinmux_pin_set_config(PIN_PA04, &config);
	system_pinmux_pin_set_config(PIN_PA05, &config);
	system_pinmux_pin_set_config(PIN_PA07, &config);
	system_pinmux_pin_set_config(PIN_PA10, &config);
	system_pinmux_pin_set_config(PIN_PB02, &config);
	system_pinmux_pin_set_config(PIN_PB03, &config);
	system_pinmux_pin_set_config(PIN_PB08, &config);
	system_pinmux_pin_set_config(PIN_PB09, &config);	

  Is pin_scan capable enough to skip over non initialized pins and only gather input from the right pins ? 

 

This topic has a solution.

Newbie to the world of Atmel SAM D microcontrollers.

Last Edited: Thu. Dec 15, 2016 - 05:50 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

No the scan will not skip. Actually the ASF adc setup in _adc_set_config() will configure the pins in the scan range. If there are only a few gaps it could be ok to just include the unused pins in the scan (and not use the results) but you seem to have a range from AIN0-AIN18 while only 9 are actually used. I guess it could still be ok to scan all in that range if you don't care about the speed. Just note in any such case to let ASF setup adc before the pins that are not going to be analogue input are configured.

/Lars

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

Cheers Lars for the prompt reply, the AIN18 seems to have made it a bit complicated. Or else, as you mentioned, it should have been easy to pin scan and ignore the ADC results from the uninitialized input pins. For now I'll scan from AIN0-AIN18 and see if it really takes a massive toll on the application speed. I'll see if they can move the pin to something like AIN9 in the new design !!!

But is there a way to access the individual scattered pins without using input scan. Or will it only lead to a code build up which eats into 64KB flash storage ?
 

With regards,
Jenson

Newbie to the world of Atmel SAM D microcontrollers.

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

Manually "scanning" is possible of course, i.e., configure the ADC and perform conversion, in the callback handling the result setup for the next input using adc_set_positive_input() and start a new conversion.

/Lars

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

Hmmm, that seems a bit tedious. But I suppose, I'll need to do that if I want to acquire the ADC results quickly. 

Thanks once again Lars. 

I'll probably use a switch case in the adc_complete_callback and keep changing the positive input pin based on the current channel. 

 

Edit: HW engineers have decided to swap the AIN18 to AIN6 in the new boards. So I'll be using the pin_scan option instead of manually setting the pins.  

Newbie to the world of Atmel SAM D microcontrollers.

Last Edited: Wed. Dec 14, 2016 - 10:30 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lajon wrote:

No the scan will not skip. Actually the ASF adc setup in _adc_set_config() will configure the pins in the scan range. If there are only a few gaps it could be ok to just include the unused pins in the scan (and not use the results) but you seem to have a range from AIN0-AIN18 while only 9 are actually used. I guess it could still be ok to scan all in that range if you don't care about the speed. Just note in any such case to let ASF setup adc before the pins that are not going to be analogue input are configured.

/Lars

I have managed to convince the the HW Engineers to reroute the AIN18 to AIN6. This would mean, my ADC inputs would be AIN0,2,3,4,5,6,7,10,11. AIN1 is connected to ADC reference. Also on SAM D20G, AIN8 and AIN 9 aren't available. So now will be able to use input_scan to automatically scan through the pins using the below code ? 
    config_adc.gain_factor = ADC_GAIN_FACTOR_DIV2;
    config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV8;
    config_adc.reference = ADC_REFERENCE_INTVCC0; 
    config_adc.positive_input = ADC_POSITIVE_INPUT_PIN0;
    config_adc.resolution = ADC_RESOLUTION_12BIT;
    config_adc.pin_scan.inputs_to_scan = 11;     // INPUT_SCAN + 9 Need to check if this correct or not
    config_adc.pin_scan.offset_start_scan = 0;

Newbie to the world of Atmel SAM D microcontrollers.

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

Should work yes except that 0-11 = 12 inputs_to_scan.

/Lars

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

Cheers once again Lars, I'll correct that mistake. 

Newbie to the world of Atmel SAM D microcontrollers.

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

Lajon wrote:

Should work yes except that 0-11 = 12 inputs_to_scan.

/Lars

 

Hi Lars, 

 

You've been quite helpful whenever I had some questions to be answered on this forum, thank you once again.

Revisiting this, if I want to pin scan  ADC inputs from AIN 16 to AIN 18 only, then is the config below correct?

    config_adc.reference = ADC_REFERENCE_INTVCC0; 
    config_adc.positive_input = ADC_POSITIVE_INPUT_PIN0;
    config_adc.resolution = ADC_RESOLUTION_12BIT;
    config_adc.pin_scan.inputs_to_scan = 16;     // Thermal sensor 0-3
    config_adc.pin_scan.offset_start_scan = 3;

 

Also, do I need to iterate 3 times through the code below for me to get the value from the above 3 AINs? ADC_SAMPLES  = 4 at the moment.  

    adc_read_buffer_job(&adc_instance, adc_buffer, ADC_SAMPLES);
		
	while (adc_read_done == false)
	{
			// Wait for asynchronous ADC read for samples.
	}
	
	for (uint8_t i = 0; i < ADC_SAMPLES; i++)
	{
			result[i] += adc_buffer[i];
	}
	
	

 

Newbie to the world of Atmel SAM D microcontrollers.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1
	config_adc.positive_input = ADC_POSITIVE_INPUT_PIN16;
	config_adc.pin_scan.offset_start_scan = 0;
	config_adc.pin_scan.inputs_to_scan = 3;

 

and ADC_SAMPLES 3 makes more sense to me. With that you will have a new sample from AIN16 in adc_buffer[0], AIN17 in adc_buffer[1] and AIN18 in adc_buffer[2] after each completed adc_read_buffer_job.
/Lars

 

Last Edited: Sun. Dec 10, 2017 - 01:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lajon wrote:

	config_adc.positive_input = ADC_POSITIVE_INPUT_PIN16;
	config_adc.pin_scan.offset_start_scan = 0;
	config_adc.pin_scan.inputs_to_scan = 3;

 

and ADC_SAMPLES 3 makes more sense to me. With that you will have a new sample from AIN16 in adc_buffer[0], AIN17 in adc_buffer[1] and AIN18 in adc_buffer[2] after each completed adc_read_buffer_job.
/Lars

 

I suspected that might be the case since it makes sense, especially since the values seemed to be different. Thanks for clarifying that, Lars. You're a life saver, indeed. 

 

Regards,
Jenson 

Newbie to the world of Atmel SAM D microcontrollers.