/** * \brief Measures and enables offset and gain corrections */ static void main_adc_correction(void) { /* ADC channel configuration structure */ struct adc_channel_config adcch_conf; uint16_t offset_correction; /* Expected value for gain correction at 1.9V * expected_value = Max. range * 1.9V / (VCC / 1.6) * Max. range = 12 bits signed = 11 bits unsigned */ const uint16_t expected_value = ((1 << 11) * 1900UL) / (3300L * 1000L / 1600L); /* Captured value for gain correction */ uint16_t captured_value; /* DAC Output 0 Volt */ main_dac_output(0); /* Capture value for 0 Volt */ adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); offset_correction = adc_get_unsigned_result(&ADCA, ADC_CH0); /* Enable offset correction */ adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); adcch_enable_correction(&adcch_conf, offset_correction, 1, 1); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); /* DAC Output 1.9 Volts */ main_dac_output(1900); /* Capture value for 1.9 Volts */ adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); captured_value = adc_get_unsigned_result(&ADCA, ADC_CH0); /* Enable offset & gain correction */ adcch_enable_correction(&adcch_conf, offset_correction, expected_value, captured_value); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); printf("\n\rADC correction: "); printf("Offset correction %d, ", offset_correction); if (expected_value > captured_value) { printf("Gain correction 1.%03u\n\r\n\r", (uint16_t) ((((uint32_t)expected_value - captured_value) * 1000) / captured_value)); } else { printf("Gain correction 0.%03u\n\r\n\r", (uint16_t) (((uint32_t)expected_value * 1000) / captured_value)); } }
/** * \brief Reads a 16-bit analog value on ADC channel 0 and returns it. * * In this application CH0 is set up to read the analog voltage from * a simulated thermometer. * * \return Temperature of the induction element. */ uint16_t ovenctl_get_plate_temperature(void) { adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); return adc_get_unsigned_result(&ADCA, ADC_CH0) / 4; }
/** * \brief Captures a values on ADC * * \return value on ADC pins (mV) */ static int16_t main_adc_input(void) { int16_t sample; /* Ignore two averaging conversions * which can include two differents voltage */ adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); /* Capture averaging */ adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); sample = adc_get_signed_result(&ADCA, ADC_CH0); /* Conversion sample to mV : * mV = sample * (VCC / 1.6) / Max. range */ return ((int32_t)sample * (3300L * 1000L / 1600L)) / (1 << 11); }
/** * \internal * \brief Test averaging conversion in 12-bit mode using the DAC * * These values are then measured using the ADC on the pins that are connected * to the DAC channel, and the results are compared and checked to see if they * are within the acceptable average of values that passes the test. * * \param test Current test case. */ static void run_averaging_conversion_test( const struct test_case *test) { int16_t volt_output; int16_t volt_min, volt_max, volt_input; /* ADC module configuration structure */ struct adc_config adc_conf; /* ADC channel configuration structure */ struct adc_channel_config adcch_conf; adc_disable(&ADCA); /* Change resolution parameter to accept averaging */ adc_read_configuration(&ADCA, &adc_conf); adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_MT12, ADC_REF_VCC); adc_write_configuration(&ADCA, &adc_conf); /* Enable averaging */ adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); adcch_enable_averaging(&adcch_conf, ADC_SAMPNUM_1024X); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); adc_enable(&ADCA); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); /* Check values */ for (volt_output = -CONV_MAX_VOLTAGE; volt_output <= CONV_MAX_VOLTAGE; volt_output += CONV_VOLTAGE_STEP) { main_dac_output(volt_output); /* first capture */ volt_input = main_adc_input(); volt_min = volt_max = volt_input; /* several capture */ for (uint8_t i = 0; i < 5; i++) { volt_input = main_adc_input(); if (volt_min > volt_input) { volt_min = volt_input; } if (volt_max < volt_input) { volt_max = volt_input; } } test_assert_true(test, (volt_max - volt_min) < CONF_TEST_ACCEPT_DELTA_AVERAGING, "ADC result is not in acceptable stable range (Min %dmV, Max %dmV)", volt_min, volt_max); } }
/** * \brief Captures a values on ADC * * \return value on ADC pins (mV) */ static uint16_t main_adc_input(void) { uint16_t sample; adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); sample = adc_get_unsigned_result(&ADCA, ADC_CH0); /* Conversion sample to mV : * mV = sample * (VCC / 1.6) / Max. range */ return ((uint32_t)sample * (3300L * 1000L / 1600L)) / (1 << 12); }
/** * \brief Wrapper function for getting and ADC sample * * \param adc_ch which channel to get the ADC samples from * /returns 16-bit signed ADC result */ static int16_t adc_get_sample(uint8_t adc_ch) { int16_t result = 0; adc_start_conversion(&CALIBRATION_ADC, adc_ch); adc_wait_for_interrupt_flag(&CALIBRATION_ADC, adc_ch); result = adc_get_result(&CALIBRATION_ADC, adc_ch); adc_clear_interrupt_flag(&CALIBRATION_ADC, adc_ch); return result; }
/** * \internal * \brief Measure differential input MUX combinations on channel * * Measures a set of input MUX combinations on a single channel, using averaging * of the number of samples specified with \ref NUM_AVERAGE_SAMPLES. * * \pre This function does not configure the ADC, only the ADC channel, and * therefore the specified ADC needs to be configured before this function * is run. * * \param adc Pointer to ADC to measure with. * \param ch_mask Mask for channel to measure with. * \param mux_pos_inputs Pointer to array of positive input MUX settings. * \param mux_neg_inputs Pointer to array of negative input MUX settings. * \param num_inputs Number of input MUX setting pairs. * \param results Pointer to array to store results in. * \param gain Gain to use for all measurements. * * \note The array which \e results points to must have at least \e num_inputs * elements. */ static void differential_signed_average(ADC_t *adc, uint8_t ch_mask, const uint8_t *mux_pos_inputs, const uint8_t *mux_neg_inputs, uint8_t num_inputs, int16_t *results, uint8_t gain) { struct adc_channel_config adcch_conf; uint8_t input; uint8_t i; int32_t sum; memset(&adcch_conf, 0, sizeof(struct adc_channel_config)); // Common configuration adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_disable_interrupt(&adcch_conf); for (input = 0; input < num_inputs; input++) { adcch_set_input(&adcch_conf, mux_pos_inputs[input], mux_neg_inputs[input], gain); adcch_write_configuration(adc, ch_mask, &adcch_conf); // Enable and do dummy conversion adc_enable(adc); adc_start_conversion(adc, ch_mask); adc_wait_for_interrupt_flag(adc, ch_mask); // Read an average sum = 0; for (i = 0; i < NUM_AVERAGE_SAMPLES; i++) { adc_start_conversion(adc, ch_mask); adc_wait_for_interrupt_flag(adc, ch_mask); sum += (int16_t)adc_get_result(adc, ch_mask); } adc_disable(adc); results[input] = sum / NUM_AVERAGE_SAMPLES; } }
int main(void) { const usart_serial_options_t usart_serial_options = { .baudrate = CONF_TEST_BAUDRATE, .charlength = CONF_TEST_CHARLENGTH, .paritytype = CONF_TEST_PARITY, .stopbits = CONF_TEST_STOPBITS, }; /* Usual initializations */ board_init(); sysclk_init(); sleepmgr_init(); irq_initialize_vectors(); cpu_irq_enable(); stdio_serial_init(CONF_TEST_USART, &usart_serial_options); printf("\x0C\n\r-- ADC Averaging Example --\n\r"); printf("-- Compiled: %s %s --\n\r\n\r", __DATE__, __TIME__); printf("Commands:\n\r"); printf("- key 'a' to enable averaging\n\r"); printf("- key 'd' to disable averaging\n\r"); /* ADC initialization */ main_adc_init(); main_adc_averaging_stop(); while (1) { if (usart_rx_is_complete(CONF_TEST_USART)) { char key = getchar(); if (key == 'a') { main_adc_averaging_start(); } if (key == 'd') { main_adc_averaging_stop(); } } /* Wait sample with or without average */ uint16_t sample; adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); sample = adc_get_unsigned_result(&ADCA, ADC_CH0); printf("ADC Value: %4u\r", sample); } }
int main(void){ char xbeebuffer[100]; int adcSample; /**Setup Xbee*/ PORTD.DIR = 0b00001000; PORTF.DIR = 3; /**Setup interrupts*/ PMIC.CTRL |= PMIC_LOLVLEX_bm | PMIC_MEDLVLEX_bm | PMIC_HILVLEX_bm | PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; sei(); USART_InterruptDriver_Initialize(&xbee, &USARTD0, USART_DREINTLVL_LO_gc); USART_Format_Set(xbee.usart, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, false); USART_RxdInterruptLevel_Set(xbee.usart, USART_RXCINTLVL_HI_gc); USART_Baudrate_Set(&USARTD0, 12 , 0); USART_Rx_Enable(xbee.usart); USART_Tx_Enable(xbee.usart); ADC_Ch_InputMode_and_Gain_Config(&ADC_BK.CH0, ADC_CH_INPUTMODE_DIFF_gc, ADC_DRIVER_CH_GAIN_NONE); // differential mode, no gain ADC_Ch_InputMux_Config(&ADC_BK.CH0, pin, ADC_CH_MUXNEG_PIN1_gc); ADC_Reference_Config(&ADC_BK, ADC_REFSEL_VCC_gc); // use Vcc/1.6 as ADC reference ADC_ConvMode_and_Resolution_Config(&ADC_BK, ADC_ConvMode_Signed, ADC_RESOLUTION_12BIT_gc); ADC_Prescaler_Config(&ADC_BK, ADC_PRESCALER_DIV32_gc); while(1){ if(readdata){ readdata = 0; if(input == 'r'){ adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); adcSample = adcch_get_signed_result(&ADCA, 0); sprintf(xbeebuffer, " %d\n\r", adcSample); sendstring(&xbee, xbeebuffer); } } } }
/** * \brief This function get the offset of the ADCB when it is configured * in signed mode * \note The ADC must be configured and enabled before this function is run. * \return Offset on the ADCB */ static int8_t adc_offset_get_signed(void) { int16_t offset = 0; uint8_t i; /* Sum four samples */ for (i = 0; i < 4; i++) { /* Do one conversion to find offset */ adc_start_conversion(&ADCB, ADC_CH0); adc_wait_for_interrupt_flag(&ADCB, ADC_CH0); /* Accumulate conversion results */ offset += adc_get_result(&ADCB, ADC_CH0); } /* Return mean value */ return ((int8_t)(offset / 4)); }
/** * \brief Get mean sample value * * Performs 2 to the power of \ref OVERSAMPLING_FACTOR successive conversions, * and computes the mean value of the resulting sample values. * * \return Mean sample value. */ static uint16_t get_mean_sample_value(void) { uint32_t sum = 0; uint16_t i; // Sum the configured number of samples. for (i = 0; i < (1 << OVERSAMPLING_FACTOR); i++) { adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); sum += adc_get_result(&ADCA, ADC_CH0); } // Compute sample mean by scaling down according to oversampling factor. sum >>= OVERSAMPLING_FACTOR; return sum; }
int read_cap_level(uint16_t avg_no) { int32_t adcresult = 0; for (uint16_t i = 0; i < avg_no; i++) { ADC_set_input_config (ADCCH_POS_PIN6); //connect ADC to ADC1 which is shorted to VDD. ioport_set_pin_dir(TOUCH_ADC_POS_PIN, IOPORT_DIR_OUTPUT); ioport_set_pin_level(TOUCH_ADC_POS_PIN, false); //set measurement pin to GND PORTA.PIN0CTRL = PORT_OPC_TOTEM_gc; //totem pole ioport_set_pin_dir(TOUCH_ADC_POS_PIN, IOPORT_DIR_INPUT); //input ADC_set_input_config (ADCCH_POS_PIN3); //connect ADC to ADC3 which is sensor previously charged to VDD. adc_start_conversion(&MY_ADC, CAP_ADC); adc_wait_for_interrupt_flag(&MY_ADC, CAP_ADC); adcresult += adc_get_result(&MY_ADC, CAP_ADC); } return adcresult / avg_no; }
/** * \brief Initialize ADC */ static void main_adc_init(void) { /* ADC module configuration structure */ struct adc_config adc_conf; /* ADC channel configuration structure */ struct adc_channel_config adcch_conf; /* Configure the ADC module: * - signed, 12-bit results * - voltage reference = VCC / 1.6 = 3.3V / 1.6 * - 200 kHz maximum clock rate * - manual conversion triggering */ adc_read_configuration(&ADCA, &adc_conf); /* Initialize structures. */ adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12, ADC_REF_VCC); adc_set_clock_rate(&adc_conf, 200000UL); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_write_configuration(&ADCA, &adc_conf); /* Configure ADC channel: * - differential measurement mode * - Input voltage V+ is ADC2 pin (PA2 pin) * - Input voltage V- is ADC3 pin (PA3 pin) * - 1x gain * - interrupt flag set on completed conversion */ adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); adcch_set_input(&adcch_conf, ADCCH_POS_PIN2, ADCCH_NEG_PIN3, 1); adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_disable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); /* Enable ADC */ adc_enable(&ADCA); /* Do useful conversion */ adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); }
int read_cap_level_ref(uint16_t avg_no) { int32_t adcresult = 0; for (uint16_t i = 0; i < avg_no; i++) { ADC_set_input_config (ADCCH_POS_PIN6); //connect ADC to ADC1 which is shorted to VDD. ioport_set_pin_dir(TOUCH_ADC_REF_PIN, IOPORT_DIR_OUTPUT); ioport_set_pin_level(TOUCH_ADC_REF_PIN, false); //set measurement pin to GND _delay_us(10); //make sure it is discharged PORTA.PIN2CTRL = PORT_OPC_TOTEM_gc; //totem pole ioport_set_pin_dir(TOUCH_ADC_REF_PIN, IOPORT_DIR_INPUT); //input ADC_set_input_config (ADCCH_POS_PIN2); //connect ADC to ADC2 which is not connected to anything _delay_us(10); adc_start_conversion(&MY_ADC, CAP_ADC); adc_wait_for_interrupt_flag(&MY_ADC, CAP_ADC); adcresult += adc_get_result(&MY_ADC, CAP_ADC); } return adcresult / avg_no; }
/** * \brief Enables averaging */ static void main_adc_averaging(void) { /* ADC module configuration structure */ struct adc_config adc_conf; /* ADC channel configuration structure */ struct adc_channel_config adcch_conf; adc_disable(&ADCA); /* Change resolution parameter to accept averaging */ adc_read_configuration(&ADCA, &adc_conf); adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_MT12, ADC_REF_VCC); adc_write_configuration(&ADCA, &adc_conf); /* Enable averaging */ adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); adcch_enable_averaging(&adcch_conf, ADC_SAMPNUM_1024X); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); adc_enable(&ADCA); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); }
int main(void) { const usart_serial_options_t usart_serial_options = { .baudrate = CONF_TEST_BAUDRATE, .charlength = CONF_TEST_CHARLENGTH, .paritytype = CONF_TEST_PARITY, .stopbits = CONF_TEST_STOPBITS, }; char binary[16 + 1]; uint8_t i; bool oversampling_is_enabled; /* Usual initializations */ board_init(); sysclk_init(); sleepmgr_init(); irq_initialize_vectors(); cpu_irq_enable(); stdio_serial_init(CONF_TEST_USART, &usart_serial_options); printf("\x0C\n\r-- ADC Over-sampling Example --\n\r"); printf("-- Compiled: %s %s --\n\r\n\r", __DATE__, __TIME__); printf("Commands:\n\r"); printf("- key 'o' to enable over-sampling\n\r"); printf("- key 'd' to disable over-sampling\n\r"); /* ADC initializations */ main_adc_init(); main_adc_oversampling_stop(); oversampling_is_enabled = false; while (1) { if (usart_rx_is_complete(CONF_TEST_USART)) { char key = getchar(); if (key == 'o') { main_adc_oversampling_start(); oversampling_is_enabled = true; } if (key == 'd') { main_adc_oversampling_stop(); oversampling_is_enabled = false; } } /* Wait sample with or without over-sampling */ uint16_t sample; adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); sample = adc_get_unsigned_result(&ADCA, ADC_CH0); if (!oversampling_is_enabled) { sample <<= 4; } i = 15; do { binary[i] = '0' + (sample & 1); sample >>= 1; } while (i--); binary[16] = 0; printf("ADC Value: %sb\r", binary); } }
void alphasense_adc_getValue( void ) { //ALPHASENSE_STATS * const ps = &g_internal; struct adc_config adc_conf; struct adc_channel_config adcch_conf; uint8_t inputgain = 1;//, elements = 20; //char szBUF[64]; // DISABLE jtag - it locks the upper 4 pins of PORT B CCP = CCP_IOREG_gc; // Secret handshake MCU.MCUCR = 0b00000001; PORTB.PIN0CTRL = PORT_OPC_TOTEM_gc; // Auxiliary Electrode PORTB.PIN2CTRL = PORT_OPC_TOTEM_gc; // Working Electrode PORTB.PIN6CTRL = PORT_OPC_TOTEM_gc; // GND x offset adc_read_configuration(&ALPHASENSE_ADC, &adc_conf); adcch_read_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf); adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12, ADC_REF_VCC); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_set_clock_rate(&adc_conf, 200000UL); adc_write_configuration(&ALPHASENSE_ADC, &adc_conf); adcch_set_input(&adcch_conf, ADCCH_POS_PIN6, ADCCH_NEG_NONE, inputgain); adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf); adc_enable(&ALPHASENSE_ADC); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); const int16_t off = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_disable(&ALPHASENSE_ADC); //sprintf_P(szBUF,PSTR("Offset: %u\t"),off); //debug_string(NORMAL,szBUF,false); //adcch_set_input(&adcch_conf, ADCCH_POS_BANDGAP, ADCCH_NEG_NONE, inputgain); //adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf); //adc_enable(&ALPHASENSE_ADC); //adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //const uint16_t gain = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //adc_disable(&ALPHASENSE_ADC); ////sprintf_P(szBUF,PSTR("gain: %u\t"),gain); ////debug_string(NORMAL,szBUF,false); adcch_set_input(&adcch_conf, ADCCH_POS_PIN0, ADCCH_NEG_NONE, inputgain); adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf); adc_enable(&ALPHASENSE_ADC); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); const int16_t adc_w = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH)-off; adc_disable(&ALPHASENSE_ADC); //sprintf_P(szBUF,PSTR("ADC_WORK: %u\t"),adc_w); //debug_string(NORMAL,szBUF,false); adcch_set_input(&adcch_conf, ADCCH_POS_PIN2, ADCCH_NEG_NONE, inputgain); adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf); adc_enable(&ALPHASENSE_ADC); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); const int16_t adc_a = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH)-off; adc_disable(&ALPHASENSE_ADC); //sprintf_P(szBUF,PSTR("ADC_AUX: %u\r\n"),adc_a); //debug_string(NORMAL,szBUF,false); //adc_enable(&ALPHASENSE_ADC); // //for (int i=0;i<elements;i++) //{ //adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //result[i]=adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); // //} //adc_disable(&ALPHASENSE_ADC); PORTB.PIN0CTRL = PORT_OPC_PULLUP_gc; PORTB.PIN2CTRL = PORT_OPC_PULLUP_gc; PORTB.PIN6CTRL = PORT_OPC_PULLUP_gc; g_recordingData_Alphasense = true; g_partialSumWork+=(int32_t)adc_w; g_partialSumAux+=(int32_t)adc_a; g_partialCount_Alphasense++; g_recordingData_Alphasense = false; //sprintf_P(szBUF,PSTR("Sample: %u\tPartialSumWork: %lu\tPartialSumAux: %lu\r\n"),g_partialCount, g_partialSumWork,g_partialSumAux); //debug_string(NORMAL,szBUF,false); //ps->working = adc_w; //ps->aux = adc_a; }
/** * \brief Measures and enables offset and gain corrections */ static void main_adc_correction_start(void) { /* ADC channel configuration structure */ struct adc_channel_config adcch_conf; static bool correction_measures_done = false; static uint16_t offset_correction; /* Expected value for gain correction at 1.9V * expected_value = Max. range (12 bits unsigned) * 1.9V / (VCC / 1.6) */ const uint16_t expected_value = ((1 << 12) * 1900UL) / (3300L * 1000L / 1600L); /* Captured value for gain correction */ static uint16_t captured_value; if (correction_measures_done) { goto main_adc_correction_enable; } printf("\n\r*Measure offset correction\n\r"); printf("Set PA0 pin to GND and press a key to trigge measurement.\n\r"); printf("Warning on STK600: Remove AREF0 jumper to do it.\n\r"); getchar(); /* Capture value for 0 Volt */ adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); offset_correction = adc_get_unsigned_result(&ADCA, ADC_CH0); /* Enable offset correction */ adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); adcch_enable_correction(&adcch_conf, offset_correction, 1, 1); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); printf("*Measure Gain correction\n\r"); printf("Set PA0 pin to 1.9 Volt"); printf(" and press a key to trigge measurement.\r\n"); printf("Reminder on STK600: Set AREF0 jumper to do it.\n\r"); getchar(); /* Capture value for 1.9 Volts */ adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); captured_value = adc_get_unsigned_result(&ADCA, ADC_CH0); correction_measures_done = true; main_adc_correction_enable: /* Enable offset & gain correction */ adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); adcch_enable_correction(&adcch_conf, offset_correction, expected_value, captured_value); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); printf("\n\r* ADC correction enabled: "); printf("Offset correction %d, ", offset_correction); if (expected_value > captured_value) { printf("Gain correction 1.%03u\n\r", (uint16_t) ((((uint32_t)expected_value - captured_value) * 1000) / captured_value)); } else { printf("Gain correction 0.%03u\n\r", (uint16_t) (((uint32_t)expected_value * 1000) / captured_value)); } }
/** * \internal * \brief Test correction conversion in 12-bit mode using the DAC * * These values are then measured using the ADC on the pins that are connected * to the DAC channel, and the results are compared and checked to see if they * are within the acceptable range of values that passes the test. * * \param test Current test case. */ static void run_correction_conversion_test( const struct test_case *test) { int16_t volt_output; int16_t volt_input; uint16_t error; /** Measures and enables offset and gain corrections */ /* ADC channel configuration structure */ struct adc_channel_config adcch_conf; uint16_t offset_correction; /* Expected value for gain correction at 1.9V * expected_value = Max. range * 1.9V / (VCC / 1.6) * Max. range = 12 bits signed = 11 bits unsigned */ const uint16_t expected_value = ((1 << 11) * 1900UL) / (3300L * 1000L / 1600L); /* Captured value for gain correction */ uint16_t captured_value; /* DAC Output 0 Volt */ main_dac_output(0); /* Capture value for 0 Volt */ adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); offset_correction = adc_get_unsigned_result(&ADCA, ADC_CH0); /* Enable offset correction */ adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); adcch_enable_correction(&adcch_conf, offset_correction, 1, 1); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); /* DAC Output 1.9 Volts */ main_dac_output(1900); /* Capture value for 1.9 Volts */ adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); captured_value = adc_get_unsigned_result(&ADCA, ADC_CH0); /* Enable offset & gain correction */ adcch_enable_correction(&adcch_conf, offset_correction, expected_value, captured_value); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); /* Check values */ for (volt_output = -CONV_MAX_VOLTAGE; volt_output <= CONV_MAX_VOLTAGE; volt_output += CONV_VOLTAGE_STEP) { main_dac_output(volt_output); volt_input = main_adc_input(); if (volt_output > volt_input) { error = volt_output - volt_input; } else { error = volt_input - volt_output; } test_assert_true(test, error < CONF_TEST_ACCEPT_DELTA_CORRECTION, "ADC result is outside acceptable range (expected %d, captured %d)", volt_output, volt_input); } }
int main(void) { struct adc_config adc_conf; struct adc_channel_config adcch_conf; board_init(); sysclk_init(); sleepmgr_init(); irq_initialize_vectors(); cpu_irq_enable(); // Initialize configuration structures. adc_read_configuration(&ADCA, &adc_conf); adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); /* Configure the ADC module: * - unsigned, 12-bit results * - bandgap (1 V) voltage reference * - 200 kHz maximum clock rate * - manual conversion triggering */ adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12, ADC_REF_BANDGAP); adc_set_clock_rate(&adc_conf, 200000UL); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_write_configuration(&ADCA, &adc_conf); /* Configure ADC channel 0: * - single-ended measurement from configured input pin * - interrupt flag set on completed conversion */ adcch_set_input(&adcch_conf, INPUT_PIN, ADCCH_NEG_NONE, 1); adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_disable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); // Enable the ADC and do one dummy conversion. adc_enable(&ADCA); adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); // Light up LED 1, wait for button press. ioport_set_pin_low(LED1_PIN); wait_for_button(); // Perform oversampling of offset. cal_data.offset = get_mean_sample_value(); // Light up LED 2, wait for button press. ioport_set_pin_low(LED2_PIN); wait_for_button(); // Perform oversampling of 0.9 V for gain calibration. cal_data.gain = get_mean_sample_value() - cal_data.offset; // Turn off LEDs. ioport_set_pin_high(LED1_PIN); ioport_set_pin_high(LED2_PIN); // Enable interrupts on ADC channel, then trigger first conversion. adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); adc_start_conversion(&ADCA, ADC_CH0); do { // Sleep until ADC interrupt triggers. sleepmgr_enter_sleep(); } while (1); }