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

comp or lpcomp for 2 analog inputs with different v-- (ref)

i am working with nrf52832

i need to check 2 analog inputs and set my own v- (ref) 

i can have value read every few seconds so no fast readings needs to be done 

if i understand correctly i better use lpcomp if no fast readings is needed?

also,  is it possible, and if there are some code examples, to be reading 2 analog inputs with 2 different v-- (references) (one for each input pin) ?

best regards

Ziv

Parents
  • Hello, 

    if i understand correctly i better use lpcomp if no fast readings is needed?

    Yes, Lpcomp is good for low-power readings of pin state changes. Have you seen the documentation for the LPCOMP peripheral, and the lpcomp example in the SDK?

    also,  is it possible, and if there are some code examples, to be reading 2 analog inputs with 2 different v-- (references) (one for each input pin) ?

    We have no examples demonstrating this directly, but you may modify the lpcomp example to use the external references on pins AIN0 and AIN1.
    Since the LPCOMP is only made to monitor one pin at the time, you will have to switch between the two pins and their references, to check the levels.

    Have you considered using the SAADC with differential ended input instead of the LPCOMP?
    Depending on your application, this might be both easier to implement and more precise.

    Best regards,
    Karl

  • thanks Karl

    since i can comp (or lpcomp) only one input pin each time and to switch between them i have to go through the handler and CPU anyway the COMP option in my case doesn't really helps

    i have started working on configuring and reading the 3 inputs pin with saadc driver, it is also not so easy, for example it is not possible to do OVERSAMPLING with multiple pins (aka SCAN MODE) (i did made a small change to the NRFX_SAADC.C file to achieve just that) but actually it is still not so clear to me how to manage the 3 inputs if i want to read each one of the in a different timing and is less CPU intervention as possible (i saw the saadc example with the timer and ppi but i am not sure how to manage that with 3 inputs, i have tried to look for a way to change the configured pin with in the saadc event handler but it fail) 

    if the saadc is kind of a new topic it is possible to close this post (i am not sure how to do that)

    best regards

    Ziv

  • Hello Ziv,

    I understand. I saw your other ticket, and your workaround for using oversampling with scan mode - in order to get the correct results then you should also make sure that burst is enabled on every channel.
    As for how to manage the three inputs in the least CPU intensive way, I would have to suggest setting up three timers and connecting them to the sample task through PPI. I have not tried this myself, but I recall reading that you may have multiple events connected to the same task just fine - you could try this and see if it fits your requirements.
    In this case, you would need to discard the measurements on the channels you are not interested in at that particular time - since the SAADC in scan mode will sample every enabled channel each time.

    ziv123 said:
    if the saadc is kind of a new topic it is possible to close this post (i am not sure how to do that)

    Yes, you are right. I will close the ticket, no worries.
    Please do not hesitate to open a new ticket if you should encounter any other issues or questions in the future.

    Good luck with you development!

    Best regards,
    Karl

Reply
  • Hello Ziv,

    I understand. I saw your other ticket, and your workaround for using oversampling with scan mode - in order to get the correct results then you should also make sure that burst is enabled on every channel.
    As for how to manage the three inputs in the least CPU intensive way, I would have to suggest setting up three timers and connecting them to the sample task through PPI. I have not tried this myself, but I recall reading that you may have multiple events connected to the same task just fine - you could try this and see if it fits your requirements.
    In this case, you would need to discard the measurements on the channels you are not interested in at that particular time - since the SAADC in scan mode will sample every enabled channel each time.

    ziv123 said:
    if the saadc is kind of a new topic it is possible to close this post (i am not sure how to do that)

    Yes, you are right. I will close the ticket, no worries.
    Please do not hesitate to open a new ticket if you should encounter any other issues or questions in the future.

    Good luck with you development!

    Best regards,
    Karl

