rheslip / PyDSA

Spectrum Analyzer for the Rigol DS1000 series oscilloscopes
131 stars 37 forks source link

Getting code working for DS1054Z on Windows 7 64bit #1

Open kerrsmith opened 8 years ago

kerrsmith commented 8 years ago

I have got the code partially working on my DS1054Z. I can see the waveform displayed on the screen but it does not continually update, it only updates when I push the run/stop button on the scope.

Below is what I have done to get it this far on Windows 7 64bit:

I first installed the latest National Instruments VISA runtime:

http://www.ni.com/download/ni-visa-run-time-engine-15.0/5379/en/ NIVISA1500runtime.exe

Next I installed Python 2.7 making sure Python was added to the path (this is so you can run python from the command line from any directory):

https://www.python.org/downloads/release/python-2711/ python-2.7.11.amd64.msi

Next I updated pip and setuptools as well as installing wheel as recommend on: http://python-packaging-user-guide.readthedocs.org/en/latest/installing/#install-pip-setuptools-and-wheel python -m pip install -U pip setuptools pip install wheel

I now updated mock as I could not get any further due to an error (on next step) saying 'Requires setuptools >=17.1 to install properly', the following fixed this issue and seemed to update a couple of other things as well:

pip install mock

Next I installed pyvisa version 1.4 as recommend (the mock update above made this work):

pip install pyvisa==1.4

Next I installed numpy, this initially did not work and showed this 'error: Unable to find vcvarsall.bat', so I installed the Microsoft Visual C++ Compiler for Python 2.7:

https://www.microsoft.com/en-gb/download/details.aspx?id=44266 VCForPython27.msi

Now numpy installed, it took a while as it needed to compile and there was no real progress update so I just left it and after a few minutes it finished and said it had installed.

pip install numpy

Next I downloaded the PyDSA code from Github:

https://github.com/rheslip/PyDSA

The file to run is in the PyDSA directory and is called PyDSA.py

Now the code needed to be altered, I used policeman0077's code to get started (see above comments) and made a few changes as this initially would not work for me:

Below is my working code so far, the changes occur in the 'Main Routine' function after line 612, run the code as follows:

python PyDSA.py

In order for it to work for me I set the trigger on the scope to AC, with the scope stopped I start the program and then after a second or two I press the run/stop button (even though it is now green and scope says triggered), now a wave form appears on the program's display. It does not automatically update but does update once if I press the run/stop button again.

============================================ Main routine ====================================================

def Sweep(): # Read samples and store the data into the arrays global X0L # Left top X value global Y0T # Left top Y value global GRW # Screenwidth global GRH # Screenheight global SIGNAL1 global RUNstatus global SWEEPsingle global SMPfftlist global SMPfftindex global SAMPLErate global SAMPLEsize global SAMPLEdepth global UPDATEspeed global STARTfrequency global STOPfrequency global COLORred global COLORcanvas global COLORyellow global COLORgreen global COLORmagenta

while (True):                                           # Main loop

    # RUNstatus = 1 : Open Stream
    if (RUNstatus == 1):
        if UPDATEspeed < 1:
            UPDATEspeed = 1.0

        TRACESopened = 1

        try:

Get the USB device, e.g. 'USB0::0x1AB1::0x0588::DS1ED141904883'

            instruments = visa.get_instruments_list()
            usb = filter(lambda x: 'USB' in x, instruments)
            if len(usb) != 1:
                print 'Bad instrument list', instruments
                sys.exit(-1)
            scope = visa.instrument(usb[0], timeout=20, chunk_size=1024000) # bigger timeout for long mem

            RUNstatus = 2
        except:                                         # If error in opening audio stream, show error
            RUNstatus = 0
            #txt = "Sample rate: " + str(SAMPLErate) + ", try a lower sample rate.\nOr another audio device."
            showerror("VISA Error","Cannot open scope")

get metadata

        #sample_rate = float(scope.ask(':ACQ:SAMP?'))
        #timescale = float(scope.ask(":TIM:SCAL?"))
        #timeoffset = float(scope.ask(":TIM:OFFS?"))
        #voltscale = float(scope.ask(':CHAN1:SCAL?'))
        #voltoffset = float(scope.ask(":CHAN1:OFFS?"))

        UpdateScreen()                                  # UpdateScreen() call

    # RUNstatus = 2: Reading audio data from soundcard
    if (RUNstatus == 2):
    # Grab the raw data from channel 1
        #try:

