Micro Measurement Display 2 (µMD2)

For Homodyne Interferometers using Single Frequency Lasers,
Linear and Rotary Encoders, and Ring Laser Gyros
Heterodyne Interferometers using Two Frequency Lasers

Installation and Operation Manual

Version 1.29 (29-Jan-24)

Copyright © 1994-2024
Sam Goldwasser and Jan Beck
--- All Rights Reserved ---

For contact info, please see the Sci.Electronics.Repair FAQ Email Links Page.

Reproduction of this document in whole or in part is permitted if both of the following conditions are satisfied:
  1. This notice is included in its entirety at the beginning.
  2. There is no charge except to cover the costs of copying.

Table of Contents


Author and Copyright

Author: Samuel M. Goldwasser

For contact info, please see the Sci.Electronics.Repair FAQ Email Links Page.

Copyright © 1994-2024
All Rights Reserved

Reproduction of this document in whole or in part is permitted if both of the following conditions are satisfied:

1. This notice is included in its entirety at the beginning.
2. There is no charge except to cover the costs of copying.


µMD2 is intended for use in hobbyist, experimental, research, and other applications where a bug in the hardware, firmware, or software, will not have a significant impact on the future of the Universe or anything else. While every effort has been made to avoid this possibility, µMD2 is an on-going development effort. We will not be responsible for any consequences of such bugs including but not limited to damage to the construction crane you picked up on eBay for $1.98 + shipping, financial loss from ending up in the Antarctic when the compass orientation provided by your home-built ring laser gyro was off by 1,536 degrees, or bruising to your pet's ego from any number of causes directly or indirectly related to µMD2. ;-)


Thanks to Jan Beck for selecting the Teensy 4.0 and writing and testing the initial version of the firmware and providing support for enhancements and bug fixes. He was also instrumental in developing the initial µMD1 firmware and GUI. And for getting me interested in actually getting involved in that project. If anyone had told me six months ago that I'd be writing code in C, MIPS assembly language, and Visual Basic - and enjoying it (sort of) - I would have suggested they were certifiably nuts. ;-) Jan maintains the master GUI source code as well as slightly different versions of both the µMD1 and µMD1 firmware and a development blog on these and other projects.


µMD2 is an inexpensive system for precision readout of displacement (change in position), angle, straightness, and more in metrology applications using (homodyne) interferometry with single frequency lasers, as well as devices like linear and rotary encoders which produce Quad-A/B signals. There is also limited support for use in heterodyne interferometry using two frequency lasers. The later is currently a "works in progress", so for now, Micro Measurement Display 1 (µMD1) is recommended for this with some exceptions that will be noted below.

While targeted for experimenters, hobbyists, and researchers, there is no reason why µMD2 can't also be of value in science and industry. The hardware platform is a readily available inexpensive microcontroller development board which communicates via USB to a Windows PC, laptop, netbook, or tablet.

The graphics below show a rotary optical encoder which uses a pair of LEDs and photodiodes physically offset by 90 degrees to generate Quad-Sin-Cos analog signals which are then thresholded to yield Quad-A-B digital signals. The specific type of sequence is called a "Gray" code (not based on color but attibutable to someone named Frank Gray) and has the property that any possible allowable change in value is a change in only a single bit. This eliminates the ambiguity with sensors using the normal binary order where two bits can change at not quite the same time.

Rotary Encoder Digital Signals as a Function of Orientation

(The animated encoder graphic seems to be all over the Web. If anyone knows who the original copyright holder is, I will acknowledge them.)

Many other types of encoders produce similar signals. They may use optical, mechanical, or magnetic sensing, among others.

The input to µMD2 are the digital signals which can have change rates of many 10s of MHz. The decoding is done in hardware and it is unlikely the upper limit will be reached by any practical application. There is no support for analog inputs now and probably never will be. However, there are hardware quadrature interpolators available that go in-line with the analog signals to multiply the effective resolution by anywhere from 2 to 1,000 or more, so they are a possible option were higher resolution is required. Those made by Renishaw are relatively inexpensive on eBay. There are also ICs available that perform this function.

For use with interferometers, the only difference is that the origin of the analog signals are from a different type of detector:

Typical Homodyne Interferometer Setup using µMD2

This also applies to devices like Ring Laser Gyros (RLGs) which have similar types of detection schemes.

For homodyne, the native resolution of single-pass interferometers is 1/8th wavelength, usually 633/8 or ~79 nm. But depending on the optics, this may be doubled or quadrupled without requiring interpolation. Specifically, the Linear Interferometer (LI, shown above) and Single Beam Interferometer (SBI) have a native resolution of ~79 nm; the Plane Mirror Interferometer (PMI) and High Stability Plane Mirror Interferometer (HSPMI) have a native resolution of ~40 nm, and the High Resolution Plane Mirror Interferometer (HRPMI) has a native resolution of ~20 nm. It is theoretically possible to convert a PMI or HSPMI into an HRPMI with the addition of a cube corner but the alignment could be quite hairy.

The heterodyne setup is similar except for the use of a two frequency laser:

Typical Heterodyne Interferometer Setup using µMD2

