Portrait Photograph

Eddie Carle - Tech Blog

Edmonton, Alberta, Canada
📧 eddie@isatec.ca
🕾 +1.780.934.9509
📻 VE6ISA
[Tech Blog] [Fun Page] [vCard] [PGP Key]

Talking to my Scopemeter

December 29, 2015

For some time now I’ve been meaning to write some simple software to pull data off of my Fluke ScopeMeter 199C. I tackle this by writing a simple python script to talk to the oscilloscope and query it’s measurement and waveform data. The code then generates pretty reports in both HTML/SVG and LaTeX/tikz.

For anyone looking to use and/or play with the code you can access the code repository at https://github.com/eddic/flukereader. Keep in mind that this has only been tested with my particular ScopeMeter so if your model differs you’ll likely need to tweak it a bit. Feel free to fork with your modifications and let me know. Enjoy!

The Protocol

Figuring out how to talk to the ScopeMeter proved to be quite intimidating at first. The device has a simple optical UART interface for which I’ve acquired an RS-232 driver. The actual protocol itself is documented quite extensively in a reference manual published by Fluke. This is actually quite a well written document so kudos to Fluke for that. Lots of code examples are included (albeit in Basic) to take away the ambiguity of the written word.

There doesn’t seem to be all that much code published online for talking to Fluke devices. Special mention should go out to ScopeGrab32 but it is a bit dated and doesn’t quite work for my model of ScopeMeter nor my OS of choice (Gentoo). Easiest solution seemed to be starting from scratch straight from the reference manual.

Screenshots

I had really hoped to be able to acquire full raster screenshots of the oscilloscope. I followed the reference manual to the tee and successfully recovered the image file raw data. Unfortunately my particular model of ScopeMeter (and all subsequent models) can only send the image in the “FBRLE2D” format. There is virtually no documentation that I can find on this particular image format and I assume it is strictly a proprietary Fluke format.

I called Fluke technical support in the hopes that they might give me some sort of reference document for this image format but they basically told me to go f💣👊💥 myself. The gentleman I talked to even proved unwilling to admit that this image format is a Fluke proprietary format. I was really quite taken back as to how rude they were to me. Never experienced anything quite that bad. If anyone is reading this and enjoys trying to reverse engineer image formats check this out.

Waveform Data

The code does a pretty good job at extracting waveform data from the scope. Between reading the reference manual and some experimentation I believe I’ve nailed down the various scope modes and their limitations.

I was quite pleased to find out that the ScopeMeter tells you what the division count/resolution is on the screen. I simply used that data to define the grid tics in GNUPlot and outputted to SVG for web use and tikz for LaTeX. It ultimately makes for a nice vectorized plot that rivals an actual screenshot. I suppose it makes up for the lack of screenshot ability. I opted to use green grid lines to represent the zero axes in both amplitude and time. The zero point in time represents the trigger point.

Normal Scope Mode

This covers operation in normal scope mode with no glitch detection, averaging or enveloping. In this mode the scope gives us 3,000 data points represented with 16 bit precision. As seen in figure 1, it ends up looking pretty damn good.

Figure 1: Normal scope mode with no glitch detection, averaging or enveloping.

Averaging

When using averaging the scope gives us 300 points with 8 bit precision. I was a little disappointed by this lack of precision but I can live with it. The result, as seen in figure 2, is some clearly visible stair-casing on waveform components with gentle slopes.

Figure 2: Averaging scope mode showing stair-casing artifacts.

Enveloping

This refers to operation in either glitch detection, enveloping, or both combined. The scope gives us 300 min/max pairs with 8 bit precision. Again, not the greatest precision but I find the artifacts are not as evident as they are in the averaging case. See figure 3 and judge for yourself.

Figure 3: Glitch detection with envelope display enabled.

Power Spectral Density from Scope Record