Set the scope the way we want it

        if SAMPLEdepth == 0:
            scope.write(':ACQ:MDEP 12000') # normal memory type
        else:
            scope.write(':ACQ:MDEP 120000') # long memory type
        #scope.write(':CHAN1:COUP DC') # DC coupling
        #scope.write(':CHAN1:DISP ON') # Channel 1 on
        #scope.write(':CHAN2:DISP ON') # Channel 2 off
        #scope.write(':CHAN1:SCAL 1') # Channel 1 vertical scale 1 volts
        #scope.write(':CHAN1:OFFS -2') # Channel 1 vertical offset 2 volts
        #scope.write(':TIM:SCAL 0.001') # time interval
        #scope.write(':TIM:OFFS .05') # Offset time 50 ms

        #scope.write(':TRIG:EDGE:SOUR CHAN1') # Edge-trigger from channel 1
        #scope.write(':TRIG:EDGE:SWE SING') # Single trigger
        #scope.write(':TRIG:EDGE:COUP AC') # trigger coupling
        #scope.write(':TRIG:EDGE:SLOP NEG') # Trigger on negative edge
        #scope.write(':TRIG:EDGE:LEV 0.01') # Trigger  volts
        scope.write(":RUN")

        #txt = "Trig"
        #x = X0L + 250
        #y = Y0T+GRH+32
        #IDtxt  = ca.create_text (x, y, text=txt, anchor=W, fill=COLORyellow)
        #root.update()       # update screen

        while scope.ask(':TRIG:STAT?') != 'STOP':
            sleep(0.1)
        #sleep(0.1)
# Grab the raw data from channel 1, which will take a few seconds for long buffer mode

        scope.write(":STOP")
        scope.write(":WAV:SOUR CHAN1")
        scope.write(":WAV:MODE RAW")
        scope.write(":WAV:FORM BYTE")
        scope.write(":WAV:STAR 1")
        if SAMPLEdepth == 0:
            scope.write(":WAV:STOP 12000")
        else:
            scope.write(":WAV:STOP 120000")

        txt = "->Acquire"
        x = X0L + 275
        y = Y0T+GRH+32
        IDtxt  = ca.create_text (x, y, text=txt, anchor=W, fill=COLORgreen)
        root.update()       # update screen

        signals= scope.ask(":WAV:DATA?")  #do this first
        data_size = len(signals)

        SAMPLErate = scope.ask_for_values(':ACQ:SRAT?')[0] #do this second
        #print 'Data size:', SAMPLEsize, "Sample rate:", SAMPLErate

        sleep(0.1)

convert data from (inverted) bytes to an array of scaled floats

this magic from Matthew Mets

        SIGNAL1 = numpy.frombuffer(signals, 'B')
        #print SIGNAL1
        SIGNAL1 = (SIGNAL1 * -1 + 255) -130  # invert
        #print SIGNAL1
        SIGNAL1 = SIGNAL1/127.0 # scale 10 +-1, has a slight DC offset
        #print SIGNAL1

        UpdateAll()                                     # Update Data, trace and screen

        if SWEEPsingle == True:  # single sweep mode, sweep once then stop
            SWEEPsingle = False
            RUNstatus = 3

    # RUNstatus = 3: Stop
    # RUNstatus = 4: Stop and restart
    if (RUNstatus == 3) or (RUNstatus == 4):
        scope.write(":KEY:FOR")
        scope.close()
        if RUNstatus == 3:
            RUNstatus = 0                               # Status is stopped
        if RUNstatus == 4:
            RUNstatus = 1                               # Status is (re)start
        UpdateScreen()                                  # UpdateScreen() call

    # Update tasks and screens by TKinter
    root.update_idletasks()
    root.update()                                       # update screens
rheslip commented 8 years ago

Thanks for showing the dependencies - I'll post that on the blog.

As for the single sweep problem, I'm not sure how to fix it since your scope is not the same as mine. I experienced similar issues when trying to get PYVISA 1.8 to work. There seem to be subtle differences in the scope firmware and timing. Try extending the sleep(.1) statements and uncomment the one right after the loop that waits for data. I set the delay times short because it worked on my system and I wanted to get the fastest sweep rate possible. Sounds like the code is hanging in the loop waiting for the scope.

kerrsmith commented 8 years ago

Hi,

Thank you very much for getting back to me, it is much appreciated.