For heterodyne, the native resolution of single-pass interferometers is 1/4th wavelength for µMD2, usually 633/4 or ~158 nm. But depending on the optics, this may be doubled or quadrupled without requiring interpolarion. Specifically, the Linear Interferometer (LI, shown above) and Single Beam Interferometer (SBI) have a native resolution of ~158 nm; the Plane Mirror Interferometer (PMI) and High Stability Plane Mirror Interferometer (HSPMI) have a native resolution of ~80 nm; and the High Resolution Plane Mirror Interferometer (HRPMI) has a native resolution of ~40 nm. Eventually, interpolation may be implemented to increase the resolution, but that is in the future. Where higher resolution is required, µMD1 does implement interpolation and has an established track record. So µMD1 should probably be used unless high-REF (above around 5 MHz) is required. Eventually µMD2 will replace µMD1 but for now, it is still a "works-in-progress" and the main benefit is that it should work with the 20 MHz REF frequency of the Zygo 7701 and 7702 lasers.

However, for stationary or slowly varying displacement (order of less than one wavelength per second), the use of a large value for the moving average in the GUI should result in a similar improvement in resolution as the sampling can be set up to be essentially random.

Note that µMD2 refers specifically to the combination of the Teensy-based hardware and firmware. It's possible there could be µMD3, .... µMDn - or µMD0 - in the future using the same GUI. :) µMD1 is already taken for the original version supporting heterodyne interferometry using two frequency lasers.

This document provides installation and operating instructions for the µMD2 hardware and software using the SG-µMD2 PCB. The PCB layout includes the line receivers and associated components for up to 3 measurement axes, eliminating hand wiring. It may also have small OLED display for local monitoring of the encoder or interferometer counting (primarily for diagnostics).

It is assumed the reader is familiar with homodyne and/or heterodyne interferometry. Linear and rotary encoders generate signals to those from homodyne interferometers. If not, back up and start with Sam's Laser FAQ: Interferometers for Precision Measurement in Metrology Applications.

Mote: Throughout this document, "µMD2 board" or simply "board" refers to the SG-µMD2 PCB. "µMD" refers to the Windows Graphical User Interface (GUI), which is identical for µMD1 and µMD2.


Specifications are subject to change without notice. :-)

Computer and Operating System Requirements

Everything that follows assumes the use of Windows. If you're really smart and run Linux instead, sorry. ;-) (However, the GUI may run on Linux under something called "wine" so there may be hope.) The µMD2 GUI is known to work under Win XP, Vista, 7, and 10, and should be fine on Win 8 as well. Microsoft Net Framework 4.0 or higher is required to run µMD2. Net 4.0 or a more recent version is probably on your computer already but is available free from the Microsoft Web site. Win 7 or higher may be required to compile and upload the firmware.

Minimal System Constructed on Solderless Breadboard

Since the external interface to the Teensy is very simple, a version of µMD2 can be put together on a solderless breadboard (or prototyping board). While this may not run at the maximum speed supported by the Teensy, it would be a quick way of getting something working. Some typical basic interface circuits for the homodyne version are shown below:

Minimal Parts Count Input Circuits

CAUTION: Teensy pins are NOT 5V tolerant - they will be unhappy if a 5 V signal is connected to them directly. Thus any signal that may go higher than 3.3 V should NEVER be connected to them, even for an instant. Bad things may happen. In the case of the Quad-Sin-Cos decoder, the LEDs provide enough voltage drop so the input to the Teensy will not be greater than 3.3 V since the outputs of the LM393 are open collector. For the Quad-A-B input, the resistor voltage dividers reduce the output of the UA9637 under 3.3 V (exactly as on the SG-µMD2 PCB.

The LM393 is an 8 pin DIP so it, along with the Nano and other parts, will easily fit on the typical 250 column 2-1/4 x 3-1/4 inch solderless breadboard with room to spare. For the Quad-Sin-Cos Decoder version, the photodiodes can be somewhat remote connected with twisted pairs. The 1M ohm positive feedback resistor adds a small amount of hysteresis to filter out fuzzy noise on the signals which appears to be capable of inducing oscllation and totally messing up the displacement due to bogus excessive slew rate. Or something. :) For the Quad-A-B Differential version (RS422), the input cables can be long and also be twisted with a single 100 ohm resistor between the two inputs for termination, but there needs to be a common ground connection somewhere. While the UA9637 is essentially a voltage comparator with built-in hysteresis, it CANNOT be used with photodiode inputs because its bias current is too high. The difference in resistor values for the red and green LEDs balances their brightnesses, mostly. Of course, the LEDs aren't *really* essential. ;-)

Tne value of 100K for the photodiode load resistors has been selected as suitable for the typical ~1 mW SLM laser to result in the signal going from near 0 to around 3 V. It's not necessary to have them be adjustable since the threshold settings are adjustable. But you can if you wish, and of course change their value to reflect the real world situation of your laser power and losses in the Quad decoder. If the source is differential analog (typically each 1 V p-p), the signals can go directly to the comparator inputs dispensing with the load resistors and trim-pot.

A photo of such a setup along with a parts list will be forthcoming. The parts list references the designations on the schematic.

It is not anticipated that later versions will differ in any major way. This is supposed to be bare bones after all. ;-)

For this simple setup, a wireless breadboard with 25 columns should be adequate. The Nano with soldered pins can plug in at the right side with the USB connector facing out, and the LM393 and associated components can be placed next to it. Those connections that cannot be made with component leads should use pieces of #22-24 AWG solid wire.

