Measuring phase shift of a 10kHz analog signal: need help getting started

I'm working with a prototype sensor that changes impedance when environmental conditions change (sorry, can't provide too many details on the sensor itself).

Currently the sensor is read by generating a 10kHz sine wave, and measuring the phase difference using two fast comparators and a digital 12 bit counter with a 2MHz clock. The comparators generate a pulse on zero crossing, one starting and one stopping the counter. The sensor value is read as a 12 bit value from the counter.

I was hoping to simplify the circuit a lot with just an external sine generator, generating a 1.65V centered, 3.3V sine (single supply). And use the nRF52840 comparator to detect zero crossing (using differential mode with the negative input at 1.65V), starting a timer when the reference signal (AIN0) crosses zero, and stopping it when the sensor signal (AIN1) crosses zero. That should give me a good enough resolution. The original circuit uses a 2MHz clock, and I should be able to use the 16MHz timer.

If I understand things correctly, I need to use the comparator, PPI and timer peripherals, using PPI to route events. And that's where I get lost, the only PPI example I found is for timer to timer PPI. I'm assuming I need to set the AIN0 comparator to generate an UP event when the + input is "zero crossing" the - input set at 1.65V (my reference point for the 0 point of the 3.3V signal), and use PPI to start TimerX. Then use the UP event for AIN1 (with same reference point) to stop the timer, and store the value for further processing

Am I on the right path? Is there any guidance on how to properly initialize PPI, comparators and timer for a case like mine? I'm not expecting code, just pointers to get started and avoid going down dead ends

