Hi, As subject.
I can read right ADC value after calibration. but I change channel from 1 to 2. The value of each channel will rise or fall with other channels. Why?
I post my code as below:
saadc_init()
void saadc_init(void)
{
ret_code_t err_code;
nrf_drv_saadc_config_t saadc_config;
nrf_saadc_channel_config_t channel_config;
// Configure SAADC
// Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=2048 (when input voltage is 3.6V for channel gain setting of 1/6).
saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
// adc_resolution = NRF_SAADC_RESOLUTION_10BIT;
// SAADC_OVERSAMPLE Setting oversample to 4x will make the SAADC output a single averaged value when the SAMPLE task is triggered 4 times.
saadc_config.oversample = NRF_SAADC_OVERSAMPLE_4X;
// Set SAADC interrupt to low priority.
saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;
// Initialize SAADC
// Initialize the SAADC with configuration and callback function. The application must then implement the saadc_callback function, which will be called when SAADC interrupt is triggered
err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
APP_ERROR_CHECK(err_code);
// Configure SAADC channel for ADC temperature
// Set internal reference of fixed 0.6 volts
channel_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
// Set input gain to 1/6. The maximum SAADC input voltage is then 0.6V/(1/6)=3.6V. The single ended input range is then 0V-3.6V
channel_config.gain = NRF_SAADC_GAIN1_6;
// Set acquisition time. Set low acquisition time to enable maximum sampling frequency of 200kHz.
// Set high acquisition time to allow maximum source resistance up to 800 kohm, see the SAADC electrical specification in the PS.
channel_config.acq_time = NRF_SAADC_ACQTIME_10US;
// Since the SAADC is single ended, the negative pin is disabled. The negative pin is shorted to ground internally.
channel_config.mode = NRF_SAADC_MODE_SINGLE_ENDED;
// Since the SAADC is single ended, the negative pin is disabled. The negative pin is shorted to ground internally.
channel_config.pin_n = NRF_SAADC_INPUT_DISABLED;
// Disable pullup resistor on the input pin
channel_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;
// Disable pulldown resistor on the input pin
channel_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
// Initialize SAADC channel
// Select the input pin for the channel. AIN2 pin maps to physical pin P0.04.
channel_config.pin_p = NRF_SAADC_INPUT_AIN0;
// Initialize SAADC channel 0 with the channel configuration
err_code = nrf_drv_saadc_channel_init(0, &channel_config);
APP_ERROR_CHECK(err_code);
// Configure burst mode for channel 0. Burst is useful together with oversampling.
// When triggering the SAMPLE task in burst mode, the SAADC will sample "Oversample" number of times as fast as it can and then output a single averaged value to the RAM buffer.
// If burst mode is not enabled, the SAMPLE task needs to be triggered "Oversample" number of times to output a single averaged value to the RAM buffer.
//NRF_SAADC->CH[0].CONFIG |= 0x01000000;
// Configure SAADC channel for ADC temperature
// Set internal reference of fixed 0.6 volts
channel_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
// Set input gain to 1/6. The maximum SAADC input voltage is then 0.6V/(1/6)=3.6V. The single ended input range is then 0V-3.6V
channel_config.gain = NRF_SAADC_GAIN1_6;
// Set acquisition time. Set low acquisition time to enable maximum sampling frequency of 200kHz.
// Set high acquisition time to allow maximum source resistance up to 800 kohm, see the SAADC electrical specification in the PS.
channel_config.acq_time = NRF_SAADC_ACQTIME_10US;
// Since the SAADC is single ended, the negative pin is disabled. The negative pin is shorted to ground internally.
channel_config.mode = NRF_SAADC_MODE_SINGLE_ENDED;
// Since the SAADC is single ended, the negative pin is disabled. The negative pin is shorted to ground internally.
channel_config.pin_n = NRF_SAADC_INPUT_DISABLED;
// Disable pullup resistor on the input pin
channel_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;
// Disable pulldown resistor on the input pin
channel_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
// Initialize SAADC channel
// Select the input pin for the channel. AIN3 pin maps to physical pin P0.05.
channel_config.pin_p = NRF_SAADC_INPUT_AIN2;
// Initialize SAADC channel 0 with the channel configuration
err_code = nrf_drv_saadc_channel_init(1, &channel_config);
APP_ERROR_CHECK(err_code);
// Configure burst mode for channel 0. Burst is useful together with oversampling.
// When triggering the SAMPLE task in burst mode, the SAADC will sample "Oversample" number of times as fast as it can and then output a single averaged value to the RAM buffer.
// If burst mode is not enabled, the SAMPLE task needs to be triggered "Oversample" number of times to output a single averaged value to the RAM buffer.
//NRF_SAADC->CH[1].CONFIG |= 0x01000000;
// Configure SAADC channel for ADC temperature
// Set internal reference of fixed 0.6 volts
channel_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
// Set input gain to 1/6. The maximum SAADC input voltage is then 0.6V/(1/6)=3.6V. The single ended input range is then 0V-3.6V
channel_config.gain = NRF_SAADC_GAIN1_6;
// Set acquisition time. Set low acquisition time to enable maximum sampling frequency of 200kHz.
// Set high acquisition time to allow maximum source resistance up to 800 kohm, see the SAADC electrical specification in the PS.
channel_config.acq_time = NRF_SAADC_ACQTIME_10US;
// Since the SAADC is single ended, the negative pin is disabled. The negative pin is shorted to ground internally.
channel_config.mode = NRF_SAADC_MODE_SINGLE_ENDED;
// Since the SAADC is single ended, the negative pin is disabled. The negative pin is shorted to ground internally.
channel_config.pin_n = NRF_SAADC_INPUT_DISABLED;
// Disable pullup resistor on the input pin
channel_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;
// Disable pulldown resistor on the input pin
channel_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
// Initialize SAADC channel
// Select the input pin for the channel. AIN3 pin maps to physical pin P0.05.
channel_config.pin_p = NRF_SAADC_INPUT_AIN3;
// Initialize SAADC channel 0 with the channel configuration
err_code = nrf_drv_saadc_channel_init(2, &channel_config);
APP_ERROR_CHECK(err_code);
// Set SAADC buffer 1. The SAADC will start to write to this buffer
err_code = nrf_drv_saadc_buffer_convert(adc_buf_adc[0],3);
APP_ERROR_CHECK(err_code);
// Set SAADC buffer 2. The SAADC will write to this buffer when buffer 1 is full. This will give the applicaiton time to process data in buffer 1.
err_code = nrf_drv_saadc_buffer_convert(adc_buf_adc[1],3);
APP_ERROR_CHECK(err_code);
}
saadc_callback()
void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
ret_code_t err_code;
//Capture offset calibration complete event
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
// Evaluate if offset calibration should be performed. Configure the SAADC_CALIBRATION_INTERVAL constant to change the calibration frequency
if((m_adc_evt_counter % 50) == 0) {
// Abort all ongoing conversions. Calibration cannot be run if SAADC is busy
nrf_drv_saadc_abort();
// Set flag to trigger calibration in main context when SAADC is stopped
m_saadc_calibrate = true;
}
//for (int i = 0; i < p_event->data.done.size; i++)
//{
//current_sense_vol = p_event->data.done.p_buffer[i];
///printf("%d", p_event->data.done.p_buffer[i]);
//}
current_sense_vol = p_event->data.done.p_buffer[0];
adc_temp_vol = p_event->data.done.p_buffer[1];
em_temp_vol = p_event->data.done.p_buffer[2];
if(m_saadc_calibrate == false)
{
//Set buffer so the SAADC can write to it again.
err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 3);
APP_ERROR_CHECK(err_code);
}
m_adc_evt_counter++;
}
else if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
{
nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
while(!nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED));
nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
//Set buffer so the SAADC can write to it again.
err_code = nrf_drv_saadc_buffer_convert(adc_buf_adc[0], 3);
APP_ERROR_CHECK(err_code);
//Need to setup both buffers, as they were both removed with the call to nrf_drv_saadc_abort before calibration.
err_code = nrf_drv_saadc_buffer_convert(adc_buf_adc[1], 3);
APP_ERROR_CHECK(err_code);
nrf_delay_us(200);
}
}
And for loop in main()
for (;;)
{
if (m_saadc_calibrate == true)
{
while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //Trigger calibration task
m_saadc_calibrate = false;
}
//nrf_pwr_mgmt_run();
}
Last, I create a 200ms timer to read ADC value
static void data_process_handler(void * p_context)
{
uint32_t err_code;
static float real_v_0 = 0;
static float real_v_1 = 0;
static float real_v_2 = 0;
err_code = nrf_drv_saadc_sample();
APP_ERROR_CHECK(err_code);
nrf_delay_ms(10);
printf("%d,%d,%d\r\n",current_sense_vol,adc_temp_vol,em_temp_vol);
if(current_sense_vol != 1024)
{
real_v_0 = (float)current_sense_vol * 3.6 / 4096.0;
real_v_1 = (float)adc_temp_vol * 3.6 / 4096.0;
real_v_2 = (float)em_temp_vol * 3.6 / 4096.0;
}
printf("%.4f,%.4f,%.4f\r\n",real_v_0,real_v_1,real_v_2);
//printf("%.4f\r\n",real_v_0);
After run nrf_drv_saadc_sample(), I will get 3 ADC value. I only have to adjust the value of one channel(Like channel 1), But channel 0 ADC value will rise or fall with channel 1. Why?
Thank you for Nordic's support.