The "cables" for the photodiodes can simply be twisted pairs. Keep them short but a foot or so should be fine. If the source is something else like a commercial optical detector or signals from a self-contained laser/interferometer, a different type of termination than the load resistors may be needed.

For more information on the Quad decoder and interface, see Construction Guidelines for Basic Quadrature-Sin-Cos Decoder and Quad-A-B Interface Kits. Some of it is redundant but there are more detailed instructions on mounting the optical parts and the actual circuits and wiring. Ignore the specifics for µMD0. ;-)

Assembly using the SG-µMD2 Board

The original PCB version was V1.00 and the current one is V1.22. Both are shown below. Clicking on these will bring up higher resolution versions in a single separate tab or window depending on your browser settings:


SG-µMD2 V1.00 PCB Layout Diagram (Left), SG-µMD2 V1.22 PCB Layout Diagram (Center), and Three Axis Populated V1.00 PCB with OLED Display (Right)
(JB1 and JB2 Jumpered for Normal Operation; JB3 and JB4 Jumpered for OLED GND on the Left and VCC on the Right)

The blue traces on the V1.22 PCB are NOT part of the artwork and are documented in the V1.2 assembly manual.

It is not anticipated that later versions will differ in any major way, but there will be some changes so a different assembly manual will be provided for each where appropriate since some part numbers and locations may have changed. These manuals include complete parts lists and Heathkit™-style step-by-step assembly instructions.

Kits are currently shipping with the V1.22 PCB. The only significant change from V1.00 is that the input terminal blocks/connectors are 5 pin on the V1.00 and 6 pin on the V1.22 (to provide a spot for power). If you'd prefer to roll your own, the µMD2 V1.22 or V1.23 Digikey Cart has most of the electronic components for a fully populated system excluding the Teensy 4.0, the optional OLED display, and miscellaneous mounting hardware. It may be necessary or desirable to tweek the Cart to your liking. ;-)

Wiring the Cables

For the normal RS422 differential signals provided by the 5517/5501B laser and 10780 optical receiver, BOTH the true and complement polarities of each one must be connected to the µMD2 inputs or else strange and random behavior will result. For a single channel Homodyne system this means 1A and 1B, and 2A and 2B. For a single channel Heterodyne system this means REF and ~REF, and MEAS1 and ~MEAS1 as shown below:

Typical µMD2 Wiring for a Single Axis System

The extension to multi-channel systems should be obvious. ;-)

Note that it doesn't matter if the signal and its complement (e.g., REF and ~REF) are swapped in the wiring. So there is no need to obsess over whether they match the markings on the 10780 or µMD2 PCB.

For RS422 differential signals, it's usually not necessary to run the return to the board even if there is no common ground connection between the board and their source. The terminating resistors will provide the ground reference. In fact, under some conditions where everything is tied together with a common ground, the return connections could add noise due to a ground loop. The line receivers only care about the difference between the voltage levels for each signal pair as long as the absolute voltage levels are within their common mode and absolute voltage specifications. For cables of a few feet or less, it's almost certain that no connections are required for the Returns. But for long runs, shielded cable or twisted pairs may be desirable. This won't apply to most hobbyist/experimenter applications. :) There has to be a common Ground somewhere though, usually via the power supply.

For single-ended signals like TTL, there are locations on the µMD2 PCB for a voltage divider to set a threshold reference. Check the schematics. A trace with runs from there across the board with pads near each axis so it's easy to wire it to the unused UA9637 inputs. For TTL, the threshold should be set at around 1.4 V. For analog 0-1 V signals, set it at 0.5 V. If they aren't all the same, some creativity will be required. :)

Using the screw terminal blocks, attaching cables is a cinch. Each of the pairs of outer two pins is the signal and its complement. Common/GND is either the center pin (PCB V1.00) or the center-right pin (PCB V1.22). Strip the wires to about 3/16" or 4 mm and insert so that no bare wire is exposed, tighten the screw. If connectors are preferred, Molex/AMP headers can be installed in place of the terminal blocks (not included in the kits but readily available). For other connector types, adapters can be easily constructed.

Arduino Pin Assignments

There's probably little need to know this unless something goes wrong. ;-)

Pins are labeled on the Teensy 4.0 PCB:

   Pin   Arduino Labeling     Homodyne        Heterodyne
  U1-1         GND              GND             GND
  U1-2         D0               1A              REF
  U1-3         D1               1B               -
  U1-4         D2               2A               -
  U1-5         D3               2B               -
  U1-6         D4                -               -
  U1-7         D5               3A               -
  U1-8         D6                -               -
  U1-9         D7               3B               -
  U1-10        D8                -               -
  U1-11        D9                -             MEAS1
  U1-12        D10               -             MEAS2
  U1-13        D11               -               -
  U1-14        D12               -               -

  U1-15        D13          Stutus LED           -
  U1-16        D14               -             MEAS3
  U1-17        D15               -               -
  U1-18        D16               -               -
  U1-19        D17               -               -
  U1-20        D18               -               -
  U1-21        D19               -               -
  U1-22        D20               -               -
  U1-23        D21               -               -
  U1-24        D22               -               -
  U1-25        D23               -               -

  U1-26        3.3V             3.3V            3.3V
  U1-27        GND              GND             GND
  U1-28      VIN (5V)         VIN (5V)        VIN (5V)