Parents
  • Hi,

    I think you should be on a right path, yes.

    For BLE applications: Some PPI channels and groups are reserved by the SoftDevice. Those are defined in nrf_soc.h. (The same applies for the SoftDevice Controller subsystem in nRF Connect SDK.) Also, some hardware peripherals (such as TIMER0) are restricted or blocked by the SoftDevice.

    There seems to be no pre-programmed channels that could be of any help.

    As for pointers, you are right that the PPI example itself (in nRF5 SDK) handles only the timer peripheral. The approach is however similar no matter which peripherals are involved in the PPI setup. There is use of PPI also in the GPIOTE example (examples/peripheral/gpiote/main.c) and the SAADC example (examples/peripheral/saadc/main.c). Most relevant to your project should be the source code for the capacitive sensor low-level library (components/libraries/csense_drv/nrf_drv_csense.c) which uses COMP events (although slightly differently from what you need.)

    The above assumes nRF5 SDK. If you use nRF Connect SDK, let me know and I will see what pointers we have for that one.

    Regards,
    Terje

  • Ok, I've done some more tests, and realized that there's only one COMP peripheral. So I can't do what I originally planned: use one comparator to start a timer, and another to stop it, using a different input.

    Ans the LPCOMP is shared with COMP, so no way to cheat either Slight smile

    Is there a way to use COMP on, say, AIN1 to detect an EVENTSUP and, as soon as it's detected, reconfigure COMP to now use AIN2 for the same type of event?

    I could not find a COMP library in the nRF5 SDK, so it's unclear to me how I can trigger an event handler from a COMP interrupt. 

    I managed to use PPI, COMP and timer: when COMP EVENTUP fires, I start a timer_count configured as a standard timer. Then use a different timer also with PPI to stop the timer_count and read its value. If I could use COMP instead of the second timer, I would have my working proof of concept

    I also read about the UP_STOP event, which would be helpful in speeding up the COMP reconfiguration. Use UP_STOP to start the timer using PPI, stop COMP and trigger a handler that reconfigures COMP (assuming I can do it fast enough to measure the sensor)

    What is the best way to trigger a fast interrupt handler on EVENTSUP or UPSTOP for the comparator? 

  • The CR filter is just that, a resistor feeding a capacitor to Gnd with the output at the CR junction. -3dB frequency set to (say) 10kHz gives 50% of available signal at the output. f=1/2pieCR, but very high values of R will be a problem depending on the impedance of the connected circuit being driven. Avoid polarised Tants, instead use ceramics for the capacitor.

    Maybe try 160R 100nF for 10kHz -3dB. Need to set PWM output pin to H0H1 drive levels, by the way, since driving a capacitive load

  • I wonder if the search for a zero-crossing detector is quite the optimal approach, since maybe phase offset is actually what is required. If the phase offset signal at 10kHz is slowly changing two SAADC channels can be used to sample the sine voltage over a period of time then use correlation to align in time the two phase-shifted sequences to get a measure of phase offset. Alternatively a time-shifted sample of the excitation and reference voltages can be used to calculated phase offset given the voltage difference.

    A reference time-shifted signal can also be used on a second PWM with the time-shift adjusted until the sensor output and the reference are time-aligned, then the time-shift indicates the phase difference.

    With a slow phase-difference change from the sensor note comparators could still be used, simply switch the comparator from one pin to the other every other 10kHz cycle.

    // Read Mode: Digital Counter Input or ADC or Comparator
    // =====================================================
    //                                                                       +--------------------
    //                                                                       |    VDD
    //   CR = 10kHz or higher, 150R optional                                 |   --#--
    //                                                                       |     |
    //                                                                       |     |
    //                                  +------+                             |     +-|
    //   +---------#--------------------[ 150R ]-----+                       |       |--+
    //   |         |                    +------+     |                       |     +-|  |
    //   |         |                    +------+     |                       |     |    |
    //   |         |       #--------#---[ 150R ]-----#-----------------------O-----#    0<-- P0.nn from PWM
    //   |         |       |        |   +------+                             |     |    |    H0H1 Output
    //   |         |       |        |                                        |     +-|  |
    //   |         |       |        |                                        |       |--+
    //   |    100nF|  100nF|        |                                        |     +-|
    //   |       -----   -----      |                                        |     |
    //   |       -----   -----      |                                        |     |
    //   |         |       |        |                                        |   =====
    //   |         |       |        |          (Dummy)                       |    ===
    //   |       =====   =====      |         +--------+                     |     =
    //   |        ===     ===       |         |        |  (Reference)        |                        Optional
    //   |         =       =        +---------0        0---------------------O-----#-------------#--> P0.nn ADC
    //   |                                    |        |                     |     |             |          Ref = VDD (Ratiometric)
    //   |                                    |        |                     |     +-|           |          or COMP
    //   |                                    |        |                     |       |<- P0.n  -----        or Digital Counter
    //   |Excitation                          +--------+                     |     +-|         -----
    //   |10kHz Sine                                                         |     |             |
    //   |                                                                   |     |             |
    //   |                                                                   |   =====         =====
    //   |                                                                   |    ===           ===
    //   |                                                                   |     -             -
    //   |                                                Sensor Excitation  |
    //   +-------------------------------------------------------------------O-----#-------------#--> P0.nn ADC
    //   |                                                                   |     |             |          Ref = VDD (Ratiometric)
    //   |                                                                   |     +-|           |          or COMP
    //   |                                                                   |       |<- P0.n  -----        or Digital Counter
    //   |                                                                   |     +-|         -----
    //   |                                                                   |     |             |
    //   |                                                                   |     |             |
    //   |                                                                   |   =====         =====
    //   |                                                                   |    ===           ===
    //   |               Unknown                                             |     =             =
    //   |               Sensor                                              |
    //   |              +--------+                                           |
    //   |              |        |                        Sensor Signal      |
    //   *--------------0        0-------------------------------------------O-----#-------------#--> P0.nn ADC
    //                  |        |                                           |     |             |          Ref = VDD (Ratiometric)
    //                  |        |                                           |     +-|           |          or COMP
    //                  |        |                                           |       |<- P0.n  -----        or Digital Counter
    //                  +--------+                                           |     +-|         -----
    //                                                                       |     |             |
    //                                                                       |     |             |
    //                                                                       |   =====         =====
    //                                                                       |    ===           ===
    //                                                                       |     =             =
    //                                                                       |
    //                                                                       +----------------------------------
    

    The FET drivers in the nRF52 have a finite resistance; in principle the external resistors could be left out by adjusting the capacitance to give a clean signal relying on that internal FET resistance.

    Low-level drivers would be preferred instead of the Nordic libraries for optimal performance.

  • If the phase offset signal at 10kHz is slowly changing two SAADC channels can be used to sample the sine voltage over a period of time then use correlation to align in time the two phase-shifted sequences to get a measure of phase offset.

    I actually did think about that as my first approach, but the SAADC of the nRF52840 is too slow for such an approach (200ksps) and the sensor resolution would be 10x lower than the current analog circuit using fast comparators to detect zero crossing with a 2MHz clock. Also, in my experience, SAADC noise would make the correlation even lower resolution than the theoretical 200kHz. Given that the sensor won't change impedance quickly, I could average over multiple values to reduce noise, but I still think it would be computationally intensive for no real value over zero crossing detection and a timer

    A reference time-shifted signal can also be used on a second PWM with the time-shift adjusted until the sensor output and the reference are time-aligned, then the time-shift indicates the phase difference.

    With a slow phase-difference change from the sensor note comparators could still be used, simply switch the comparator from one pin to the other every other 10kHz cycle.

    Oooh, clever. This is a really interesting idea, need to mull this over, thanks!

  • I think you may be asking the wrong question in terms of a PWM sine wave, but more of that anon. Here is the error with the 40-step PWM spoofing a 'scope with 10x sampling (160MHz of the 10kHz signal):

    Note the error is worst at the point of most interest.

    Returning to my earlier comment, PWM sine waves are often generated with a constant sampling interval, constant in terms of time as they are often derived from a periodic timer, however a better curve fit can be generated by using a constant amplitude interval. For (say) 40 samples for one cycle that means 10 intervals per quadrant, and arcsin(step) as the  time increment. A little awkward with this PWM as we can't change the underlying clock frequency but can change the repeat interval COUNTERTOP. This was my back-of-envelope spreadsheet waveform, which may well be promising:

    So what question might give a better answer? It depends on the unknown sensor, but purity of the sine wave is (probably) only critical near the zero-crossing points, as that is all that is actually used for the sample. So - and as this figure shows - it might be better to cuddle up more samples around the zero-crossings.

  • .. and of course I forgot to add the promising addition that might help, and now can't edit the response. Anyway note the error could be reduced by adding a second output pin. That could be done using two PWM peripherals but may as just use a second output on the same PWM as the clock signal would be the same in both cases 16MHz with no phase shift. This won't help unless the two output pins are combined with a (small) phase shift and amplitude attenuation on the correction phase. You might get away with simply using 150R 100nF on the primary output pin and connect a larger value resistor from the second output pin to the same capacitor; larger is try-it-and-see, but maybe 820R as it will both introduce a phase shift and attenuate the error signal. Worst-case use a potential divider on the error signal; the curve looks like 10% error so maybe attenuate by 10. I don't recall actually trying this ..

    The other point is that the secret sensor may not be ground-referenced in which case instead of using a half-bridge PWM (single pin) a full-bridge PWM (two pins) could be used with the second pin a simple table-inversion of the first pin. With full-bridge error-correction that would then require 4 pins but only 4 resistors and a single capacitor. Full-bridge doubles the excitation voltage on the sensor, which in turn compensates for the attenuation caused by the CR filter.

Reply
  • .. and of course I forgot to add the promising addition that might help, and now can't edit the response. Anyway note the error could be reduced by adding a second output pin. That could be done using two PWM peripherals but may as just use a second output on the same PWM as the clock signal would be the same in both cases 16MHz with no phase shift. This won't help unless the two output pins are combined with a (small) phase shift and amplitude attenuation on the correction phase. You might get away with simply using 150R 100nF on the primary output pin and connect a larger value resistor from the second output pin to the same capacitor; larger is try-it-and-see, but maybe 820R as it will both introduce a phase shift and attenuate the error signal. Worst-case use a potential divider on the error signal; the curve looks like 10% error so maybe attenuate by 10. I don't recall actually trying this ..

    The other point is that the secret sensor may not be ground-referenced in which case instead of using a half-bridge PWM (single pin) a full-bridge PWM (two pins) could be used with the second pin a simple table-inversion of the first pin. With full-bridge error-correction that would then require 4 pins but only 4 resistors and a single capacitor. Full-bridge doubles the excitation voltage on the sensor, which in turn compensates for the attenuation caused by the CR filter.

Children
Related