changeset 62:ffc9292eb00b

Use edge detection to log time differences between edges
author Daniel O'Connor <doconnor@gsoft.com.au>
date Fri, 08 Jan 2021 14:06:52 +1030
parents b6dc43e6f6f0
children c90db15a497e
files logpps.py
diffstat 1 files changed, 125 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/logpps.py	Fri Jan 08 14:06:52 2021 +1030
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2021
+#      Daniel O'Connor <darius@dons.net.au>.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# Expected DB schema
+# CREATE TABLE ppslog (
+#   name TEXT,
+#   time TIMESTAMP WITH TIME ZONE,
+#   delta NUMERIC(15, 12)
+# );
+
+import datetime
+import matplotlib.pylab as pylab
+import numpy
+import psycopg2
+#import sqlite3
+import sys
+import time
+# Should try this code instead: https://github.com/python-ivi/python-usbtmc
+import usb488
+
+def main():
+    u = usb488.USB488Device()
+    print('Found device')
+
+    # See "TDS2000 Programmer.pdf"
+    res = u.ask('*IDN?')
+    print('IDN reports ' + res)
+
+    #dbh = sqlite3.connect('logpps.db')
+    dbh = psycopg2.connect('host=vm11 user=ppslog dbname=ppslog')
+    test(u, dbh, 'ncu-iono2-tx')
+
+def test(u, dbh = None, name = None):
+    if dbh != None:
+        cur = dbh.cursor()
+
+    u.write('ACQ:MODE SAMPLE')
+    u.write('ACQ:STATE STOP')
+
+    #u.write('DATA:ENC RIB')		# Big endian signed
+    #u.write('DATA:WIDTH 2')		# 2 bytes wide
+
+    vscale1 = float(u.ask('CH1:SCALE?').split()[1])
+    print(('Channel 1 scale is %.2f volts/div' % (vscale1)))
+
+    vscale2 = float(u.ask('CH2:SCALE?').split()[1])
+    print(('Channel 2 scale is %.2f volts/div' % (vscale2)))
+
+    hscale = float(u.ask('HOR:MAIN:SCALE?').split()[1])
+    print(('Horizontal scale is %.5f nsec/div' % (hscale * 1e9)))
+    # TEK2024B doesn't grok HOR:DIV? so hard code 10 (has 8 vertically)
+    acqwindow = hscale * 10.0
+
+    while True:
+        ary1, ary2 = acquire(u, vscale1, vscale2)
+        #pylab.plot(ary1)
+        #pylab.plot(ary2)
+        #pylab.show()
+        sampletime = acqwindow / len(ary1)
+        d = getpdiffedge(ary1, ary2) * sampletime
+
+        print('Delta is %.1f nsec' % (d * 1e9))
+        if dbh != None:
+            now = datetime.datetime.now()
+            cur.execute('INSERT INTO ppslog(name, time, delta) VALUES(%s, %s, %s)', (name, now, d))
+            dbh.commit()
+
+def getchannel(u, ch, vscale):
+        u.write('DAT:SOU CH%d' % (ch))	# Set the curve source to desired channel
+        result = u.ask('CURVE?', 1.0)	# Ask for the curve data
+        data1 = result[13:]		# Chop off the header (should verify this really..)
+        ary = numpy.frombuffer(data1, dtype = '>h')
+        ary = ary / 32768.0 * vscale # Scale to volts
+        return ary
+
+def acquire(u, vscale1, vscale2):
+        u.write('ACQ:STATE 1')	# Do a single acquisition
+        u.write('*OPC?')
+        u.read(2.0)	# Wait for it to complete
+
+        ary1 = getchannel(u, 1, vscale1)
+        ary2 = getchannel(u, 2, vscale2)
+
+        return ary1, ary2
+
+def getpdiffedge(ary1, ary2):
+    '''Return phase difference in samples between two signals by edge detection'''
+
+    # Rescale to 0-1
+    ary1 = ary1 - ary1.min()
+    ary1 = ary1 / ary1.max()
+    ary2 = ary2 - ary2.min()
+    ary2 = ary2 / ary2.max()
+
+    # Find rising edge of each
+    ary1pos = numpy.argmax(ary1 > 0.2)
+    ary2pos = numpy.argmax(ary2 > 0.2)
+
+    return ary1pos - ary2pos
+
+if __name__ == '__main__':
+    main()