CAUTION: Teensy pins are NOT 5V tolerant - they will be unhappy if a 5 V signal is connected to them directly. Thus any signal that may go higher than 3.3V should NEVER be connected to them, even for an instant. Bad things may happen. 3.3V is acceptable through a current limiting resistor (just to be doubly safe, for the micro that is). Hooking raw power to what may be a logic output (accidentally or otherwise) is never a good thing! P.S. "Unhappy" and "Bad things may happen" could mean that you'll ruin the Teensy board.

The pin assignments for REF, MEAS1, MEAS2, and MEAS3 for heterodyne are preliminary and may change without any notice of any kind, even to the developers.

The µMD2 Firmware

Latest Versions of the Firmware

The (non-Alpha) versions of the firmware are absolutely guaranteed to be new and improved in terms of features, capabilities, and performance. This probably means there will be some new and improved bugs as well. The Alpha versions are even more likely to have some juicy bugs. Please contact us via the link at the top of this page should any dare to appear (or for any other legitimate reason). ;-)

There is separate firmware for homodyne and heterodyne and whatever version is pre-loaded will likely be out of data anyhow. :( :) For this reason, and because it may be necessary to configure the firmware, one of the following should be compiled and loaded:

CAUTION: Running firmware incompatible with the PCB board version and/or usage (heterodyne or homodyne) may result in strange and unpredictable behavior.

Firmware Hardware Assignments and Communications Format

Here are the Teensy signals for both homodyne and heterodyne:

Homodyne V1.26: This should be stable.

   Input  Timer  Arduino Pin  Teensy Pin
    1A      1        D1          3
    1B      1        D2          4
    2A      2        D3          5
    2B      2        D4          6
    3A      3        D5          7
    3B      3        D7          9

Heterodyne firmware V2.20: This version frees up D13 to be the used for status or the heartbeat indicator, as well as shortening PCB trace lengths. V2.20 and V2.09 are otherwise functionally equivalent. These also apply to V2.47r and other newer versions should they appear.

   Input  Timer  Arduino Pin  Teensy Pin
    REF     2        D0          2
   MEAS1    4        D9         11
   MEAS2    1       D10         12
   MEAS3    3       D14         16

Heterodyne firmware V2.09: Original released version. About the only reason to use V2.09 would if you have already wired the jumpers on the SG-µMD2 PCB with these pin assignments.

   Input  Timer  Arduino Pin  Teensy Pin
    REF     4        D9         11
   MEAS1    1       D10         12
   MEAS2    2       D13         15
   MEAS3    3       D14         16

The status LED on D13 is the heartbeat/status indicator for homodyne depending on firmware version. Currently it pulses at between a 1 and 2 Hz rate. Since heterodyne firmware V2.09 MEAS2 uses that pin, it is not available. The availability of that critical LED is the major reason for the firmware upgrade. This is all fully subject to change without any notice. ;-)

Most of these details are really only relevant if there is a desire to modify the firmware, which is not advised since no support will be provided if even 1 character in a comment field is changed without prior approval from µMD2 Central. :) This approval process normally requires a minimum of 3 years, 7 months, 24 days, 11 hours, 35 minutes, and 22.37 seconds, but often takes a lot longer. :-) For wiring using the firmware provided, only the pin assignments matter.

Note that if updating firmware, the GUI may also need to be updated and vice-versa. However, given the stability of the GUI, this is unlikely. And none of the 5,263,782.5 known bugs are significant enough to recall the µMD2 crew back from their extended vacation any time soon.

Here is the communications format between the firmware and GUI. This information is of little relevance if using the GUI, but will be useful if writing your own application software or for data analysis. Each of the values is sent as an ASCII string representing a signed (if needed) decimal number separated by spaces at the sampling rate. The firmware maintains a FIFO buffer so that if the USB data is delayed for some reason, no data should be lost (hopefully):

