This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Reading ADC values from multiple pins

Hello, I'm using nRF51822-mKIT for a research.

I recently posted a question related to "reading ADC value from analog input", having issues with reading proper ADC value from input pin. However, after narrowing down, I have found out that the root cause was that I tried to read ADC values simultaneously from multiple pins.

The following is the code that I have right now:

static void rr_interval_timeout_handler(void * p_context) {
    UNUSED_PARAMETER(p_context);
    if (m_rr_interval_enabled) {
		/*!<AIn2 corrosponds to Vgas>*/
		/*!<AIn4 corrosponds to Vref>*/
		data[2] = (uint16_t) adc_read(ADC_CONFIG_PSEL_AnalogInput6); /*!<AIn6 corrosponds to Vtemp>*/
    }
}

unsigned short adc_read(unsigned int adc_in_mask)
{
	uint16_t adc_result;
    // interrupt ADC
    NRF_ADC->INTENSET = (ADC_INTENSET_END_Disabled << ADC_INTENSET_END_Pos); /*!< Interrupt enabled. */
    // config ADC
    NRF_ADC->CONFIG	= (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos) /* Bits 17..16 : ADC external reference pin selection. */
					| (adc_in_mask << ADC_CONFIG_PSEL_Pos)	 /*!< Use analog input 0 as analog input. */
					| (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) /*!< Use internal 1.2V bandgap voltage as reference for conversion. */
					| (ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) /*!< Analog input specified by PSEL with no prescaling used as input for the conversion. */
					| (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos);	 /*!< 10bit ADC resolution. */ 
    // enable ADC		
    NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled; /* Bit 0 : ADC enable. */
    // start ADC conversion
    NRF_ADC->TASKS_START = 1;
    // wait for conversion to end
    while (!NRF_ADC->EVENTS_END)
    {}
    NRF_ADC->EVENTS_END	= 0;
    adc_result = ADC_RESULT_IN_MILLI_VOLTS(NRF_ADC->RESULT);
    //Use the STOP task to save current. Workaround for PAN_028 rev1.1 anomaly 1.
    NRF_ADC->TASKS_STOP = 1;
    return adc_result;
}

You can see that I am currently collecting an ADC value from AnalogInput6 only. What I want to have is a code that collects ADC values from AnalogInput2 and AnalogInput4 as well in a very short interval (simultaneously if possible).

The bottom code is the one that I tried and failed to get correct ADC values:

static void rr_interval_timeout_handler(void * p_context) {
    UNUSED_PARAMETER(p_context);
    if (m_rr_interval_enabled) {
        data[0] = (uint16_t) adc_read(ADC_CONFIG_PSEL_AnalogInput2); /*!<AIn2 corrosponds to Vgas>*/
        data[1] = (uint16_t) adc_read(ADC_CONFIG_PSEL_AnalogInput4); /*!<AIn4 corrosponds to Vref>*/
        data[2] = (uint16_t) adc_read(ADC_CONFIG_PSEL_AnalogInput6); /*!<AIn6 corrosponds to Vtemp>*/
    }
}

Is there any way that I could read ADC values from multiple pins? Thank you in advance.

=====SOLUTION=====

Thanks to Stefan, I got a working code! Hope this helps to people who were having similar problem. I have modified my code to collect ADC values from each pin sequentially, using a counter.

uint8_t count = 0;

static void rr_interval_timeout_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    if (m_rr_interval_enabled)
    {
		if(count == 0) {
			data[0] = (uint16_t) adc_read(ADC_CONFIG_PSEL_AnalogInput2); /*!<AIn2 corrosponds to Vgas>*/
		} else if(count == 1) {
			data[1] = (uint16_t) adc_read(ADC_CONFIG_PSEL_AnalogInput4); /*!<AIn4 corrosponds to Vref>*/
		} else if(count == 2) {
			data[2] = (uint16_t) adc_read(ADC_CONFIG_PSEL_AnalogInput6); /*!<AIn6 corrosponds to Vtemp>*/
		}
    }
}

static void heart_rate_meas_timeout_handler(void * p_context)
{
    uint32_t        err_code;
    UNUSED_PARAMETER(p_context);

    ble_hrs_rr_interval_add(&m_hrs, data[count]);
	err_code = ble_hrs_heart_rate_measurement_send(&m_hrs, count);
	count++;
	if(count > 2) {
		count = 0;
	}
    if ((err_code != NRF_SUCCESS) &&
        (err_code != NRF_ERROR_INVALID_STATE) &&
        (err_code != BLE_ERROR_NO_TX_BUFFERS) &&
        (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
    )
    {
        APP_ERROR_HANDLER(err_code);
    }
}
Related