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

How do I use registers to configure SAADC for my Arduino Nano 33?

The documentation is a little unclear. I am using Arduino Nano 33 BLE. Using the analogread() functions of Arduino I get a much worse performance than the nRF is supposed to handle. How can I use the registers with the void setup() and void loop() to leverage the full performance of SAADC? 

I am using Arduino on PlatformIO IDE on VSCode. 

This is the closest think I have found: https://github.com/andenore/NordicSnippets/blob/master/examples/saadc/main.c 

But it is not working as I am too inexperienced to figure out the GPIO. 

Parents
  • #include <Arduino.h>
    #include <nrf.h>
    
     uint32_t result = 0;
     uint32_t result_channel;
     uint32_t amount =0;
      float precise_result = 0;
    
    void setup() {
    
      Serial.begin(9600);
    
      // Configure SAADC singled-ended channel, Internal reference (0.6V) and 1/6 gain.
      NRF_SAADC->CH[1].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_20us        << SAADC_CH_CONFIG_TACQ_Pos);
    
      // Configure the SAADC channel with VDD as positive input, no negative input(single ended).
      NRF_SAADC->CH[1].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput1 << SAADC_CH_PSELP_PSELP_Pos;
      NRF_SAADC->CH[1].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;
    
      // 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));
    
      NRF_SAADC->SAMPLERATE=0x20<<SAADC_SAMPLERATE_CC_Msk;
    
        // 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;
                        
    }
    
    
    void loop() {
      
      Serial.println("Measure");
    
      // 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
      result =NRF_SAADC->RESULT.PTR;
      result_channel = result & 0x0000FFFF;
      precise_result =result_channel/4551.1;
    
      Serial.println("===============");
      // Serial.println(SAADC_CH_PSELN_PSELN_AnalogInput0);
      Serial.println(result,HEX);
      Serial.println(precise_result);
      Serial.println(NRF_SAADC->RESULT.AMOUNT);
      Serial.println();
    
    
      // //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;
    
      //   while (1)
      // {
      //   __WFE();
      // }
    
    
    }

    This is my code so far but I only get 0. I have checked the pin numbers and all is where it should be. I do not know what is wrong. I am using Arduino Nano BLE 33

Reply
  • #include <Arduino.h>
    #include <nrf.h>
    
     uint32_t result = 0;
     uint32_t result_channel;
     uint32_t amount =0;
      float precise_result = 0;
    
    void setup() {
    
      Serial.begin(9600);
    
      // Configure SAADC singled-ended channel, Internal reference (0.6V) and 1/6 gain.
      NRF_SAADC->CH[1].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_20us        << SAADC_CH_CONFIG_TACQ_Pos);
    
      // Configure the SAADC channel with VDD as positive input, no negative input(single ended).
      NRF_SAADC->CH[1].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput1 << SAADC_CH_PSELP_PSELP_Pos;
      NRF_SAADC->CH[1].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;
    
      // 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));
    
      NRF_SAADC->SAMPLERATE=0x20<<SAADC_SAMPLERATE_CC_Msk;
    
        // 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;
                        
    }
    
    
    void loop() {
      
      Serial.println("Measure");
    
      // 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
      result =NRF_SAADC->RESULT.PTR;
      result_channel = result & 0x0000FFFF;
      precise_result =result_channel/4551.1;
    
      Serial.println("===============");
      // Serial.println(SAADC_CH_PSELN_PSELN_AnalogInput0);
      Serial.println(result,HEX);
      Serial.println(precise_result);
      Serial.println(NRF_SAADC->RESULT.AMOUNT);
      Serial.println();
    
    
      // //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;
    
      //   while (1)
      // {
      //   __WFE();
      // }
    
    
    }

    This is my code so far but I only get 0. I have checked the pin numbers and all is where it should be. I do not know what is wrong. I am using Arduino Nano BLE 33

Children
Related