The same format is used for both homodyne and Heterodyne modes but not all fields will be filled in or relevant for homodyne.

 Standard (Single Axis) Data (8 values):

   0: Axis 1 Count/REF Frequency Count* = REF frequency/Sample Frequency
   1: MEAS Frequency Count 1* = MEAS 1 frequency/Sample Frequency
   2: Displacement 1 (in 1/2, 1/4, or 1/8 wavelength)
   3: Velocity Count 1 = (Displacement 1 - Previous Displacement 1)/Sample Frequency
   4: Phase 1 = Signed fractional offset between Displacement increments.  The
      typical range is -128 to +127 (8 bit 2's complement).

      If Phase is not valid, then an error code is sent instead (heterodyne

        0x200 = no counter 1st REF
        0x400 = no counter 2nd REF
        0x800 = no counter MEAS 1
        0x1000 = no PORTB 1st REF
        0x2000 = no PORTB 2nd REF
        0x4000 = no PORTB MEAS 1

   5: Sequence Number (Unique serial number for each sample)
   6: LowSpeedCode (See below)
   7: LowSpeedData (see below)
   The following 8 values will also be sent when Multiple Axis Mode is active:

   8: Axis 2 Count/MEAS Frequency Count 2*
   9: Displacement 2
  10: Velocity Count 2
  11: 0/Phase 2
  12: Axis 3 Count/MEAS Frequency Count 3*
  13: Displacement 3
  14: Velocity Count 3
  15: 0/Phase 3

  LowSpeedCode (specifies contents of LowSpeedData):

     0-99: GUI Data/Control:

      0: No Data
      1: Laser Power
      2: Signal Strength
      3: Temperature 1 (XXX.YY, °C, 0 to 70.00)
      4: Temperature 2 (XXX.YY, °C, 0 to 70.00)
      5: Pressure (XXX.YY mBar, 500.00 to 2000.00)
      6: Humidity (XXX.Y percent, 0 to 100.0)

      8: Sample Frequency (XXX.YY Hz)

     10: Firmware Version (XXX.YY)

     20: Homodyne Interferometer (if non-zero)
          Low byte: # homodyne axes
          Next byte: counts/cycle (4 for quadpulse)

     (Not all of these are currently implemented.)

   100-199: Diagnostics

   200-255: Reserved

* The REF and MEAS Counts are the incremental change since the last sample, NOT the total value.

Loading the Arduino IDE

(If you purchased the from me directly, or via eBay, the latest released version of the firmware has been preloaded, so the following step should not be necessary unless a later release is available or you would like to hack the firmware - which is not really recommended.)

The Arduino IDE will work with all versions of the firmware. As of Spring 2021, the latest version that supports the Teensy is 1.8.13. It can be downloaded free from the Arduino Web Site but since it isn't the latest, go to "Software", "Previous Release", and there will be an option for version 1.8.13. Save it to your Downloads directory or any other convenient location. It will probably be an executable, so just run it. There is no actual installation, it will just unpack and copy files to the selected Arduino program directory. (With Windows, this is typically located under "Program Files" or something similar but has no relation to where the actual sketches and contributed libraries may be located.) It can be named anything but "Arduino IDE" or "Arduino V1.8.13" are suggestions.

Go to Download Teensyduino.... and follow the instructions for your OS (assuming Windows). If this is your first time using an Arduino board, it may ask to install the device driver. When it finished, start the Arduino IDE and go to "Tools", "Board", "Teensyduino", and select "Teensy 4.0".

If the OLED display is enabled ("#define OLED 1" is present and not commented out near the start of the firmware), an additional library will be required. Go to "Tools", "Manage Libraries", search for "u8x8" and install the library that it finds.

Plug the board into any available USB port. Windows should recognize it. Go to "Tools", "Port", and select the correct port. With the µMD2 firmware, it will be named something like "COM7 Serial (Teensy 4.0)".

Note: Plugging in a virgin :) Teensy (one probably having only the Blink sketch or another one that doesn't open a COM port) may result in Windows issuing notifications about installing a new device. It's best to wait until that completes before attempting to upload a sketch. Before then, the COM Port in "Tools","Port" may be something strange. This should not be an issue with Teensys having µMD2 firmware pre-loaded.

Windows seems to like to reassign Teensy COM ports for unfathomable reasons, so check COM port setting for uploads and the µMD2 GUI.

Uploading the µMD2 Firmware

If you purchased the from me directly, or via eBay, the latest released version of the firmware has been preloaded, so the following step should not be necessary unless a later release is available or you would like to hack the firmware - which is not really recommended.

The firmware (via the links, above) is provided as a source file which probably has an extension of ".pde" or ".ino" (though the specific name doesn't matter - it's just a text file). However, the name may NOT contain any dashes "-" due to the peculiar restrictions of Java or something. Make a directory with the name of the firmware (without the extension) and put the firmware file there. For example, if the file is named umd2_FW_v123.ino, make a directory called umd2_fw_v123. and put umd2_FW_v123.ino in it. Note that case matters so the name of the directory and name of the firmware file (without the extension) must match case character-by-character exactly. Thus Interferometer.pde is not the same as interferometer.pde

In my experience so far, compiling and uploading firmware has been a bit fiddly for the Teensy 4.0, mostly related to the USB (COM) port assignments and whether or not the software or hardware reset button needs to be depressed. These were never issues with the Atmega boards. More to come on this topice as it becomes available.

  1. Plug the board into a USB port. I've occasionally seen problems using a USB port replicator though these generally are acceptable. But if the board doesn't come up or behavior is more erratic than usual, go to a direct USB port.

  2. Use Ctrl-O to open the firmware file. Select the directory, double click on it, and then open the firmware file itself. The source code should appear in the same window unless a file is already open, in which case a new window will appear.

    (Or for testing, just go to Files->Examples->01.Basics->Blink and upload that. It's easy to make change and then see immediately that thay are taking effect without risking the rest of the Universe.)

  3. Use Ctrl-U to compile and upload the firmware to the board. This typically takes a minute or two, unlike UECIDE which may finish almost before the command is issued. :( :) Once complete, status lines will appear at the bottom of the Arduino window, the board will be automatically reset and start running the firmware. No other status messages will appear unless there are errors.

    Windows should recognize that the COM port dropped out momentarily and reappeared. The µMD2 firmware will be spitting out sequences of numbers at the sampling rate. These may be viewed by going to: Tools->Serial Monitor. With no interferometer hardware, they will be rather boring with only the sixth value incrementing sequentially (Sequence Number) and the 7th and 8th values cycling among some obscure numbers (Low Speed Code and Low Speed Data). To Windows, the board appears as a COM port. Thus any application that processes COM port data can be used in place of the µMD2 GUI, should this be desired.

    If the firmware crashed somehow, Windows may display a message saying something about the USB port not working. But that shouldn't happen with any firmware downloaded from here. :) And on rare occasions a cosmic ray or hardware glitch may result in the upload failing with a checksum or other error. Just try again. If the selected COM port is incorrect, cancel and retry.

    Sometimes the Arduino IDE decides to change the COM port for no good reason I can fathom. Go to Tools->Port, and make sure it has selected the COM Port with "(Teensy)" after it.

Once loaded, the firmware is retained in non-volatile memory so this only needs to be done at most once - or until a firmware update is available!

The firmware may also be compiled without uploading by using Ctrl-R. Since you haven't messed with the code, it should compile without errors. This is slightly faster for testing and doesn't use the board at all so it can be off doing whatever it pleases. :)

Important: Terminate any instances of the µMD2 GUI before uploading the firmware and put the board into program mode (again if necessary) AFTER doing this even if LED1 is flashing.

Testing the Board and Firmware

With µMD2 firmware loaded, the simplest way to test that the board is working without running the GUI is to use the "Serial Monitor" (under "Tools" in the Arduino IDE.) With the board reset, then open the Serial Monitor. For only one axis enabled, the terminal window should begin spewing forth data similar to the following:

  0 0 0 0 0 18016 0 0
  0 0 0 0 0 18017 10 124
  0 0 0 0 0 18018 8 100000
  0 0 0 0 0 18019 0 0
  0 0 0 0 0 18020 0 0
  0 0 0 0 0 18021 0 0
  0 0 0 0 0 18022 0 0
  0 0 0 0 0 18023 0 0
  0 0 0 0 0 18024 0 0
  0 0 0 0 0 18025 0 0
  0 0 0 0 0 18026 0 0
  0 0 0 0 0 18027 0 0
  0 0 0 0 0 18028 0 0
  0 0 0 0 0 18029 20 4099 
  0 0 0 0 0 18030 0 0

If all three axes are enabled in the firmware, the terminal window should begin spewing forth data similar to the following:

  0 0 0 0 0 18016 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 18017 10 124 0 0 0 0 0 0 0 0
  0 0 0 0 0 18018 8 100000 0 0 0 0 0 0 0 0
  0 0 0 0 0 18019 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 18020 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 18021 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 18022 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 18023 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 18024 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 18025 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 18026 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 18027 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 18028 0 0 0 0 0 0 0 0 0 0
  0 0 0 0 0 18029 20 4099 0 0 0 0 0 0 0 0
  0 0 0 0 0 18030 0 0 0 0 0 0 0 0 0 0

If there is a display like one of these with the 6th number incrementing by 1, the board is probably working.

(Should you care, the 6th and 7th values are the "Low Speed Code" and "Low Speed Data", respectively. 10,124 is the firmware version 1.24; 8,100000 is the sample rate of 1,000 x 100, and 20,4099 specifies 3 homodyne axes + a homodyne multiplier of 4 x 256.) Refer back to the main µMD2 manual for more info.

Frequency Counter Firmware

If the OLED is present, V2.47r firmware and above has the option to display the REF frequency and can be used as a stand-alone frequency counter for this or any other application which can provide a signal to the REF RS422 inputs. It has been tested with HP 5517B/C/Ds lasers up to at least 4 MHz but should respond well beyond 20 Mhz.

For the REF frequency display, the following statements near the beginning of the firmware should be set as shown below:

   #define OLED 1                // Enables OLED
// #define OLED_Displacement 1   // Disables display of displacement counts
   #define OLED_REF 2            // Enables display of REF frequency

This will display the REF frequency in large digits on the OLED. Other combinations of the #defines for these three parameters may result in strange behavior but feel free to fix that. ;-)

Only power to the SG-µMD2 PCB is required for the REF frequency display. Power is most conveniently provided by a USB port, USB charger cube, or 5 VDC power supply to +5V on the board or via the USB connector. (A USB backup battery pack would also work but these may shut down if the current is too low, as is likely here.) If connected to a USB port, µMD2 will still behave normally for measurements.

The µMD2 GUI

Latest Version of the GUI

The GUI has been stable for several years with µMD1, with only a few updates mostly relating to environmental compensation. It is compatible with all versions of the firmware. The GUI for µMD2 is identical.

Save the µMD2 GUI .exe file into any convenient directory. (There's a small chance that the first time it's run, an error is produced since there is no configuration file associated with it. Simply continue and the GUI will come up. When it is closed using "Finish", valid settings will be saved so that the error should ot appear again.)

When started, the µMD2 GUI (henceforth simply called the "GUI") comes up in Displacement mode with graphing enabled. The only action required by the user is to select the USB COM port. Once selected, the readout and graph will begin displaying the interferometer data.

Even if there is no encoder or interferometer hardware attached to the board, it is possible to confirm that the Teensy is talking to the GUI. Go to "USB Port" and select the same COM as used to upload the firmware. The graph should immediately start scrolling to the left indicating that it is accepting valid data, even if it is all 0s. With homodyne, there will be no error detection, but the fact that it started scrolling means the communications link is working.


For homodyne mode with µMD2, the default sample rate is fixed at 1,000 samples/second. (1 ks/s/). This can be changed in the firmware. While doing so is strongly discouraged, setting to one of those used by µMD1 (457.76, 610.35, or 732.42 s/s) will not cause problems and the DFT should then return reasonable results, hopefully.

The following is intended for homodyne systems; for specific aspects of the GUI screen displays for heterodyne systems, refer to the Micro Measurement Display 1 (µMD1) Installation and Operation Manual. The actual GUi is identical.

The data includes counts for each axis including displacement, and velocity; a unique sequence number to identify samples; as well as other low speed data such as environmental sensors and diagnostics. (More info can be found a few paragraphs above.) The GUI displays are updated at approximately 60 Hz.

All the screenshots below except for ring laser gyro use simulated data, which was more convenient for developing this manual! However, it also means you can play around and recreate these displays before building your interferometer.

Main Window Controls and Readouts

This graphic below shows the typical GUI main window at startup.

µMD2 Main Window in Displacement Mode with Graphing Enabled (Startup Settings)

(REF, MEAS. and DIFF only valid for heterodyne; may not appear for homodyne. Other mostly meaningless parameters may appear above the WL line depending on if the GUI thinks they are enabled. Go to "Test Mode" to turn them off. The GUI will remember the setting.)

Main Window Controls

The first set are the selection buttons at the top of the window. Note that except for USB Port, these require only a single click to activate:

µMD2 Main Window with Test Mode Function Generator Triangle Displacement Waveform

These may all be accessed via Alt-first letter.

The next set are the buttons, checkboxes, and other widgets on the main window:

The format is slightly modified when Frequency mode is selected. This graphic shows the actual DFT of the triangle waveform in the one above. Note that the DFT coefficients go as 1/N rather than 1/N-squared because it's actually using the velocity data, which is a squarewave.

µMD2 Main Window in Frequency Mode with Graphing Enabled

Main Window Indicators

Next are the various fields for displaying information in the Main Window:

µMD2 Main Window Showing Most Indicator Fields

Interferometer Configuration Window

These entries provide for selection of the type of interferometer used for displacement/velocity measurements, the measurement units to be used for the Main Readout and graph, parameters for the strightness and angular optics, and whether to enable use sub-count interpolation. All interferometer configuration parameters are saved when exiting the GUI.

µMD2 Interferometer Configuration Window

Linear coefficienets:

These settings only affect linear measurements.

Units (as appropriate)

Known quirk: If neither the COM Port or Test Mode is active, switching among the Units buttons will only change the Units lable and/move the decimal point/precision without affecting the readings. Just thought you should know. ;-)

Parameters (as appropriate):


Environmental Compensation Window

This provides for entry of temperature, pressure, and humidity, or to select the use of environmental sensor data if available. All environmental compensation parameters are saved when exiting the GUI.

µMD2 Environmental Compensation window

Note 1: With the current GUI, the Factors for Temperature, Pressure, and Humidity will change based on the entered values However, their exact value is not guaranteed to be meningful and should only be considered for trends. This was supposed to be fixed when the environmental calculations were corrected using the NIST formulas, but the staff assigned to do the work took a couple decades off, sorry.

Note 2: With Environmental Compensation turned OFF, the vacuum wavelength is used in calculations. Therefore, Environmental Compensation should be turned ON for laser interferometers even if using standard values.

Test Mode Window

The primary use of Test Mode is to exercise the GUI without the need for a laser or actual interferometer hardware. :) The only other user function that is useful would to disable error detection suring setup and alignment of the laser and optics.

