<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Fadil Eledath, Author at DMC, Inc.</title>
	<atom:link href="https://static.dmcinfo.com/blog/author/fadile/feed/index.xml" rel="self" type="application/rss+xml" />
	<link></link>
	<description></description>
	<lastBuildDate>Fri, 04 Sep 2026 21:36:10 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.2</generator>

<image>
	<url>https://static.dmcinfo.com/wp-content/uploads/2025/04/site-icon-150x150.png</url>
	<title>Fadil Eledath, Author at DMC, Inc.</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>LabVIEW + Python Over TCP: A Reusable Architecture Pattern for Industrial Software</title>
		<link>https://static.dmcinfo.com/blog/47156/labview-python-tcp-integration-architecture/</link>
		
		<dc:creator><![CDATA[Fadil Eledath]]></dc:creator>
		<pubDate>Mon, 13 Jul 2026 11:00:00 +0000</pubDate>
				<category><![CDATA[LabVIEW]]></category>
		<category><![CDATA[Test and Measurement Automation]]></category>
		<category><![CDATA[LabVIEW Programming]]></category>
		<category><![CDATA[Modbus TCP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Systems Integration]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/?p=47156</guid>

					<description><![CDATA[<p>LabVIEW is still one of the best environments for operator interfaces, machine state logic, and deterministic control workflows. However, many teams now need to ship features that evolve faster than traditional LabVIEW development cycles can accommodate, including computer vision, advanced analytics, AI-assisted decision support, and custom tooling. The practical answer is not to rewrite everything. [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/47156/labview-python-tcp-integration-architecture/">LabVIEW + Python Over TCP: A Reusable Architecture Pattern for Industrial Software</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">LabVIEW is still one of the best environments for operator interfaces, machine state logic, and deterministic control workflows. However, many teams now need to ship features that evolve faster than traditional LabVIEW development cycles can accommodate, including computer vision, advanced analytics, AI-assisted decision support, and custom tooling.</p>



<p class="wp-block-paragraph">The practical answer is not to rewrite everything. Instead, a split-runtime architecture allows teams to keep LabVIEW where it shines and move high-change computation into Python services connected over TCP.</p>



<p class="wp-block-paragraph">This Python integration approach supports a wide range of industrial use cases, including:</p>



<ul class="wp-block-list">
<li>Vision inference and image analysis.</li>



<li>Statistical quality calculations.</li>



<li>Optimization and scheduling support.</li>



<li>Report generation and data enrichment.</li>



<li>AI-assisted engineering tools.</li>
</ul>



<p class="wp-block-paragraph">The end result is an architecture in which LabVIEW remains the orchestration and operator-layer interface for complex hardware systems, while Python hosts features that benefit from rapid iteration and rich libraries. One particularly salient reason to integrate Python in this way is that it integrates cleanly with the latest AI coding agents and tooling, supporting accelerated development.</p>



<h2 id="h-why-tcp-is-the-right-approach" class="wp-block-heading">Why TCP Is the Right Approach</h2>



<p class="wp-block-paragraph">There are multiple ways to connect runtimes, many of which DMC has explored across numerous domains. For example, we’ve worked with MQTT, RabbitMQ, NATS, Redis, as well as other messaging tools and protocols. In this tutorial, we use a simple request-reply pattern. Here, TCP is the best fit since it is:</p>



<ul class="wp-block-list">
<li style="padding-bottom:var(--wp--preset--spacing--30)"><strong>Language neutral:</strong>&nbsp;Both LabVIEW and Python support sockets natively.</li>



<li style="padding-bottom:var(--wp--preset--spacing--30)"><strong>Low overhead:</strong>&nbsp;Efficient for frequent request/response cycles without added protocol information.</li>



<li style="padding-bottom:var(--wp--preset--spacing--30)"><strong>Process isolated:</strong>&nbsp;UI/control failures and compute-service failures are easier to contain. No need to manage the lifecycle of a binary outside of two processes communicating with each other.</li>



<li><strong>Flexible in deployment: </strong>Run components on the same machine or distribute later without changing the contract.</li>
</ul>



<h2 id="h-labview-python-tcp-reference-architecture" class="wp-block-heading">LabVIEW Python TCP Reference Architecture</h2>



<p class="wp-block-paragraph">A reusable version of this request-reply pattern looks like this:</p>



<ol class="wp-block-list">
<li>LabVIEW gathers the request parameters and sends a typed request.</li>



<li>The Python service receives the request and executes the requested logic.</li>



<li>Python returns typed results plus optional status and timing metadata.</li>



<li>LabVIEW processes the reply body as needed.</li>
</ol>



<p class="wp-block-paragraph">This same structural loop applies whether the compute workload is vision, forecasting, anomaly scoring, or rule evaluation.</p>



<h2 id="h-socket-wrappers-for-labview-and-python-communication" class="wp-block-heading">Socket Wrappers for LabVIEW and Python Communication</h2>



<p class="wp-block-paragraph">This is a minimal implementation of a socket wrapper that serves as a skeleton you can use to add type safety, error checking, and other safeguards to make your code more robust. The wire format is a fixed header to ensure that reads are deterministic:</p>



<ul class="wp-block-list">
<li style="padding-bottom:var(--wp--preset--spacing--30)"><strong>LabVIEW to Python:</strong> 1 byte message type + 4 byte big-endian payload size + payload bytes.</li>



<li><strong>Python to LabVIEW:</strong> 4-byte big-endian payload size + payload bytes, since the message type defines the response.</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Python</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import json
from enum import Enum


class Lv2PyMessageType(Enum):
    ANALYZE_ANIMAL = 0
    FETCH_WEATHER = 1
    EXIT = 2


class LVSocket:
    def __init__(self, sock):
        self.sock = sock

    def await_message(self) -&gt; tuple&#91;Lv2PyMessageType, bytes&#93;:
        msg_type = Lv2PyMessageType(int.from_bytes(self._recv_exact(1), "big"))
        size = int.from_bytes(self._recv_exact(4), "big")
        return msg_type, self._recv_exact(size)

    def send_message(self, payload: bytes):
        self.sock.sendall(len(payload).to_bytes(4, "big"))
        self.sock.sendall(payload)

    def _recv_exact(self, n: int) -&gt; bytes:
        out = b""
        while len(out) &lt; n:
            chunk = self.sock.recv(n - len(out))
            if not chunk:
                raise ConnectionError("Socket closed")
            out += chunk
        return out</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> json</span></span>
<span class="line"><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> enum </span><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> Enum</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">Lv2PyMessageType</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">Enum</span><span style="color: #D4D4D4">):</span></span>
<span class="line"><span style="color: #D4D4D4">    ANALYZE_ANIMAL = </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">    FETCH_WEATHER = </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #D4D4D4">    EXIT = </span><span style="color: #B5CEA8">2</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">LVSocket</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">__init__</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">sock</span><span style="color: #D4D4D4">):</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.sock = sock</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">await_message</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">) -&gt; tuple&#91;Lv2PyMessageType, </span><span style="color: #4EC9B0">bytes</span><span style="color: #D4D4D4">&#93;:</span></span>
<span class="line"><span style="color: #D4D4D4">        msg_type = Lv2PyMessageType(</span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4">.from_bytes(</span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">._recv_exact(</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">), </span><span style="color: #CE9178">&quot;big&quot;</span><span style="color: #D4D4D4">))</span></span>
<span class="line"><span style="color: #D4D4D4">        size = </span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4">.from_bytes(</span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">._recv_exact(</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">), </span><span style="color: #CE9178">&quot;big&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> msg_type, </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">._recv_exact(size)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">send_message</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">payload</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">bytes</span><span style="color: #D4D4D4">):</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.sock.sendall(</span><span style="color: #DCDCAA">len</span><span style="color: #D4D4D4">(payload).to_bytes(</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;big&quot;</span><span style="color: #D4D4D4">))</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.sock.sendall(payload)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">_recv_exact</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">n</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4">) -&gt; </span><span style="color: #4EC9B0">bytes</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        out = </span><span style="color: #569CD6">b</span><span style="color: #CE9178">&quot;&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">while</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">len</span><span style="color: #D4D4D4">(out) &lt; n:</span></span>
<span class="line"><span style="color: #D4D4D4">            chunk = </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.sock.recv(n - </span><span style="color: #DCDCAA">len</span><span style="color: #D4D4D4">(out))</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> chunk:</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #C586C0">raise</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">ConnectionError</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Socket closed&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">            out += chunk</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> out</span></span></code></pre></div>



<figure class="wp-block-image size-full is-resized"><img fetchpriority="high" decoding="async" width="577" height="220" src="https://static.dmcinfo.com/wp-content/uploads/2026/07/labview-python-over-tcp-1.png" alt="LabVIEW block diagram showing TCP/IP communication using TCP Read and Write functions, including payload handling, connection management, and error handling clusters." class="wp-image-47162" style="aspect-ratio:2.6228373702422147;width:839px;height:auto" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/07/labview-python-over-tcp-1.png 577w, https://static.dmcinfo.com/wp-content/uploads/2026/07/labview-python-over-tcp-1-300x114.png 300w" sizes="(max-width: 577px) 100vw, 577px" /></figure>



<h2 id="h-service-loops" class="wp-block-heading">Service Loops</h2>



<p class="wp-block-paragraph">The service itself is just a&nbsp;<code>while True</code>&nbsp;loop: wait for a typed message, branch on it, compute, and send the reply. This pattern keeps the service logic straightforward and maintainable.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Python</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import socket

PORT = 12345

def analyze_animal(payload):
    # parse the payload for this message and generate your response here
    ...

def fetch_weather(payload):
    # parse the payload for this message and generate your response here
    ...

def serve(sock):
    lv = LVSocket(sock)
    while True:
        msg_type, payload = lv.await_message()
        if msg_type == Lv2PyMessageType.ANALYZE_ANIMAL:
            result = analyze_animal(payload)
            lv.send_message(json.dumps(result).encode("utf-8"))
        elif msg_type == Lv2PyMessageType.FETCH_WEATHER:
            result = fetch_weather(payload)
            lv.send_message(json.dumps(result).encode("utf-8"))
        elif msg_type == Lv2PyMessageType.EXIT:
            break

if __name__ == "__main__":
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind(("localhost", PORT))
        s.listen()
        print("Waiting for LabVIEW to connect...")
        conn, addr = s.accept()
        print(f"Connected by {addr}")
        with conn:
            serve(conn)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> socket</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">PORT = </span><span style="color: #B5CEA8">12345</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">analyze_animal</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">payload</span><span style="color: #D4D4D4">):</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># parse the payload for this message and generate your response here</span></span>
<span class="line"><span style="color: #D4D4D4">    ...</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">fetch_weather</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">payload</span><span style="color: #D4D4D4">):</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># parse the payload for this message and generate your response here</span></span>
<span class="line"><span style="color: #D4D4D4">    ...</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">serve</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">sock</span><span style="color: #D4D4D4">):</span></span>
<span class="line"><span style="color: #D4D4D4">    lv = LVSocket(sock)</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">while</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">True</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        msg_type, payload = lv.await_message()</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> msg_type == Lv2PyMessageType.ANALYZE_ANIMAL:</span></span>
<span class="line"><span style="color: #D4D4D4">            result = analyze_animal(payload)</span></span>
<span class="line"><span style="color: #D4D4D4">            lv.send_message(json.dumps(result).encode(</span><span style="color: #CE9178">&quot;utf-8&quot;</span><span style="color: #D4D4D4">))</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">elif</span><span style="color: #D4D4D4"> msg_type == Lv2PyMessageType.FETCH_WEATHER:</span></span>
<span class="line"><span style="color: #D4D4D4">            result = fetch_weather(payload)</span></span>
<span class="line"><span style="color: #D4D4D4">            lv.send_message(json.dumps(result).encode(</span><span style="color: #CE9178">&quot;utf-8&quot;</span><span style="color: #D4D4D4">))</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">elif</span><span style="color: #D4D4D4"> msg_type == Lv2PyMessageType.EXIT:</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">break</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">__name__</span><span style="color: #D4D4D4"> == </span><span style="color: #CE9178">&quot;__main__&quot;</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">with</span><span style="color: #D4D4D4"> socket.socket(socket.AF_INET, socket.SOCK_STREAM) </span><span style="color: #C586C0">as</span><span style="color: #D4D4D4"> s:</span></span>
<span class="line"><span style="color: #D4D4D4">        s.bind((</span><span style="color: #CE9178">&quot;localhost&quot;</span><span style="color: #D4D4D4">, PORT))</span></span>
<span class="line"><span style="color: #D4D4D4">        s.listen()</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #DCDCAA">print</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Waiting for LabVIEW to connect...&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">        conn, addr = s.accept()</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #DCDCAA">print</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">f</span><span style="color: #CE9178">&quot;Connected by </span><span style="color: #569CD6">{</span><span style="color: #D4D4D4">addr</span><span style="color: #569CD6">}</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">with</span><span style="color: #D4D4D4"> conn:</span></span>
<span class="line"><span style="color: #D4D4D4">            serve(conn)</span></span></code></pre></div>



<p class="wp-block-paragraph">We can handle these messages from LabVIEW using the built-in TCP functions and pass a wide range of data in the message body.</p>



<h2 id="h-lifecycle-management" class="wp-block-heading">Lifecycle Management</h2>



<p class="wp-block-paragraph">The next step is to start and stop our Python script along with our LabVIEW code while gracefully handling errors and exits. We can use the&nbsp;<code>System Exec.vi</code>&nbsp;function to accomplish this, as shown in the snippet below.</p>



<p class="wp-block-paragraph">We can also safely manage the lifecycle of the Python script by, in addition to the EXIT message type, adding handling for socket disconnections by gracefully exiting the Python script if the socket is closed from the LabVIEW side. With this approach, operators can restart Python service, for any reason, by simply stopping and restarting the LabVIEW application, without needing to manage the Python process separately.</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img decoding="async" width="1174" height="541" src="https://static.dmcinfo.com/wp-content/uploads/2026/07/labview-python-over-tcp-2.png" alt="LabVIEW block diagram showing TCP/IP data reception for an Analyze Animal function, including external script execution via command line, resource management, and error handling using case structures." class="wp-image-47163" style="aspect-ratio:2.172079421271356;width:1200px;height:auto" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/07/labview-python-over-tcp-2.png 1174w, https://static.dmcinfo.com/wp-content/uploads/2026/07/labview-python-over-tcp-2-300x138.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/07/labview-python-over-tcp-2-1024x472.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2026/07/labview-python-over-tcp-2-768x354.png 768w" sizes="(max-width: 1174px) 100vw, 1174px" /></figure>



<h2 id="h-packaging-for-deployment" class="wp-block-heading">Packaging for Deployment</h2>



<p class="wp-block-paragraph">Finally, to deploy this architecture, package the Python script so it can be distributed alongside the LabVIEW build for client systems. This can be done with tools like PyInstaller, which creates a standalone executable from your Python script. You can then conditionally call this executable from LabVIEW using the&nbsp;<code>System Exec.vi</code>&nbsp;as shown below. This approach simplifies testing in development and deployment to production without needing to manage Python environments on the target machines.</p>



<h2 id="h-reliability-requirements-for-production" class="wp-block-heading">Reliability Requirements for Production</h2>



<p class="wp-block-paragraph">Industrial systems need graceful behavior under real-world conditions, including dropped connections, overloaded services, and operator restarts.</p>



<p class="wp-block-paragraph">Baseline reliability checklist includes:</p>



<ul class="wp-block-list">
<li>Request timeout and retry policy.</li>



<li>Reconnect strategy with back-off.</li>



<li>Health check or heartbeat message.</li>



<li>Structured logs on both sides.</li>



<li>Fail-safe startup and shutdown behavior.</li>



<li>Logging of exceptions and edge cases for postmortem analysis.</li>
</ul>



<p class="wp-block-paragraph">These patterns are essential for production readiness, and they also build trust with operations teams by ensuring the system won&#8217;t fail silently or require manual intervention.</p>



<h2 id="h-why-integrating-python-matters-for-ai-adoption-in-labview-teams" class="wp-block-heading">Why Integrating Python Matters for AI Adoption in LabVIEW Teams</h2>



<p class="wp-block-paragraph">This architecture also enables AI adoption. It allows teams to build key software components outside LabVIEW, where AI-assisted development can be faster due to:</p>



<ul class="wp-block-list">
<li>Rapid prototyping of analysis components.</li>



<li>Quick generation of helper tools and scripts.</li>



<li>Faster experimentation with algorithms and thresholds.</li>



<li>Simplified profiling and optimization workflows.</li>
</ul>



<p class="wp-block-paragraph">LabVIEW still governs system behavior; Python becomes the iteration engine. This division allows teams to leverage AI productively while preserving control-system rigor.</p>



<h2 id="h-key-takeaways" class="wp-block-heading">Key Takeaways</h2>



<ul class="wp-block-list">
<li>LabVIEW + Python over TCP is a reusable and extensible architecture pattern across many industrial use cases.</li>



<li>Keep LabVIEW for orchestration and UI; externalize high-change compute to Python.</li>



<li>The pattern creates a practical path for AI-assisted software development in industrial systems.</li>
</ul>



<p class="wp-block-paragraph">If you want to modernize an existing LabVIEW application, TCP-connected Python services are one of the highest-leverage places to start.</p>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step">Partner with DMC to accelerate your next LabVIEW project.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">DMC’s <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/">Test &amp; Measurement </a>experts can help you design and deploy robust TCP-based architectures tailored to your application.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://static.dmcinfo.com/blog/47156/labview-python-tcp-integration-architecture/">LabVIEW + Python Over TCP: A Reusable Architecture Pattern for Industrial Software</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Use Raspberry Pi as a DAQ Device in LabVIEW</title>
		<link>https://static.dmcinfo.com/blog/46615/raspberry-pi-labview-data-acquisition/</link>
		
		<dc:creator><![CDATA[Fadil Eledath]]></dc:creator>
		<pubDate>Wed, 08 Jul 2026 11:00:00 +0000</pubDate>
				<category><![CDATA[LabVIEW]]></category>
		<category><![CDATA[Test and Measurement Automation]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[Data Acquisition]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/?p=46615</guid>

					<description><![CDATA[<p>LabVIEW simplifies the process of quickly acquiring data from hardware and processing it into an output for application users. Compared to text-based programming languages, LabVIEW’s treatment of data flow as code makes tasks like parallel processing and hardware resource management much simpler. This is especially true when using hardware created by the group behind it, [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/46615/raspberry-pi-labview-data-acquisition/">How to Use Raspberry Pi as a DAQ Device in LabVIEW</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">LabVIEW simplifies the process of quickly acquiring data from hardware and processing it into an output for application users. Compared to text-based programming languages, LabVIEW’s treatment of data flow as code makes tasks like parallel processing and hardware resource management much simpler. This is especially true when using hardware created by the group behind it, National Instruments. Their DAQ (data acquisition) devices are designed for ease of use in the LabVIEW programming environment and can be configured and used in code to effectively replace typical workbench equipment.</p>



<p class="wp-block-paragraph">There are, of course, other types of hardware that someone might want to acquire data from. Our clients often need us to integrate all kinds of equipment based on their technical and budget needs from a specialized hipot meter to a general-purpose DMM. One such client needed us to integrate a Raspberry Pi, which was collecting data from a set of sensors, with a LabVIEW app that was already collecting data from NI hardware.</p>



<p class="wp-block-paragraph">Raspberry Pis are pretty popular among hobbyists and hardware engineers alike for prototyping and actual production use since they’re inexpensive, fairly robust, and have a broad ecosystem of products that work nicely with them. Their GPIO (General Purpose Input/Output) pins make it easy to interface with hardware over different low-level protocols like SPI or I2C. The boards also come with WiFi, Bluetooth, Ethernet, and USB if you need to connect to something over a higher-level interface. This brings us to the question of how to use a Raspberry Pi in a way that is fast and reliable from a LabVIEW application running on a separate PC—effectively using it as a DAQ device.</p>



<h2 id="h-the-easy-way-fastapi" class="wp-block-heading">The Easy Way: FastAPI</h2>



<p class="wp-block-paragraph">Let&#8217;s begin with a simple approach—we can set up a minimal REST API service on the Raspberry Pi using FastAPI that, when queried, creates and returns your measurement.</p>



<h3 id="h-setting-up-the-api" class="wp-block-heading">Setting Up the API</h3>



<p class="wp-block-paragraph">FastAPI is a modern Python web framework that makes it simple to create REST APIs. On your Raspberry Pi, you can install it along with a production server like <code>uvicorn</code>:</p>



<p class="wp-block-paragraph"><code>pip install fastapi uvicorn</code></p>



<p class="wp-block-paragraph">Then create a simple API endpoint that reads from your sensor:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Python</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>from fastapi import FastAPI
import time

app = FastAPI()

@app.get("/sensor/read")
def read_sensor():
    # Your sensor reading code here
    # For example, reading from an I2C device
    value = read_i2c_sensor()
    timestamp = time.time()

    return {
        "value": value,
        "timestamp": timestamp
    }

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> fastapi </span><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> FastAPI</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> time</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">app = FastAPI()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">@app.get</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;/sensor/read&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">read_sensor</span><span style="color: #D4D4D4">():</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># Your sensor reading code here</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># For example, reading from an I2C device</span></span>
<span class="line"><span style="color: #D4D4D4">    value = read_i2c_sensor()</span></span>
<span class="line"><span style="color: #D4D4D4">    timestamp = time.time()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #CE9178">&quot;value&quot;</span><span style="color: #D4D4D4">: value,</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #CE9178">&quot;timestamp&quot;</span><span style="color: #D4D4D4">: timestamp</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">__name__</span><span style="color: #D4D4D4"> == </span><span style="color: #CE9178">&quot;__main__&quot;</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> uvicorn</span></span>
<span class="line"><span style="color: #D4D4D4">    uvicorn.run(app, </span><span style="color: #9CDCFE">host</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;0.0.0.0&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">port</span><span style="color: #D4D4D4">=</span><span style="color: #B5CEA8">8000</span><span style="color: #D4D4D4">)</span></span></code></pre></div>



<p class="wp-block-paragraph">From LabVIEW, you can use the HTTP Client VIs to make GET requests to <code>&lt;http://your-pi-ip:8000/sensor/read&gt;</code> and parse the JSON response to extract your sensor data.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="620" height="269" src="https://static.dmcinfo.com/wp-content/uploads/2026/07/raspberry-pi-with-labview-application-1.png" alt="LabVIEW block diagram performing an HTTP GET request to a Raspberry Pi, parsing JSON sensor data, timestamping results, and processing output with built-in error handling." class="wp-image-46842" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/07/raspberry-pi-with-labview-application-1.png 620w, https://static.dmcinfo.com/wp-content/uploads/2026/07/raspberry-pi-with-labview-application-1-300x130.png 300w" sizes="(max-width: 620px) 100vw, 620px" /></figure>



<h3 id="h-the-issues" class="wp-block-heading">The Issues</h3>



<p class="wp-block-paragraph">While this approach is straightforward and gets you up and running quickly, it has some significant limitations for serious data acquisition:</p>



<p class="wp-block-paragraph"><strong>Not Truly Time-Series</strong>: Each request creates a new measurement on demand. If you&#8217;re trying to capture a continuous stream of data, you&#8217;ll miss all the samples between requests. This is fine for slow-changing values like temperature readings every few seconds, but inadequate for high-speed data acquisition.</p>



<p class="wp-block-paragraph"><strong>Request Overhead</strong>: Every HTTP request involves substantial overhead, TCP handshaking, HTTP headers, JSON serialization/deserialization, and network latency. If you need to sample at high rates (say, 1000 samples per second), making 1000 individual HTTP requests per second is inefficient and will likely introduce timing jitter and missed samples.</p>



<p class="wp-block-paragraph">For applications where you need occasional readings or the data changes slowly, this approach works great. But for continuous, high-speed data acquisition, we need something better.</p>



<h2 id="h-the-high-speed-way-redis-streams" class="wp-block-heading">The High-Speed Way: Redis Streams</h2>



<p class="wp-block-paragraph">Redis is an in-memory data structure store that&#8217;s fast and supports various data types, including streams &#8211; perfect for time-series data collection. The architecture here is more sophisticated but provides much better performance:</p>



<p class="wp-block-paragraph">In production, you may implement the sensor loop in C or another lower-level language for tighter timing, but Python is a good way to understand and prototype the architecture.</p>



<ol class="wp-block-list">
<li>A Python process on the Raspberry Pi continuously reads sensors and writes to a Redis stream.</li>



<li>Redis stores the data in memory as a time-ordered stream.</li>



<li>LabVIEW periodically reads from the stream, getting batches of new data.</li>



<li>Webdis provides an HTTP interface to Redis, making it accessible from LabVIEW.</li>
</ol>



<h3 id="h-setting-up-redis" class="wp-block-heading">Setting Up Redis</h3>



<p class="wp-block-paragraph">First, install Redis on your Raspberry Pi:</p>



<p class="wp-block-paragraph"><code>sudo apt-get install redis-server</code></p>



<p class="wp-block-paragraph">Install the Python Redis client as well:</p>



<p class="wp-block-paragraph"><code>pip install redis</code></p>



<p class="wp-block-paragraph">Configure Redis to start on boot and ensure it&#8217;s listening on the network if your LabVIEW application is on a different machine:</p>



<p class="wp-block-paragraph"><code>sudo systemctl enable redis-server<br>sudo systemctl start redis-server</code></p>



<h3 id="h-the-data-collection-process" class="wp-block-heading">The Data Collection Process</h3>



<p class="wp-block-paragraph">Create a Python script that continuously reads your sensors and writes to a Redis stream:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Python</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import time
import json
import redis

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

def collect_data():
    interval = 0.001  # 1ms = 1000 Hz sampling
    cycle_time = time.time()
    while True:

        # Read your sensor
        sensor_value = read_i2c_sensor()

        # Add to Redis stream
        r.xadd('sensor_stream', {
            'value': sensor_value,
            'timestamp': cycle_time
        })

        # Delay enough to start next loop at the interval rate
        time_to_next_cycle = cycle_time + interval - time.time()
        sleep_time = max(0, time_to_next_cycle)
        time.sleep(sleep_time)
        cycle_time += interval

if __name__ == "__main__":
    collect_data()</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> time</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> json</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> redis</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">r = redis.Redis(</span><span style="color: #9CDCFE">host</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&apos;localhost&apos;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">port</span><span style="color: #D4D4D4">=</span><span style="color: #B5CEA8">6379</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">decode_responses</span><span style="color: #D4D4D4">=</span><span style="color: #569CD6">True</span><span style="color: #D4D4D4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">collect_data</span><span style="color: #D4D4D4">():</span></span>
<span class="line"><span style="color: #D4D4D4">    interval = </span><span style="color: #B5CEA8">0.001</span><span style="color: #D4D4D4">  </span><span style="color: #6A9955"># 1ms = 1000 Hz sampling</span></span>
<span class="line"><span style="color: #D4D4D4">    cycle_time = time.time()</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">while</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">True</span><span style="color: #D4D4D4">:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955"># Read your sensor</span></span>
<span class="line"><span style="color: #D4D4D4">        sensor_value = read_i2c_sensor()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955"># Add to Redis stream</span></span>
<span class="line"><span style="color: #D4D4D4">        r.xadd(</span><span style="color: #CE9178">&apos;sensor_stream&apos;</span><span style="color: #D4D4D4">, {</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #CE9178">&apos;value&apos;</span><span style="color: #D4D4D4">: sensor_value,</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #CE9178">&apos;timestamp&apos;</span><span style="color: #D4D4D4">: cycle_time</span></span>
<span class="line"><span style="color: #D4D4D4">        })</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955"># Delay enough to start next loop at the interval rate</span></span>
<span class="line"><span style="color: #D4D4D4">        time_to_next_cycle = cycle_time + interval - time.time()</span></span>
<span class="line"><span style="color: #D4D4D4">        sleep_time = </span><span style="color: #DCDCAA">max</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">, time_to_next_cycle)</span></span>
<span class="line"><span style="color: #D4D4D4">        time.sleep(sleep_time)</span></span>
<span class="line"><span style="color: #D4D4D4">        cycle_time += interval</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">__name__</span><span style="color: #D4D4D4"> == </span><span style="color: #CE9178">&quot;__main__&quot;</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    collect_data()</span></span></code></pre></div>



<p class="wp-block-paragraph">This process runs independently, continuously writing data to the stream regardless of whether anyone is reading it. Redis handles the buffering and ensures data isn&#8217;t lost.</p>



<h3 id="h-accessing-redis-from-labview-with-webdis" class="wp-block-heading">Accessing Redis from LabVIEW with Webdis</h3>



<p class="wp-block-paragraph">Webdis is a simple web server that provides an HTTP interface to Redis. Install it on your Raspberry Pi:</p>



<p class="wp-block-paragraph"><code>git clone https://github.com/nicolasff/webdis.git<br>cd webdis<br>make<br>./webdis &amp;</code></p>



<p class="wp-block-paragraph">Now you can access Redis commands via HTTP. From LabVIEW, you can read from the stream using the HTTP Client VIs to make requests like:</p>



<p class="wp-block-paragraph"><code>http://your-pi-ip:7379/XREAD/COUNT/&lt;count>/STREAMS/sensor_stream/$</code></p>



<p class="wp-block-paragraph">The <code>$</code> special ID means &#8220;only entries added after this request begins&#8221; &#8211; it&#8217;s useful for your initial read when you want to ignore old buffered samples and start with future data. For subsequent reads to get all new data since your last read, you&#8217;ll need to use the actual stream ID you received from the previous read instead of <code>$</code>.</p>



<p class="wp-block-paragraph">The <code>&lt;count&gt;</code> value represents the maximum number of entries to return. Based on your sample rate and how often you want to read buffered data from the device, you will want to modify this value to keep up with data production on the Raspberry Pi.</p>



<h3 id="h-labview-implementation" class="wp-block-heading">LabVIEW Implementation</h3>



<p class="wp-block-paragraph">In your LabVIEW VI:</p>



<ol class="wp-block-list">
<li>Store the last stream ID you read (starting with &#8220;$&#8221;).</li>



<li>Periodically poll the stream using XREAD with your last ID.</li>



<li>Parse the JSON response to extract the sensor values.</li>



<li>Update your last stream ID for the next request.</li>



<li>Process the batch of samples.</li>
</ol>



<figure class="wp-block-image size-full"><img decoding="async" width="926" height="404" src="https://static.dmcinfo.com/wp-content/uploads/2026/07/raspberry-pi-with-labview-application-2.png" alt="LabVIEW block diagram showing an HTTP GET request to a Raspberry Pi, with JSON parsing and a loop for processing response data, including error handling clusters." class="wp-image-46843" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/07/raspberry-pi-with-labview-application-2.png 926w, https://static.dmcinfo.com/wp-content/uploads/2026/07/raspberry-pi-with-labview-application-2-300x131.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/07/raspberry-pi-with-labview-application-2-768x335.png 768w" sizes="(max-width: 926px) 100vw, 926px" /></figure>



<p class="wp-block-paragraph">This approach dramatically reduces overhead; instead of 1000 requests per second for 1000 samples, you might make 10 requests per second and get 100 samples each time.</p>



<h3 id="h-advantages" class="wp-block-heading">Advantages</h3>



<ul class="wp-block-list">
<li><strong>Continuous Collection: </strong>The Python process collects data continuously without gaps.</li>



<li><strong>Buffering:</strong> Redis buffers recent data in memory, so if LabVIEW is briefly busy, samples remain available.</li>



<li><strong>Batch Processing: </strong>LabVIEW can read multiple samples per request, reducing overhead.</li>
</ul>



<h3 id="h-adding-time-synchronization" class="wp-block-heading">Adding Time Synchronization</h3>



<p class="wp-block-paragraph">When combining data from multiple sources (like your NI DAQ and Raspberry Pi), timestamp synchronization becomes critical. The Raspberry Pi&#8217;s clock and your Windows PC&#8217;s clock will drift apart over time, making it difficult to properly align and correlate data.</p>



<p class="wp-block-paragraph">There are several approaches to tackle this problem:</p>



<p class="wp-block-paragraph"><strong>Measuring Clock Offset:</strong> Create a calibration routine in which LabVIEW requests the current time from the Pi and measures the round-trip time to calculate the clock offset. Apply this offset to align timestamps. Keep in mind that different hardware clocks will experience drift and you will need to regularly re-calibrate to account for this.</p>



<p class="wp-block-paragraph"><strong>Network Time Protocol (NTP):</strong> Configure both systems to sync with the same NTP server. This gets you in the ballpark but won&#8217;t give you perfect alignment due to network delays and update intervals.</p>



<h2 id="h-conclusion" class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">Integrating a Raspberry Pi as a data acquisition device in your LabVIEW application enables cost-effective, flexible hardware integration. Your chosen approach depends on your requirements.</p>



<p class="wp-block-paragraph" style="padding-bottom:var(--wp--preset--spacing--40)">For our client&#8217;s application, we used the Redis approach with time synchronization to integrate their Raspberry Pi sensors with their LabVIEW system, achieving reliable 1 kHz data collection aligned with their NI DAQ data.</p>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step">Have an upcoming project? DMC can help you take the next step.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">Whether integrating Raspberry Pis, NI DAQs, mixed or specialized hardware, DMC can help build robust <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/">test and measurement systems</a>.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://static.dmcinfo.com/blog/46615/raspberry-pi-labview-data-acquisition/">How to Use Raspberry Pi as a DAQ Device in LabVIEW</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>3 Ways AI Improves Real-Time Vision Inspection with Python</title>
		<link>https://static.dmcinfo.com/blog/46368/ai-real-time-vision-inspection-python-optimization/</link>
		
		<dc:creator><![CDATA[Fadil Eledath]]></dc:creator>
		<pubDate>Thu, 02 Jul 2026 11:00:00 +0000</pubDate>
				<category><![CDATA[Test and Measurement Automation]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Vision Inspection]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/?p=46368</guid>

					<description><![CDATA[<p>Real-time vision inspection has an unforgiving constraint: every product on the conveyor has to be analyzed before the next set of frames arrives. A pipeline that&#8217;s accurate but too slow is just as unusable as one that&#8217;s fast but wrong. Getting both requires deliberate optimization, which has historically been difficult, but using AI and Python [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/46368/ai-real-time-vision-inspection-python-optimization/">3 Ways AI Improves Real-Time Vision Inspection with Python</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Real-time vision inspection has an unforgiving constraint: every product on the conveyor has to be analyzed before the next set of frames arrives. A pipeline that&#8217;s accurate but too slow is just as unusable as one that&#8217;s fast but wrong. Getting both requires deliberate optimization, which has historically been difficult, but using AI and Python together can make it much easier.</p>



<p class="wp-block-paragraph">Here are three practical ways DMC has used AI and Python to optimize a real-time inspection system and deliver real results to our clients.</p>



<h2 id="h-1-profile-your-pipeline-to-find-the-bottlenecks" class="wp-block-heading">1. Profile Your Pipeline to Find the Bottlenecks</h2>



<p class="wp-block-paragraph">As you move from implementation to production, the slower parts of your code can become painful while remaining hidden. In fact, slow lines of code can show up in surprising places and, depending on how your pipeline is structured, have an outsized effect on your speed. The solution is to bring a magnifying glass to your code by profiling it.</p>



<figure class="wp-block-image alignleft size-full is-resized has-custom-border" style="margin-bottom:var(--wp--preset--spacing--50)"><img decoding="async" width="458" height="250" src="https://static.dmcinfo.com/wp-content/uploads/2026/06/optimizing-python-vision-inspection-system-1.png" alt="Generated image of a conveyor belt with a robotic sensor and an HMI screen showing defects on a tortilla on the conveyor belt." class="wp-image-46382" style="border-top-left-radius:20px;border-top-right-radius:20px;border-bottom-left-radius:20px;border-bottom-right-radius:20px;width:500px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/06/optimizing-python-vision-inspection-system-1.png 458w, https://static.dmcinfo.com/wp-content/uploads/2026/06/optimizing-python-vision-inspection-system-1-300x164.png 300w" sizes="(max-width: 458px) 100vw, 458px" /></figure>



<p class="wp-block-paragraph">I’ve been a heavy user of Jupyter notebooks inside VS Code, which allows me to use the AI coding agent of my choice to easily set up and run experiments against my inspection pipeline to understand how it runs in practice against specific examples and, more relevantly, how long each section of the pipeline takes to run.</p>



<p class="wp-block-paragraph">For example, one recent system DMC worked on involved belt masking. A client needed to inspect yellow tortillas moving down a blue conveyor belt, so we had to isolate each tortilla on each frame, separating it from the background for later steps in our analysis. The naive-but-useful approach we started with computed a full-resolution color distance, each pixel relative to the average color of the belt. This gave us a reference for what a functionally correct approach looks like, but profiling the code in conversation with AI showed us that it took up the majority of its time analyzing each frame.</p>



<h2 id="h-2-redesign-expensive-metrics-to-be-computationally-cheaper" class="wp-block-heading">2. Redesign Expensive Metrics to be Computationally Cheaper</h2>



<p class="wp-block-paragraph">Once you know which stage is slow, the next lever is the algorithms inside it. Many vision metrics have a naive implementation that&#8217;s accurate but expensive, and a smarter implementation that&#8217;s nearly as accurate and far faster.</p>



<figure class="wp-block-image alignright size-full is-resized has-custom-border" style="margin-bottom:var(--wp--preset--spacing--60)"><img decoding="async" width="458" height="250" src="https://static.dmcinfo.com/wp-content/uploads/2026/06/optimizing-python-vision-inspection-system-2.png" alt="Generated image of a blue conveyor belt with with tortillas." class="wp-image-46384" style="border-top-left-radius:20px;border-top-right-radius:20px;border-bottom-left-radius:20px;border-bottom-right-radius:20px;aspect-ratio:1.8320261063720158;width:500px;height:auto" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/06/optimizing-python-vision-inspection-system-2.png 458w, https://static.dmcinfo.com/wp-content/uploads/2026/06/optimizing-python-vision-inspection-system-2-300x164.png 300w" sizes="(max-width: 458px) 100vw, 458px" /></figure>



<p class="wp-block-paragraph">After profiling the inspection system, we looked for ways to optimize it. A faster approach involved shrinking the frame by 50% on each side to reduce the number of computations by 75%. Comparing against the full-frame approach, we saw minimal reduction in accuracy. Additionally, by computing distances, we were performing a square root operation before comparing the distance to a threshold parameter; we could ditch that operation by squaring the threshold parameter and then comparing the squared distance, which sped up the process even further with no reduction in accuracy.</p>



<p class="wp-block-paragraph">Eventually, we switched from checking RGB color distance to an axis-aligned range, which had similar accuracy while drastically reducing the computational load per frame. AI was vital here for quickly brainstorming and drafting these alternative formulations so we could compare their performance and accuracy.</p>



<h2 id="h-3-use-synthetic-data-to-stress-test-thresholds-and-edge-cases" class="wp-block-heading">3. Use Synthetic Data to Stress-Test Thresholds and Edge Cases</h2>



<p class="wp-block-paragraph">Optimization isn&#8217;t only about speed; it&#8217;s also about ensuring the system remains correct under pressure and across the full range of inputs. It&#8217;s hard to verify with only a handful of real images, which is often the case at the pre-deployment stage of a project.</p>



<figure class="wp-block-image alignleft size-full is-resized has-custom-border" style="margin-bottom:var(--wp--preset--spacing--50)"><img decoding="async" width="608" height="250" src="https://static.dmcinfo.com/wp-content/uploads/2026/06/optimizing-python-vision-inspection-system-3.png" alt="" class="wp-image-46385" style="border-top-left-radius:20px;border-top-right-radius:20px;border-bottom-left-radius:20px;border-bottom-right-radius:20px;width:500px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/06/optimizing-python-vision-inspection-system-3.png 608w, https://static.dmcinfo.com/wp-content/uploads/2026/06/optimizing-python-vision-inspection-system-3-300x123.png 300w" sizes="(max-width: 608px) 100vw, 608px" /></figure>



<p class="wp-block-paragraph">Synthetic data can fill this gap. By generating test subjects across the entire pass/fail spectrum, including rare failure modes, you can stress-test thresholds and confirm the optimized pipeline still behaves correctly on edge cases.</p>



<p class="wp-block-paragraph">In our example of the tortilla inspection project, we used a Python script to programmatically generate AI images of tortillas with different levels and types of defects by varying the prompts. For example, each tortilla prompt was given a probability of having a prompt addition specifying a torn edge or a burn mark. After generating 100 tortillas, we used another script to create simulated footage of these tortillas moving down a looping belt texture, with added random noise and motion blur, which we then used to verify our pipeline&#8217;s capabilities before we had any real footage to work with. These efforts allowed us to deploy our code into production quickly for our client.</p>



<h2 id="h-conclusion" class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">These threThese three practices work together to create a more efficient and reliable system:</p>



<ul class="wp-block-list">
<li><strong>Profiling</strong> identifies where to focus your optimization efforts.</li>



<li><strong>Metric redesign</strong> speeds up slow stages exposed by your profiling.</li>



<li><strong>Synthetic data</strong> ensures your system remains accurate across edge cases.</li>
</ul>



<p class="wp-block-paragraph">Each of these stages has always been essential to vision inspection, but AI and modern coding tools have made them faster and easier to implement. Additionally, unlike certain uses of AI that have greater exposure to risk, like code implementation, using AI here is less likely to cause major faults in your system. That said, AI should be an accelerator, not a replacement for engineering judgment. It is essential to verify that AI-generated code is correct and aligned with system requirements.</p>



<p class="wp-block-paragraph">Ultimately, the impact of these practices is clear. By combining these approaches, you can confidently improve the speed and reliability of your real-time vision inspection pipeline.</p>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step">Kicking off a Vision Inspection project? DMC can help you take the next step!</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">Contact DMC&#8217;s <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/">Test &amp; Measurement</a> team today to learn more about our experience in <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/vision-inspection/" id="494">vision inspection systems</a> and how we can help you achieve your goals.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://static.dmcinfo.com/blog/46368/ai-real-time-vision-inspection-python-optimization/">3 Ways AI Improves Real-Time Vision Inspection with Python</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>DMC-Complete: Faster LabVIEW Coding with Old-Fashioned AI</title>
		<link>https://static.dmcinfo.com/blog/40065/dmc-complete-faster-labview-coding-with-old-fashioned-ai/</link>
		
		<dc:creator><![CDATA[Fadil Eledath]]></dc:creator>
		<pubDate>Wed, 10 Dec 2025 15:00:00 +0000</pubDate>
				<category><![CDATA[LabVIEW]]></category>
		<category><![CDATA[Test and Measurement Automation]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/?p=40065</guid>

					<description><![CDATA[<p>When you start using LabVIEW, one of the first tools you’ll encounter is the Functions Palette. This palette helps you locate the blocks needed to build your program&#8217;s logic by organizing them into various sections. As you gain experience, you start using the QuickDrop tool, which lets you add blocks and structures by searching for [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/40065/dmc-complete-faster-labview-coding-with-old-fashioned-ai/">DMC-Complete: Faster LabVIEW Coding with Old-Fashioned AI</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">When you start using LabVIEW, one of the first tools you’ll encounter is the Functions Palette. This palette helps you locate the blocks needed to build your program&#8217;s logic by organizing them into various sections. As you gain experience, you start using the QuickDrop tool, which lets you add blocks and structures by searching for them.</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-0e47273b wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p class="wp-block-paragraph"><strong>Figure 1: Functions Palette</strong></p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="640" height="931" src="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-1-1.png" alt="Figure 1" class="wp-image-40066" style="width:483px;height:auto" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-1-1.png 640w, https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-1-1-206x300.png 206w" sizes="(max-width: 640px) 100vw, 640px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p class="wp-block-paragraph"><strong>Figure 2: QuickDrop</strong></p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="575" height="488" src="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-2-1.png" alt="Figure 2" class="wp-image-40067" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-2-1.png 575w, https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-2-1-300x255.png 300w" sizes="(max-width: 575px) 100vw, 575px" /></figure>
</div>
</div>



<p class="wp-block-paragraph">To complement QuickDrop, we have been working on DMC-Complete: a tool that has the potential to supercharge the way you use LabVIEW by predicting the blocks you need right when you need them. View Our Demo.</p>



<figure class="wp-block-embed is-type-rich is-provider-embed-handler wp-block-embed-embed-handler"><div class="wp-block-embed__wrapper">
<div style="width: 640px;" class="wp-video"><video class="wp-video-shortcode" id="video-40065-1" width="640" height="360" preload="metadata" controls="controls"><source type="video/mp4" src="https://static.dmcinfo.com/wp-content/uploads/2025/11/DMC-Complete-Demo.mp4?_=1" /><a href="https://static.dmcinfo.com/wp-content/uploads/2025/11/DMC-Complete-Demo.mp4">https://static.dmcinfo.com/wp-content/uploads/2025/11/DMC-Complete-Demo.mp4</a></video></div>
</div></figure>



<p class="wp-block-paragraph">Simply clicking on a block triggers the DMC-Complete interface to predict what block you are most likely to use next, speeding up the process of programming so you can focus on the logic of your code rather than the tedium of searching for a specific block.</p>



<p class="wp-block-paragraph"><strong>DMC-Complete Offers:</strong></p>



<ul class="wp-block-list">
<li>Blazing speed – predictions happen in milliseconds</li>



<li>Fully local operation – no internet required</li>



<li>Minimal resource usage – runs efficiently even on VMs</li>



<li>Full library compatibility – works with custom and VIPM packages</li>



<li>Strong privacy – your code stays on your device</li>



<li>Easy retraining – add or remove packages with minimal effort</li>



<li>Open-source access – check out the code, available under the BSD 3-Clause License</li>
</ul>



<h2 id="h-getting-started" class="wp-block-heading">Getting Started </h2>



<p class="wp-block-paragraph">If you want to get started with using DMC-Complete, check out <a href="https://github.com/fadilf/DMC-Complete" type="link" id="https://github.com/fadilf/DMC-Complete" target="_blank" rel="noreferrer noopener">our repository</a> where the code for this project lives.</p>



<p class="wp-block-paragraph">The Installation and Usage sections of the README.md file should help you get up and running with the tool in no time! Keep in mind that the project is currently an early beta, so if you encounter any issues while using it, please file them on the GitHub page.</p>



<h2 id="h-how-it-works" class="wp-block-heading">How It Works</h2>



<p class="wp-block-paragraph">At GDevCon NA in Chicago this year, DMC got a chance to give a talk on how the tool works in more detail!</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="LabVIEW Autocomplete - Fadil Eledath. GDevCon N.A. 2025" width="500" height="281" src="https://www.youtube.com/embed/vfY3ENiGERk?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<h3 id="h-markov-chains" class="wp-block-heading">Markov Chains</h3>



<p class="wp-block-paragraph">The key to understanding DMC Complete? <a href="https://en.wikipedia.org/wiki/Markov_chain" target="_blank" rel="noreferrer noopener">Markov chains</a>. A Markov chain can model a sequence of events in which the probability of each event depends only on a limited set of prior states. This approach can be used to model things as important as the weather or something as mundane as your opponent’s next move in rock-paper-scissors:</p>



<p class="wp-block-paragraph">[&#8230;, <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2600.png" alt="☀" class="wp-smiley" style="height: 1em; max-height: 1em;" />, <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2601.png" alt="☁" class="wp-smiley" style="height: 1em; max-height: 1em;" />, <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f327.png" alt="🌧" class="wp-smiley" style="height: 1em; max-height: 1em;" />] → <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26c8.png" alt="⛈" class="wp-smiley" style="height: 1em; max-height: 1em;" /> (50%) / <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f327.png" alt="🌧" class="wp-smiley" style="height: 1em; max-height: 1em;" /> (30%) / <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2601.png" alt="☁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> (20%)</p>



<p class="wp-block-paragraph">[&#8230;, rock, paper, scissors] → rock (60%) / paper (30%) / scissors (10%)</p>



<p class="wp-block-paragraph">These simple statistical relationships form the basis for predicting the next LabVIEW block in your block diagram.</p>



<h3 id="h-analyzing-block-diagrams" class="wp-block-heading">Analyzing Block Diagrams</h3>



<p class="wp-block-paragraph"><strong>Figure 3</strong></p>



<figure class="wp-block-image size-full"><img decoding="async" width="975" height="244" src="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-3-1.png" alt="Figure 3 " class="wp-image-40070" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-3-1.png 975w, https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-3-1-300x75.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-3-1-768x192.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure>



<p class="wp-block-paragraph">Let’s look at an example block diagram. We’ve got different types of blocks like controls, indicators, constants, DAQmx functions, etc., as well as a for loop structure. If we ignore structures, our block diagram looks like this:</p>



<p class="wp-block-paragraph"><strong>Figure 4</strong></p>



<figure class="wp-block-image size-full"><img decoding="async" width="975" height="244" src="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-4-1.png" alt="" class="wp-image-40071" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-4-1.png 975w, https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-4-1-300x75.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-4-1-768x192.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure>



<p class="wp-block-paragraph">We then genericize the blocks so we can treat them as Markov states for analysis. You might notice that this looks a lot like a directed acyclic graph.</p>



<p class="wp-block-paragraph"><strong>Figure 5</strong></p>



<figure class="wp-block-image size-full"><img decoding="async" width="1024" height="272" src="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-5-1.png" alt="" class="wp-image-40072" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-5-1.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-5-1-300x80.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-5-1-768x204.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Once we have this set of Markov states, we can start to observe patterns of blocks to make predictions later. If we count 2-block sequences, a pattern begins to emerge.</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-0e47273b wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p class="wp-block-paragraph"><strong>Figure 6</strong></p>



<figure class="wp-block-image size-full"><img decoding="async" width="974" height="329" src="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-6-1.png" alt="" class="wp-image-40073" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-6-1.png 974w, https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-6-1-300x101.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/11/Figure-6-1-768x259.png 768w" sizes="(max-width: 974px) 100vw, 974px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p class="wp-block-paragraph"><strong>Figure 7</strong></p>



<figure class="wp-block-image size-full"><img decoding="async" width="1144" height="1000" src="https://static.dmcinfo.com/wp-content/uploads/2025/11/image.psd7_.png" alt="" class="wp-image-40080" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/11/image.psd7_.png 1144w, https://static.dmcinfo.com/wp-content/uploads/2025/11/image.psd7_-300x262.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/11/image.psd7_-1024x895.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2025/11/image.psd7_-768x671.png 768w" sizes="(max-width: 1144px) 100vw, 1144px" /></figure>
</div>
</div>



<p class="wp-block-paragraph">Once you have a table like figure 7, you can reorganize it into a Markov model, which looks more like this:</p>



<p class="wp-block-paragraph"><strong>Figure 8</strong></p>



<figure class="wp-block-image size-full"><img decoding="async" width="2000" height="957" src="https://static.dmcinfo.com/wp-content/uploads/2025/11/New-Project8.jpg" alt="" class="wp-image-40081" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/11/New-Project8.jpg 2000w, https://static.dmcinfo.com/wp-content/uploads/2025/11/New-Project8-300x144.jpg 300w, https://static.dmcinfo.com/wp-content/uploads/2025/11/New-Project8-1024x490.jpg 1024w, https://static.dmcinfo.com/wp-content/uploads/2025/11/New-Project8-768x367.jpg 768w, https://static.dmcinfo.com/wp-content/uploads/2025/11/New-Project8-1536x735.jpg 1536w" sizes="(max-width: 2000px) 100vw, 2000px" /></figure>



<p class="wp-block-paragraph">Now, when we see a numeric control, we know that the next block is either a Sine Wave (50% chance), a DAQmx Create Channel block (~33% chance), or a DAQmx Timing block (~17% chance). If we apply this process to our entire training set, including the example files included with LabVIEW and any libraries we install, we get a model that learns the pattern of how we code with the blocks we have.</p>



<p class="wp-block-paragraph">This model is just a mapping/dictionary, so it only takes up a few megabytes on disk and in memory. Using it is as simple as a map lookup, so it’s an instant O(1) operation. Behind the scenes, there is a caching mechanism that takes place, so if you want to retrain with fewer/more files, the retraining process runs very quickly. The slowest part of training is the initial conversion of a VI file into a graph, which is why we have taken on the burden of creating a pre-made cache that should speed up initial training as well.</p>



<h2 id="h-summary" class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">DMC-Complete demonstrates how classical AI techniques can deliver surprising results. By combining the simple principle of Markov modeling with the power of LabVIEW’s graphical programming, you can have a practical, private, and responsive coding companion. Sometimes, the simplest solutions are the most effective.</p>



<p class="wp-block-paragraph">By developing this tool, we hope to contribute to the ever-growing landscape of open-source projects written in LabVIEW that work to improve productivity and serve our needs as well as our clients’ needs better. Contributions to the project are welcome at the repository link provided above.</p>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step"><strong>Accelerate Your LabVIEW Development</strong> with DMC-Complete.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">Use AI techniques with DMC-Complete to deliver high-quality solutions for your <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/labview-programming/" data-type="page" data-id="584">LabVIEW </a>projects. Learn more about our <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/" data-type="page" data-id="428">Test &amp; Measurement</a> capabilities.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://static.dmcinfo.com/blog/40065/dmc-complete-faster-labview-coding-with-old-fashioned-ai/">DMC-Complete: Faster LabVIEW Coding with Old-Fashioned AI</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		<enclosure url="https://static.dmcinfo.com/wp-content/uploads/2025/11/DMC-Complete-Demo.mp4" length="413435" type="video/mp4" />

			</item>
		<item>
		<title>WebTDMS: A Powerful TDMS and CSV Analyzer</title>
		<link>https://static.dmcinfo.com/blog/16273/webtdms-a-powerful-tdms-and-csv-analyzer/</link>
		
		<dc:creator><![CDATA[Fadil Eledath]]></dc:creator>
		<pubDate>Thu, 30 Jan 2025 19:20:00 +0000</pubDate>
				<category><![CDATA[Test and Measurement Automation]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/16273/webtdms-a-powerful-tdms-and-csv-analyzer/</guid>

					<description><![CDATA[<p>If you’ve ever used a LabVIEW application that generates a lot of data very quickly, you’ve probably dealt with TDMS files. TDMS files store data in a binary format that allows you to rapidly write data as waveform chunks. This&#160;works well for the kind of high-frequency data we handle often in the world of test [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/16273/webtdms-a-powerful-tdms-and-csv-analyzer/">WebTDMS: A Powerful TDMS and CSV Analyzer</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">If you’ve ever used a LabVIEW application that generates a lot of data very quickly, you’ve probably dealt with TDMS files.</p>



<p class="wp-block-paragraph">TDMS files store data in a binary format that allows you to rapidly write data as waveform chunks. This&nbsp;works well for the kind of high-frequency data we handle often in the world of test and measurement. When working with LabVIEW, it serves as a complement to their DAQ API which reads high-frequency data in chunks from a hardware buffer. In contrast, writing such data to CSV files would usually require either writing data a few rows at a time or storing data in memory until it is ready to be written in uncompressed plaintext.</p>



<p class="wp-block-paragraph">For all these reasons, it is a great format to write to except for the fact that reading TDMS files can sometimes be a hassle.</p>



<p class="wp-block-paragraph">Currently, if you want to view TDMS files, you have a few options:</p>



<ul class="wp-block-list">
<li><strong>DMC SuperViewer:</strong> I might be biased but our <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/labview-programming/tdms-file-viewer">free downloadable utility</a> to browse TDMS files is probably the best offline option.</li>



<li><strong>TDM Excel Add-In:</strong> This <a href="https://www.ni.com/en/support/downloads/tools-network/download.tdm-excel-add-in-for-microsoft-excel.html?srsltid=AfmBOoqSJbkAd6OFl6izi4BGxhaU258xFwBBM6AkeCSPq06q1hV_0AfQ#378046" target="_blank">NI plugin</a> lets you open your TDMS files in Excel. If your machine has an MS Office subscription, then it might be a viable option.</li>



<li><strong>NI DIAdem:</strong> A <a href="https://www.ni.com/en/shop/data-acquisition-and-control/application-software-for-data-acquisition-and-control-category/what-is-diadem.html?srsltid=AfmBOoqfeUKWYJ7opii5wlmchjc5kt5MCON-yZijFL4w11lppVdUlYAa" target="_blank">powerful application</a> that lets you process multiple streams of data but requires an NI license.</li>



<li><strong>NI FlexLogger</strong>: As part of a larger feature set, <a href="https://www.ni.com/en/shop/data-acquisition-and-control/flexlogger.html?srsltid=AfmBOoqzzbiWqZ_pb9KlMNVKgfwHvNMVLC7I9iW7pP-oj29ReHxc0Iia" target="_blank">NI FlexLogger</a>&nbsp;allows you to view TDMS files. The Lite version is free.</li>
</ul>



<p class="wp-block-paragraph">These options&nbsp;all require a download and installation process.</p>



<p class="wp-block-paragraph">As an alternative, we’ve developed a <a href="https://web-tdms.streamlit.app/" target="_blank">WebTDMS</a>–a TDMS and CSV file viewer which you can open in your browser. There&#8217;s no&nbsp;installation necessary! It is designed to be flexible with its many advanced analysis tools but easy to use with its clean interface.</p>



<h2 id="h-features" class="wp-block-heading">Features</h2>



<p class="wp-block-paragraph">On the left side, you can drop in your various TDMS and CSV files to be read. You can also explore the example data that displays by default to test its various features. Let’s review the various tabs to see what features we have.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1600" height="790" src="https://static.dmcinfo.com/wp-content/uploads/2025/01/DMC_WebTDMS.png" alt="DMC's WebTDMS Viewer" class="wp-image-37438" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/01/DMC_WebTDMS.png 1600w, https://static.dmcinfo.com/wp-content/uploads/2025/01/DMC_WebTDMS-300x148.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/01/DMC_WebTDMS-1024x506.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2025/01/DMC_WebTDMS-768x379.png 768w, https://static.dmcinfo.com/wp-content/uploads/2025/01/DMC_WebTDMS-1536x758.png 1536w" sizes="(max-width: 1600px) 100vw, 1600px" /></figure>



<h2 id="h-charts" class="wp-block-heading">Charts</h2>



<p class="wp-block-paragraph">On the left side, you can select all the waveforms you would like to view in each file that you’ve uploaded. On&nbsp;the right side, you can view those waveforms as a scatter plot, line plot, or histogram.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="" height="272" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/image003_1.png" width="163"><img decoding="async" alt="" height="165" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/image005_1.png" width="194"><img decoding="async" alt="" height="169" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/image007_1.png" width="197"><img decoding="async" alt="" height="174" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/image009_1.png" width="205"></p></p>



<h2 id="h-raw-data" class="wp-block-heading">Raw Data</h2>



<p class="wp-block-paragraph">You can view the raw data from your files next to each other and even download all your data as a single CSV file. You can even use filters to exclude rows where values for a column are outside your specified range.</p>


<div style="text-align: center;"><img decoding="async" alt="" height="286" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/image011_1.png" width="747" /></div>


<h2 id="h-profiler" class="wp-block-heading">Profiler</h2>



<h3 id="h-data-tab" class="wp-block-heading">Data Tab</h3>



<p class="wp-block-paragraph">This section has a separate raw data viewer with paginated rows as well as an indication of the distributions of each column’s values.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="" height="425" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/image013.png" width="702"></p></p>



<h3 id="h-visualization-view" class="wp-block-heading">Visualization View</h3>



<p class="wp-block-paragraph">For a more complicated multivariate analysis of data, you can use the Visualization section.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="" height="528" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/image015.png" width="740"></p></p>



<h2 id="h-group-channel-properties" class="wp-block-heading">Group/Channel Properties</h2>



<p class="wp-block-paragraph">In this section, you can view the group and channel properties for TDMS files alongside a preview of each channel.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="" height="409" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/image017.png" width="740"></p></p>



<h2 id="h-calculated-channels" class="wp-block-heading">Calculated Channels</h2>



<p class="wp-block-paragraph">Finally, we have the flagship feature that lets you quickly perform mathematical analysis on your data. Taking inspiration from what makes LabVIEW great for data–that it is a dataflow language–this section allows you to create new channels that you can use in all the sections above using blocks of logic.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="" height="494" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/image019.png" width="900"></p></p>



<p class="wp-block-paragraph">The logic above creates the chart below in the Charts section:</p>



<p class="wp-block-paragraph"><p align="center"><img decoding="async" alt="" height="331" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/image021.png" width="583"></p></p>



<p class="wp-block-paragraph">There is also a <a href="https://web-tdms.streamlit.app/" type="link" id="https://web-tdms.streamlit.app/" target="_blank" rel="noreferrer noopener">public version of the app</a> with a 50 MB file limit that you can access. If you think this application is useful and that maybe a customized version of it would be perfect for your needs, please <a href="https://static.dmcinfo.com/contact">reach out to us</a>!</p>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step"><strong>Analyze Test Data Directly in Your Browser</strong>.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">See how our <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/" data-type="page" data-id="428">Test &amp; Measurement</a> solutions for TDMS and CSV visualization, calculated channels, and custom web-based data analysis tools.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://static.dmcinfo.com/blog/16273/webtdms-a-powerful-tdms-and-csv-analyzer/">WebTDMS: A Powerful TDMS and CSV Analyzer</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Creating Custom AI Tools to Analyze LabVIEW Code</title>
		<link>https://static.dmcinfo.com/blog/16249/creating-custom-ai-tools-to-analyze-labview-code/</link>
		
		<dc:creator><![CDATA[Fadil Eledath]]></dc:creator>
		<pubDate>Wed, 05 Jun 2024 14:25:52 +0000</pubDate>
				<category><![CDATA[LabVIEW]]></category>
		<category><![CDATA[Test and Measurement Automation]]></category>
		<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/16249/creating-custom-ai-tools-to-analyze-labview-code/</guid>

					<description><![CDATA[<p>In the field of test and measurement&#160;we do tons of work with NI hardware and software. Clients often lean on DMC engineers as experts of the NI stack to help them figure out what’s going wrong and how to make things right with their test systems. Hardware experts don&#8217;t always have hours of time to [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/16249/creating-custom-ai-tools-to-analyze-labview-code/">Creating Custom AI Tools to Analyze LabVIEW Code</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In the field of <a href="https://static.dmcinfo.com/services/test-and-measurement-automation">test and measurement</a>&nbsp;we do tons of work with NI hardware and software. Clients often lean on DMC engineers as experts of the NI stack to help them figure out what’s going wrong and how to make things right with their test systems.</p>



<p class="wp-block-paragraph">Hardware experts don&#8217;t always have hours of time to invest in staying updated on the latest in LabVIEW like we do at DMC. Understandably, this can result in code that doesn’t follow standard architecture or best practices.</p>



<p class="wp-block-paragraph">We&#8217;ve seen every kind of graphical code structure under the sun. It takes time to follow the hundreds of wires and many parallel loops to figure out what makes a program behave the way that it does.</p>



<p class="wp-block-paragraph"><p align="center"><img decoding="async" alt="" height="362" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/pepe-labview.png" width="482"><br>
Me analyzing LabVIEW code for the first time</p></p>



<h2 id="h-using-openai-and-labview" class="wp-block-heading">Using OpenAI and LabVIEW</h2>



<p class="wp-block-paragraph">Text-based languages have benefitted from recent advancements&nbsp;in tools used to analyze and write code&nbsp;like Python with tools like GitHub Copilot. NI has been hard at work too, as evidenced by their recent demo of <a href="https://www.youtube.com/live/Bk-dmXEp5xk?si=7aURtiBINJvDBGEg&amp;t=3070">Nigel</a>, but they haven’t yet released it.</p>



<p class="wp-block-paragraph">In the meantime, I thought I could try something rudimentary to achieve a similar outcome using the GPT API from OpenAI with a few tricks to make it work on VI files (files for LabVIEW written in their G language). I wanted to see if I could use GPT to describe LabVIEW code.</p>



<p class="wp-block-paragraph">Here are the steps:</p>



<ol class="wp-block-list">
<li>Convert the LabVIEW graphical code to text-based code.</li>



<li>Pass the text-based code to GPT and ask it to analyze the code.</li>
</ol>



<h2 id="h-converting-graphical-code-to-text-based-code" class="wp-block-heading">Converting Graphical Code to Text-Based Code</h2>



<p class="wp-block-paragraph">Step 1 basically describes a transpiler which is a compiler that takes code in one language and produces equivalent code in a target language, though as we’ll see that’s easier said than done. For my purposes, I decided to target Python-like code&nbsp;since it isn’t strictly typed and would let me get away with leaving out a lot of information about data types. It’s also likely that GPT is trained on tons of Python code and trying to use a language more equivalent to LabVIEW code would mean implementing more programming constructs in the transpiler or creating a proprietary intermediary language as NI has been doing with Nigel.</p>



<p class="wp-block-paragraph">The first major hurdle is the fact that LabVIEW code isn’t written as a series of sequential statements.&nbsp;Instead, it is a data-flow language which uses “wires” to transfer information from block to block. This makes it especially great for simple-looking implementations of multi-threaded applications but annoying for our purposes. Luckily, this construct maps well onto the concept of computational graphs and we can try to move from code to a more abstract graph to make our life simpler. We can think of LabVIEW code as a “directed acyclic graph” with a set of start nodes (controls) and end nodes (indicators) connected by edges (wires).</p>



<p class="wp-block-paragraph"><p align="center"><img decoding="async" alt="" height="245" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Untitled-Diagram_drawio2.png" width="454"></p></p>



<p class="wp-block-paragraph">But how do we convert LabVIEW code to a computational graph? Using VI Scripting of course! NI has a library of tools that lets you find all instances of a specified type of LabVIEW programming construct and if we look for all wires and note what pair of objects each one joins, we can build our graph.</p>



<p class="wp-block-paragraph"><p align="center"><img decoding="async" alt="" height="347" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/VISight-Snippet.png" width="1112"></p></p>



<p class="wp-block-paragraph">We then take the graph and use a custom scheduler algorithm to create a sequence of operations for each of the code blocks and finally use the metadata of each wire’s two terminals to provide some additional data in the transpiled code.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="" height="517" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Screenshot-2024-05-09-161224.png" width="339"> &nbsp;&nbsp;<img decoding="async" alt="" height="517" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Screenshot-2024-05-09-161333.png" width="329"></p></p>



<h2 id="h-ask-gpt-to-analyze-the-code" class="wp-block-heading">Ask GPT to Analyze the Code</h2>



<p class="wp-block-paragraph">Add in some logic to avoid accidentally using the variable names in multiple places using UIDs and we’re basically done! All we do now is ask GPT to describe the code in terms of what it represents and not the actual variables themselves and we have a crude AI-powered VI analysis tool.</p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="" height="110" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/GPT-prompt_1.png" width="654"></p></p>



<p class="wp-block-paragraph"><p style="text-align: center;"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/VISight.gif"></p></p>



<p class="wp-block-paragraph">Except that it doesn’t work for:</p>



<ul class="wp-block-list">
<li>For loops</li>



<li>While loops</li>



<li>Broken code</li>



<li>Cases where there are orphaned blocks</li>



<li>Feedback loops</li>



<li>Analyzing sub-VIs</li>



<li>Etc.</li>
</ul>



<p class="wp-block-paragraph">You get the idea. Perhaps with a more structured approach to VI scripting and fine-tuning with example code, it might be possible to get more out of this idea, but I think this serves as a useful demo to see what might one day possible!</p>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step"><strong>Bring AI-Powered Analysis to LabVIEW Code</strong>.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">See more about our <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/" data-type="page" data-id="428">Test &amp; Measurement</a> capabilities and <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/labview-programming/" data-type="page" data-id="584">LabVIEW</a> solutions for code analysis, architecture evaluation, and custom AI tool development.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://static.dmcinfo.com/blog/16249/creating-custom-ai-tools-to-analyze-labview-code/">Creating Custom AI Tools to Analyze LabVIEW Code</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using Algorithms for Efficient Multiplexing</title>
		<link>https://static.dmcinfo.com/blog/16958/using-algorithms-for-efficient-multiplexing/</link>
		
		<dc:creator><![CDATA[Fadil Eledath]]></dc:creator>
		<pubDate>Mon, 18 Dec 2023 20:22:35 +0000</pubDate>
				<category><![CDATA[Battery Pack Test Systems]]></category>
		<category><![CDATA[Test and Measurement Automation]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/16958/using-algorithms-for-efficient-multiplexing/</guid>

					<description><![CDATA[<p>In Test and Measurement Automation projects, we often have to make numerous, quick measurements for test points on a device being tested, which we make with multiplexers. For a recent project, we needed to measure multiple AC voltages on a&#160;Mobile Energy Storage System. We chose multiplexers that are rated for high voltages, can carry a [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/16958/using-algorithms-for-efficient-multiplexing/">Using Algorithms for Efficient Multiplexing</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In <a href="https://static.dmcinfo.com/services/test-and-measurement-automation">Test and Measurement Automation</a> projects, we often have to make numerous, quick measurements for test points on a device being tested, which we make with multiplexers. For a recent project, we needed to measure multiple AC voltages on a&nbsp;<a href="https://static.dmcinfo.com/latest-thinking/case-studies/view/id/641/automated-testing-of-a-mobile-energy-storage-system">Mobile Energy Storage System</a>.</p>



<p class="wp-block-paragraph">We chose multiplexers that are rated for high voltages, can carry a decent amount current, and are rated by their manufacturer to have their relays switched on and off plenty of times. These are mechanical systems, however, and, if you build enough test systems with multiplexers that constantly switch relays on and off, one of them will eventually fail. Any part of a factory line system failing means downtime, which can lead&nbsp;to losses.</p>



<p class="wp-block-paragraph">The best approach to test systems that last and deliver value is to expect that they may fail at some point. At DMC, we design tools to delay and diagnose the inevitable as opposed to ignoring it.</p>



<p class="wp-block-paragraph">To this end, we deployed our project with a diagnostic sequence and additional hardware that the client&nbsp;could use&nbsp;periodically to detect wiring and relay faults so we can fix them. There are several&nbsp;ways in which this idea can be applied.</p>



<p class="wp-block-paragraph">Take the example of testing a standard 120V AC outlet: we need to check that we see ~120V between live and neutral as well as live and ground but ~0V between neutral and ground.<br>
&nbsp;<br>
In our case, we mapped DMM and each of the test points to multiplexer coordinate “paths” and those paths to human-readable names through our custom “MUX Manager” library. This enabled us to control relays with Python lines like these:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Python</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
mux_manager.get_pin_path(&lt;Pin Name>, &lt;Rail>)

mux_manager.set_pin(&lt;Pin Path>, &lt;New State>)

mux_manager.read_pin(&lt;Pin Path>)

mux_manager.clear_all()</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #D4D4D4">mux_manager.get_pin_path(&lt;Pin Name&gt;, &lt;Rail&gt;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">mux_manager.set_pin(&lt;Pin Path&gt;, &lt;New State&gt;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">mux_manager.read_pin(&lt;Pin Path&gt;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">mux_manager.clear_all()</span></span></code></pre></div>



<p class="wp-block-paragraph">If we wrote a generic method in a test class to measure the voltage between two pins, a first attempt would look something like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Python</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
 class VoltageTest:
    …

    def test_voltage(self, pin_a, pin_b, expected, tolerance): 

        self.mux_manager.clear_all()

        path_a = self.mux_manager.get_pin_path(pin_a, Rail.POSITIVE) 

        path_b = self.mux_manager.get_pin_path(pin_b, Rail.NEGATIVE) 

 

        self.mux_manager.set_pin(path_a, True) 

        self.mux_manager.set_pin(self.dmm_positive_path, True) 

        self.mux_manager.set_pin(path_b, True) 

        self.mux_manager.set_pin(self.dmm_negative_path, True) 

        measurement = self.dmm.read_voltage()

        # Clearing up connections

        self.mux_manager.clear_all()

        if (expected - tolerance) &lt; measurement &lt; (expected + tolerance): 

            return "PASS"

        else:

            return "FAIL"</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">VoltageTest</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    …</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">test_voltage</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">pin_a</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">pin_b</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">expected</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">tolerance</span><span style="color: #D4D4D4">): </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.mux_manager.clear_all()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        path_a = </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.mux_manager.get_pin_path(pin_a, Rail.POSITIVE) </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        path_b = </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.mux_manager.get_pin_path(pin_b, Rail.NEGATIVE) </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.mux_manager.set_pin(path_a, </span><span style="color: #569CD6">True</span><span style="color: #D4D4D4">) </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.mux_manager.set_pin(</span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.dmm_positive_path, </span><span style="color: #569CD6">True</span><span style="color: #D4D4D4">) </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.mux_manager.set_pin(path_b, </span><span style="color: #569CD6">True</span><span style="color: #D4D4D4">) </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.mux_manager.set_pin(</span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.dmm_negative_path, </span><span style="color: #569CD6">True</span><span style="color: #D4D4D4">) </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        measurement = </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.dmm.read_voltage()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955"># Clearing up connections</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.mux_manager.clear_all()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (expected - tolerance) &lt; measurement &lt; (expected + tolerance): </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;PASS&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4">:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;FAIL&quot;</span></span></code></pre></div>



<p class="wp-block-paragraph">We need to clear up the connections at the end of each function call to leave the multiplexer in a clean state so that calls to test_voltage can be rearranged in a test sequence by an engineer without worrying about what pins are previously enabled. On the other hand, when we imagine how such a method would be used, we start to see some redundancy. In testing the 3-pin outlet, we would have to enable and disable DMM pins 12 times and get similar inefficiencies with the pins being tested.The problem is compounded when this generic function is run hundreds of times in one sequence and that sequence is run hundreds of times. The likelihood of a single relay failing (and therefore risk of downtime) is made unnecessarily high by lazy programming.</p>



<p class="wp-block-paragraph"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/before.gif"><br>
&nbsp;<br>
Instead, we could use our knowledge about our system and the math abilities of Python to eliminate this redundancy with a method in the MUX Manager:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Python</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
class MUXManager:

    …

    def masked_set_pins(self, pin_and_rail_list):

        high_pins = set()

        for pin_name in self.pin_names: 

            pin_path_positive = self.get_pin_path(pin_name, Rail.POSITIVE) 

            pin_path_negative = self.get_pin_path(pin_name, Rail.NEGATIVE) 

            if self.read_pin(pin_path_positive):

                high_pins.add(pin_path_positive) 

            if self.read_pin(pin_path_negative):

                high_pins.add(pin_path_negative)

        need_to_be_high_pins = set()

        for pin_name, rail in pin_and_rail_list:

            pin_path = self.get_pin_path(pin_name, rail)

            need_to_be_high_pins.add(pin_path)


        need_to_make_low_pins = high_pins - need_to_be_high_pins

        for path in need_to_make_low_pins:

            self.set_pin(path, False)

        need_to_make_high_pins = need_to_be_high_pins - high_pins

        for path in need_to_make_high_pins:

            self.set_pin(path, True) </textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">MUXManager</span><span style="color: #D4D4D4">:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    …</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">masked_set_pins</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">pin_and_rail_list</span><span style="color: #D4D4D4">):</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        high_pins = </span><span style="color: #4EC9B0">set</span><span style="color: #D4D4D4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> pin_name </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.pin_names: </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            pin_path_positive = </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.get_pin_path(pin_name, Rail.POSITIVE) </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            pin_path_negative = </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.get_pin_path(pin_name, Rail.NEGATIVE) </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.read_pin(pin_path_positive):</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">                high_pins.add(pin_path_positive) </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.read_pin(pin_path_negative):</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">                high_pins.add(pin_path_negative)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        need_to_be_high_pins = </span><span style="color: #4EC9B0">set</span><span style="color: #D4D4D4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> pin_name, rail </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> pin_and_rail_list:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            pin_path = </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.get_pin_path(pin_name, rail)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            need_to_be_high_pins.add(pin_path)</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        need_to_make_low_pins = high_pins - need_to_be_high_pins</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> path </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> need_to_make_low_pins:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.set_pin(path, </span><span style="color: #569CD6">False</span><span style="color: #D4D4D4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        need_to_make_high_pins = need_to_be_high_pins - high_pins</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> path </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> need_to_make_high_pins:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.set_pin(path, </span><span style="color: #569CD6">True</span><span style="color: #D4D4D4">) </span></span></code></pre></div>



<p class="wp-block-paragraph">By using set differences, we know which&nbsp;relays to turn off and on from a previous state and avoid any calls in the process that would be redundant.</p>



<p class="wp-block-paragraph">This is not a perfect approach and requires knowledge of the system such as whether you would be performing any hot switching or&nbsp;there needs to be an order to the switch calls.</p>



<p class="wp-block-paragraph">For our voltage tests, however, this approach was the right one and worked best for our client’s needs.&nbsp;We can rewrite our test_voltage method to incorporate this new method as follows:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Python</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
class VoltageTest:

    …

    def test_voltage(self, pin_a: str, pin_b: str, expected, tolerance): 

        self.mux_manager.masked_set_high_pins(&#91;

            (pin_a, Rail.POSITIVE), 

            ("DMM+", Rail.POSITIVE), 

            (pin_b, Rail.NEGATIVE), 

            ("DMM-", Rail.NEGATIVE),

        &#93;) 

        measurement = self.dmm.read_voltage()

        if (expected - tolerance) &lt; measurement &lt; (expected + tolerance): 

            return "PASS"

        else:

            return "FAIL"    </textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">VoltageTest</span><span style="color: #D4D4D4">:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    …</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">test_voltage</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">pin_a</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">str</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">pin_b</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">str</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">expected</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">tolerance</span><span style="color: #D4D4D4">): </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.mux_manager.masked_set_high_pins(&#91;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            (pin_a, Rail.POSITIVE), </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            (</span><span style="color: #CE9178">&quot;DMM+&quot;</span><span style="color: #D4D4D4">, Rail.POSITIVE), </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            (pin_b, Rail.NEGATIVE), </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            (</span><span style="color: #CE9178">&quot;DMM-&quot;</span><span style="color: #D4D4D4">, Rail.NEGATIVE),</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        &#93;) </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        measurement = </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.dmm.read_voltage()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (expected - tolerance) &lt; measurement &lt; (expected + tolerance): </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;PASS&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4">:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;FAIL&quot;</span><span style="color: #D4D4D4">    </span></span></code></pre></div>



<p class="wp-block-paragraph">Our method is more readable and efficient while reducing the relay switches per measurement. The animation given shows the decreased switching actions needed (from 24 down to 12) with this new approach — which is even more pronounced for outlets with more pins.</p>



<p class="wp-block-paragraph"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/after.gif">&nbsp;<br>
What I like most about this whole endeavor is that it confronts the fact that it illustrates how thoughtful engineering design can be exemplified in many ways —&nbsp;in hardware and software. By complicating how our software works, our hardware takes fewer steps and lives longer. Good multiplexing is, well,&nbsp;multiplex.</p>



<p class="wp-block-paragraph"><strong>Learn more about DMC&#8217;s <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/battery-pack-and-bms-test-systems">Battery Pack and BMS Test Systems</a>&nbsp;and <a href="https://static.dmcinfo.com/contact">contact us</a> today for your next project.</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/16958/using-algorithms-for-efficient-multiplexing/">Using Algorithms for Efficient Multiplexing</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
