Jump to content
  • 0

Python digital continuous record (AD2/DD)


Piotr Rzeszut

Question

Hi,

Using python script I want to constantly collect digital data form 6 lines (so 8 lines would be sampled) with a rate of 1MSPS, with transfer to the PC.

I have read:

 

And I am not sure if I should use record mode with data compression or scan screen mode.

I suppose record mode would be best, but I don't know how to set unlimited number of samples for digital record (there is no function FDwfAnalogInRecordLengthSet for Digital inputs), as the only method to set number of samples is calling dwf.FDwfDigitalInTriggerPositionSet and dwf.FDwfDigitalInTriggerPrefillSet...

At the other hand, will scan screen mode allow the sample rate of 1MSPS to be transmitted to PC?

I would be grateful for any suggestions @attila. I have searched through the forum but only found mentioned discussion and some materials related to analog acquisition....

 

Link to comment
Share on other sites

4 answers to this question

Recommended Posts

Hi @Piotr Rzeszut 

See the following script: DigitalIn_Record2.py

Without trigger or pre-trigger data there is no need to align the data.
The data compression will be only applied with Analog Discovery and EExplorer boards which have less device buffer.
The noticed glitches are due to the jitter of asynchronous domains between the generator and acquisition device, or difference between rise and fall times. When the bus is captured exactly, at nano or picosecond timing on transition, like a 0x3F transition to 0x40, it might be captured as 0x7F, 0x6A, 0x52, 0x4E....

image.png.5fe8849463a42015198baab7b2e1a308.png

Link to comment
Share on other sites

Well, I figured out somehow following code:

"""
   DWF Python Example
   Author:  Digilent, Inc.
   Revision: 11/24/2014

   Requires:
       Python 2.7, numpy,
"""
from ctypes import *
from dwfconstants import *
import math
import sys
import time
import matplotlib as mpl
import matplotlib.pyplot as plt

if sys.platform.startswith("win"):
    dwf = cdll.dwf
elif sys.platform.startswith("darwin"):
    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
else:
    dwf = cdll.LoadLibrary("libdwf.so")

# declare ctype variables
hdwf = c_int()
sts = c_byte()
cdevices = c_int()
devicename = create_string_buffer(64)

# print DWF version
version = create_string_buffer(16)
dwf.FDwfGetVersion(version)
print "DWF Version: " + version.value

#enumerate and print device information
#4 for AD2
dwf.FDwfEnum(c_int(0), byref(cdevices))
print "Number of Devices: "+str(cdevices.value)

# open device
print "Opening device:"
for i in range(0, cdevices.value):
    dwf.FDwfEnumDeviceName (c_int(i), devicename)
    if devicename.value == "Digital Discovery":
        dwf.FDwfDeviceOpen(c_int(i), byref(hdwf))
        print "\t", i, " : ", devicename.value

if hdwf.value == hdwfNone.value:
    print "failed to open device"
    quit()

print "Configuring Digital Out / In..."

dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(1), c_double(3.3))
time.sleep(0.1)

dwf.FDwfDigitalInReset(hdwf)
#dwf.FDwfDigitalOutReset(hdwf)
dwf.FDwfDigitalInInputOrderSet(hdwf, c_bool(False))

# generate counter
#for i in range(0, 8):
#    dwf.FDwfDigitalOutEnableSet(hdwf, c_int(i), c_int(1))
#    dwf.FDwfDigitalOutDividerSet(hdwf, c_int(i), c_int(1 << i))
#    dwf.FDwfDigitalOutCounterSet(hdwf, c_int(i), c_int(1000), c_int(1000))

#dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))



# set number of sample to acquire
nSamples = 200000
rgwSamples = (c_uint8 * nSamples)()
cAvailable = c_int()
cLost = c_int()
cCorrupted = c_int()
iSample = 0
fLost = 0
fCorrupted = 0