µMD2 Test Mode Window

Multiple Axis Support:

While the firmware handles up to three measurement axes, only limited support is provided in the GUI due to the software complexity and lack of demand at the present time. (Though it's unlikely any amount of demand will make the slightest difference.) What is present should be enough to get started. It's possible this could chenge in the future but don't hold your breath in anticipation. It may never happen.

The "#define Homodyne n" or "#define Heterodyne n" line in the firmware specifies how many axes will be displayed. The value for "n" may be 1 or 3. Setting it to 2 will do the same thing as 3.

µMD2 Main Window with Multiple Axes Active

All GUI functions apply to the primary axis, which defaults on startup to Axis 1. The primary axis is what the Main Readout, REF/MEAS/DIFF frequency displays, frequency analysis, averaging, and graph apply to. Clicking on the Axis 1, Axis 2, or Axis 3 labels will select it to be the primary axis and change the color of the selected axis label to identify it as the primary axis. The units of the primary axis are also used for the others. Error detection (if enabled) only applies to the primary axis. Averaging is NOT applied to the Axis 1, Axis 2, or Axis 3 readouts, even the one that is the same as the primary axis.

Note that in Multiple Axis Mode, the communications format sends somewhat more data over the USB COM port and the GUI must perform more computation. Thus this may cause problems for a wimpy pre-Jurassic PC operating on the hairy edge of what's possible. Once Multiple Axis Mode is entered using the interferometer hardware, the only way to return to Single Axis Mode is to restart both the firmware and GUI. This is because neither has any way to know whether dropouts of measurement clock signals are due to a beam path being momentarily interruprted or an axis actually being shut off (whatever that might mean).

Test Mode is also capable of exercising all three axes singly or in combination but the function generator data will be the same for all. This is controlled by the Multiple Axis Mode checkbox. When enabled, Axis 1, Axis 2, and Axis 3 checkboxes will appear below it with Axis 1 being the default on startup. Turning Multiple Axis Mode off will put the GUI back in Single Axis Mode. But this will be overidden when Test Mode is turned off if the USB port is enabled and the firmware is running with multiple axes.

Multiple Axis GUI support is no longer under development. So the specifications and behavior are not likely to change much with or without notice. ;-)

