ADC filter with SAM3U

Discussion around product based on ARM Cortex M3 core.

Moderators: nferre, ncollot

krunalwin
Posts: 3
Joined: Fri Apr 24, 2015 9:09 am

ADC filter with SAM3U

Sat May 30, 2015 12:14 pm

hi,
following is the mean filter code i want to use with kit.
Kindly suggest for the improvement:

Code: Select all

/****
This code is testing for mode filter of datasets which will be filled up by incoming values from any input terminal or peripherls (like ADC).
mode filter is : average of middle values of mean filtered datas. It is extended mean filter. It is combo of mean & average filter.
mean filter is : middle value of given datasets. e.g: dataset={3,101,34,70,50}, mean value of that dataset is= 50.
mean value deciding logic: arrange out the data of dataset in ascending or descending order and then find the middle value of the dataset.
The logic will work only for the datasets which will be filled up by incoming values from any input terminal or peripherls (like ADC).
For the datasets which would be already filled up, logic should be modified.
**/


#include <stdio.h>
#define SAMPLE 10		// number of data to be stored in dataset.

void mode_filter(void);


int main(int argc, char** argv) {
	printf("mode filter for datasets!\n");
	
	mode_filter();
	
	return 0;
}


void mode_filter(void)
{
	unsigned int readValue =0;
	unsigned int arrayvalue[SAMPLE];
	unsigned int i=0; 
	int j=0;
	
	// Initialize array elements to 0
	for(i=0; i<=SAMPLE; i++ )
		arrayvalue[i]= 0;
		
	// get the first reading of dataset	
	i=0;
	printf("Enter Value %u:\n", i);
	scanf("%u", &readValue);
	arrayvalue[0] = readValue;
	
	// process the dataset to put it in ascending order so that mean value can be extracted.
	// note that : following for loop will be iterated after each incoming updated data into the dataset
	for(i=1; i<SAMPLE; i++)
	{
		printf("Enter Value %u:\n", i);
		scanf("%u", &readValue);
		
		for(j=i; j>=0; j--)
		{
			if(j==0)
			{
				arrayvalue[j] = readValue;
				break;		// get out of the last for loop: here it is "j" for loop
			}	
			
			// If incoming data is less than the previous data of dataset, then move the previous data to right of the dataset (make it in ascending order).
			if(arrayvalue[j-1] > readValue)
			{
				arrayvalue[j] = arrayvalue[j-1];		
			}
			else
			{
				arrayvalue[j] = readValue;
				break;		// get out of the last for loop: here it is "j" for loop	
			}

		}
		
	}
	
	printf("numbers in ascending order are: \n");
	
	for(j=0; j<SAMPLE; j++)
		printf("%u \n", arrayvalue[j]);
	
	
	// get the average value of middle mean values of the dataset
	readValue=0;
	for(i=(SAMPLE/2)-2; i<((SAMPLE/2) +2); i++)
	{
    	 readValue +=arrayvalue[i];
   	}
   	
	readValue = readValue/4;	// here, 4 middle values of asceding ordered dataset has been averaged
	
	printf("mode average of mean value is:%u \n", readValue);
}

void display_hex2ascii_console(uint32_t hex_value)
{
	uint8_t nibble=0;
	usb_put_char('h');
	for(int8_t tc=7; tc>=0; tc--)
	{
		nibble = (hex_value >> (tc*4)) & 0x0F;
		if(nibble > 9)
			usb_put_char(nibble + 0x37);		// extract A,B,C,D,E,F from ASCII table
		else
			usb_put_char(nibble + 0x30);		// extract 0 to 9 from ASCII table
	}
}


void display_dec2ascii_console(uint32_t dec_value)
{
	uint8_t digit[10]={0,0,0,0,0,0,0,0,0,0};
	int8_t d_cnt=0;
	usb_put_char('d');
	while(dec_value>=10)
	{
		digit[d_cnt] = dec_value % 10;
		d_cnt++;
		dec_value = dec_value/10;
		
	}
	
	digit[d_cnt]=dec_value;
	for(;d_cnt>=0;d_cnt--)
	{
		usb_put_char(digit[d_cnt] + 0x30);	// extract 0 to 9 from ASCII table
	}
	
}