I don't suppose you could also post the code under the post you just added for me on your blog - it is a slight modification of the code by policeman0077 (further up the page) as that version had a few missing commands where it does the actual data retrieval from the scope (specifically the 'Grab the raw data from channel 1' part).

I did try to get the code looking neat on Github but it kept insisting on formatting it and highlighting all the comments - after a while fiddling with it I decided to just leave it as it was, copied straight out my working code. The main parts are quite clear even if the comments are a bit on the large side.

I will try adjusting the timing as suggested and let you know how it goes - it is very close to working I think. I have not used Python before yesterday but it is not so different from C++ and PHP which I am used to working with. It is also my first time trying to talk to my scope from my computer...

Anyway, as mentioned above, if you could add the code just after my post I think it would help others get to the same point as me - which is almost working I think. I will paste the code below this email so you have an easy to copy version:

Thanks again for your suggestions and I will let you know how I get on,

Kerr

============================================ Main routine

def Sweep(): # Read samples and store the data into the arrays global X0L # Left top X value global Y0T # Left top Y value global GRW # Screenwidth global GRH # Screenheight global SIGNAL1 global RUNstatus global SWEEPsingle global SMPfftlist global SMPfftindex global SAMPLErate global SAMPLEsize global SAMPLEdepth global UPDATEspeed global STARTfrequency global STOPfrequency global COLORred global COLORcanvas global COLORyellow global COLORgreen global COLORmagenta

while (True):                                           # Main loop

    # RUNstatus = 1 : Open Stream
    if (RUNstatus == 1):
        if UPDATEspeed < 1:
            UPDATEspeed = 1.0

        TRACESopened = 1

        try:

Get the USB device, e.g. 'USB0::0x1AB1::0x0588::DS1ED141904883'

            instruments = visa.get_instruments_list()
            usb = filter(lambda x: 'USB' in x, instruments)
            if len(usb) != 1:
                print 'Bad instrument list', instruments
                sys.exit(-1)
            scope = visa.instrument(usb[0], timeout=20,

chunk_size=1024000) # bigger timeout for long mem

            RUNstatus = 2
        except:                                         # If error in

opening audio stream, show error RUNstatus = 0

txt = "Sample rate: " + str(SAMPLErate) + ", try a lower

sample rate.\nOr another audio device." showerror("VISA Error","Cannot open scope")

get metadata

        #sample_rate = float(scope.ask(':ACQ:SAMP?'))
        #timescale = float(scope.ask(":TIM:SCAL?"))
        #timeoffset = float(scope.ask(":TIM:OFFS?"))
        #voltscale = float(scope.ask(':CHAN1:SCAL?'))
        #voltoffset = float(scope.ask(":CHAN1:OFFS?"))

        UpdateScreen()                                  #

UpdateScreen() call

    # RUNstatus = 2: Reading audio data from soundcard
    if (RUNstatus == 2):
    # Grab the raw data from channel 1
        #try:

Set the scope the way we want it

        if SAMPLEdepth == 0:
            scope.write(':ACQ:MDEP 12000') # normal memory type
        else:
            scope.write(':ACQ:MDEP 120000') # long memory type
        #scope.write(':CHAN1:COUP DC') # DC coupling
        #scope.write(':CHAN1:DISP ON') # Channel 1 on
        #scope.write(':CHAN2:DISP ON') # Channel 2 off
        #scope.write(':CHAN1:SCAL 1') # Channel 1 vertical scale 1 volts
        #scope.write(':CHAN1:OFFS -2') # Channel 1 vertical offset 2

volts

scope.write(':TIM:SCAL 0.001') # time interval

        #scope.write(':TIM:OFFS .05') # Offset time 50 ms
        #scope.write(':TRIG:EDGE:SOUR CHAN1') # Edge-trigger from

channel 1

scope.write(':TRIG:EDGE:SWE SING') # Single trigger

        #scope.write(':TRIG:EDGE:COUP AC') # trigger coupling
        #scope.write(':TRIG:EDGE:SLOP NEG') # Trigger on negative edge
        #scope.write(':TRIG:EDGE:LEV 0.01') # Trigger  volts
        scope.write(":RUN")
        #txt = "Trig"
        #x = X0L + 250
        #y = Y0T+GRH+32
        #IDtxt  = ca.create_text (x, y, text=txt, anchor=W,

fill=COLORyellow)

root.update() # update screen

        while scope.ask(':TRIG:STAT?') != 'STOP':
            sleep(0.1)
        #sleep(0.1)
