SAM4S Xplained Pro ADC Demo

Posted on Sep 11, 2016 | 2 comments


SAM4S Xplained Pro ADC Demo

ASF version

Tested for ASF version 3.31.0

ASF Modules required 

  • ADC – Analog-to-digital Converter (driver)

Basic Demo

This demo shows in the screen the light intensity as read by the light sensor. The light sensor creates an output analog voltage, which is a function of the amount of light falling upon the transducer. The ADC converts this voltage to a digital value between 0 and 4096 (12-bits resolution) and places it in one of the ADC registers, from where it can be read by the drivers.

The project requires uses the OLED Drivers module.

See video: Light Sensor Demo.

Code

#include <asf.h>
#include <string.h>


static void configure_adc(void)
{
	/* Configure ADC pin for light sensor. */
	gpio_configure_pin(LIGHT_SENSOR_GPIO, LIGHT_SENSOR_FLAGS);

	/* Enable ADC clock. */
	pmc_enable_periph_clk(ID_ADC);

	/* Configure ADC. */
	adc_init(ADC, sysclk_get_cpu_hz(), 1000000, ADC_MR_STARTUP_SUT0);
	adc_enable_channel(ADC, ADC_CHANNEL_4);
	adc_configure_trigger(ADC, ADC_TRIG_SW, 1);
}

int main(void)
{

	uint32_t adc_value;
	uint32_t normalized_adc_value;
	uint32_t value[6];
	
	sysclk_init();
	board_init();
	ssd1306_init();
	
	//Configure ADC
	configure_adc();

	//start ADC
	adc_start(ADC);
		
	while(true){
			
		// get light sensor information.
		adc_value = adc_get_channel_value(ADC, ADC_CHANNEL_4);

		//normalize
		normalized_adc_value = 35 - (adc_value * 35 / 4096);
	
		//get string with value
		sprintf(value, "%d", adc_value);
	
		//clear screen
		ssd1306_clear();	
		
		//print value
		ssd1306_set_page_address(0);
		ssd1306_set_column_address(0);
		ssd1306_write_text(value);
		
		//print light bar
		ssd1306_set_page_address(3);
		ssd1306_set_column_address(0);
		for(uint32_t i=0; i<normalized_adc_value; i++)
			ssd1306_write_text("/");
		
		delay_ms(15);
	}
	
}

 

Advanced Demo

The demo uses the Light sensor in the IO1 board, and the PWM+ pin in the PROTO1 board. The Light sensor is physically connected to the MCU’s ADC Line 4. Depending on the light intensity the program generates a square wave of variable frequency. The squares wave feed a piezo electric buzzer. PWM drivers must be added to the project.

See video: Light Sensor Buzzer Demo
Code

#include <asf.h>

#define PMWA IOPORT_CREATE_PIN(PIOA, 23) //PWM+ in PROTO1 Board
#define MAX_PERIOD	150 //1.5ms maximum period

static void configure_adc(void);
static void configure_and_start_pwm(void);

pwm_channel_t pwm_opts;

int main(void){
	
	sysclk_init();
	board_init();
	configure_and_start_pwm();
	
	//Configure ADC
	configure_adc();

	//start ADC
	adc_start(ADC);
	
	uint32_t adc_value;
	uint32_t normalized_adc_value;
	uint32_t value[6];
	
	while(true){
		// get light sensor reading
		adc_value = adc_get_channel_value(ADC, ADC_CHANNEL_4);

		//normalize
		normalized_adc_value = MAX_PERIOD - (adc_value * MAX_PERIOD / 4096);

		//update period
		pwm_channel_update_period( PWM, &pwm_opts, normalized_adc_value );
		
		delay_ms(50); //sounds better
	}
}

static void configure_adc(void)
{
	/* Configure ADC pin for light sensor. */
	gpio_configure_pin(LIGHT_SENSOR_GPIO, LIGHT_SENSOR_FLAGS);

	/* Enable ADC clock. */
	pmc_enable_periph_clk(ID_ADC);

	/* Configure ADC. */
	adc_init(ADC, sysclk_get_cpu_hz(), 1000000, ADC_MR_STARTUP_SUT0);
	adc_enable_channel(ADC, ADC_CHANNEL_4);
	adc_configure_trigger(ADC, ADC_TRIG_SW, 1);
}

static void configure_and_start_pwm(void)
{
	//PWM Clock options
	pwm_clock_t pwm_clock_opts = {
		.ul_clka = 100000, //100Khz clock frequency = .01 ms steps
		.ul_clkb = 0,
		.ul_mck =  sysclk_get_main_hz() //main clock speed is 240Mhz!, not 120mhz
	};
	
	//PWM options
	pwm_opts.ul_prescaler = PWM_CMR_CPRE_CLKA;
	pwm_opts.ul_period = MAX_PERIOD; 
	pwm_opts.ul_duty = 7; //10% duty cycle
	pwm_opts.channel = PWM_CHANNEL_0;
	
	//configure IO pins
	pio_configure_pin( PMWA, PIO_TYPE_PIO_PERIPH_B );
	
	//Enable PWM clock
	pmc_enable_periph_clk(ID_PWM);
	
	//disable temporarily
	pwm_channel_disable(PWM, PWM_CHANNEL_0);
	
	//Start PWM
	pwm_init( PWM, &pwm_clock_opts );
	pwm_channel_init( PWM, &pwm_opts );
	pwm_channel_enable( PWM, PWM_CHANNEL_0 );
	
}

 

2 Comments

  1. After extensively searching the Atmel guides, this page helped me fix and issue with my project. Thanks so much for posting this!

    Post a Reply
    • No problem!

      Post a Reply

Submit a Comment

Your email address will not be published. Required fields are marked *