void reed_sense_Handler(uint32_t id, uint32_t mask)
{
	/* Enable PIO line interrupts. */
	pio_disable_interrupt(REEDIN_PORT, REEDIN_MASK);

	// All the USB related functions implemented in this interrupt handler function, will be executed in time only if UDPHS interrupt priority is set higher than the REED input change interrupt priority.
	// otherwise all USB related function will get executed after this interrupt handler gets completed.
	// usb_put_char('+');
	if (REEDIN_PORT_ID == id && REEDIN_MASK == mask)
	{
		turn_off_pmt();
		gpio_set_pin_low(BL1_LEDIO);
		gpio_set_pin_low(BL2_LEDIO);
		gpio_set_pin_low(UV_LEDIO);
		//usb_put_char('E');		
		usb_put_string("Close the lid\r\n");
	}
	//delay_ms(100);
	// stay here till reed switch will remain opened.
	while(1 == (((REEDIN_PORT->PIO_PDSR) >> (REEDIN_PIN & 0x1F)) & 0x01));
	
	uint32_t dummy_int_read = pio_get_interrupt_status(REEDIN_PORT);	// clear all pending interrupt.
	// usb_put_char('O');
	usb_put_string("Operate the device\r\n");
	/* ReEnable PIO line interrupts. */
	pio_enable_interrupt(REEDIN_PORT, REEDIN_MASK);

}			


void init_reed_input(void)
{
	pmc_enable_periph_clk(REEDIN_PORT_ID);		// It is must to enable the PIO clock before setting the debounce time for Input pin.
	
	gpio_configure_pin(REEDIN_PIN, REEDIN_FLAG);		// configure the input as normal GPIO input
	/* Adjust pio debounce filter parameters, uses DEBOUCE_TIME. */
	pio_set_debounce_filter(REEDIN_PORT, REEDIN_MASK, (1000/80));
	
	// set the interrupt priority for REED Switch Input change event at lower than the UDPHS (USB) interrupt priority.
	// This interrupt priority setting is must. Because, UDPHS (USB) interrupt priority must be higher than the REED input change interrupt,.....
	// in order to get the USB related functions executed during REED switch interrupt routine (reed_sense_Handler) get performed.
	pio_handler_set_priority(REEDIN_PORT, PIOA_IRQn, REED_INTR_PRIO);	
	
	/* Initialize pios interrupt handlers, see PIO definition in board.h. */
	pio_handler_set(REEDIN_PORT, REEDIN_PORT_ID, REEDIN_MASK, REEDIN_FLAG, reed_sense_Handler);	/* Interrupt on rising edge  */

	/* Enable PIO controller IRQs. */
	NVIC_EnableIRQ((IRQn_Type) REEDIN_PORT_ID);

	/* Enable PIO line interrupts. */
	pio_enable_interrupt(REEDIN_PORT, REEDIN_MASK);

}




/*
 * Keypad.c
 *
 * Created: 04-May-15 12:46:40 PM
 *  Author: ELECTRON
 */ 
#include "Keypad.h"
#include <delay_systick.h>

uint8_t is_key_released = TRUE;		// flag to check if last pressed key has been released or not.

										 
void configure_wakeup_input_pin(void)
{
	pmc_enable_periph_clk(WAKEUP_KEY_PORTID);		// It is must to enable the PIO clock before setting the debounce time for Input pin.
	pio_set_writeprotect(WAKEUP_KEY_PORT, 0);	// disable the write protection for the input filter enable register (write protected) to be modified.
	gpio_configure_pin(PIN_WAKEUP, KEYIO_FLAGS);		// configure the input as normal GPIO input (NOT as wakeup input).
	pio_set_debounce_filter(WAKEUP_KEY_PORT, (1<< (PIN_WAKEUP & 0x1F)), (1000/DEBOUCE_TIME));
}


