Automated Field of View System
Last Updated: 15th May 2020By Travis Olds
Table of Contents
In this article I describe the construction of an automated field of view measurement tool for micromineral photographers using a bellows and plan apochromatic objectives. I first need to acknowledge Stephan Wolfsried for his suggestions on how to assemble a high-resolution microphotography system; the setup I use is based primarily on his suggestions and similar components outlined in several of his helpful articles[1]. However, the numerous adapters required to assemble the optical column makes the calculation of field of view difficult, and I was forced to take field of view measurements after each new bellows setting using a micrometer slide for an accurate result. This got tedious and time consuming, so I wanted to design something that could measure, in real time, the field of view (FOV) of any bellows distance used.
The automated FOV system relies on a time-of-flight IR laser distance sensor to measure the bellows extension length. After an external calibration with a micrometer slide, the bellows distance is automatically converted and averaged via code with an Arduino Uno microcontroller to display quite precise (+/- ~0.02 mm) FOV on a LCD screen, updated every second with a rolling average. I have housed the LCD screen and Uno inside a 3D resin-printed case with ¼”-20 screw mount; this is not a necessary component, but I can provide details for its build if you have access to a 3D printer. Considering the cost of most photography equipment, the cost of this adaptation is relatively low (~$100 USD) and can be assembled and up-and-running in roughly 2 hours using these instructions. The Arduino sketch, an example Excel calibration spreadsheet, and .stl files for the optional case are available on github:
https://github.com/toldxls/Automated-FOV-system
*In this build the distance sensor works well on the flat surfaces of a Balpro1 bellows mount, however, I have not tested other bellows – if you use a different bellows it may require some modifications by side mounting the distance sensor. See Step 3 below for more details on how that might be done. Just by eye, the Nikon PB6 and some of the Fotodiox bellows may well work.
Parts list
I’ve listed some of the cheapest options below, however many can be easily substituted.
(prices are relevant ~May 2020)
Soldering kit ($20.95) https://www.amazon.com/Soldering-Iron-Kit-Temperature-Desoldering/dp/B07S61WT16
Arduino Uno R3 ($12.99) https://www.amazon.com/ELEGOO-Board-ATmega328P-ATMEGA16U2-Compliant/dp/B01EWOE0UU
LCD 16x2 shield ($19.95) https://www.adafruit.com/product/772
Breadboard Wires (or any wires really) (~$6) https://www.amazon.com/EDGELEC-Breadboard-Optional-Assorted-Multicolored/dp/B07GD2BWPY
VL1680X ($13.95) https://www.adafruit.com/product/3316
Scotch double sided tape ($7.99) https://www.amazon.com/Scotch-Removable-Dispenser-Standard-667/dp/B00006IF63
A reflective material, white tape/masking tape/label/paper/aluminum foil (~$5) https://www.amazon.com/Avery-All-Purpose-Labels-Inches-White/dp/B000BQOCRK
Micrometer slide (~$10) https://www.amazon.com/0-01mm-Micrometer-Microscope-Camera-Calibration/dp/B078QJHKFX
USB-A extension cable (2 m) ($3.99) https://www.amazon.com/dp/B00007FGU5
Step 1: Uno + LCD shield construction
Adafruit provides an easy to follow installation guide for their LCD shield, see the link below. It involves ~30 minutes of soldering several resistors, a potentiometer, an i2c chip, pin headers and pushbuttons. I did the soldering under a microscope. Note, other LCD “shields” have slightly different pinouts and the LCD itself can have slightly different positioning with respect to the underlying Uno board. Bear in mind that the 3D printed case I designed only fits with the Adafruit shield, however other printable LCD shield cases are available on Thingiverse.com (e.g. the shield from Sainsmart). Below is a photo of the fully assembled shield, including the necessary connections to the VL6180X sensor that will be made in the next step.
LCD shield assembly: https://learn.adafruit.com/rgb-lcd-shield/assembly
Step 2: Powering up and connecting the VL6180X to the Uno
The Uno can be powered via an USB-B cable, the sort used with printers, and additionally I use a 2 meter extension cable to connect it to my PC. NOTE: when first powered on, the LCD backlight will light up but nothing will display. The orange contrast potentiometer on the shield can be adjusted to display characters. With no code uploaded to the Uno, adjusting the potentiometer until boxes appear is close enough. In step 4 you will adjust the potentiometer to set the best contrast for characters on the display.
Assembling the VL6180X: https://learn.adafruit.com/adafruit-vl6180x-time-of-flight-micro-lidar-distance-sensor-breakout/assembly
The connections needed between the Uno and sensor are straightforward and are described in the Adafruit tutorial link above. I will summarize them briefly here. Strip the plastic from all ends of 4 multicolor breadboard wires, solder one wire to the 5V pin on the shield, and the other end of the same wire to the 5V pin on the VL6180X. Do the same for the ground, SCL and SDA pins, being sure to use the 2nd ground terminal on the shield (rightmost GND pin).
Step 3: Mounting the VL6180X sensor and reflective surface
I mount the sensor onto the base of the frontmost inner mount of the Balpro1 using a small piece Scotch double-sided tape, with the laser emitting module and wires towards the bottom. On the Balpro1 there is a convenient gap to guide the sensor wires between the bellows mount and through the rail tracks, out to the Uno and LCD. The infrared laser of the distance sensor is emitted as a relatively narrow cone of light and I have found that my sensor has a useable range of ~10 to ~210 mm under low ambient light levels. In order to preserve its luminosity, it is important not to keep the laser module powered for long periods. After several months of use and several calibrations I have found that the minimum useable range has increased slightly to ~12 mm, with high nonlinearity for measurements below 12 mm. Be sure to remove the plastic covering on the black rectangular laser and detection module of the sensor before continuing - it must have an unobstructed path between the source and the opposing measurement surface, which in my case is the opposing inner edge of the bellows mount. Any obstacles, wires or other materials in the beam path will lead to non-linear or inaccurate distance measurements. On the opposite edge of the bellows mount that reflects the laser pulses I have placed a white sticker label to increase the reflective surface area; a piece of aluminum foil or reflective tape may work even better for this.
If you do not use the Balpro1 bellows and there is not sufficient clearance for the laser (if the baffles of the bellows interfere) then you may have to attach an extension/protrusion from each end of the bellows mounts, one for the laser sensor and one for the opposite measurement face. This might be done easily with two popsicle sticks and tape, but of course a stable and permanent mount (drilled & tapped holes) for the sensor and reflective face are ideal.
Step 4: Load the Arduino Sketch code to the Uno
I have written an Arduino sketch that captures distance data from the sensor and displays it on the LCD screen using a rolling average FOV calculation. You can download the code from the Github link below, or if you are familiar with sketch coding then perhaps you can write something better that suits your needs or your preferred microcontroller.
Download the Arduino IDE for your system from: https://www.arduino.cc/en/Main/Software
Download my sketch file (FOVcalibratedLCDaverage_m6mark2_20x.ino) from: https://github.com/toldxls/Automated-FOV-system
Once installed, the first step is to ensure that the Arduino IDE is connected to your Arduino. An easy way to test this is to click the "Tools" tab, then hover over "Port" to see if a COM channel is given. Another method is to try uploading something to your Uno, by opening and uploading one of the example sketches. The classic test for an LCD is the "Hello World" sketch, and can be opened by clicking "File," then "Examples," navigate down to "Adafruit RGB LCD Shield Library," and click "HelloWorld." To upload the sketch, click "Control" and "U" together, or use the "Sketch" tab and click "Upload." If not connected, try a restart of your computer and repeat. You now need to adjust the orange contrast potentiometer on the shield to have the LCD display text. I needed to make quite a lot of counterclockwise turns before the contrast changes occurred. If the Uno-sensor connections were made properly, the LCD will display "HelloWorld."
Once you've ensured the Uno is connected, open up the "FOVcalibratedLCDaverage..." sketch. There are a series of additional “libraries” that this sketch calls upon in order to function, and they must be installed. In the IDE, click the "Tools" tab, then "Manage Libraries..." and use the white search bar to type in and install the following necessary libraries:
LiquidCrystal
Adafruit_VL6180X
Adafruit RGB LCD Shield Library
Adafruit MCP23017 Arduino Library
Once the library installations have finished, perform a test compile of the sketch by pressing Control + R, or use the "Sketch" tab and click "Verify/Compile," then upload the FOV sketch onto the Uno. The LCD should now display the distance and FOV in mm as in the image below, however until you complete the external calibration the reported FOV will be inaccurate.
Step 5: FOV Calibration
In this step you will calculate the characteristic conversion factors used in the Arduino sketch to convert the measured bellows distance to an average field of view. You will prepare a graph using multiple bellows distances measured by the laser sensor and the corresponding field of view measured with a microscope micrometer. The procedure takes about 30-40 minutes. I use 12 distance measurements with the Balpro1 at ~10 mm intervals (12, 22, 32…. 122). Your conversion factor values will vary depending on the distance between the objective and camera you use, but will also scale proportionally with the magnification of the objective used if they are mutually parfocal. In other words, if you perform the calibration with a 10x objective, but use a different magnification objective of the same focal length for other photos then the FOV reported on the LCD after calibration will be ½ of the reported value if using a 5x objective, 2x for a 20x objective, and so on. The calibration procedure is as follows:
With the sensor mounted, sketch uploaded, and Uno connected and running, open the serial monitor (CTRL+SHIFT+M on windows, or by clicking "Tools," then "Serial Monitor") to view the distance in millimeters reported by the sensor. The sketch will report 2 measurements every second. Although the readout speed can be changed, keep in mind that the LCD screens have a limited refresh rate. If set to refresh very quickly (<0.5 seconds) the LCD text output will become jumbled.
Set the bellows length so that the sensor can take a measurement near the minimum bellows extension. My sensor does not read well below ~12 mm, so I set it to where the sensor reads ~12 +/-2 mm. Next, orient and focus the micrometer slide in the field of view of your camera so that the length of the tick marks are square and in focus over the majority of the live view image (if you use tethered shooting) or captured image. Snap a photo of the micrometer at this distance setting. You will next need to measure the number of pixels between corresponding tick marks in order to calculate the field of view of the image just taken. Open the photograph of the micrometer using a program that can readout the number of pixels; I use “Preview” on MacOS, but the program ImageJ on Windows can also be used.
To calculate the field of view of the image, determine the number of pixels between the markers on your micrometer. I have a micrometer with 0.2 mm demarcations and use the number of pixels found between every 2 marks (0.4 mm). The FOV of your image is the product of the number of horizontal pixels in a full image (Pfull) with the ratio of the distance between demarcations (I use 2 markers, so 0.4 mm) and the number of pixels found between the demarcations (Pcal):
FOV = Pfull x (0.4/Pcal)
For example, I use a Canon M6 Mark II that captures images with 6960 horizontal pixels. At a bellows distance of ~12 mm on the distance sensor and using a 20x objective, the number of pixels between 2 micrometer demarcations is ~1830 pixels. So the FOV of the image at this bellows distance is:
FOV = 6960 x (0.4/1830) = 1.52 mm
Next you will need to calculate an average distance readout from the sensor using the serial monitor. If not already open, press CTRL+SHIFT+M and uncheck the autoscroll option on the serial monitor window, then copy and paste enough values for a good statistical average to Excel/Origin/whichever program you prefer. I use ~1 minute worth of distance measurements, and calculate the average with Excel. My average readout for the first bellows setting was 14.47 mm.
The first calibration point on my graph is then X(measured distance) = 14.47 mm, Y(FOV) = 1.52 mm. Repeat this procedure by moving the bellows another ~10 mm further, snapping a photo once the micrometer is focused and then calculate the average sensor distance readout from the serial monitor. Exact 10 mm steps are not necessary, but being close will allow you to check that the distance measured by the sensor is linear throughout the bellows extension range.
From the series of X,Y points calculate a linear regression to determine the slope and Y intercept of what should be a linear calibration. My values with a 20x objective are -0.005 and 1.5688, with R(squared) = 0.994. An R(squared) closest to 1 is ideal.
Last step: Editing the Sketch Code for your calibration
Replace the slope (X) and Y intercept with your values in the 2 lines of the sketch highlighted below.
Compile the sketch and upload it to the Uno. Once uploaded, the FOV reported on the LCD will need ~10 seconds to reach a stable moving average value. FOV measurements are most precise with very low ambient light levels (room lights off). The system is now ready and should be re-calibrated every few months, or if the sensor or reflective surface is moved. I found that my sensor and reflective material took several days to fully settle in place because neither was permanently mounted.
If you use multiple cameras, or a variety of different objectives/lenses from different manufacturers that are not mutually parfocal then they will each need a separate calibration. In this case, you could prepare a calibrated sketch for each scenario and load the proper file to the Uno when using it.
I hope that this article is helpful to anyone who might enjoy automated FOV readouts. I am open to suggestions on how to make this article and system better, more accurate, or accessible for more micromineral photographers.
Dr. Travis Olds
Assistant Curator of Minerals
Carnegie Museum of Natural History
*UPDATES: Editing the sketch file is now much simpler. At the top of the sketch you will find just two values to edit with your calibration values (float CTRLX = -0.005; float CTRLY = 1.5688;). The calculated FOV values are now constrained to 2 decimal places for the output, which seems to have fixed the text overlap problem for fast refresh rates. Thank you, Jolyon, for those two fixes. So I have also scaled down the size of the array for rolling averages and increased the refresh rate, and response time on bellows distance changes is MUCH faster (~5 seconds)!
Footnotes
Article has been viewed at least 2685 times.
Quick NavParts listStep 1: Uno + LCD shield constructionStep 2: Powering up and connecting the VL6180X to the UnoStep 3: Mounting the VL6180X sensor and reflective surfaceStep 4: Load the Arduino Sketch code to the UnoStep 5: FOV CalibrationLast step: Editing the Sketch Code for your calibrationFootnotes