Children
  • thanks

    i will check , i have been looking through the saadc driver and HAL API, i didn't find the way to configur some of the pins to HIGH or LOW values to use the event type:

    NRF_SAADC_EVENT_CH1_LIMITH 

    NRF_SAADC_EVENT_CH1_LIMITL

    if i am to use one saadc periferial with 3 channels (for 3 input pins), i wish to use 2 of them as high/low interrupts for the analog input and one that reads the values.. can you help with giving me direction or a close example?

    also, if i use the 'app_timer' , does it changes the way i work with the ppi in the "least CPU intensive wat" asspect ?

    best regards

    Ziv

  • also i wonder what if i have 3 instances of timer that activates the saadc sample and at one point both timer call the saadc sample (read values ->oversample = time consuming) task, wouldn't that cause a problem ?

  • Hello,

    You will need to make sure that the sampling criterias in the SAADC documentation is satisfied, to ensure proper function of the SAADC. Mainly, this would be the continuous mode criteria:

     fSAMPLE < 1/[tACQ + tconv]

    and the scan mode criteria: 

    Total time < Sum(CH[x].tACQ+tCONV), x=0..enabled channels

    As for the event that multiple triggers for the SAMPLE task happens at the same time, or in close succession I do not know what the output will be, since this is undefined behavior. My guess is that one of the triggers is ignored, which will cause you to loose a sample if you are going to only extract 1 of the samples each trigger.

    ziv123 said:
    also, if i use the 'app_timer' , does it changes the way i work with the ppi in the "least CPU intensive wat" asspect ?

    I am not sure I understand what you are asking? The app timer module sets up the timer peripheral, which does not require CPU interaction after it is started. However, if it is operating in single_shot_mode, then you will need to have the CPU restart the timer every so often, for example.

    ziv123 said:
    if i am to use one saadc periferial with 3 channels (for 3 input pins), i wish to use 2 of them as high/low interrupts for the analog input and one that reads the values.. can you help with giving me direction or a close example?

    Please see the "Limits event monitoring" section of the SAADC documentation.
    As it is described there, you must set each channels limits, which will then trigger the events you mention when they are exceeded. You could use the set_limits function for this. 
    Be advised that when having limits enabled and using scan mode, the limit event will trigger every time the channel is sampled and the limits are exceeded.

    Best regards,
    Karl

  • well .. not sure i know where to go now... 

    1. if i init sampeling (  nrf_drv_saadc_sample() ) via timer1 or flage in timer 1's handler, and uninit the saadc ( nrf_drv_saadc_uninit() ) in the saadc_callback function, i can risk calling for sampeling twice if i understood your answer correctly, which is something i don't want to do if it can cause problems

    so there is no known safe solution to do the analog readings for each channel in a different period of time (for each channel, to be clear),  if i understand corrctly again

    2. where this beeing my init:

    "

    ret_code_t err_code;

    // set adc port for battery and level sensors
       nrf_drv_saadc_config_t saadc_config;
       nrf_saadc_channel_config_t channel_config0;

    //Configure SAADC
       saadc_config.resolution = NRF_SAADC_RESOLUTION_10BIT; 
       saadc_config.oversample = NRF_SAADC_OVERSAMPLE_4X; 
       saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW; //Set SAADC interrupt to low priority.
       saadc_config.low_power_mode = NRFX_SAADC_CONFIG_LP_MODE;

    //Configure SAADC channel
       channel_config0.reference = NRF_SAADC_REFERENCE_INTERNAL; 
       channel_config0.gain = NRF_SAADC_GAIN1_6; 
       channel_config0.acq_time = NRF_SAADC_ACQTIME_10US; 
       channel_config0.mode = NRF_SAADC_MODE_SINGLE_ENDED; 
       channel_config0.pin_n = NRF_SAADC_INPUT_DISABLED; 
       channel_config0.resistor_p = NRF_SAADC_RESISTOR_DISABLED; 
       channel_config0.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
       channel_config0.burst = NRF_SAADC_BURST_ENABLED;

    //Initialize SAADC
       err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
       APP_ERROR_CHECK(err_code);

       channel_config0.pin_p = IRRIGATION_LOW_LEVEL_ANALOG_SENS_PIN_IN;
       err_code = nrf_drv_saadc_channel_init(0, &channel_config0);
       APP_ERROR_CHECK(err_code);
       channel_config0.pin_p = EVACUATION_LOW_LEVEL_ANALOG_SENS_PIN_IN;
       err_code = nrf_drv_saadc_channel_init(1, &channel_config0);
       APP_ERROR_CHECK(err_code);

       channel_config0.pin_p = BATTERY_MILLI_WATT_PIN_IN;
       err_code = nrf_drv_saadc_channel_init(2, &channel_config0);
       APP_ERROR_CHECK(err_code);

    // seting limits for the analog values read of the tanks:
       nrf_drv_saadc_limits_set(1, IRRI_TANK_LOW_V_LIMIT, IRRI_TANK_HIGH_V_LIMIT);
       nrf_drv_saadc_limits_set(2, EVAC_TANK_LOW_V_LIMIT, EVAC_TANK_HIGH_V_LIMIT);


       err_code = nrf_drv_saadc_buffer_convert(adc_read_buffer[0], NUMBER_OF_ADC_SAMPLES);
       APP_ERROR_CHECK(err_code);

       err_code = nrf_drv_saadc_buffer_convert(adc_read_buffer[1], NUMBER_OF_ADC_SAMPLES);
       APP_ERROR_CHECK(err_code);

    "

    and this beeing my saadc callback (and for the moment all reading as i understand are in the same time :

    "

    static void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
      if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
      {
           // here i need to read the battery value likewise
           battery_val = (uint16_t)(((uint32_t)(p_event->data.done.p_buffer[0])*3600)/1024);
      }
      if (p_event->type == NRFX_SAADC_EVT_LIMIT)
      {
          // i need to know somehow wich pin triggered the event and if it was high limit or low limit ??? how can           i do that ??
      }
    }

    "

    i need to know somehow wich pin triggered the event and if it was high limit or low limit ??? how can i do that ?? 

    3. you wrote: "Be advised that when having limits enabled and using scan mode, the limit event will trigger every time the channel is sampled and the limits are exceeded."

    does that means that when limits enable then the saadc works all the time, or just when triggered via some timer for example? 

    will each limits event will raise the NRFX_SAADC_EVT_LIMIT event type event followed by NRF_DRV_SAADC_EVT_DONE event type ?

    also, if i want to be reading all 3 channels at the same time like that, the first channel will generate only the NRF_DRV_SAADC_EVT_DONE  event, so can i miss an event of type NRFX_SAADC_EVT_LIMIT  ? 

    sorry for so many questions but i just don't get the right way to do 1 analog value read for one pin and 2 analog limits or compares for 2 other pins .. maybe it will be better to use LPCOMP afterall, and find out how to switch the pins in each read which means CPU intervention but i don't know what other option there is

    4. can using this function

    and this 

    or this

    help to configure an event for each channel ?

    best regards

    Ziv

  • Hello Ziv,

    Do I understand you correctly that you are intending to use the one SAADC channel to read the battery voltage of the device, and the two others to compare the pin levels to a reference?
    If this is the case, you should see the Shared Resources documentation, and you might also want to have a look at this ticket(NB its for the nRF51 series).

    ziv123 said:
    1. if i init sampeling (  nrf_drv_saadc_sample() ) via timer1 or flage in timer 1's handler, and uninit the saadc ( nrf_drv_saadc_uninit() ) in the saadc_callback function, i can risk calling for sampeling twice if i understood your answer correctly, which is something i don't want to do if it can cause problems

    What I said in my last comment was that double sampling(having two PPI events trigger the SAMPLE TASK at the same time) is undefined behavior - meaning it is not specified what happens if this occurs. You could test it out and see, my guess is that one of the trigger events will be ignored(only 1 sample will occur).

    ziv123 said:
    2. where this beeing my init:

    Please use the "Insert->Code" option, to drastically increase readability.
    At first glance you code looks alright to me, but I notice that you are configuring your channels are single ended inputs - instead of double ended? From earlier I think you said you wanted to use double ended(with an external reference?).
    I also wonder whether you intend for all the 3 sampling channels to have the same configurations?
    I also note that your saadc callback seems very sparse.
    The limit event will contain both channel that triggered the event, and the type of limit that was exceeded, as can be seen here in the limit event documentation. 
    For an example on how to set up and use the battery level service(if you are intending to do so), you can see it demonstrated in the ble_peripheral proximity example.

    ziv123 said:
    i need to know somehow wich pin triggered the event and if it was high limit or low limit ??? how can i do that ?? 

     As stated in my initial comment, LPCOMP is intended for use on one pin - which means you will know which pin that triggered the event every time it happens. The challenge with using LPCOMP for multiple pins is the constant reconfiguration. Please see this ticket for further detail.

    ziv123 said:
    does that means that when limits enable then the saadc works all the time, or just when triggered via some timer for example? 

     The sampling will still only occur when the SAMPLE TASK is triggered. The limit events will trigger based on the value of the acquired sample.

    ziv123 said:
    will each limits event will raise the NRFX_SAADC_EVT_LIMIT event type event followed by NRF_DRV_SAADC_EVT_DONE event type ?

    The DONE event will occur once the sampling completes. The LIMIT events may trigger whenever a new sample is gathered, that exceeds the limits. So the order would be DONE then LIMIT. You will get an event for each channel, if there are multiple LIMIT events.

    ziv123 said:
    sorry for so many questions

     No problem at all! I am happy to help.

    ziv123 said:
    help to configure an event for each channel ?

    I would not recommend mixing HAL and driver function calls in your application, since this may unintentionally put the driver into an invalid state. What happens when you build and run the code you included above?

    Best regards,
    Karl

Related