void init_keypad(void)
{
	pio_set_writeprotect(KEY_PORT, 0);	// disable the write protection for the input filter enable register (write protected) to be modified.
		
	gpio_configure_group(KEY_PORT, PIN_KEYIO_MASK, KEYIO_FLAGS);
		
	pmc_enable_periph_clk(KEY_PORTID);		// It is must to enable the PIO clock before setting the debounce time for Input pin.
		
	// Adjust pio debounce filter parameters, uses DEBOUNCE_TIME.
	pio_set_debounce_filter(KEY_PORT, PIN_KEYIO_MASK, (1000/DEBOUCE_TIME));
	
	configure_wakeup_input_pin();
		
}



uint8_t process_key_event(void)
{
	uint8_t key_data = NO_KEY;
	volatile uint8_t key_raw_data = 0x0F;
	
	// get KEY_PIN value :
	key_raw_data = ((KEY_PORT->PIO_PDSR) >> (PIN_KEY0 & 0x1F)) & 0x0F;
	if(key_raw_data != 0x0F)		// Check if any key  is low, i.e. any key is pressed (if key_raw_data=0x0F, then no key has been pressed).
	{
		if(is_key_released == FALSE)
				return (key_data);
				
		is_key_released =FALSE;
		switch(key_raw_data)
		{
			case 0x0E:		// @ PIN_KEY0
				key_data =0;
				break;
				
			case 0x0D:		// @ PIN_KEY1
				key_data =1;
				break;
			
			case 0x0B:		// @ PIN_KEY2
				key_data =2;
				break;
				
			case 0x07:		// @ PIN_KEY3
				key_data =3;
				break;
							
			default:
				key_data = '+';		// it will make sure only one key is pressed at a time.
				break;
		}
			
	}
	else
	{
		is_key_released =TRUE;
	}
	
	return (key_data);
	
}







/*
 * Keypad.h
 *
 * Created: 04-May-15 12:46:57 PM
 *  Author: ELECTRON
 */ 


#ifndef KEYPAD_H_
#define KEYPAD_H_

#include <asf.h>
#include "pmc.h"
#include "pio.h"


#define TRUE 1
#define FALSE 0

#define TOTAL_KEY	4
#define PIN_KEY0	PIO_PC23_IDX		// MEASURE key
#define PIN_KEY1	PIO_PC24_IDX		// FLOUR key
#define PIN_KEY2	PIO_PC25_IDX		// CALIB key
#define PIN_KEY3	PIO_PC26_IDX


#define MEASURE_KEY 0
#define FLOUR_KEY	1
#define CALIB_KEY	2

#define PIN_WAKEUP			PIO_PB2_IDX		// WKUP15 @ PB2 
#define WAKEUPIO_FLAG		(PIO_INPUT | PIO_DEGLITCH | PIO_PULLUP)
#define WAKEUP_KEY_PORT		PIOB
#define WAKEUP_KEY_PORTID	ID_PIOB

#define PIN_KEYIO_MASK	(((1<<TOTAL_KEY) -1) << (PIN_KEY0 & 0x1F))
#define KEYIO_FLAGS		(PIO_INPUT | PIO_DEBOUNCE | PIO_PULLUP | PIO_DEFAULT)		// internal PullUp and debounce is enabled.

#define KEY_PORTID	ID_PIOC
#define KEY_PORT	PIOC
  
#define DEBOUCE_TIME	40		// debounce time in millisecond : used for built in on-chip debounce
#define NO_KEY	255

// Step-Up voltage regulator enable GPIO configured as Output.
// SHDN = high : regulator OFF, SHDN = low : regulator ON.
#define LT1303_SHDN_PIN		(PIO_PC29_IDX)
#define LT1303_SHDN_FLAG	(PIO_TYPE_PIO_OUTPUT_1 | PIO_DEFAULT)
#define LT1303_SHDN_PIO		PIOC
#define LT1303_SHDN_PIOID	ID_PIOC