Where more than three physical axes are desired, a single laser with enough power can be used with additional beam-splitters as long as the beams can be set up to satisfy the requirements for orientation relative to the interferometers. This should be generally doable but may be tricky especially for something with non-orthogonal geometry like a hexapod. ;-) (Of course accommodating non-orthogonal geometry can be tricky regardless of the number of axes!) Additional instances of the SG-µMD2 PCB will function on the same PC with the µMD GUIs in separate windows. Each could have different sets of units like Displacement and Angle. None of this has been tested though so your mileage may vary. ;) Of course, separate lasers, interferometers, remote reflectors, and SG-µMD2 PCBs can also be used on one PC, which is essentially just multiple systems. Merging saved data for either implementation is left as an exercise for the well motivated student.

Help Menu

µMD2 About Window

Heterodyne Interpolation

In principle, interpolation using the Teensy 4.0 platform should be able to improve the resolution to 1 or 2 nm or below from where it is now at 158 nm using a Plane Mirror Interferometer. (Due to possible asymmetries in the high and low portions of REF and MEAS electrical signals, the default double resolution mode is not currently being used with interpolation.) And for the most part, this has been achieved. It produces fabulously smooth and accurate sub-wavelength resolution. However, there are still serious issues resulting in "glitches" in displacement over a small part of the range of relative phase of REF and MEAS when close to 0°. The following information is intended to present the theory, implementation up to the present time, and possible approaches to solving the glitch issue or at least minimizing it. Anyone who is really determined to get interpolation working is free to give it their best shot. I will assist but will probably not get down in the weeds of coding at the present time.

