Extract waveform data from Siglent oscilloscope binary files
Binary .bin captures are the fastest way to move deep-memory waveforms off a scope — here is how the format works and how to convert the raw codes back into volts and seconds with Python.
Waveform data can be saved in many formats, but binary (.bin) gives the smallest files and the fastest USB/LAN transfers — essential when a capture holds millions of points. The trade-off: binary is not human-readable. This note explains the structure of Siglent's binary waveform files and how to convert the raw sample codes back into real voltages and time.
The file structure in a nutshell
- A header holds the acquisition context: which channels are on, V/div and offset per channel, timebase, trigger delay, sample rate and the code-per-division scaling
- The data section follows: one sample code per point per enabled channel (8-bit on most models, 16-bit on high-resolution scopes)
- The header layout is versioned via a
bin_head_verfield — the official spec documents every version chapter by chapter, with byte-exact offsets (e.g.ch1_vert_code_per_divat 0x268)
Always read bin_head_ver first and use the matching chapter of the spec — field offsets differ between versions, and mixing them up produces garbage waveforms that still look plausible.
The four conversion formulas
Everything you need to reconstruct the waveform comes down to four documented formulas (values from the header; examples from the spec):
sample_rate = wave_length / (hori_div_num * time_div_val) vert_offset = (ch_vert_offset - 220) * (ch_volt_div_val / pixel_per_div) time_delay = (time_offset - 349) * (time_div_val / pixel_per_div) voltage[i] = (code[i] - 128) * ch_volt_div_val / 1000 / code_per_div + vert_offset
A practical Python skeleton
import numpy as np
with open('SDS_capture.bin','rb') as f:
raw = f.read()
# 1) read header fields at the offsets for YOUR bin_head_ver (see the spec)
# e.g. vdiv, vert_offset, sample_rate, code_per_div, data_start, n_points
# 2) slice the data section and convert codes -> volts
codes = np.frombuffer(raw, dtype=np.int8, count=n_points, offset=data_start)
volts = codes.astype(float) * vdiv / code_per_div + vert_offset
t = np.arange(n_points) / sample_rate + time_delay
# 3) plot or process
import matplotlib.pyplot as plt
plt.plot(t, volts); plt.xlabel('s'); plt.ylabel('V'); plt.show()1,000,000 samples converted -> 1.00 GSa/s, CH1 50 mV/div peak-peak: 0.312 V mean: -0.0021 V
Working with a 12-bit HD scope? The data section uses 16-bit codes — read with dtype=np.int16 and the HD code-per-div value from the header. The same four formulas apply.
Get the full format specification
The complete 62-page specification — every header field, every bin_head_ver version, all unit and magnitude tables — is available as a PDF: How to Extract Data from the Binary File of SIGLENT Oscilloscope (EN03B).
With the header decoded once for your scope's format version, the actual conversion is three lines of NumPy — and binary transfers stay an order of magnitude faster than CSV for deep-memory captures.
Instruments used in this note
All current SDS series save .bin waveforms
Deep 200 Mpts captures — from €899
Related application notes
Our engineers use these instruments daily — ask us anything.