// MAX4238 OpAmp output enable configuration using GPIO as output.
// purpose : Control gain of PMT should be set to 0 before PMT's power get shut down.
// SHDN =low : OpAmp enabled, SHDN=high: OpAmp disabled
#define MAX4238_SHDN_PIN	(PIO_PC28_IDX)
#define MAX4238_SHDN_FLAG	(PIO_TYPE_PIO_OUTPUT_1 | PIO_DEFAULT)
#define MAX4238_SHDN_PIO	PIOC
#define MAX4238_SHDN_PIOID	ID_PIOC


#define REEDIN_PIN			(PIO_PA27_IDX)
#define	REEDIN_PORT_ID		ID_PIOA
#define REEDIN_PORT			PIOA
#define REEDIN_FLAG			(PIO_INPUT | PIO_DEBOUNCE | PIO_PULLUP | PIO_IT_HIGH_LEVEL)
#define REEDIN_MASK			(1 << (REEDIN_PIN & 0x1F))
// Interrupt priority number for the REED switch input change detection.
// Higher number means lower priority in interrupt service execution.
#define REED_INTR_PRIO		2		// 2 is given as UDPHS(USB) default interrupt priority is 0: means higher priority than REED input change interrupt.


void init_keypad(void);
uint8_t process_key_event(void);
void configure_wakeup_input_pin(void);

#endif /* KEYPAD_H_ */








void usb_put_char(int8_t ch)
{
	if(udi_cdc_is_tx_ready())
	   udi_cdc_putc(ch);
}


void usb_put_string(char* ch_string)
{
	while(*ch_string != '\0')
	{
		usb_put_char(*ch_string++);
	}
}










