SAADC sampling at different rates, but not simultaneously

OK, I'm working with the nRF52832 and NCS V2.6.0, and I have two different actions I need to complete at various times with the SAADC:

  1. Every ~ 3 seconds, I need to sample one ADC input (called "RMS Voltage") for 32 samples, at 312usec between each sample (I'm basically taking 32 samples of a 1/2 cycle of the 50Hz AC voltage and using that to calculate RMS voltage and do an FFT on the sampled waveform to get an idea of harmonics present on the supply).  I only need to do this measurement once every 3 seconds, so am only in this mode for 10msec every 3 sec, as this is the time it will take to get my 32 samples
  2. For the remaining time, have the SAADC sampling at maximum rate (I think this is something like 200kHz) and checking a different ADC input (called "LIMIT") to see if it is above or below limits.  I want to do this for all the time that I'm not doing the first part (so, the remaining 2.99 seconds of each 3 second cycle)

I'm just trying to get a picture of the best way of approaching this, before I spend a heap of time going down a path that isn't going to work.

Two options I'm considering are:

1. For the RMS voltage measurement, initialise the SAADC in simple non-blocking mode, then trigger the sampling using a counter and a call to nrfx_saadc_mode_trigger each time the counter callback is called (I'm actually doing it this way successfully at the moment, but haven't implemented the second part of what I need to do).  Then, when this is done, reconfigure the SAADC in advanced non-blocking mode, with the limits enabled for the LIMIT ADC input, and a buffer to store all the results its accumulating, and set it off at maximum sampling rate, using PPI to trigger the sampling to keep it going.  Then, when I come back around to the time I want to check the RMS voltage, reconfigure the SAADC back to its original setting.  Then I just cycle around this process indefinitely, switching from one configuration to the next and back again

2. Set everything up in the advanced non-blocking mode, and have the sampling being done at maximum speed on both ADC inputs simultaneously.  I'll only have the limits set and enabled for the LIMIT ADC input, and not the RMS voltage input.  Then (and I'm not sure how this would work), when it comes to doing the RMS voltage measurement, I use my 312usec counter to grab a result for the RMS Voltage ADC channel from the buffer.

There are pros and cons to both approaches as I see it:

  • The first one I can control the RMS Voltage sampling rate much more accurately, but I have to configure and reconfigure the saadc each time I want to do one measurement or the other.
  • The second one may be easier to set up and get working, but there is potential for my 312usec period to not be that accurate.  If a sample takes 10usec to aquire and convert, then I'm realistically looking at a time between samples of either 310usec or 320usec.  Not sure this will have a massive impact on the accuracy of my RMS voltage measurement to be honest.  But then I'm not sure how I identify that particular sample in the buffer that I want to use when my counter expires.  Basically, I'm not sure how the buffers are all configured in advanced mode with multiple channels (I've been looking at the advanced non-blocking with internal timer example, and its not clear from that how I expand things to cover more than one channel being sampled) and how I would know which sample in the buffer was the one at my 312usec (or, 310usec realistically) sample period.

Can anyone that's more knowledgeable about the SAADC and nrfx drivers give me a bit of guidance on which is the easiet of the two options to implement, and how I might go about setting things up?

Regards,

Mike

