Semi fast ADC w/ timestamp at 200-400SPS

Hello,
I am interested in using the BBB to monitor a sensor (geophone) at about 200-400sps. I am currently using the Adafruit_BBIO.ADC library to do this in Python. Ultimately, there are two goals for this project, and I would love some input on how to approach this.

  1. Time stamp when the input voltage reaches 0.5v - The geohone is generating a sine wave, the stronger the vibration/movement of the geophone, the higher the amplitude/voltage of the signal is produced. I would hope to accurately place a timestamp at the exact moment the voltage crossed that threshold. As far as timing goes, I am using onboard GPS with 1 PPS output and Chrony for sync.

  2. I also have a contact closure that I would like to monitor. Right now, I am pushing 1v through the closure, and monitoring the ADC for a voltage change from 0v to 1v, then applying a timestamp. Any thoughts here?

I have read about the PRU on the BBB and am wondering if that is what I need to be using to obtain sub millisecond accuracy on my timestamp. Any thoughts here?

Thanks!

On Fri, 31 Aug 2018 08:35:06 -0700 (PDT),
tremmert@lonestartracking.com declaimed the
following:

Hello,
I am interested in using the BBB to monitor a sensor (geophone) at about
200-400sps. I am currently using the Adafruit_BBIO.ADC library to do this
in Python. Ultimately, there are two goals for this project, and I would
love some input on how to approach this.

1) Time stamp when the input voltage reaches 0.5v - The geohone is
generating a sine wave, the stronger the vibration/movement of the
geophone, the higher the amplitude/voltage of the signal is produced. I
would hope to accurately place a timestamp at the exact moment the voltage
crossed that threshold. As far as timing goes, I am using onboard GPS with
1 PPS output and Chrony for sync.

  At 400 samples/second you have 2.5msec between samples (and a whopping
5msec at 200 samples/second). The only way I see to get more precise timing
would be to interpolate the crossing point of two samples (one before the
threshold, the other immediately after threshold crossing) and also
interpolate the timestamps of those samples. I don't know the resolution of
the BBB OS clock -- time.time, time.clock, and datetime module are likely
limited to the OS clock.
https://www.pythoncentral.io/measure-time-in-python-time-time-vs-time-clock/
time.clock may not be appropriate since it is not wall-clock time on
Linux/UNIX (also not the caveat -- if you have something else that adjusts
the system clock backwards, you'll get anomalous times.

  You don't state the frequency of the sine wave; if it is faster than
100Hz you may fall afoul of Nyquist sampling theory. Rectifying and
filtering the sine wave to produce a DC voltage may be advisable.

2) I also have a contact closure that I would like to monitor. Right now,
I am pushing 1v through the closure, and monitoring the ADC for a voltage
change from 0v to 1v, then applying a timestamp. Any thoughts here?

  Push it to 3.3V (level shifter?) and use a regular GPIO -- then setup
add_event_detect for rising edge with a callback function to create the
timestamp. You can also provide a debounce time for the switch before it
activates the callback. (wait_for_event will probably block your ADC
reading unless you put it into a separate thread -- but that then limits
your timing to the Python interpreter thread switching logic.

Sub millisecond time resolution can’t be done from user space. My own experiments using the Beaglebone’s built-in A/D converter to make voltage measurements from a user-space program show sampling time jitter of around 5ms. This is OK for doing measurements of a slowly varying or DC signal, but is not good for doing anything approaching audio speeds.

One possibility for you is to use the ADC-001, which is a sampling A/D designed for audio and DSP applications. More information about it is here:

https://elinux.org/ADC-001

It is an open hardware project, so schematics, driver, and several example codes are available for download. Drawbacks for you are the code is in C, and the low-frequency cut-off of the circuit is 50Hz. Of course, you can always learn C, and if you’re adept at electronics you can easily modify the board to work down to DC.

Full disclosure: I am the ADC-001 designer, so I am always interested in seeing people use it.

Stuart

Hi!

Hello,
I am interested in using the BBB to monitor a sensor (geophone) at about 200-400sps. I am currently using the Adafruit_BBIO.ADC library to do this in Python. Ultimately, there are two goals for this project, and I would love some input on how to approach this.

  1. Time stamp when the input voltage reaches 0.5v - The geohone is generating a sine wave, the stronger the vibration/movement of the geophone, the higher the amplitude/voltage of the signal is produced. I would hope to accurately place a timestamp at the exact moment the voltage crossed that threshold. As far as timing goes, I am using onboard GPS with 1 PPS output and Chrony for sync.

libpruio is designed for such tasks. Use it in MM mode (MeasureMent mode). Up to four triggers can be set to specify the sampling start. Even pre-triggers are possible. See http://users.freebasic-portal.de/tjf/Projekte/libpruio/doc/html/_cha_features.html#SubSecTriggers for details.

When measurement starts, the value of AdcUdt::DRam[1] drops down to 0 (zero). So by monitoring that value you can generate a timestamp with Python accuracy. If this isn’t accurate enough, you could use the other PRU just for the timestamp.

Next version 0.6 will ship with Python bindings and example sources.

  1. I also have a contact closure that I would like to monitor. Right now, I am pushing 1v through the closure, and monitoring the ADC for a voltage change from 0v to 1v, then applying a timestamp. Any thoughts here?

Since version 0.4 libpruio can handle GPIO input in MM mode. Ie configure a pulled-up GPIO-input and groud the pin by your closure. (You can also continue with ADC input, but in MM mode the data evaluation has to be done after the measurement.)

Regards

TJF,
This is absolutely AWESOME! What a great library! I am just now reading through the documentation and reviewing your recommendations but have a question… I plan on utilizing a GPIO pin and setting up MM mode and monitoring AdcUdt::DRam[1]. How do you recommend I monitor AdcUdt::DRam[1]? Just setup a loop in python or do you recommend another method? Basically I need to put a timestamp at the leading edge of the input.

Thanks!

Thanks for feedback! And sorry for my mistake: replace AdcUdt::DRam[1] by PruIo::DRam[1]!

It’s not that easy. The call to PruIo::mm_start() waits for the end of the measurement. You have to cover that call in one thread and use another thread to monitor PruIo::DRam[1] for your timestamp.

Find example code in triggers.bas (sorry, FreeBASIC only).

Regards