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

Simple analog read on nrf52

Hello. How i can do a simple read an 0 -> 3 Volt (vdd) signal on Analog 0 P0.03? I try it with saadc without sucess

            int result = 0;
		
			NRF_SAADC->CH[0].CONFIG = (
						SAADC_CH_PSELN_PSELN_AnalogInput0 << SAADC_CH_CONFIG_BURST_Pos |
						SAADC_CH_CONFIG_BURST_Enabled << SAADC_CH_CONFIG_BURST_Pos |
						SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos |
						SAADC_CH_CONFIG_TACQ_10us << SAADC_CH_CONFIG_TACQ_Pos |
						SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_TACQ_Pos |
						SAADC_CH_CONFIG_GAIN_Gain1_5 << SAADC_CH_CONFIG_GAIN_Pos |
						SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos |
						SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos );

			NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_VDD;
			NRF_SAADC->CH[0].PSELN = SAADC_CH_PSELN_PSELN_NC;
		
			// Configure the SAADC resolution.
			NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_14bit << SAADC_RESOLUTION_VAL_Pos;
			NRF_SAADC->OVERSAMPLE = SAADC_OVERSAMPLE_OVERSAMPLE_Over256x << SAADC_OVERSAMPLE_OVERSAMPLE_Pos;

			//Setup memory location
			NRF_SAADC->RESULT.PTR = (uint32_t)&result;

			// No automatic sampling, will trigger with TASKS_SAMPLE.
			NRF_SAADC->SAMPLERATE = SAADC_SAMPLERATE_MODE_Task << SAADC_SAMPLERATE_MODE_Pos;

			// Enable SAADC (would capture analog pins if they were used in CH[0].PSELP)
			NRF_SAADC->ENABLE = SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos;
  • Correct me if I'm wrong, but I can't see "where" do you trigger the TASK_SAMPLE. Why don't you use the library "nrf_dr_saadc"? It's very easy to use

  • Hi,

    You can find an example of a simple read using the SAADC on the NordicSnippets GitHub page.

    If you want to use the SAADC driver, included in the SDK, you can find a simple example in this thead.

    Best regards,

    Jørgen

  • ...mmmh maybe i am completely wrong, but i try the code on the example without an result i get an result on the varaible "result" this result is about 12000 and changes +/- 10 on every round.

    int main(void)
    {
      uint32_t err_code;
      bool erase_bonds;
    	__WFE();
      // Initialize.
    //APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
    //uart_init();
    
    //buttons_leds_init(&erase_bonds);
    //ble_stack_init();
    //    gap_params_init();
    //    services_init();
    //    advertising_init();
    //    conn_params_init();
    
    //    printf("\r\nUART Start!\r\n");
    //    err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
    //    APP_ERROR_CHECK(err_code);
    
    
    
    // Enter main loop.
    for (;;)
    {
    			//#define EX1_COUNT 5
    			//float ex1_result_f[EX1_COUNT];
    			//int16_t ex1_result[EX1_COUNT];
        //power_manage();
    			//read_right_hand_keys();
    
    			volatile int16_t result = 0;
    			volatile float precise_result = 0;
    
    			// Start HFCLK from crystal oscillator, this will give the SAADC higher accuracy
    			NRF_CLOCK->TASKS_HFCLKSTART = 1;
    			while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
    			NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    
    			// Configure SAADC singled-ended channel, Internal reference (0.6V) and 1/6 gain.
    			NRF_SAADC->CH[0].CONFIG = (SAADC_CH_CONFIG_GAIN_Gain1_6    << SAADC_CH_CONFIG_GAIN_Pos) |
    																(SAADC_CH_CONFIG_MODE_SE         << SAADC_CH_CONFIG_MODE_Pos) |
    																(SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_Pos) |
    																(SAADC_CH_CONFIG_RESN_Bypass     << SAADC_CH_CONFIG_RESN_Pos) |
    																(SAADC_CH_CONFIG_RESP_Bypass     << SAADC_CH_CONFIG_RESP_Pos) |
    																(SAADC_CH_CONFIG_TACQ_3us        << SAADC_CH_CONFIG_TACQ_Pos);
    
    			// Configure the SAADC channel with VDD as positive input, no negative input(single ended).
    			NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_VDD << SAADC_CH_PSELP_PSELP_Pos;
    			NRF_SAADC->CH[0].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;
    
    			// Configure the SAADC resolution.
    			NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_14bit << SAADC_RESOLUTION_VAL_Pos;
    
    			// Configure result to be put in RAM at the location of "result" variable.
    			NRF_SAADC->RESULT.MAXCNT = 1;
    			NRF_SAADC->RESULT.PTR = (uint32_t)&result;
    
    			// No automatic sampling, will trigger with TASKS_SAMPLE.
    			NRF_SAADC->SAMPLERATE = SAADC_SAMPLERATE_MODE_Task << SAADC_SAMPLERATE_MODE_Pos;
    
    			// Enable SAADC (would capture analog pins if they were used in CH[0].PSELP)
    			NRF_SAADC->ENABLE = SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos;
    
    			// Calibrate the SAADC (only needs to be done once in a while)
    			NRF_SAADC->TASKS_CALIBRATEOFFSET = 1;
    			while (NRF_SAADC->EVENTS_CALIBRATEDONE == 0);
    			NRF_SAADC->EVENTS_CALIBRATEDONE = 0;
    			while (NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy <<SAADC_STATUS_STATUS_Pos));
    
    			// Start the SAADC and wait for the started event.
    			NRF_SAADC->TASKS_START = 1;
    			while (NRF_SAADC->EVENTS_STARTED == 0);
    			NRF_SAADC->EVENTS_STARTED = 0;
    
    			// Do a SAADC sample, will put the result in the configured RAM buffer.
    			NRF_SAADC->TASKS_SAMPLE = 1;
    			while (NRF_SAADC->EVENTS_END == 0);
    			NRF_SAADC->EVENTS_END = 0;
    
    			// Convert the result to voltage
    			// Result = [V(p) - V(n)] * GAIN/REFERENCE * 2^(RESOLUTION)
    			// Result = (VDD - 0) * ((1/6) / 0.6) * 2^14
    			// VDD = Result / 4551.1
    			precise_result = (float)result / 4551.1f;
    			precise_result; // to get rid of set but not used warning
    
    			// Stop the SAADC, since it's not used anymore.
    			NRF_SAADC->TASKS_STOP = 1;
    			while (NRF_SAADC->EVENTS_STOPPED == 0);
    			NRF_SAADC->EVENTS_STOPPED = 0;
    		
    		
    
    		
    
    }
    
  • what do the Task_sample? How i can find the nrf_dr_saadc ? i had only copiing the code from an sample. But i the PIC MCU world was this ADC read simpler :-)

  • ...mmmh maybe i am completely wrong, but i try the code on the example without an result i get an result on the varaible "result" this result is about 12000 and changes +/- 10 on every round.

Related