# Grab the raw data from channel 1, which will take a few seconds for

long buffer mode

        scope.write(":STOP")
        scope.write(":WAV:SOUR CHAN1")
        scope.write(":WAV:MODE RAW")
        scope.write(":WAV:FORM BYTE")
        scope.write(":WAV:STAR 1")
        if SAMPLEdepth == 0:
            scope.write(":WAV:STOP 12000")
        else:
            scope.write(":WAV:STOP 120000")

        txt = "->Acquire"
        x = X0L + 275
        y = Y0T+GRH+32
        IDtxt  = ca.create_text (x, y, text=txt, anchor=W,

fill=COLORgreen) root.update() # update screen

        signals= scope.ask(":WAV:DATA?")  #do this first
        data_size = len(signals)

        SAMPLErate = scope.ask_for_values(':ACQ:SRAT?')[0] #do this

second

print 'Data size:', SAMPLEsize, "Sample rate:", SAMPLErate

        sleep(0.1)

convert data from (inverted) bytes to an array of scaled floats

this magic from Matthew Mets

        SIGNAL1 = numpy.frombuffer(signals, 'B')
        #print SIGNAL1
        SIGNAL1 = (SIGNAL1 * -1 + 255) -130  # invert
        #print SIGNAL1
        SIGNAL1 = SIGNAL1/127.0 # scale 10 +-1, has a slight DC offset
        #print SIGNAL1

        UpdateAll()                                     # Update Data,

trace and screen

        if SWEEPsingle == True:  # single sweep mode, sweep once then

stop SWEEPsingle = False RUNstatus = 3

    # RUNstatus = 3: Stop
    # RUNstatus = 4: Stop and restart
    if (RUNstatus == 3) or (RUNstatus == 4):
        scope.write(":KEY:FOR")
        scope.close()
        if RUNstatus == 3:
            RUNstatus = 0                               # Status is

stopped if RUNstatus == 4: RUNstatus = 1 # Status is (re)start UpdateScreen() # UpdateScreen() call

    # Update tasks and screens by TKinter
    root.update_idletasks()
    root.update()                                       # update screens
kerrsmith commented 8 years ago

That's great, thanks.

I am not sure why I am not able to post properly.

I will have a look at the code and see if I can figure anything out - I will keep you updated.

Thanks again,

Kerr

On 31 January 2016 at 17:52, rheslip notifications@github.com wrote:

Kerr - I posted your code on the blog. Once you get it sweeping could you send me a zip of it ? I can put in in github as a 1054Z version which will make it a lot easier for other people to use it. Just send it to me directly rheslip@hotmail.com Thanks, Rich