# in record mode samples after trigger are acquired only
dwf.FDwfDigitalInAcquisitionModeSet(hdwf, acqmodeRecord)
# sample rate = system frequency / divider, 100MHz/100 = 1MHz
dwf.FDwfDigitalInDividerSet(hdwf, c_int(100))
# 16bit per sample format
dwf.FDwfDigitalInSampleFormatSet(hdwf, c_int(8))
# number of samples after trigger
dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(0))  # 50%
# number of samples before trigger
dwf.FDwfDigitalInTriggerPrefillSet(hdwf, c_int(1))
# enable data compression by select used lines
dwf.FDwfDigitalInSampleSensibleSet(hdwf, c_int(0x00FF))
# trigger when all digital pins are low
dwf.FDwfDigitalInTriggerSourceSet(hdwf, trigsrcNone)
# trigger detector mask:                  low &   hight & ( rising | falling )
# dwf.FDwfDigitalInTriggerSet(hdwf, c_uint(0xFFFF), c_uint(0), c_uint(0), c_uint(0))


# begin acquisition
dwf.FDwfDigitalInConfigure(hdwf, c_bool(1), c_bool(1))

print "Starting record"

mpl.rcParams['toolbar'] = 'None'
ax1 = plt.gca()


while True:
    dwf.FDwfDigitalInStatus(hdwf, c_int(1), byref(sts))
    dwf.FDwfDigitalInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))

    iSample += cLost.value
    iSample %= nSamples

    if cLost.value:
        fLost = 1
    if cCorrupted.value:
        fCorrupted = 1

    iBuffer = 0
    while cAvailable.value > 0:
        cSamples = cAvailable.value
        # we are using circular sample buffer, make sure to not overflow
        if iSample + cAvailable.value > nSamples:
            cSamples = nSamples - iSample
        dwf.FDwfDigitalInStatusData2(hdwf, byref(rgwSamples, iSample), c_int(iBuffer), c_int(cSamples))
        iBuffer += cSamples
        cAvailable.value -= cSamples
        iSample += cSamples
        iSample %= nSamples
        #print sts.value, " ", iSample

    if sts.value == DwfStateDone.value:
        break

    if not plt.get_fignums():
        print "CLOSED"
        break

    ax1.clear()
    ax1.plot(rgwSamples)
    plt.pause(0.0001)

dwf.FDwfDeviceClose(hdwf)

print "Recording finished"
if fLost:
    print "Samples were lost! Reduce sample rate"
if cCorrupted:
    print "Samples could be corrupted! Reduce sample rate"

f = open("record.csv", "w")
for i in range(0, nSamples):
    iAlign = (i + iSample) % nSamples  # first sample in our buffer is at iSample index
    f.write("%s\n" % rgwSamples[iAlign])
f.close()



But quite often I get reading with nasty glitches:

image.png.2df072f6150692e603392ae9401d8ad4.png

The signal is generated using Analog Discovery 2. For a connection I am using High-speed inputs 0..7 of DD and DIO 0..7 for AD2.

Configuration of AD2:

image.png.91573dd765042fa40eba62877f31cfb9.png

Link to comment
Share on other sites

Hi @attila,

Thank you for your answer. 

In my next attempts I have removed aligning of the data, and achieved the same using following settings:

# number of samples after trigger
dwf.FDwfDigitalInTriggerPositionSet(hdwf, c_int(0))
# number of samples before trigger
dwf.FDwfDigitalInTriggerPrefillSet(hdwf, c_int(1))

It would be nice to include information what effect have setting one of these parameters to 0 or -1 in the documentation.

The explanation of the glitches is very clear, as we are running devices with separate clock domains without any synchronization stages - it turned out to be very nice demonstration of the effect ;)

Link to comment
Share on other sites

Hi @Piotr Rzeszut

The prefill is used for record with trigger to make sure at last the required number of samples are collected before arming, before looking for trigger event.
With prefill 0 the recording process will stream data only after trigger event.
With prefill more than zero the data will be streamed until trigger occurs plus the number of samples specified by trigger position.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...