µMD1 used generally similar techniques but due to the superior I/O architecture of the PIC32, any glitches were far fewer and could be effectively eliminated using minimal averaging. While the Teensy 4.0 has fabulous clock speed specifications, I/O is quite mediocre (or at least we haven't found a way to take advantage of its full potential).

The approach to interpolation

In a nutshell, the basic idea is to capture snapshots of the digital REF and MEAS waveforms and compute their relative phase. During each sample period (1 ms), buffers are loaded with the I/O bits for the REF and MEAS counters, the edges are located and their positions are averaged over as many will fit into the buffers, currently set to 1,000. The resulting phase is converted to a fraction of the raw resolution adjusted for the interferometer optics and used as the Phase value returned by the firmware via USB. Up to that point, everything works GREAT!

The problem occurs when the relative phase of REF and MEAS is close to zero - their rising edges occur nearly at the same time. Since the waveform sampling in firmware cannot be done at exactly the same time as the hardware counters are sampled, there is an uncertaintly in the actual value of displacement to which the Phase value refers. Put another way, a change in displacement computed using the waveforms cannot be correlated with a change in the displacement computed using the REF and MEAS hardware counters. Over most of the range of phase between REF and MEAS, there is no problem. Only where their edges are very close together does the uncertainty arise. When far enough apart - which is only a small fraction of the REF or MEAS period - there is no ambiguity. This range can be minimized with careful coding but not be eliminated entirely.

It is believed that even a hardware implementation this algorithm would suffer from the same issues, but the probability of glitches occuring could be reduced to a vanishing small enough value to be irrelevant. However, other approaches would be available in hardware that are not available in firmware to potentially totally eliminate it.

However, there should be heuristic approaches to dealing with the conditions that cause the glitches and eliminate them or greatly reduce their effect.

Interpolation Algorithm Description

(For this description, only Axis 1 assumed, but the same computation would be required for axes 2 and 3.)

Two values must be determined to define a unique displacement with sub-wavelength resolution:

  1. The integer count equal to the difference between the total accumulated counts for REF and MEAS1.

  2. The relative phase of the REF and MEAS signals.

The interger counts are kept track of in the Teensy 4.0's 4 hardware "Timers", configured as individual 64 bit counters. Without interpolation, simple integer calculation on these is sufficient to provide all the information needed by the µMD2 GUI. Most of that code is identical with or without interpolation, and similar to what is in firmware V2.20.

It's the relative phase that is the challenge. The algorithm is roughly as follows:


Currently, there is code following the phase computation in an attempt to remove or at least minimize the glitches. I think it's overly complex with a convoluted state machine (and unfinished as well!).

Here is a simple proposal (so it's on the record): Rather than the full state machine, immediately after the phase calculation, simply test whether both the count has changed by ±1 AND the phase has changed by approximately 1/2 the maximum. If it has, all is fine as that is what should happen. But if only one of those conditions is met, copy the previous values into the current values.

Since the error condition is where there is inconsistency, this *should* detect it and then just use the old values which shouldn't be far off. As long as the inconsistency presists, the old values will continue to be used and only when both change, will it change.

So here is the proposed algorithm. This would be done just after the phase computation: