This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Read one channel ADC value OK after SAADC calibration. But I change to two ADC channel, The ADC value of each channel will rise or fall with other channels

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.

Related