Date: Sun, 31 Jan 2016 08:35:51 -0800 From: notifications@github.com To: PyDSA@noreply.github.com CC: rheslip@hotmail.com Subject: Re: [PyDSA] Getting code working for DS1054Z on Windows 7 64bit (#1)

Hi,

Thank you very much for getting back to me, it is much appreciated.

I don't suppose you could also post the code under the post you just added

for me on your blog - it is a slight modification of the code by

policeman0077 (further up the page) as that version had a few missing

commands where it does the actual data retrieval from the scope

(specifically the 'Grab the raw data from channel 1' part).

I did try to get the code looking neat on Github but it kept insisting on

formatting it and highlighting all the comments - after a while fiddling

with it I decided to just leave it as it was, copied straight out my

working code. The main parts are quite clear even if the comments are a

bit on the large side.

I will try adjusting the timing as suggested and let you know how it goes -

it is very close to working I think. I have not used Python before

yesterday but it is not so different from C++ and PHP which I am used to

working with. It is also my first time trying to talk to my scope from my

computer...

Anyway, as mentioned above, if you could add the code just after my post I

think it would help others get to the same point as me - which is almost

working I think. I will paste the code below this email so you have an

easy to copy version:

Thanks again for your suggestions and I will let you know how I get on,

Kerr

============================================ Main routine

def Sweep(): # Read samples and store the data into the arrays

global X0L # Left top X value

global Y0T # Left top Y value

global GRW # Screenwidth

global GRH # Screenheight

global SIGNAL1

global RUNstatus

global SWEEPsingle

global SMPfftlist

global SMPfftindex

global SAMPLErate

global SAMPLEsize

global SAMPLEdepth

global UPDATEspeed

global STARTfrequency

global STOPfrequency

global COLORred

global COLORcanvas

global COLORyellow

global COLORgreen

global COLORmagenta

while (True): # Main loop

RUNstatus = 1 : Open Stream

if (RUNstatus == 1):

if UPDATEspeed < 1:

UPDATEspeed = 1.0

TRACESopened = 1

try:

Get the USB device, e.g. 'USB0::0x1AB1::0x0588::DS1ED141904883'

instruments = visa.get_instruments_list()

usb = filter(lambda x: 'USB' in x, instruments)

if len(usb) != 1:

print 'Bad instrument list', instruments

sys.exit(-1)

scope = visa.instrument(usb[0], timeout=20,

chunk_size=1024000) # bigger timeout for long mem

RUNstatus = 2

except: # If error in

opening audio stream, show error

RUNstatus = 0

txt = "Sample rate: " + str(SAMPLErate) + ", try a lower

sample rate.\nOr another audio device."

showerror("VISA Error","Cannot open scope")

get metadata

sample_rate = float(scope.ask(':ACQ:SAMP?'))

timescale = float(scope.ask(":TIM:SCAL?"))

timeoffset = float(scope.ask(":TIM:OFFS?"))

voltscale = float(scope.ask(':CHAN1:SCAL?'))

voltoffset = float(scope.ask(":CHAN1:OFFS?"))

UpdateScreen() #

UpdateScreen() call

RUNstatus = 2: Reading audio data from soundcard

if (RUNstatus == 2):

Grab the raw data from channel 1

try:

Set the scope the way we want it

if SAMPLEdepth == 0:

scope.write(':ACQ:MDEP 12000') # normal memory type

else:

scope.write(':ACQ:MDEP 120000') # long memory type

scope.write(':CHAN1:COUP DC') # DC coupling

scope.write(':CHAN1:DISP ON') # Channel 1 on

scope.write(':CHAN2:DISP ON') # Channel 2 off

scope.write(':CHAN1:SCAL 1') # Channel 1 vertical scale 1 volts

scope.write(':CHAN1:OFFS -2') # Channel 1 vertical offset 2

volts

scope.write(':TIM:SCAL 0.001') # time interval

scope.write(':TIM:OFFS .05') # Offset time 50 ms

scope.write(':TRIG:EDGE:SOUR CHAN1') # Edge-trigger from

channel 1

scope.write(':TRIG:EDGE:SWE SING') # Single trigger

scope.write(':TRIG:EDGE:COUP AC') # trigger coupling

scope.write(':TRIG:EDGE:SLOP NEG') # Trigger on negative edge

scope.write(':TRIG:EDGE:LEV 0.01') # Trigger volts

scope.write(":RUN")

txt = "Trig"

x = X0L + 250

y = Y0T+GRH+32

IDtxt = ca.create_text (x, y, text=txt, anchor=W,

fill=COLORyellow)

root.update() # update screen

while scope.ask(':TRIG:STAT?') != 'STOP':

sleep(0.1)

sleep(0.1)

Grab the raw data from channel 1, which will take a few seconds for

long buffer mode

scope.write(":STOP")

scope.write(":WAV:SOUR CHAN1")

scope.write(":WAV:MODE RAW")

scope.write(":WAV:FORM BYTE")

scope.write(":WAV:STAR 1")

if SAMPLEdepth == 0:

scope.write(":WAV:STOP 12000")

else:

scope.write(":WAV:STOP 120000")

txt = "->Acquire"

x = X0L + 275

y = Y0T+GRH+32

IDtxt = ca.create_text (x, y, text=txt, anchor=W,

fill=COLORgreen)

root.update() # update screen

signals= scope.ask(":WAV:DATA?") #do this first

data_size = len(signals)

SAMPLErate = scope.ask_for_values(':ACQ:SRAT?')[0] #do this

second

print 'Data size:', SAMPLEsize, "Sample rate:", SAMPLErate

sleep(0.1)

convert data from (inverted) bytes to an array of scaled floats

this magic from Matthew Mets

SIGNAL1 = numpy.frombuffer(signals, 'B')

print SIGNAL1

SIGNAL1 = (SIGNAL1 * -1 + 255) -130 # invert

print SIGNAL1

SIGNAL1 = SIGNAL1/127.0 # scale 10 +-1, has a slight DC offset

print SIGNAL1

UpdateAll() # Update Data,

trace and screen

if SWEEPsingle == True: # single sweep mode, sweep once then

stop

SWEEPsingle = False

RUNstatus = 3

RUNstatus = 3: Stop

RUNstatus = 4: Stop and restart

if (RUNstatus == 3) or (RUNstatus == 4):

scope.write(":KEY:FOR")

scope.close()

if RUNstatus == 3:

RUNstatus = 0 # Status is

stopped

if RUNstatus == 4:

RUNstatus = 1 # Status is

(re)start

UpdateScreen() #

UpdateScreen() call

Update tasks and screens by TKinter

root.update_idletasks()

root.update() # update screens

— Reply to this email directly or view it on GitHub.

— Reply to this email directly or view it on GitHub https://github.com/rheslip/PyDSA/issues/1#issuecomment-177563896.

kerrsmith commented 8 years ago

I have now got the code working, the issue was that the code was stuck in a loop on line 605. This while loop was waiting for a 'STOP' message from the scope but it was not getting it - my scope sends 'TD' initially then mainly 'AUTO' but sometimes another 'TD' every so often.

I also removed the sleep commands from this main routine function and the program still works, I get an update rate of 2 to 3 screen updates a second.

I have attached my current working file to this message.

PyDSA.zip

hb020 commented 8 years ago

Thanks for the work here. From my side I took up this code, added:

I did all this in an effort to reduce the noise level, and am mostly interested in audio. I know the scope's ADC has a rather low resolution for audio, but I decided to give it a go anyway, hoping to compensate with a large sample size.

But: For some reason I still have much better noise reduction when averaging over multiple passes than just providing one (huge) sample set. Even when the sample set is 10+ times bigger than the all the data one uses when averaging. And yes, I did adapt the FFT sample buffer size to the nearest-lower-power-of-2 value suitable for the scope's sample size. Now the last time I did some serious work on FFT theory is more than 30 years ago, so I may be a bit rusty, but this does not sound good to me.

And on top of that, the damn thing is LOUD. For every data read (and when reading large data sets one has a lot of that) the scope beeps. (I may be able to switch that beep off, haven't looked). And it is SLOW (the scope, python and the USB transfer are all partly responsible for that). Not ideal.

So in case anyone is interested, I can share my work, and I may even look into it some more, but my conclusion is that a dedicated FFT machine or some high resolution sampling card with good PC or Mac software would be more suited for serious work.

rheslip commented 8 years ago

For audio you should take a look at PA2OHH's code on which PyDSA is based: http://www.qsl.net/pa2ohh/11sa.htm Regards, Rich

Date: Sun, 6 Mar 2016 12:29:09 -0800 From: notifications@github.com To: PyDSA@noreply.github.com CC: rheslip@hotmail.com Subject: Re: [PyDSA] Getting code working for DS1054Z on Windows 7 64bit (#1)

Thanks for the work here. From my side I took up this code, added:

larger sample depths with corresponding fft handling sizes (this requires reading the data of a sample in multiple batches, as 250K is the max per VISA level read) adaptive display of the frequency (not everything in MHz, sometimes kHz is needed also...) better stop/run/single shot handling (to ensure we have fresh data at every run) adapt to the latest version of the VISA software (which is a PAIN to install on OS/X by the way) removed some bugs (one must discard the sample header from the FFT data for example)

I did all this in an effort to reduce the noise level, and am mostly interested in audio. I know the scope's ADC has a rather low resolution for audio, but I decided to give it a go anyway, hoping to compensate with a large sample size.

But: For some reason I still have much better noise reduction when averaging over multiple passes than just providing one (huge) sample set. Even when the sample set is 10+ times bigger than the all the data one uses when averaging. And yes, I did adapt the FFT sample buffer size to the nearest-lower-power-of-2 value suitable for the scope's sample size. Now the last time I did some serious work on FFT theory is more than 30 years ago, so I may be a bit rusty, but this does not sound good to me.

And on top of that, the damn thing is LOUD. For every data read (and when reading large data sets one has a lot of that) the scope beeps. (I may be able to switch that beep off, haven't looked). And it is SLOW (the scope, python and the USB transfer are all partly responsible for that). Not ideal.

So in case anyone is interested, I can share my work, and I may even look into it some more, but my conclusion is that a dedicated FFT machine or some high resolution sampling card with good PC or Mac software would be more suited for serious work.

— Reply to this email directly or view it on GitHub.

Prodigity commented 8 years ago

@hb020

And on top of that, the damn thing is LOUD. For every data read (and when reading large data sets one has a lot of that) the scope beeps.

Try adding in a: scope.write(":BEEP:ENAB OFF")