Data logging with an Analog Discovery 3 on a Mac

WaveForms runs natively on Apple Silicon, and its Record mode streams an Analog Discovery 3 well past the 32,768-sample buffer, at up to about 5 MS/s total to disk.

Britt Espinosa··6 min read

The Digilent Analog Discovery 3 is a USB-C instrument with a two-channel oscilloscope, a two-channel waveform generator, power supplies and 16 digital I/O. Its scope is built for short, fast captures. Logging means minutes or hours of data on disk at a modest rate with nothing dropped, and the AD3 can do it from a Mac if you pick the right capture mode and stay inside Digilent’s published limits.

WaveForms on macOS and Apple Silicon

WaveForms, Digilent’s free software for the Discovery line, comes as a .dmg that you drag into Applications. It contains the WaveForms application, the WaveForms Runtime (the library and device support files) and the WaveForms SDK. If macOS blocks the first launch, click Open Anyway in Privacy and Security settings.

WaveForms 3.25.1 (March 2026) ships as one Universal installer for Intel and Apple Silicon Macs running macOS 12 or later. Digilent staff have said on the support forum that the runtime libraries are universal and the SDK works from x86_64 and arm64 applications, so a native arm64 Python can load the SDK library directly. Older releases ran under Rosetta 2, so check which version you have.

The numbers that set your limits

From Digilent’s published specifications:

Analog Discovery 3Analog Discovery 2
Scope channels2, differential2, differential
Resolution14-bit (16-bit with averaging)14-bit
Max sample rate125 MS/s per channel100 MS/s
BufferUp to 32,768 samples per channel (65,536 with one channel)Up to 16k samples per channel (8k in the default configuration)
Input ranges±2.5 V and ±25 V±25 V
Input impedance1 MΩ ‖ 24 pF1 MΩ ‖ 24 pF
Bandwidth (−3 dB)9 MHz with flywires, 30+ MHz with the BNC adapter9 MHz with flywires, 30+ MHz with the BNC adapter
Record modeUp to ~10 MS/s total to RAM, ~5 MS/s total to diskAbout 1 to 2 MHz to file, per Digilent support

At the full 125 MS/s, 32,768 samples is 262 µs of signal, and at 100 kS/s it is 0.33 s. Anything longer has to stream to the computer while the capture runs.

The AD3’s ADC runs at the system clock, which is adjustable from 50 to 125 MHz, and WaveForms averages or decimates down to the rate you ask for. Digilent specifies 15-bit resolution at half the system frequency and 16-bit at a quarter or below, so a logging run at 100 kS/s gets more effective resolution than a 125 MS/s capture.

Capture modes in WaveForms

Scope, Repeated or Single

The normal scope modes fill the device buffer and transfer it. Each capture is limited to the buffer and nothing is recorded between captures, so these modes are for viewing waveforms, not logging.

Scope, Record mode

Record mode streams samples continuously to the host, either into the Mac’s RAM or straight to a file using the Rec. button next to Export. Digilent’s AD3 specs put the ceiling at about 10 MS/s total to RAM and about 5 MS/s total to disk, and note that the achieved rate depends on the host computer. The totals cover both channels together, so two channels to disk is about 2.5 MS/s each. Use Record mode when you need the raw waveform later, for power-up transients over several seconds, vibration, audio-band signals or anything you might FFT.

Logger

The Logger instrument takes over both scope channels while it runs and records values computed from short windows of scope data, such as DC, AC or RMS level, at slow rates, such as a supply rail’s DC level over a day or an RMS level once a second. It discards the underlying waveform, so if you may need to see what happened between log points, use Record mode at a modest rate instead.

Plan the file size before a long run

One channel at 1 MS/s for an hour is 3.6 billion samples, which is 7.2 GB as 16-bit integers and several times that as CSV text. The DAQ file size calculator runs these numbers for any rate, channel count and format. For long runs, pick the lowest rate that captures your signal with margin (the sample rate calculator helps) and export to a binary format. The formats are compared in choosing a file format for test data.