Parents
  • My first comment is that working with a half-cycle of an AC signal seems problematic, at least to me. Signals with frequency near or below the bandwidth of the window you've selected are not easy to analyze with FFT. Something like 5 or 6 cycles would give ~0.1 s of data to work with, and more accurate determination of the fundamental for comparison with the harmonics. 

    My second comment is that it's not clear to me that you're taking advantage of the hardware's ability to sample all the channels into a buffer using a sequence, and unpack after during processing. Sampling at 200 kHz will be much faster and noisier than you want for the "RMS Voltage" input, but you can do the averaging in software. You might find this code I wrote helpful, which does something similar, or at least related. I think we're using different drivers, however.

  •  

    Thanks for your input.  My FFT measurement isn't (or in fact doesn't need to be) anywhere near as precise as yours.  I'm only really concerned about the 3rd and 5th harmonic content of a 50Hz (or 60Hz, depending on where this thing is deployed) AC signal.

    And I believe if I'm going to use PPI, I'm forced to use the Nordic SAADC drivers, rather than the Zephyr ones.

    I've had all of this working on a Cypress IC for years, but of course with all the issues with supply chains, couldn't get any more of the IC we were using, so we took a punt and moved everything over to Nordic about 2 years ago.  I'm frantically porting all my Cypress stuff over to Nordic, which kinda explains the background of why I've been approaching this as I have - a bit of "that's how I did it before".

    Anyway, with some modification, I think your idea would be the best approach.  That is:

    1.  Sample my two channels as fast as I need to for the LIMIT channel to do what I need it to do, using PPI to trigger the SAADC in advanced non-blocking mode

    2. When I need to do an RMS voltage measurement, grab the contents of the buffers and do a bunch of averaging to get the information I need. Then do my RMS calc as per normal.

    We're pretty limited with the amount of RAM we have left, so can't just have a bunch of 2000 element buffers that we then copy over to another buffer for post-sampling processing (We're using 12 bit resolution). So we would need to be doing some processing of the info in each buffer once its filled, grab an average or something out of that, and then store that elsewhere.  One idea I did have, and I'm not sure if its going to work, is to have a dual buffer, each buffer only storing one sample for each channel, and things rapidly swapping back and forth between them as samples are collected.  Then, I can trigger an event where I save one of those samples into my 32 sample array using my Counter/Timer as I currently am.  Not sure how much overhead the buffer swapping process adds to the acquisition process and what that would mean for the maximum sampling rate I can achieve.  I'm only interested in fast sampling for the LIMIT channel, to detect when its outside my limits.  I don't actually need to know what value that channel is at any point.

    The other thing I haven't yet been able to get my head around, just looking at the saadc examples, is how to configure the buffers that are used in the NRFX_SAADC_EVT_BUF_REQ event.  I'm needing to set up a dual buffer, with however many elements for the number of samples I need to take, and for the two channels I am sampling.  I could use a bit of help understanding the mechanics of how to get that right

    Regards,

    Mike

Reply
  •  

    Thanks for your input.  My FFT measurement isn't (or in fact doesn't need to be) anywhere near as precise as yours.  I'm only really concerned about the 3rd and 5th harmonic content of a 50Hz (or 60Hz, depending on where this thing is deployed) AC signal.

    And I believe if I'm going to use PPI, I'm forced to use the Nordic SAADC drivers, rather than the Zephyr ones.

    I've had all of this working on a Cypress IC for years, but of course with all the issues with supply chains, couldn't get any more of the IC we were using, so we took a punt and moved everything over to Nordic about 2 years ago.  I'm frantically porting all my Cypress stuff over to Nordic, which kinda explains the background of why I've been approaching this as I have - a bit of "that's how I did it before".

    Anyway, with some modification, I think your idea would be the best approach.  That is:

    1.  Sample my two channels as fast as I need to for the LIMIT channel to do what I need it to do, using PPI to trigger the SAADC in advanced non-blocking mode

    2. When I need to do an RMS voltage measurement, grab the contents of the buffers and do a bunch of averaging to get the information I need. Then do my RMS calc as per normal.

    We're pretty limited with the amount of RAM we have left, so can't just have a bunch of 2000 element buffers that we then copy over to another buffer for post-sampling processing (We're using 12 bit resolution). So we would need to be doing some processing of the info in each buffer once its filled, grab an average or something out of that, and then store that elsewhere.  One idea I did have, and I'm not sure if its going to work, is to have a dual buffer, each buffer only storing one sample for each channel, and things rapidly swapping back and forth between them as samples are collected.  Then, I can trigger an event where I save one of those samples into my 32 sample array using my Counter/Timer as I currently am.  Not sure how much overhead the buffer swapping process adds to the acquisition process and what that would mean for the maximum sampling rate I can achieve.  I'm only interested in fast sampling for the LIMIT channel, to detect when its outside my limits.  I don't actually need to know what value that channel is at any point.

    The other thing I haven't yet been able to get my head around, just looking at the saadc examples, is how to configure the buffers that are used in the NRFX_SAADC_EVT_BUF_REQ event.  I'm needing to set up a dual buffer, with however many elements for the number of samples I need to take, and for the two channels I am sampling.  I could use a bit of help understanding the mechanics of how to get that right

    Regards,

    Mike

Children
No Data
Related