I opted to try using the scope record mode for power spectral density plots. Note that you can also use simple trace mode but I figured 3,000 points is not all that much of a sample size. When in record mode with no glitch detection or enveloping the scopes gives 30,000 data points at 16 bit precision. This proved to be a rather useful tool for spectral plots. Unfortunately the maximum sample rate in record mode is surprisingly low thereby limiting the spectral analysis to stuff in the audio range.

For the actual spectral calculation I opted to use the SciPy welch function. I put the window size at 2,048 and used generous overlap with a hamming window. No configurability exists for these options since I found this PSD stuff rather limited in value. See figure 4 for an example.

Figure 4: Power spectral density calculation from scope record mode.

Measurements

The facilities for pulling measurements off of the ScopeMeter are pretty slick. You can pull both cursor and reading measurements. They all come with a precision value which I use to calculate significant digits.

The script allows the user to set up measurements and then pull them off. Groups of measurements are associated with a figure and are adding to the bottom of said figure in a table. See figure 5.

Aquisition TimeDecember 29, 2015 at 16:09:55
Peak to Peak Voltage(2.02 ± 0.01) V
Pulse Width(417.0 ± 0.1) μs
Pulse Rise Time(37.6 ± 0.4) μs
Pulse Fall Time(37.2 ± 0.4) μs
Figure 5: Normal scope mode with some measurements.

Usage

After waffling back and forth I opted for an interface style that combines both command line interface and a series of modal prompts. I’m not a UI guy and really I just wanted it to be as quick and efficient as possible.

The command line usage is as follows:

usage: flukereader.py [-h] [-p PORT] [-i] [-d] [-s] [-t] [-l]

Talk to a Fluke ScopeMeter.

optional arguments:
  -h, --help            show this help message and exit
  -p PORT, --port PORT  serial port name (/dev/ttyS0)
  -i, --identify        get identity of ScopeMeter
  -d, --datetime        set the date/time of the ScopeMeter
  -s, --screenshot      get a screenshot from the ScopeMeter
  -t, --tex             Generate a tex report of results
  -l, --html            Generate an html report of results

As far as the modal progression goes, here is an example of the process used to generate figure 5:

eddie@dorado ~ $ flukereader.py -l
Opening and configuring serial port...done
Reconciling serial port baud rate...done
Enter figure title (blank to quit): Normal scope mode with some measurements.
 (a) single trace
 (b) single psd
 (c) single envelope
 (d) single trend
 (e) dual trace
 (f) dual psd
 (g) dual envelope
 (h) dual trend
 (i) dual power
 (j) quit
What type of waveform will this be? a
Downloading waveform admin data from ScopeMeter...done
Processing waveform admin data from ScopeMeter...done
Downloading waveform sample data from ScopeMeter...done
Processing waveform sample data from ScopeMeter...done
Enter title for waveform #0: Voltage

***** Starting Measurements *****


***** Doing Measurement #1 *****

 (a) single
 (b) first + second
 (c) first - second
 (d) first * second
 (e) first / second
 (f) quit
What type of measurement will this be? a
Setup your measurement and press enter when ready
Downloading measurement metadata from ScopeMeter...done
 (a) Reading 1:
          Source: Input A
            Type: Peak to Peak
            Unit: V
       Precision: 10 mV
 (b) Reading 2:
          Source: Input A
            Type: Pulse Width Positive
            Unit: s
       Precision: 100 ns
Enter desired reading and hit enter: a
Fetching reading from ScopeMeter...done
Result: (2.02 ± 0.01) V
Enter title (empty to discard): Peak to Peak Voltage

***** Doing Measurement #2 *****

 (a) single
 (b) first + second
 (c) first - second
 (d) first * second
 (e) first / second
 (f) quit
What type of measurement will this be? a
Setup your measurement and press enter when ready
Downloading measurement metadata from ScopeMeter...done
 (a) Reading 1:
          Source: Input A
            Type: Peak to Peak
            Unit: V
       Precision: 10 mV
 (b) Reading 2:
          Source: Input A
            Type: Pulse Width Positive
            Unit: s
       Precision: 100 ns
