LoginSignup
1
0

More than 1 year has passed since last update.

OWON VDS3104 をpythonで制御 (その4)

Posted at

前回までで、OWON の USBオシロスコープ VDS3104(LAN無しモデル) をpythonで制御することができるようになりました。私にとって、VDS3104の一番の不満点は波形のズーム機能がまともに使えないことです。そこで、VDS3104から保存したバイナリーデータを解析して、matplotlibで表示するようにしてみました。

データ解析

何パターンかのデータをバイナリーエディターで眺めてみて、データフォーマットが分かってきましたので、下記のデータ解析クラスを作りました。コード中、d0~d8、およびstruct.unpackのパデング(x)にした部分のデータが今のところ謎なのですが、とりあえず、表示に必要な項目はわかりました。

vdsDat.py
import struct

TBScales = [float(str(a)+'e'+str(b)) for b in range(-9,3) for a in [1,2,5]][1:34]
VScales = [float(str(a)+'e'+str(b)) for b in range(-3,1) for a in [1,2,5]][1:12]

class vdsDat:
    sizHed = 32 #ヘッダーのサイズ
    sizChI = 67 #チャネル情報(1ch分)のサイズ
    sizTbI = 27 #タイムベース情報のサイズ
    class chInfo:
        def __init__(self, src):
            self.dat = src
            name, self.sizInfo, self.inv, d0, self.samplesPerScreen, d1, d2, d3, d4, \
             self.sizDat, d6, self.vOffset, self.scaleCode, self.probeRateCode, d7, d8, self.ofsDat \
             = struct.unpack('>3s16i', src)
            self.name = name.decode()
            self.probeRate = 10**self.probeRateCode
            self.scale = VScales[self.scaleCode] * self.probeRate
            self.VPP = self.scale / 25

    def __init__(self, src):
        self.header = src[0:self.sizHed]
        model, self.sizFile, self.sizDat = struct.unpack('>10s13x1i1x1i', self.header)
        self.model = model.decode

        pt = self.sizHed + self.sizDat  #データポインター
        self.tbInfo = src[pt:pt+self.sizTbI]
        self.tbScaleCode, self.tbOffset, self.sizChIs = struct.unpack('>17x1b1i3x1H', self.tbInfo)
        self.tbScale = TBScales[self.tbScaleCode]
        self.numCh = self.sizChIs // self.sizChI
        pt += self.sizTbI
        self.chI = [self.chInfo(src[p:p+self.sizChI]) for p in range(pt, pt+self.sizChIs, self.sizChI)]

        self.sizChD = self.sizDat // self.numCh
        pt = self.sizHed
        f = str(self.sizChD) + 'b'
        self.chDat = [struct.unpack(f, src[p:p+self.sizChD]) for p in range(pt, pt + self.sizDat, self.sizChD)]

matplotlibで表示

vds_datPlot.py
import sys
import matplotlib.pyplot as plt
import numpy as np
from vdsDat import *

pltColor = {
    'CH1' : 'red',
    'CH2' : 'orange',
    'CH3' : 'blue',
    'CH4' : 'purple'
}

if __name__ == '__main__':
    srcFile = sys.argv[1]
    with open(srcFile, 'rb') as f:
        srcDat = f.read()
        dat0 = vdsDat(srcDat)
        unitTime = 20 * dat0.tbScale / dat0.chI[0].samplesPerScreen
        xmin = unitTime * (dat0.chI[0].samplesPerScreen * dat0.tbOffset / 1000  - dat0.chI[0].sizDat / 2)
        xmax = unitTime * dat0.chI[0].sizDat + xmin
        xax = np.arange(xmin, xmax, unitTime)

        fig, ax = plt.subplots(2, 1, sharex = True)
        for chi, chd in zip(dat0.chI, dat0.chDat):
            name = chi.name
            ax[0].plot(xax, chd, label=name, color=pltColor[name])
            dat = (np.array(chd) - chi.vOffset) * chi.VPP
            ax[1].plot(xax, dat, label=name, color=pltColor[name])
        ax[0].legend(loc='upper right')
        ax[0].set_xlim(xmin, xmax)
        ax[0].set_ylim(-128, 127)
        plt.show()

この例では、上にオシロの画面に近いイメージ、下に電圧に換算した値をプロットしてみました。
image.png

これだけでも、matplotlibの機能を使って気になるところをズームして見られるので便利です。
image.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0