In Part 1, I talked about important things to know about LabVIEW Units. In this part, I will focus more on a few use cases where I find them valuable.
Depth of Field with LabVIEW Units
When I was first learning how to use LabVIEW Units, I wrote a photography “depth of field calculator” using LabVIEW Units. As many of my readers know, I’m an avid photographer. Check out bhpowell.com! In photography, the “depth of field” is a measure of how much of an image is in focus.
There are four variables that go into calculating depth of field.
- Lens focal length — this is almost always represented in millimeters, such as a 50mm lens.
- Aperture — a unitless measure of how big the lens opening is. It’s like our own eye’s iris, which closes down in bright light, and opens up in low light. Because of the way light travels through the lens, a narrower opening gives greater depth of field. Aperture is also called the “F Stop”, and the bigger the number, the smaller the opening. As we’ll see, it’s also a square relationship (based on area), so an f/4 opening lets in twice as much light as f/5.6, and four times as much as f/8.
- Focus distance — the further away your subject is, the more distance front to back is in focus. The depth of field is relative to this focus point, so with an extreme closeup, you may only have a few millimeters front to back in focus. Distance is measured in whatever is natural for the country we each live in. Feet in the USA, meters almost everywhere else.
- Circle of confusion — this interesting sounding term is a measure of how precise you want to be when you say something is “in focus”. Exact focus is an infinitely tiny point, so the “circle of confusion” is a measure of how much area of the sensor is considered to be the same point. It’s usually measured in fractions of a millimeter, and is usually related to the sensor or file size of the camera.
There’s an example that ships with LabVIEW that demonstrates this simple calculation. It produces three results:
The near and far distance are the front and back distances considered in focus, so everything from 5 to 7.5 meters is in focus when I have a 50mm lens at f/2.8 focused at 6 meters. The example also lets me replace “m” with “ft” and the code stays the same:
The hyperfocal distance is an intermediate computation, and basically answers the question, “at what distance do I need to focus if I want the far horizon to be in focus?” If I were to run the calculation with focus set to 29.8 meters, for example:
The far distance is computed as almost 75 kilometers away, which is effectively infinite. Oh, as an aside, if you use the “SI” numeric display format, it plays nicely with units.
In the example above, instead of showing “74.50k”, it moved the “k” to the unit and automatically became “74.50 km”.
This example lends itself to LabVIEW Units because the computation is a mix of lengths represented with different units–millimeters and meters or millimeters and feet. Having LabVIEW Units as part of the data type provides some guardrails for my programming. If I try to add or subtract aperture from length, the wires will break, letting me know I’ve done something wrong. If, after all my multiplies and divides, I don’t end up with length as a result, I know I’ve left out part of the computation.
Representing duration with LabVIEW Units
Here’s another simple example of where units are useful.
I have one application that acquires data at about 1 Hz, with a front panel graph that can display the last hour, last day, or last week of data. Originally, I encoded the duration as constant containing a number of seconds:
- 3600 (one hour)
- 86,400 (one day)
- 604,800 (one week)
I added a comment next to each to explain what the values mean.
Then it occurred to me that I could put a unit on that value, and instead use:
This is more descriptive, but also more likely to be correct. (If I mistyped “604800” as “608400”, would I immediately recognize that I did it wrong?).
Converting complex formulas with LabVIEW Units
My third example is a customer application that is computing the time a vehicle will reach a particular travel point, based on the vehicle’s velocity and the distance between sensors monitoring its progress. As an added bonus, the system was designed with the metric system in mind (km/h for speed), but the distance displays are both metric (meters) and imperial (feet and inches).
Originally, the operator had to use a spreadsheet with undocumented formulas of velocity and distance, and then paste them into a LabVIEW front panel. The LabVIEW application then took those numbers to program counter/timer hardware.
I replaced the spreadsheet with a LabVIEW VI and used Units. Again, using Units provided guardrails as I translated the algorithm into LabVIEW. As an example, here’s one of the Excel formulas I needed to make sense of:
Based on other documentation, I began to deduce that these specific Excel cell values represented time. From there, I could conjecture that “279” was also time (e.g., milliseconds), and I also conjectured that “40” and “10” were in kHz. (Or was 10 in micro- or nanoseconds? Or in ticks of an 80MHz clock?)
By assigning units to my LabVIEW translation, I’d get a broken wire whenever I didn’t have a unit right. Using units gave me confidence that I understood my code and could document it when I got done. I even went so far as to replace a formula node (a builtin feature that doesn’t work with Units) with add, subtract, and divide primitives (which do work with Units). I kept the formula as a comment, since its algebraic nature is easier to understand at a glance.
When you next write a LabVIEW application that represents a physical unit, I recommend that you give units a try. A fair warning that there’s a bit of a slippery slope to using units. If you add units to one control, there’s a good chance that you’ll want to follow that wire and add units to subVIs and other controls and indicators, and you’ll soon find yourself committed to using units in the application. It’s a good feeling, though, when you’re done.
The other piece of advice, which I mentioned in the previous post, is to not force units into reuse libraries. Sure, use units in a reusable VI if it’s always working with length or another physical unit, but sometimes it’s easier to not have units (even polymorphic ones), and let the user use Convert Unit outside of your reuse library. In other words, it’s okay to define boundaries between components where you will add or remove units.
My point of writing these two blog posts is to encourage you to use Units where they work well, and discourage you from using them where they don’t. I could go on about ways I wished they worked better, but I still think they’re a great feature worthy of more attention.