Enter desired reading and hit enter: b
Fetching reading from ScopeMeter...done
Result: (417.0 ± 0.1) μs
Enter title (empty to discard): Pulse Width

***** Doing Measurement #3 *****

 (a) single
 (b) first + second
 (c) first - second
 (d) first * second
 (e) first / second
 (f) quit
What type of measurement will this be? a
Setup your measurement and press enter when ready
Downloading measurement metadata from ScopeMeter...done
 (a) Cursor 1 Amplitude:
          Source: Input A
            Type: None
            Unit: V
       Precision: 20 mV
 (b) Cursor 2 Amplitude:
          Source: Input A
            Type: None
            Unit: V
       Precision: 20 mV
 (c) Cursor Relative Amplitude:
          Source: Input A
            Type: Rise Time
            Unit: s
       Precision: 400 ns
Enter desired reading and hit enter: c
Fetching reading from ScopeMeter...done
Result: (37.6 ± 0.4) μs
Enter title (empty to discard): Pulse Rise Time

***** Doing Measurement #4 *****

 (a) single
 (b) first + second
 (c) first - second
 (d) first * second
 (e) first / second
 (f) quit
What type of measurement will this be? a
Setup your measurement and press enter when ready
Downloading measurement metadata from ScopeMeter...done
 (a) Cursor 1 Amplitude:
          Source: Input A
            Type: None
            Unit: V
       Precision: 20 mV
 (b) Cursor 2 Amplitude:
          Source: Input A
            Type: None
            Unit: V
       Precision: 20 mV
 (c) Cursor Relative Amplitude:
          Source: Input A
            Type: Fall Time
            Unit: s
       Precision: 400 ns
Enter desired reading and hit enter: c
Fetching reading from ScopeMeter...done
Result: (37.2 ± 0.4) μs
Enter title (empty to discard): Pulse Fall Time

***** Doing Measurement #5 *****

 (a) single
 (b) first + second
 (c) first - second
 (d) first * second
 (e) first / second
 (f) quit
What type of measurement will this be? f

***** Figure “Normal scope mode with some measurements.” *****

***** Waveform “Voltage” Details *****
   Channel: A
Trace Type: trace
     Units: s vs V
 Timestamp: 16:09:55 on December 29, 2015
      Size: 2400
  Filename: 2015-12-29-16-09-55_input-A_trace_s-vs-V

***** Measurement Details *****
┌────────────────────┬────────────────┐
│Peak to Peak Voltage│(2.02 ± 0.01) V │
│         Pulse Width│(417.0 ± 0.1) μs│
│     Pulse Rise Time│(37.6 ± 0.4) μs │
│     Pulse Fall Time│(37.2 ± 0.4) μs │
└────────────────────┴────────────────┘
Enter figure title (blank to quit): 
eddie@dorado ~ $

The end result is a DAT file in the current directory containing the plot points and and new folder named html. In the html folder resides a Makefile, the GNUPlot GPI file and an HTML file named report.html. Running make in the html folder generates the SVG graphic files. The contents of the GPI file are as follows:

set term svg enhanced size 608,430 font "Serif"
set output '2015-12-29-16-09-55_normal_scope_mode_with_some_measurements.svg'
set encoding utf8
set xlabel "Time (50 μs/div)"
set xrange [-4.980000e-04:1.020000e-04]
set xtics 5.000000e-05
set xzeroaxis lt 1 lc rgb 'green'
set format x ''
set yrange [-2.000000e+00:2.000000e+00]
set ytics 5.000000e-01
set yzeroaxis lt 1 lc rgb 'green'
set format y ''
set grid
set parametric
unset key
set ylabel "Voltage (500 mV/div)"
plot '../2015-12-29-16-09-55_input-A_trace_s-vs-V.dat' \
    using 1:2 with lines lt 1 lc rgb 'black'

If you want any more information on it’s usage you’ll have to to check the code itself out.