Recording from Python with the WaveForms SDK

The SDK is a C library (dwf.framework on macOS, dwf.dll on Windows, libdwf.so on Linux) that Digilent’s Python samples load with ctypes. This script follows Digilent’s record sample. It sets record mode and a fixed length in seconds, then loops, pulling whatever is available and counting lost and corrupt samples. Close WaveForms first, since only one program can hold the device.

import time
from ctypes import *
dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")  # macOS
hz, seconds = 100e3, 60.0
n = int(hz * seconds)
buf = (c_double * n)()
hdwf, sts = c_int(), c_ubyte()
avail, lost, corrupt = c_int(), c_int(), c_int()
if not dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf)):
    raise SystemExit("No device found (is WaveForms still open?)")
dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_int(1))
dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(5.0))  # 5 V p-p range
dwf.FDwfAnalogInAcquisitionModeSet(hdwf, c_int(3))       # acqmodeRecord
dwf.FDwfAnalogInFrequencySet(hdwf, c_double(hz))
dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(seconds))  # -1 = no limit
time.sleep(2)                      # let the input offset settle
dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
got, bad = 0, 0
while got < n:
    dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
    if got == 0 and sts.value in (1, 4, 5):    # Armed, Config, Prefill
        continue
    dwf.FDwfAnalogInStatusRecord(hdwf, byref(avail), byref(lost), byref(corrupt))
    got += lost.value              # keep the timeline honest across gaps
    bad += lost.value + corrupt.value
    k = min(avail.value, n - got)
    if k > 0:
        dwf.FDwfAnalogInStatusData(hdwf, c_int(0), byref(buf, 8 * got), c_int(k))
        got += k
dwf.FDwfDeviceClose(hdwf)

Nonzero lost or corrupt counts mean the host didn’t pull data fast enough and the device buffer overflowed. The recording has a gap there even though the sample count looks right. Lower the rate, record fewer channels, or move file writing to a separate thread so this loop only drains the device. Sixty seconds at 100 kS/s held as doubles is 48 MB, so for longer runs write each block to disk as it arrives. Python data acquisition across vendors shows that pattern.

Pitfalls on the bench

  • Range. The AD3 has two input ranges, and WaveForms picks between them from the volts-per-division setting. At 0.5 V/div and below you get the ±2.5 V range, with 0.336 mV absolute resolution and ±10 mV ±0.5% accuracy. Above that you get ±25 V, with 3.36 mV resolution and ±100 mV ±0.5%. A small signal logged on the wrong scale loses a factor of ten in resolution. In the SDK, a range of 5 selects the low range and 50 the high one.
  • Differential inputs. On the flywire header each scope channel has a positive and a negative input. For a single-ended measurement, Digilent’s advice is to connect the negative input to ground. A floating negative lead gives readings that wander.
  • Input impedance. 1 MΩ in parallel with 24 pF loads high-impedance sources. A divider made of 1 MΩ resistors will read noticeably low. Use a 10x probe through the BNC adapter or buffer the signal.
  • Overvoltage. Protection is rated ±50 V DC or ±30 V RMS, so keep the inputs off mains circuits.
  • USB bandwidth and power. The AD3 uses USB 2.0 data rates, so the Record mode ceilings above are shared with anything else on the same bus. Digilent also specifies that a USB-A host port must supply USB 3.2-level power when you aren’t using the auxiliary supply, so use a USB 3 port or the external supply, not a passive hub.
  • Sleep. A Mac that sleeps mid-run ends the recording. Start long captures with the lid open on power, or run caffeinate -i in Terminal for the duration.

DAQAtlas, which is in development, loads the WaveForms SDK to record the Analog Discovery 3 and Analog Discovery 2 alongside other bench hardware. The beta list is open.