void init_sleep(void)
{
	uint32_t oldPll0;
	//uint32_t oldPll1;
	//uint32_t oldOsc;
	uint32_t oldMck;
	uint32_t oldPeriphClk;
	uint32_t temp;
	ui_com_close();
	
	// Save current working clock
	// SaveWorkingClock(&oldPll, &oldMck);
	oldPll0 = PMC->CKGR_PLLAR;
	oldMck = PMC->PMC_MCKR;
	
    // Save previous values peripheral clock then disable all
    oldPeriphClk = PMC->PMC_PCSR0;
    pmc_disable_all_periph_clk();
	
	// Stop UTMI
	PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN;
							
	// Disable Brownout Detector
	SUPC->SUPC_MR |= ((0xA5 << 24) | (0x01 << 13));
	SUPC->SUPC_MR = SUPC->SUPC_MR & (~(0x01 << 12));		// disable BODRSTEN bit: BOD reset 
	// Configure PIO for wakeup
	// PB2(WAKEUP15) has been configured as WAKEUP source.
	// for reference : #define PIN_WAKEUP	PIO_PB2_IDX	 
	// for reference : #define KEYIO_FLAGS	(PIO_INPUT | PIO_DEBOUNCE | PIO_PULLUP | PIO_DEFAULT)
	gpio_configure_pin(PIN_WAKEUP, KEYIO_FLAGS);	
	//supc_set_wakeup_inputs(SUPC, SUPC_WUIR_WKUPEN15_ENABLE, SUPC_WUIR_WKUPT15_HIGH_TO_LOW);
	// set Debounce time for wakeup pin to be detected.
	//SUPC->SUPC_WUMR = (SUPC->SUPC_WUMR & (~SUPC_WUMR_WKUPDBC_Msk)) | SUPC_WUMR_WKUPDBC_512_SCLK;
	SUPC->SUPC_WUMR = (SUPC->SUPC_WUMR & (~SUPC_WUMR_WKUPDBC_Msk)) | SUPC_WUMR_WKUPDBC_4096_SCLK;
	
	    PMC->PMC_FSMR &= ~0xFFFFFFFF;		// This register can only be written if the WPEN bit is cleared in the “PMC Write Protect Mode Register”.
	    PMC->PMC_FSMR |= SUPC_WUIR_WKUPEN15_ENABLE;
		
	 // Switch clock frequency
	 PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk)
	 | PMC_MCKR_CSS_SLOW_CLK;
	 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));

	 PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_PRES_Msk)
	 | PMC_MCKR_PRES_CLK_64;
	 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
	 
	 // Stop PLL A
	 // MULA: PLL A Multiplier 0 = The PLL A is deactivated.
	 PMC->CKGR_PLLAR &= ~(CKGR_PLLAR_MULA_Msk);
	 // Stop Main Oscillator
	 PMC->CKGR_MOR = (0x37 << 16) | (0x3F << 8);
	 
	// Enter Sleep Mode
	PMC->PMC_FSMR &= ~PMC_FSMR_LPM;		// LPM=0
	SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;		// SLEEPDEEP =0
	__WFE();
			
	// Restore working clock
		 // Switch to slow clock first
		 PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk)
		 | PMC_MCKR_CSS_SLOW_CLK;
		 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));

		 PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_PRES_Msk)
		 | PMC_MCKR_PRES_CLK_1;
		 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
	 
		 // Restart Main Oscillator
		 PMC->CKGR_MOR = (0x37 << 16) | (0x3F<<8) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
		 while (!(PMC->PMC_SR & PMC_SR_MOSCXTS));
		 // Switch to moscsel
		 PMC->CKGR_MOR = (0x37 << 16) | (0x3F<<8) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
		 while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));

		 // Switch to main oscillator
		 PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk) |
		 PMC_MCKR_CSS_MAIN_CLK;
		 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));

		 PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_PRES_Msk)
		 | PMC_MCKR_PRES_CLK_1;
		 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));

		 // Restart PLL A
		 PMC->CKGR_PLLAR = oldPll0;
		 while(!(PMC->PMC_SR & PMC_SR_LOCKA));

		 // Switch to fast clock
		 PMC->PMC_MCKR = (oldMck & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
		 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));

		 PMC->PMC_MCKR = oldMck;
		 while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
		
	// disable wakeup feature on relevant input pin. and re-configure as normal GPIO input pin.
	supc_set_wakeup_inputs(SUPC, SUPC_WUIR_WKUPEN15_NOT_ENABLE, SUPC_WUIR_WKUPT15_HIGH_TO_LOW);
	//configure_wakeup_input_pin();
		pio_set_writeprotect(WAKEUP_KEY_PORT, 0);	// disable the write protection for the input filter enable register (write protected) to be modified.
		gpio_configure_pin(PIN_WAKEUP, KEYIO_FLAGS);	// configure the input as normal GPIO input (NOT as wakeup input).
		pmc_enable_periph_clk(WAKEUP_KEY_PORTID);		// It is must to enable the PIO clock before setting the debounce time for Input pin.
		pio_set_debounce_filter(WAKEUP_KEY_PORT, (1<< (PIN_WAKEUP & 0x1F)), (1000/DEBOUCE_TIME));
	
	// Restore peripheral clock
	PMC->PMC_PCER0 = oldPeriphClk;
	
	// Start UTMI
	PMC->CKGR_UCKR |= (CKGR_UCKR_UPLLCOUNT_Msk & (3 << 20)) | CKGR_UCKR_UPLLEN;
	while (!(PMC->PMC_SR & PMC_SR_LOCKU));
	
	// Enable Brownout Detector
	temp = SUPC->SUPC_MR & 0x00FFFFFF;
	SUPC->SUPC_MR = (0xA5 << 24) | (temp & (~(0x01 << 13)));
	
	// stay here until wakeup key has been released.
	while(0 == (((WAKEUP_KEY_PORT->PIO_PDSR) >> (PIN_WAKEUP & 0x1F)) & 0x01));
	
	
}



Also can someone explain which type of digital filter would be appropriate choice according to adc input signal condition?
I mean when it should be appropriate to use simle average filter or median or Butterworth ?

Thanks
Last edited by krunalwin on Tue Jun 16, 2015 9:53 am, edited 1 time in total.

Return to “SAM3 Cortex-M3 MCU”

Who is online

Users browsing this forum: No registered users and 1 guest