<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://community.element14.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Build Your Own USB Looper for Serial Debugging and File Transfer -- Episode 702</title><link>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702</link><description /><dc:language>en-US</dc:language><generator>Telligent Community 12</generator><item><title>Build Your Own USB Looper for Serial Debugging and File Transfer -- Episode 702</title><link>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702</link><pubDate>Thu, 19 Feb 2026 11:01:37 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ac0e986d-170b-4d78-b9a0-ce61d4a7b5bb</guid><dc:creator>vivekvelusamy</dc:creator><comments>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702#comments</comments><description>Current Revision posted to Documents by vivekvelusamy on 2/19/2026 11:01:37 AM&lt;br /&gt;
&lt;p&gt;&lt;span&gt;Clem introduces the &amp;quot;Blooper&amp;quot;, USB Looper, a modern null-modem style tool for UART debugging, device emulation and file transfer without a network. See how it logs serial data, enables full-duplex chat between computers, and safely connects two USB hosts.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqmd0ec0"&gt;&lt;span&gt;Watch&amp;nbsp;Clem Build the Blooper&lt;/span&gt;&lt;/h2&gt;
&lt;p data-start="267" data-end="671"&gt;&lt;a href="https://youtu.be/TqhYRmpYBO0"&gt;https://youtu.be/TqhYRmpYBO0&lt;/a&gt;&lt;/p&gt;
&lt;p data-start="267" data-end="671"&gt;Some tools begin as personal workflow helpers and quietly become essential to multiple projects. Clem&amp;rsquo;s USB Looper. nicknamed the &lt;strong data-start="398" data-end="411"&gt;&amp;ldquo;&lt;/strong&gt;Blooper&lt;strong data-start="398" data-end="411"&gt;&amp;rdquo;,&lt;/strong&gt;&amp;nbsp;clearly falls into that category. What started as a practical debugging aid has grown into a fully documented, open-source hardware tool designed to solve real development problems around UART, USB and device emulation. Of course, it comes Clem endorsed:&lt;/p&gt;
&lt;blockquote data-start="722" data-end="835"&gt;
&lt;p data-start="724" data-end="835"&gt;&amp;ldquo;This tool has saved so many projects&amp;hellip; and guess what? I made it myself.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="837" data-end="1004"&gt;The Blooper is best understood as a modern reinterpretation of the classic null modem cable, but built for today&amp;rsquo;s USB-centric workflows and development environments.&lt;/p&gt;
&lt;p data-start="837" data-end="1004"&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-03-81/3580.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs0" data-start="1011" data-end="1043"&gt;What the Blooper Actually Does&lt;/h2&gt;
&lt;p data-start="1045" data-end="1265"&gt;At first glance, the Blooper appears simple: a small device with two USB-C ports. Internally, however, it enables something surprisingly powerful. When connected, the computer sees two independent USB serial devices.&lt;/p&gt;
&lt;p data-start="1267" data-end="1284"&gt;As Clem explains:&lt;/p&gt;
&lt;blockquote data-start="1286" data-end="1410"&gt;
&lt;p data-start="1288" data-end="1410"&gt;&amp;ldquo;The blooper appears as two independent devices&amp;hellip; they both just talk to each other.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1412" data-end="1662"&gt;This means a single computer can communicate with itself as if it were talking to an external embedded system. From the OS perspective, the data looks like it is coming from another device entirely, even though it&amp;rsquo;s looped back through the hardware.&lt;/p&gt;
&lt;p data-start="1664" data-end="1796"&gt;This hardware loop-back is central to why the tool exists. While software loop-back can be simulated, Clem points out the limitations:&lt;/p&gt;
&lt;blockquote data-start="1798" data-end="1970"&gt;
&lt;p data-start="1800" data-end="1970"&gt;&amp;ldquo;You could emulate this in software, but the setup is not as easy&amp;hellip; and I don&amp;rsquo;t think it works on any computer. And this thing does.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1972" data-end="2027"&gt;This reliability and portability is the key difference.&lt;/p&gt;
&lt;p data-start="1972" data-end="2027"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-03-81/2084.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs1" data-start="2034" data-end="2076"&gt;Logging Serial Output Like a Real Device&lt;/h2&gt;
&lt;p data-start="2078" data-end="2194"&gt;One of Clem&amp;rsquo;s first demonstrations focuses on logging serial data to a file, a task common in embedded development.&lt;/p&gt;
&lt;p data-start="2196" data-end="2229"&gt;He explains the scenario clearly:&lt;/p&gt;
&lt;blockquote data-start="2231" data-end="2395"&gt;
&lt;p data-start="2233" data-end="2395"&gt;&amp;ldquo;For the computer, it was exactly the same as if the data was coming from an external device. It can&amp;rsquo;t make any difference.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="2397" data-end="2586"&gt;The supporting Python script shows exactly how this is achieved. The logging workflow is implemented in logfile.py, which timestamps incoming serial data and writes it directly to disk:&lt;/p&gt;
&lt;p data-start="2397" data-end="2586"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.readline().decode(&amp;#39;utf-8&amp;#39;).strip()
timestamp = time.strftime(&amp;#39;%Y-%m-%d %H:%M:%S&amp;#39;)
log_entry = f&amp;quot;{timestamp} - {incoming_data}\n&amp;quot;
f.write(log_entry)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;&lt;/span&gt;&lt;/code&gt;This reinforces a major use case: testing software that normally expects real hardware output. Because the Blooper behaves like real external hardware, tools such as Arduino IDE, terminal monitors, and custom serial apps can be tested safely and repeatedly.&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="3068" data-end="3117"&gt;Clem highlights how widely he uses this workflow:&lt;/p&gt;
&lt;blockquote data-start="3119" data-end="3249"&gt;
&lt;p data-start="3121" data-end="3249"&gt;&amp;ldquo;I use this to log stuff from Arduinos or out of computers or Raspberry Pi&amp;rsquo;s or whatever.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqob46n0" data-start="3256" data-end="3297"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-03-81/5226.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs2" data-start="3256" data-end="3297"&gt;Revisiting the Null Modem Cable Concept&lt;/h2&gt;
&lt;p data-start="3299" data-end="3361"&gt;The Blooper&amp;rsquo;s inspiration comes directly from older workflows.&lt;/p&gt;
&lt;p data-start="3363" data-end="3377"&gt;Clem reflects:&lt;/p&gt;
&lt;blockquote data-start="3379" data-end="3523"&gt;
&lt;p data-start="3381" data-end="3523"&gt;&amp;ldquo;Back in the early 2000, my means of transporting files from one computer to another was&amp;hellip; floppy disks.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3525" data-end="3683"&gt;Before networking was ubiquitous, null modem cables allowed direct PC-to-PC communication over UART. The Blooper recreates this idea with modern USB hardware:&lt;/p&gt;
&lt;blockquote data-start="3685" data-end="3792"&gt;
&lt;p data-start="3687" data-end="3792"&gt;&amp;ldquo;USB ports are kind of a serial port hidden inside a USB protocol.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3794" data-end="3952"&gt;Internally, the Blooper converts USB to UART on both sides. The result is two hosts communicating directly, bypassing traditional USB host-device constraints.&lt;/p&gt;
&lt;p data-start="3954" data-end="4060"&gt;This is what allows two computers, or even one computer with two terminals, to chat over a single cable.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqobr0h1" data-start="4067" data-end="4114"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-03-81/5621.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs3" data-start="4067" data-end="4114"&gt;Building a Full-Duplex Chat Between Computers&lt;/h2&gt;
&lt;p data-start="4116" data-end="4264"&gt;To demonstrate full duplex communication, Clem runs a simple Python chat application. This behaviour is implemented in chat.py and chat2.py.&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;The scripts use two threads: one for reading serial input and one for writing. This enables real-time two-way communication:&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;&lt;pre class="ui-code" data-mode="python"&gt;threading.Thread(target=read_from_serial, args=(ser,), daemon=True).start()
write_to_serial(ser)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="4504" data-end="4717"&gt;This simple threading approach makes the serial link behave like a messaging app, demonstrating how easily developers can test command protocols or debug communication stacks.&lt;/p&gt;
&lt;p data-start="4719" data-end="4760"&gt;Clem summarises the usefulness perfectly:&lt;/p&gt;
&lt;blockquote data-start="4762" data-end="4915"&gt;
&lt;p data-start="4764" data-end="4915"&gt;&amp;ldquo;This also works if you plug both ends into the same computer&amp;hellip; which is very handy for debugging applications.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqocqqa2" data-start="4922" data-end="4960"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-03-81/2577.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs4" data-start="4922" data-end="4960"&gt;Transferring Files Without a Network&lt;/h2&gt;
&lt;p data-start="4962" data-end="5056"&gt;Another demonstration recreates a classic use case: transferring files without network access.&lt;/p&gt;
&lt;p data-start="5058" data-end="5086"&gt;Clem explains the relevance:&lt;/p&gt;
&lt;blockquote data-start="5088" data-end="5245"&gt;
&lt;p data-start="5090" data-end="5245"&gt;&amp;ldquo;While transferring data without a network is not as common today&amp;hellip; this can still be useful in air-gapped systems.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="5247" data-end="5320"&gt;The Python tools behind this are filesender.py and filereader.p&lt;strong data-start="5302" data-end="5319"&gt;y&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;Sending a file is straightforward:&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;&lt;pre class="ui-code" data-mode="python"&gt;with open(&amp;#39;log_file.txt&amp;#39;, &amp;#39;r&amp;#39;) as file:
    data = file.read()
ser.write(data.encode())&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5461" data-end="5520"&gt;Receiving and saving the data uses continuous serial reads:&lt;/p&gt;
&lt;p data-start="5461" data-end="5520"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.read(ser.in_waiting).decode()
file.write(incoming_data)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;These scripts mirror how firmware is often uploaded to embedded systems.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5687" data-end="5721"&gt;Clem explicitly connects the dots:&lt;/p&gt;
&lt;blockquote data-start="5723" data-end="5866"&gt;
&lt;p data-start="5725" data-end="5866"&gt;&amp;ldquo;This is the same way that you would upload firmware over serial&amp;hellip; or configure industrial machinery.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqofgaj3" data-start="5873" data-end="5920"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-03-81/3157.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs5" data-start="5873" data-end="5920"&gt;Hardware Design Choices That Make It Reliable&lt;/h2&gt;
&lt;p data-start="5922" data-end="6048"&gt;The transcript adds substantial technical depth beyond the original write-up, especially around the hardware design decisions.&lt;/p&gt;
&lt;p data-start="6050" data-end="6118"&gt;One of the most important details is the use of FTDI USB-UART chips:&lt;/p&gt;
&lt;blockquote data-start="6120" data-end="6285"&gt;
&lt;p data-start="6122" data-end="6285"&gt;&amp;ldquo;They always enumerate perfectly&amp;hellip; they don&amp;rsquo;t need any external crystals. This has to be reliable and bootable at any time.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6287" data-end="6414"&gt;This is a key engineering decision: the Blooper is meant to be a tool, not an experiment. Reliability takes priority over cost.&lt;/p&gt;
&lt;p data-start="6416" data-end="6456"&gt;Other critical hardware details include:&lt;/p&gt;
&lt;p data-start="6458" data-end="6712"&gt;&amp;bull; USB-C CC pull-downs (5.1k&amp;Omega;) to ensure correct power negotiation&lt;br data-start="6523" data-end="6526" /&gt; &amp;bull; Schottky diode to prevent reverse powering&lt;br data-start="6570" data-end="6573" /&gt; &amp;bull; Ground stitching vias to prevent cross-talk&lt;br data-start="6617" data-end="6620" /&gt; &amp;bull; Shared reset circuit with pull-up resistor&lt;br data-start="6664" data-end="6667" /&gt; &amp;bull; Dual LED indicators for traffic direction&lt;/p&gt;
&lt;p data-start="6714" data-end="6737"&gt;Clem emphasises safety:&lt;/p&gt;
&lt;blockquote data-start="6739" data-end="6860"&gt;
&lt;p data-start="6741" data-end="6860"&gt;&amp;ldquo;If you don&amp;rsquo;t do that, you get weird behaviour&amp;hellip; and this could damage the port.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6862" data-end="7002"&gt;These considerations ensure the device is safe to connect between two computers, something normally discouraged with USB-A-to-USB-A cables.&lt;/p&gt;
&lt;p data-start="6862" data-end="7002"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-03-81/7380.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs6" data-start="7009" data-end="7045"&gt;Assembly and Practical Build Notes&lt;/h2&gt;
&lt;p data-start="7047" data-end="7118"&gt;The assembly process introduces several practical lessons for builders.&lt;/p&gt;
&lt;p data-start="7120" data-end="7166"&gt;Clem notes the challenges of USB-C connectors:&lt;/p&gt;
&lt;blockquote data-start="7168" data-end="7301"&gt;
&lt;p data-start="7170" data-end="7301"&gt;&amp;ldquo;Be aware that USB-C ports that have pins underneath them&amp;hellip; might be really hard to rework.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7303" data-end="7415"&gt;He deliberately chose USB-C connectors limited to USB 2.0 to simplify assembly and avoid unnecessary complexity.&lt;/p&gt;
&lt;p data-start="7417" data-end="7462"&gt;For enclosure, he chose a pragmatic approach:&lt;/p&gt;
&lt;blockquote data-start="7464" data-end="7605"&gt;
&lt;p data-start="7466" data-end="7605"&gt;&amp;ldquo;Heat shrink is the absolute easiest way to make a case&amp;hellip; it&amp;rsquo;s completely functional and compliant.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7607" data-end="7659"&gt;This reinforces the project&amp;rsquo;s focus on practicality.&lt;/p&gt;
&lt;p data-start="7607" data-end="7659"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-03-81/2480.jpg" /&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-03-81/6523.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs7" data-start="7666" data-end="7689"&gt;Why This Tool Matters and&amp;nbsp;Open Source and Future Potential&lt;/h2&gt;
&lt;p data-start="7691" data-end="7746"&gt;Perhaps the most telling reflection comes near the end:&lt;/p&gt;
&lt;blockquote data-start="7748" data-end="7873"&gt;
&lt;p data-start="7750" data-end="7873"&gt;&amp;ldquo;A lot of my projects would not work out as good as they actually do without this.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7875" data-end="7963"&gt;The Blooper is not just a demonstration device. It&amp;rsquo;s a daily workflow tool that enables:&lt;/p&gt;
&lt;p data-start="7965" data-end="8103"&gt;&amp;bull; Device emulation&lt;br data-start="7983" data-end="7986" /&gt; &amp;bull; Protocol testing&lt;br data-start="8004" data-end="8007" /&gt; &amp;bull; Serial debugging&lt;br data-start="8025" data-end="8028" /&gt; &amp;bull; File transfer without networking&lt;br data-start="8062" data-end="8065" /&gt; &amp;bull; Reliable UART testing environments&lt;/p&gt;
&lt;p data-start="8105" data-end="8156"&gt;Clem also highlights one of the most powerful uses:&lt;/p&gt;
&lt;blockquote data-start="8158" data-end="8276"&gt;
&lt;p data-start="8160" data-end="8276"&gt;&amp;ldquo;I could pretend that I&amp;rsquo;m an Arduino&amp;hellip; and see if the command parsing works.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8278" data-end="8384"&gt;This ability to emulate hardware responses opens up a wide range of development and testing possibilities.The project is fully open source and available for the community to build and modify. Clem encourages others to adapt and extend the tool:&lt;/p&gt;
&lt;blockquote data-start="8567" data-end="8681"&gt;
&lt;p data-start="8569" data-end="8681"&gt;&amp;ldquo;Do you have any tools that you made yourself to make your life easier?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8683" data-end="8842"&gt;The Blooper may have started as a personal helper, but it now stands as a practical tool for developers working with embedded systems and serial communication.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;It brings an old idea, the null modem cable, firmly into modern development workflows.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlpnguf" data-start="8844" data-end="8932"&gt;Supporting Links and Files&lt;/h2&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;-&amp;nbsp;&amp;nbsp;&lt;a href="https://community.element14.com/challenges-projects/element14-presents/m/files/151004"&gt;Episode 702 Resources&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcc"&gt;Bill of Materials&lt;/h2&gt;
&lt;table class="e14-product-bom-main"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;&lt;a id="e14-product-link-fbb6d" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2&amp;nsku=83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_BUY_KIT" class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('fbb6d'));" data-farnell="2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2" data-newark="83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Kit&lt;/a&gt; &lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FT230XS-R&lt;/td&gt;
&lt;td&gt;FTDI&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-e42d2" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2&amp;nsku=83T7087~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('e42d2'));" data-farnell="2081321~2" data-newark="83T7087~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usb-c port&lt;/td&gt;
&lt;td&gt;Molex&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-8e04e" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3702965~2&amp;nsku=30AK0565~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('8e04e'));" data-farnell="3702965~2" data-newark="30AK0565~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Led 0603&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-b84b6" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3796321~2&amp;nsku=73AJ8834~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('b84b6'));" data-farnell="3796321~2" data-newark="73AJ8834~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5k1 resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-af4cb" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447404~4&amp;nsku=94X1664~4&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('af4cb'));" data-farnell="2447404~4" data-newark="94X1664~4" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;68Ohm resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-ae8d8" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447422~2&amp;nsku=94X1713~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('ae8d8'));" data-farnell="2447422~2" data-newark="94X1713~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;schottky diode&lt;/td&gt;
&lt;td&gt;bourns&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-81fe6" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2807974~2&amp;nsku=43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('81fe6'));" data-farnell="2807974~2" data-newark="43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="xs-hide"&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcd"&gt;Additional Parts&lt;/h2&gt;
&lt;table class="e14-product-bom-additional"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCB made by Aisler&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heatshrink tubing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mcetoc_1jhqlp2dce"&gt;&lt;/h3&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: open source hardware usb, hardware debugging tools, serial device emulation, serial loopback testing, uart file transfer, usb null modem, embedded serial debugging, usb looper, usb uart project, usb serial logging, ftdi uart bridge, usb host to host communication, usb serial chat application, uart debugging tool, friday_release, air gapped file transfer&lt;/div&gt;
</description></item><item><title>Build Your Own USB Looper for Serial Debugging and File Transfer -- Episode 702</title><link>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702/revision/9</link><pubDate>Thu, 19 Feb 2026 11:01:37 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ac0e986d-170b-4d78-b9a0-ce61d4a7b5bb</guid><dc:creator>cstanton</dc:creator><comments>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702#comments</comments><description>Revision 9 posted to Documents by cstanton on 2/19/2026 11:01:37 AM&lt;br /&gt;
&lt;p&gt;&lt;span&gt;Clem introduces the &amp;quot;Blooper&amp;quot;, USB Looper, a modern null-modem style tool for UART debugging, device emulation and file transfer without a network. See how it logs serial data, enables full-duplex chat between computers, and safely connects two USB hosts.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqmd0ec0"&gt;&lt;span&gt;Watch&amp;nbsp;Clem Build the Blooper&lt;/span&gt;&lt;/h2&gt;
&lt;p data-start="267" data-end="671"&gt;&lt;a href="https://youtu.be/TqhYRmpYBO0"&gt;https://youtu.be/TqhYRmpYBO0&lt;/a&gt;&lt;/p&gt;
&lt;p data-start="267" data-end="671"&gt;Some tools begin as personal workflow helpers and quietly become essential to multiple projects. Clem&amp;rsquo;s USB Looper. nicknamed the &lt;strong data-start="398" data-end="411"&gt;&amp;ldquo;&lt;/strong&gt;Blooper&lt;strong data-start="398" data-end="411"&gt;&amp;rdquo;,&lt;/strong&gt;&amp;nbsp;clearly falls into that category. What started as a practical debugging aid has grown into a fully documented, open-source hardware tool designed to solve real development problems around UART, USB and device emulation. Of course, it comes Clem endorsed:&lt;/p&gt;
&lt;blockquote data-start="722" data-end="835"&gt;
&lt;p data-start="724" data-end="835"&gt;&amp;ldquo;This tool has saved so many projects&amp;hellip; and guess what? I made it myself.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="837" data-end="1004"&gt;The Blooper is best understood as a modern reinterpretation of the classic null modem cable, but built for today&amp;rsquo;s USB-centric workflows and development environments.&lt;/p&gt;
&lt;p data-start="837" data-end="1004"&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/3580.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs0" data-start="1011" data-end="1043"&gt;What the Blooper Actually Does&lt;/h2&gt;
&lt;p data-start="1045" data-end="1265"&gt;At first glance, the Blooper appears simple: a small device with two USB-C ports. Internally, however, it enables something surprisingly powerful. When connected, the computer sees two independent USB serial devices.&lt;/p&gt;
&lt;p data-start="1267" data-end="1284"&gt;As Clem explains:&lt;/p&gt;
&lt;blockquote data-start="1286" data-end="1410"&gt;
&lt;p data-start="1288" data-end="1410"&gt;&amp;ldquo;The blooper appears as two independent devices&amp;hellip; they both just talk to each other.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1412" data-end="1662"&gt;This means a single computer can communicate with itself as if it were talking to an external embedded system. From the OS perspective, the data looks like it is coming from another device entirely, even though it&amp;rsquo;s looped back through the hardware.&lt;/p&gt;
&lt;p data-start="1664" data-end="1796"&gt;This hardware loop-back is central to why the tool exists. While software loop-back can be simulated, Clem points out the limitations:&lt;/p&gt;
&lt;blockquote data-start="1798" data-end="1970"&gt;
&lt;p data-start="1800" data-end="1970"&gt;&amp;ldquo;You could emulate this in software, but the setup is not as easy&amp;hellip; and I don&amp;rsquo;t think it works on any computer. And this thing does.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1972" data-end="2027"&gt;This reliability and portability is the key difference.&lt;/p&gt;
&lt;p data-start="1972" data-end="2027"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/2084.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs1" data-start="2034" data-end="2076"&gt;Logging Serial Output Like a Real Device&lt;/h2&gt;
&lt;p data-start="2078" data-end="2194"&gt;One of Clem&amp;rsquo;s first demonstrations focuses on logging serial data to a file, a task common in embedded development.&lt;/p&gt;
&lt;p data-start="2196" data-end="2229"&gt;He explains the scenario clearly:&lt;/p&gt;
&lt;blockquote data-start="2231" data-end="2395"&gt;
&lt;p data-start="2233" data-end="2395"&gt;&amp;ldquo;For the computer, it was exactly the same as if the data was coming from an external device. It can&amp;rsquo;t make any difference.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="2397" data-end="2586"&gt;The supporting Python script shows exactly how this is achieved. The logging workflow is implemented in logfile.py, which timestamps incoming serial data and writes it directly to disk:&lt;/p&gt;
&lt;p data-start="2397" data-end="2586"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.readline().decode(&amp;#39;utf-8&amp;#39;).strip()
timestamp = time.strftime(&amp;#39;%Y-%m-%d %H:%M:%S&amp;#39;)
log_entry = f&amp;quot;{timestamp} - {incoming_data}\n&amp;quot;
f.write(log_entry)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;&lt;/span&gt;&lt;/code&gt;This reinforces a major use case: testing software that normally expects real hardware output. Because the Blooper behaves like real external hardware, tools such as Arduino IDE, terminal monitors, and custom serial apps can be tested safely and repeatedly.&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="3068" data-end="3117"&gt;Clem highlights how widely he uses this workflow:&lt;/p&gt;
&lt;blockquote data-start="3119" data-end="3249"&gt;
&lt;p data-start="3121" data-end="3249"&gt;&amp;ldquo;I use this to log stuff from Arduinos or out of computers or Raspberry Pi&amp;rsquo;s or whatever.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqob46n0" data-start="3256" data-end="3297"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/5226.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs2" data-start="3256" data-end="3297"&gt;Revisiting the Null Modem Cable Concept&lt;/h2&gt;
&lt;p data-start="3299" data-end="3361"&gt;The Blooper&amp;rsquo;s inspiration comes directly from older workflows.&lt;/p&gt;
&lt;p data-start="3363" data-end="3377"&gt;Clem reflects:&lt;/p&gt;
&lt;blockquote data-start="3379" data-end="3523"&gt;
&lt;p data-start="3381" data-end="3523"&gt;&amp;ldquo;Back in the early 2000, my means of transporting files from one computer to another was&amp;hellip; floppy disks.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3525" data-end="3683"&gt;Before networking was ubiquitous, null modem cables allowed direct PC-to-PC communication over UART. The Blooper recreates this idea with modern USB hardware:&lt;/p&gt;
&lt;blockquote data-start="3685" data-end="3792"&gt;
&lt;p data-start="3687" data-end="3792"&gt;&amp;ldquo;USB ports are kind of a serial port hidden inside a USB protocol.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3794" data-end="3952"&gt;Internally, the Blooper converts USB to UART on both sides. The result is two hosts communicating directly, bypassing traditional USB host-device constraints.&lt;/p&gt;
&lt;p data-start="3954" data-end="4060"&gt;This is what allows two computers, or even one computer with two terminals, to chat over a single cable.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqobr0h1" data-start="4067" data-end="4114"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/5621.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs3" data-start="4067" data-end="4114"&gt;Building a Full-Duplex Chat Between Computers&lt;/h2&gt;
&lt;p data-start="4116" data-end="4264"&gt;To demonstrate full duplex communication, Clem runs a simple Python chat application. This behaviour is implemented in chat.py and chat2.py.&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;The scripts use two threads: one for reading serial input and one for writing. This enables real-time two-way communication:&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;&lt;pre class="ui-code" data-mode="python"&gt;threading.Thread(target=read_from_serial, args=(ser,), daemon=True).start()
write_to_serial(ser)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="4504" data-end="4717"&gt;This simple threading approach makes the serial link behave like a messaging app, demonstrating how easily developers can test command protocols or debug communication stacks.&lt;/p&gt;
&lt;p data-start="4719" data-end="4760"&gt;Clem summarises the usefulness perfectly:&lt;/p&gt;
&lt;blockquote data-start="4762" data-end="4915"&gt;
&lt;p data-start="4764" data-end="4915"&gt;&amp;ldquo;This also works if you plug both ends into the same computer&amp;hellip; which is very handy for debugging applications.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqocqqa2" data-start="4922" data-end="4960"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/2577.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs4" data-start="4922" data-end="4960"&gt;Transferring Files Without a Network&lt;/h2&gt;
&lt;p data-start="4962" data-end="5056"&gt;Another demonstration recreates a classic use case: transferring files without network access.&lt;/p&gt;
&lt;p data-start="5058" data-end="5086"&gt;Clem explains the relevance:&lt;/p&gt;
&lt;blockquote data-start="5088" data-end="5245"&gt;
&lt;p data-start="5090" data-end="5245"&gt;&amp;ldquo;While transferring data without a network is not as common today&amp;hellip; this can still be useful in air-gapped systems.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="5247" data-end="5320"&gt;The Python tools behind this are filesender.py and filereader.p&lt;strong data-start="5302" data-end="5319"&gt;y&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;Sending a file is straightforward:&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;&lt;pre class="ui-code" data-mode="python"&gt;with open(&amp;#39;log_file.txt&amp;#39;, &amp;#39;r&amp;#39;) as file:
    data = file.read()
ser.write(data.encode())&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5461" data-end="5520"&gt;Receiving and saving the data uses continuous serial reads:&lt;/p&gt;
&lt;p data-start="5461" data-end="5520"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.read(ser.in_waiting).decode()
file.write(incoming_data)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;These scripts mirror how firmware is often uploaded to embedded systems.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5687" data-end="5721"&gt;Clem explicitly connects the dots:&lt;/p&gt;
&lt;blockquote data-start="5723" data-end="5866"&gt;
&lt;p data-start="5725" data-end="5866"&gt;&amp;ldquo;This is the same way that you would upload firmware over serial&amp;hellip; or configure industrial machinery.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqofgaj3" data-start="5873" data-end="5920"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/3157.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs5" data-start="5873" data-end="5920"&gt;Hardware Design Choices That Make It Reliable&lt;/h2&gt;
&lt;p data-start="5922" data-end="6048"&gt;The transcript adds substantial technical depth beyond the original write-up, especially around the hardware design decisions.&lt;/p&gt;
&lt;p data-start="6050" data-end="6118"&gt;One of the most important details is the use of FTDI USB-UART chips:&lt;/p&gt;
&lt;blockquote data-start="6120" data-end="6285"&gt;
&lt;p data-start="6122" data-end="6285"&gt;&amp;ldquo;They always enumerate perfectly&amp;hellip; they don&amp;rsquo;t need any external crystals. This has to be reliable and bootable at any time.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6287" data-end="6414"&gt;This is a key engineering decision: the Blooper is meant to be a tool, not an experiment. Reliability takes priority over cost.&lt;/p&gt;
&lt;p data-start="6416" data-end="6456"&gt;Other critical hardware details include:&lt;/p&gt;
&lt;p data-start="6458" data-end="6712"&gt;&amp;bull; USB-C CC pull-downs (5.1k&amp;Omega;) to ensure correct power negotiation&lt;br data-start="6523" data-end="6526" /&gt; &amp;bull; Schottky diode to prevent reverse powering&lt;br data-start="6570" data-end="6573" /&gt; &amp;bull; Ground stitching vias to prevent cross-talk&lt;br data-start="6617" data-end="6620" /&gt; &amp;bull; Shared reset circuit with pull-up resistor&lt;br data-start="6664" data-end="6667" /&gt; &amp;bull; Dual LED indicators for traffic direction&lt;/p&gt;
&lt;p data-start="6714" data-end="6737"&gt;Clem emphasises safety:&lt;/p&gt;
&lt;blockquote data-start="6739" data-end="6860"&gt;
&lt;p data-start="6741" data-end="6860"&gt;&amp;ldquo;If you don&amp;rsquo;t do that, you get weird behaviour&amp;hellip; and this could damage the port.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6862" data-end="7002"&gt;These considerations ensure the device is safe to connect between two computers, something normally discouraged with USB-A-to-USB-A cables.&lt;/p&gt;
&lt;p data-start="6862" data-end="7002"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/7380.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs6" data-start="7009" data-end="7045"&gt;Assembly and Practical Build Notes&lt;/h2&gt;
&lt;p data-start="7047" data-end="7118"&gt;The assembly process introduces several practical lessons for builders.&lt;/p&gt;
&lt;p data-start="7120" data-end="7166"&gt;Clem notes the challenges of USB-C connectors:&lt;/p&gt;
&lt;blockquote data-start="7168" data-end="7301"&gt;
&lt;p data-start="7170" data-end="7301"&gt;&amp;ldquo;Be aware that USB-C ports that have pins underneath them&amp;hellip; might be really hard to rework.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7303" data-end="7415"&gt;He deliberately chose USB-C connectors limited to USB 2.0 to simplify assembly and avoid unnecessary complexity.&lt;/p&gt;
&lt;p data-start="7417" data-end="7462"&gt;For enclosure, he chose a pragmatic approach:&lt;/p&gt;
&lt;blockquote data-start="7464" data-end="7605"&gt;
&lt;p data-start="7466" data-end="7605"&gt;&amp;ldquo;Heat shrink is the absolute easiest way to make a case&amp;hellip; it&amp;rsquo;s completely functional and compliant.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7607" data-end="7659"&gt;This reinforces the project&amp;rsquo;s focus on practicality.&lt;/p&gt;
&lt;p data-start="7607" data-end="7659"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/2480.jpg" /&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/6523.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs7" data-start="7666" data-end="7689"&gt;Why This Tool Matters and&amp;nbsp;Open Source and Future Potential&lt;/h2&gt;
&lt;p data-start="7691" data-end="7746"&gt;Perhaps the most telling reflection comes near the end:&lt;/p&gt;
&lt;blockquote data-start="7748" data-end="7873"&gt;
&lt;p data-start="7750" data-end="7873"&gt;&amp;ldquo;A lot of my projects would not work out as good as they actually do without this.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7875" data-end="7963"&gt;The Blooper is not just a demonstration device. It&amp;rsquo;s a daily workflow tool that enables:&lt;/p&gt;
&lt;p data-start="7965" data-end="8103"&gt;&amp;bull; Device emulation&lt;br data-start="7983" data-end="7986" /&gt; &amp;bull; Protocol testing&lt;br data-start="8004" data-end="8007" /&gt; &amp;bull; Serial debugging&lt;br data-start="8025" data-end="8028" /&gt; &amp;bull; File transfer without networking&lt;br data-start="8062" data-end="8065" /&gt; &amp;bull; Reliable UART testing environments&lt;/p&gt;
&lt;p data-start="8105" data-end="8156"&gt;Clem also highlights one of the most powerful uses:&lt;/p&gt;
&lt;blockquote data-start="8158" data-end="8276"&gt;
&lt;p data-start="8160" data-end="8276"&gt;&amp;ldquo;I could pretend that I&amp;rsquo;m an Arduino&amp;hellip; and see if the command parsing works.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8278" data-end="8384"&gt;This ability to emulate hardware responses opens up a wide range of development and testing possibilities.The project is fully open source and available for the community to build and modify. Clem encourages others to adapt and extend the tool:&lt;/p&gt;
&lt;blockquote data-start="8567" data-end="8681"&gt;
&lt;p data-start="8569" data-end="8681"&gt;&amp;ldquo;Do you have any tools that you made yourself to make your life easier?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8683" data-end="8842"&gt;The Blooper may have started as a personal helper, but it now stands as a practical tool for developers working with embedded systems and serial communication.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;It brings an old idea, the null modem cable, firmly into modern development workflows.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlpnguf" data-start="8844" data-end="8932"&gt;Supporting Links and Files&lt;/h2&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;-&amp;nbsp;&amp;nbsp;&lt;a href="https://community.element14.com/challenges-projects/element14-presents/m/files/151004"&gt;Episode 702 Resources&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcc"&gt;Bill of Materials&lt;/h2&gt;
&lt;table class="e14-product-bom-main"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;&lt;a id="e14-product-link-b13e5" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2&amp;nsku=83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_BUY_KIT" class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('b13e5'));" data-farnell="2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2" data-newark="83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Kit&lt;/a&gt; &lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FT230XS-R&lt;/td&gt;
&lt;td&gt;FTDI&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-1a99b" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2&amp;nsku=83T7087~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('1a99b'));" data-farnell="2081321~2" data-newark="83T7087~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usb-c port&lt;/td&gt;
&lt;td&gt;Molex&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-cfea7" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3702965~2&amp;nsku=30AK0565~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('cfea7'));" data-farnell="3702965~2" data-newark="30AK0565~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Led 0603&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-41dd1" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3796321~2&amp;nsku=73AJ8834~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('41dd1'));" data-farnell="3796321~2" data-newark="73AJ8834~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5k1 resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-9dd1b" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447404~4&amp;nsku=94X1664~4&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('9dd1b'));" data-farnell="2447404~4" data-newark="94X1664~4" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;68Ohm resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-6ee86" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447422~2&amp;nsku=94X1713~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('6ee86'));" data-farnell="2447422~2" data-newark="94X1713~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;schottky diode&lt;/td&gt;
&lt;td&gt;bourns&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-e2a66" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2807974~2&amp;nsku=43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('e2a66'));" data-farnell="2807974~2" data-newark="43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="xs-hide"&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcd"&gt;Additional Parts&lt;/h2&gt;
&lt;table class="e14-product-bom-additional"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCB made by Aisler&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heatshrink tubing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mcetoc_1jhqlp2dce"&gt;&lt;/h3&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: open source hardware usb, hardware debugging tools, serial device emulation, serial loopback testing, uart file transfer, usb null modem, embedded serial debugging, usb looper, usb uart project, usb serial logging, ftdi uart bridge, usb host to host communication, usb serial chat application, uart debugging tool, friday_release, air gapped file transfer&lt;/div&gt;
</description></item><item><title>Build Your Own USB Looper for Serial Debugging and File Transfer -- Episode 702</title><link>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702/revision/8</link><pubDate>Thu, 19 Feb 2026 10:55:46 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ac0e986d-170b-4d78-b9a0-ce61d4a7b5bb</guid><dc:creator>cstanton</dc:creator><comments>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702#comments</comments><description>Revision 8 posted to Documents by cstanton on 2/19/2026 10:55:46 AM&lt;br /&gt;
&lt;p&gt;&lt;span&gt;Clem introduces the &amp;quot;Blooper&amp;quot;, USB Looper, a modern null-modem style tool for UART debugging, device emulation and file transfer without a network. See how it logs serial data, enables full-duplex chat between computers, and safely connects two USB hosts.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqmd0ec0"&gt;&lt;span&gt;Watch&amp;nbsp;Clem Build the Blooper&lt;/span&gt;&lt;/h2&gt;
&lt;p data-start="267" data-end="671"&gt;&lt;a href="https://youtu.be/TqhYRmpYBO0"&gt;https://youtu.be/TqhYRmpYBO0&lt;/a&gt;&lt;/p&gt;
&lt;p data-start="267" data-end="671"&gt;Some tools begin as personal workflow helpers and quietly become essential to multiple projects. Clem&amp;rsquo;s USB Looper. nicknamed the &lt;strong data-start="398" data-end="411"&gt;&amp;ldquo;&lt;/strong&gt;Blooper&lt;strong data-start="398" data-end="411"&gt;&amp;rdquo;,&lt;/strong&gt;&amp;nbsp;clearly falls into that category. What started as a practical debugging aid has grown into a fully documented, open-source hardware tool designed to solve real development problems around UART, USB and device emulation. Of course, it comes Clem endorsed:&lt;/p&gt;
&lt;blockquote data-start="722" data-end="835"&gt;
&lt;p data-start="724" data-end="835"&gt;&amp;ldquo;This tool has saved so many projects&amp;hellip; and guess what? I made it myself.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="837" data-end="1004"&gt;The Blooper is best understood as a modern reinterpretation of the classic null modem cable, but built for today&amp;rsquo;s USB-centric workflows and development environments.&lt;/p&gt;
&lt;p data-start="837" data-end="1004"&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/3580.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs0" data-start="1011" data-end="1043"&gt;What the Blooper Actually Does&lt;/h2&gt;
&lt;p data-start="1045" data-end="1265"&gt;At first glance, the Blooper appears simple: a small device with two USB-C ports. Internally, however, it enables something surprisingly powerful. When connected, the computer sees two independent USB serial devices.&lt;/p&gt;
&lt;p data-start="1267" data-end="1284"&gt;As Clem explains:&lt;/p&gt;
&lt;blockquote data-start="1286" data-end="1410"&gt;
&lt;p data-start="1288" data-end="1410"&gt;&amp;ldquo;The blooper appears as two independent devices&amp;hellip; they both just talk to each other.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1412" data-end="1662"&gt;This means a single computer can communicate with itself as if it were talking to an external embedded system. From the OS perspective, the data looks like it is coming from another device entirely, even though it&amp;rsquo;s looped back through the hardware.&lt;/p&gt;
&lt;p data-start="1664" data-end="1796"&gt;This hardware loop-back is central to why the tool exists. While software loop-back can be simulated, Clem points out the limitations:&lt;/p&gt;
&lt;blockquote data-start="1798" data-end="1970"&gt;
&lt;p data-start="1800" data-end="1970"&gt;&amp;ldquo;You could emulate this in software, but the setup is not as easy&amp;hellip; and I don&amp;rsquo;t think it works on any computer. And this thing does.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1972" data-end="2027"&gt;This reliability and portability is the key difference.&lt;/p&gt;
&lt;p data-start="1972" data-end="2027"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/2084.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs1" data-start="2034" data-end="2076"&gt;Logging Serial Output Like a Real Device&lt;/h2&gt;
&lt;p data-start="2078" data-end="2194"&gt;One of Clem&amp;rsquo;s first demonstrations focuses on logging serial data to a file, a task common in embedded development.&lt;/p&gt;
&lt;p data-start="2196" data-end="2229"&gt;He explains the scenario clearly:&lt;/p&gt;
&lt;blockquote data-start="2231" data-end="2395"&gt;
&lt;p data-start="2233" data-end="2395"&gt;&amp;ldquo;For the computer, it was exactly the same as if the data was coming from an external device. It can&amp;rsquo;t make any difference.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="2397" data-end="2586"&gt;The supporting Python script shows exactly how this is achieved. The logging workflow is implemented in logfile.py, which timestamps incoming serial data and writes it directly to disk:&lt;/p&gt;
&lt;p data-start="2397" data-end="2586"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.readline().decode(&amp;#39;utf-8&amp;#39;).strip()
timestamp = time.strftime(&amp;#39;%Y-%m-%d %H:%M:%S&amp;#39;)
log_entry = f&amp;quot;{timestamp} - {incoming_data}\n&amp;quot;
f.write(log_entry)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;&lt;/span&gt;&lt;/code&gt;This reinforces a major use case: testing software that normally expects real hardware output. Because the Blooper behaves like real external hardware, tools such as Arduino IDE, terminal monitors, and custom serial apps can be tested safely and repeatedly.&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="3068" data-end="3117"&gt;Clem highlights how widely he uses this workflow:&lt;/p&gt;
&lt;blockquote data-start="3119" data-end="3249"&gt;
&lt;p data-start="3121" data-end="3249"&gt;&amp;ldquo;I use this to log stuff from Arduinos or out of computers or Raspberry Pi&amp;rsquo;s or whatever.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqob46n0" data-start="3256" data-end="3297"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/5226.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs2" data-start="3256" data-end="3297"&gt;Revisiting the Null Modem Cable Concept&lt;/h2&gt;
&lt;p data-start="3299" data-end="3361"&gt;The Blooper&amp;rsquo;s inspiration comes directly from older workflows.&lt;/p&gt;
&lt;p data-start="3363" data-end="3377"&gt;Clem reflects:&lt;/p&gt;
&lt;blockquote data-start="3379" data-end="3523"&gt;
&lt;p data-start="3381" data-end="3523"&gt;&amp;ldquo;Back in the early 2000, my means of transporting files from one computer to another was&amp;hellip; floppy disks.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3525" data-end="3683"&gt;Before networking was ubiquitous, null modem cables allowed direct PC-to-PC communication over UART. The Blooper recreates this idea with modern USB hardware:&lt;/p&gt;
&lt;blockquote data-start="3685" data-end="3792"&gt;
&lt;p data-start="3687" data-end="3792"&gt;&amp;ldquo;USB ports are kind of a serial port hidden inside a USB protocol.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3794" data-end="3952"&gt;Internally, the Blooper converts USB to UART on both sides. The result is two hosts communicating directly, bypassing traditional USB host-device constraints.&lt;/p&gt;
&lt;p data-start="3954" data-end="4060"&gt;This is what allows two computers, or even one computer with two terminals, to chat over a single cable.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqobr0h1" data-start="4067" data-end="4114"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/5621.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs3" data-start="4067" data-end="4114"&gt;Building a Full-Duplex Chat Between Computers&lt;/h2&gt;
&lt;p data-start="4116" data-end="4264"&gt;To demonstrate full duplex communication, Clem runs a simple Python chat application. This behaviour is implemented in chat.py and chat2.py.&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;The scripts use two threads: one for reading serial input and one for writing. This enables real-time two-way communication:&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;&lt;pre class="ui-code" data-mode="python"&gt;threading.Thread(target=read_from_serial, args=(ser,), daemon=True).start()
write_to_serial(ser)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="4504" data-end="4717"&gt;This simple threading approach makes the serial link behave like a messaging app, demonstrating how easily developers can test command protocols or debug communication stacks.&lt;/p&gt;
&lt;p data-start="4719" data-end="4760"&gt;Clem summarises the usefulness perfectly:&lt;/p&gt;
&lt;blockquote data-start="4762" data-end="4915"&gt;
&lt;p data-start="4764" data-end="4915"&gt;&amp;ldquo;This also works if you plug both ends into the same computer&amp;hellip; which is very handy for debugging applications.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqocqqa2" data-start="4922" data-end="4960"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/2577.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs4" data-start="4922" data-end="4960"&gt;Transferring Files Without a Network&lt;/h2&gt;
&lt;p data-start="4962" data-end="5056"&gt;Another demonstration recreates a classic use case: transferring files without network access.&lt;/p&gt;
&lt;p data-start="5058" data-end="5086"&gt;Clem explains the relevance:&lt;/p&gt;
&lt;blockquote data-start="5088" data-end="5245"&gt;
&lt;p data-start="5090" data-end="5245"&gt;&amp;ldquo;While transferring data without a network is not as common today&amp;hellip; this can still be useful in air-gapped systems.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="5247" data-end="5320"&gt;The Python tools behind this are filesender.py and filereader.p&lt;strong data-start="5302" data-end="5319"&gt;y&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;Sending a file is straightforward:&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;&lt;pre class="ui-code" data-mode="python"&gt;with open(&amp;#39;log_file.txt&amp;#39;, &amp;#39;r&amp;#39;) as file:
    data = file.read()
ser.write(data.encode())&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5461" data-end="5520"&gt;Receiving and saving the data uses continuous serial reads:&lt;/p&gt;
&lt;p data-start="5461" data-end="5520"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.read(ser.in_waiting).decode()
file.write(incoming_data)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;These scripts mirror how firmware is often uploaded to embedded systems.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5687" data-end="5721"&gt;Clem explicitly connects the dots:&lt;/p&gt;
&lt;blockquote data-start="5723" data-end="5866"&gt;
&lt;p data-start="5725" data-end="5866"&gt;&amp;ldquo;This is the same way that you would upload firmware over serial&amp;hellip; or configure industrial machinery.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqofgaj3" data-start="5873" data-end="5920"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/3157.jpg" /&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs5" data-start="5873" data-end="5920"&gt;Hardware Design Choices That Make It Reliable&lt;/h2&gt;
&lt;p data-start="5922" data-end="6048"&gt;The transcript adds substantial technical depth beyond the original write-up, especially around the hardware design decisions.&lt;/p&gt;
&lt;p data-start="6050" data-end="6118"&gt;One of the most important details is the use of FTDI USB-UART chips:&lt;/p&gt;
&lt;blockquote data-start="6120" data-end="6285"&gt;
&lt;p data-start="6122" data-end="6285"&gt;&amp;ldquo;They always enumerate perfectly&amp;hellip; they don&amp;rsquo;t need any external crystals. This has to be reliable and bootable at any time.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6287" data-end="6414"&gt;This is a key engineering decision: the Blooper is meant to be a tool, not an experiment. Reliability takes priority over cost.&lt;/p&gt;
&lt;p data-start="6416" data-end="6456"&gt;Other critical hardware details include:&lt;/p&gt;
&lt;p data-start="6458" data-end="6712"&gt;&amp;bull; USB-C CC pull-downs (5.1k&amp;Omega;) to ensure correct power negotiation&lt;br data-start="6523" data-end="6526" /&gt; &amp;bull; Schottky diode to prevent reverse powering&lt;br data-start="6570" data-end="6573" /&gt; &amp;bull; Ground stitching vias to prevent cross-talk&lt;br data-start="6617" data-end="6620" /&gt; &amp;bull; Shared reset circuit with pull-up resistor&lt;br data-start="6664" data-end="6667" /&gt; &amp;bull; Dual LED indicators for traffic direction&lt;/p&gt;
&lt;p data-start="6714" data-end="6737"&gt;Clem emphasises safety:&lt;/p&gt;
&lt;blockquote data-start="6739" data-end="6860"&gt;
&lt;p data-start="6741" data-end="6860"&gt;&amp;ldquo;If you don&amp;rsquo;t do that, you get weird behaviour&amp;hellip; and this could damage the port.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6862" data-end="7002"&gt;These considerations ensure the device is safe to connect between two computers, something normally discouraged with USB-A-to-USB-A cables.&lt;/p&gt;
&lt;p data-start="6862" data-end="7002"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/7380.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs6" data-start="7009" data-end="7045"&gt;Assembly and Practical Build Notes&lt;/h2&gt;
&lt;p data-start="7047" data-end="7118"&gt;The assembly process introduces several practical lessons for builders.&lt;/p&gt;
&lt;p data-start="7120" data-end="7166"&gt;Clem notes the challenges of USB-C connectors:&lt;/p&gt;
&lt;blockquote data-start="7168" data-end="7301"&gt;
&lt;p data-start="7170" data-end="7301"&gt;&amp;ldquo;Be aware that USB-C ports that have pins underneath them&amp;hellip; might be really hard to rework.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7303" data-end="7415"&gt;He deliberately chose USB-C connectors limited to USB 2.0 to simplify assembly and avoid unnecessary complexity.&lt;/p&gt;
&lt;p data-start="7417" data-end="7462"&gt;For enclosure, he chose a pragmatic approach:&lt;/p&gt;
&lt;blockquote data-start="7464" data-end="7605"&gt;
&lt;p data-start="7466" data-end="7605"&gt;&amp;ldquo;Heat shrink is the absolute easiest way to make a case&amp;hellip; it&amp;rsquo;s completely functional and compliant.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7607" data-end="7659"&gt;This reinforces the project&amp;rsquo;s focus on practicality.&lt;/p&gt;
&lt;p data-start="7607" data-end="7659"&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/2480.jpg" /&gt;&lt;img loading="lazy" alt="image" style="max-height:360px;max-width:640px;"  src="/resized-image/__size/1280x720/__key/communityserver-wikis-components-files/00-00-00-04-35/6523.jpg" /&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs7" data-start="7666" data-end="7689"&gt;Why This Tool Matters and&amp;nbsp;Open Source and Future Potential&lt;/h2&gt;
&lt;p data-start="7691" data-end="7746"&gt;Perhaps the most telling reflection comes near the end:&lt;/p&gt;
&lt;blockquote data-start="7748" data-end="7873"&gt;
&lt;p data-start="7750" data-end="7873"&gt;&amp;ldquo;A lot of my projects would not work out as good as they actually do without this.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7875" data-end="7963"&gt;The Blooper is not just a demonstration device. It&amp;rsquo;s a daily workflow tool that enables:&lt;/p&gt;
&lt;p data-start="7965" data-end="8103"&gt;&amp;bull; Device emulation&lt;br data-start="7983" data-end="7986" /&gt; &amp;bull; Protocol testing&lt;br data-start="8004" data-end="8007" /&gt; &amp;bull; Serial debugging&lt;br data-start="8025" data-end="8028" /&gt; &amp;bull; File transfer without networking&lt;br data-start="8062" data-end="8065" /&gt; &amp;bull; Reliable UART testing environments&lt;/p&gt;
&lt;p data-start="8105" data-end="8156"&gt;Clem also highlights one of the most powerful uses:&lt;/p&gt;
&lt;blockquote data-start="8158" data-end="8276"&gt;
&lt;p data-start="8160" data-end="8276"&gt;&amp;ldquo;I could pretend that I&amp;rsquo;m an Arduino&amp;hellip; and see if the command parsing works.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8278" data-end="8384"&gt;This ability to emulate hardware responses opens up a wide range of development and testing possibilities.The project is fully open source and available for the community to build and modify. Clem encourages others to adapt and extend the tool:&lt;/p&gt;
&lt;blockquote data-start="8567" data-end="8681"&gt;
&lt;p data-start="8569" data-end="8681"&gt;&amp;ldquo;Do you have any tools that you made yourself to make your life easier?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8683" data-end="8842"&gt;The Blooper may have started as a personal helper, but it now stands as a practical tool for developers working with embedded systems and serial communication.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;It brings an old idea, the null modem cable, firmly into modern development workflows.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlpnguf" data-start="8844" data-end="8932"&gt;Supporting Links and Files&lt;/h2&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;-&amp;nbsp;&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcc"&gt;Bill of Materials&lt;/h2&gt;
&lt;table class="e14-product-bom-main"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;&lt;a id="e14-product-link-af247" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2&amp;nsku=83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_BUY_KIT" class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('af247'));" data-farnell="2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2" data-newark="83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Kit&lt;/a&gt; &lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FT230XS-R&lt;/td&gt;
&lt;td&gt;FTDI&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-9b0a3" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2&amp;nsku=83T7087~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('9b0a3'));" data-farnell="2081321~2" data-newark="83T7087~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usb-c port&lt;/td&gt;
&lt;td&gt;Molex&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-e38cc" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3702965~2&amp;nsku=30AK0565~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('e38cc'));" data-farnell="3702965~2" data-newark="30AK0565~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Led 0603&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-46e9c" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3796321~2&amp;nsku=73AJ8834~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('46e9c'));" data-farnell="3796321~2" data-newark="73AJ8834~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5k1 resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-0400c" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447404~4&amp;nsku=94X1664~4&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('0400c'));" data-farnell="2447404~4" data-newark="94X1664~4" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;68Ohm resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-f244a" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447422~2&amp;nsku=94X1713~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('f244a'));" data-farnell="2447422~2" data-newark="94X1713~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;schottky diode&lt;/td&gt;
&lt;td&gt;bourns&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-4aa1e" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2807974~2&amp;nsku=43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('4aa1e'));" data-farnell="2807974~2" data-newark="43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="xs-hide"&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcd"&gt;Additional Parts&lt;/h2&gt;
&lt;table class="e14-product-bom-additional"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCB made by Aisler&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heatshrink tubing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mcetoc_1jhqlp2dce"&gt;&lt;/h3&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: open source hardware usb, hardware debugging tools, serial device emulation, serial loopback testing, uart file transfer, usb null modem, embedded serial debugging, usb looper, usb uart project, usb serial logging, ftdi uart bridge, usb host to host communication, usb serial chat application, uart debugging tool, friday_release, air gapped file transfer&lt;/div&gt;
</description></item><item><title>Build Your Own USB Looper for Serial Debugging and File Transfer -- Episode 702</title><link>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702/revision/7</link><pubDate>Thu, 19 Feb 2026 10:42:06 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ac0e986d-170b-4d78-b9a0-ce61d4a7b5bb</guid><dc:creator>cstanton</dc:creator><comments>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702#comments</comments><description>Revision 7 posted to Documents by cstanton on 2/19/2026 10:42:06 AM&lt;br /&gt;
&lt;p&gt;&lt;span&gt;Clem introduces the &amp;quot;Blooper&amp;quot;, USB Looper, a modern null-modem style tool for UART debugging, device emulation and file transfer without a network. See how it logs serial data, enables full-duplex chat between computers, and safely connects two USB hosts.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqmd0ec0"&gt;&lt;span&gt;Watch&amp;nbsp;Clem Build the Blooper&lt;/span&gt;&lt;/h2&gt;
&lt;p data-start="267" data-end="671"&gt;&lt;a href="https://youtu.be/TqhYRmpYBO0"&gt;https://youtu.be/TqhYRmpYBO0&lt;/a&gt;&lt;/p&gt;
&lt;p data-start="267" data-end="671"&gt;Some tools begin as personal workflow helpers and quietly become essential to multiple projects. Clem&amp;rsquo;s USB Looper. nicknamed the &lt;strong data-start="398" data-end="411"&gt;&amp;ldquo;&lt;/strong&gt;Blooper&lt;strong data-start="398" data-end="411"&gt;&amp;rdquo;,&lt;/strong&gt;&amp;nbsp;clearly falls into that category. What started as a practical debugging aid has grown into a fully documented, open-source hardware tool designed to solve real development problems around UART, USB and device emulation.&lt;/p&gt;
&lt;p data-start="673" data-end="720"&gt;Early in the video, Clem sets the tone clearly:&lt;/p&gt;
&lt;blockquote data-start="722" data-end="835"&gt;
&lt;p data-start="724" data-end="835"&gt;&amp;ldquo;This tool has saved so many projects&amp;hellip; and guess what? I made it myself.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="837" data-end="1004"&gt;The Blooper is best understood as a modern reinterpretation of the classic null modem cable, but built for today&amp;rsquo;s USB-centric workflows and development environments.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqmt2l30" data-start="1011" data-end="1043"&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs0" data-start="1011" data-end="1043"&gt;What the Blooper Actually Does&lt;/h2&gt;
&lt;p data-start="1045" data-end="1265"&gt;At first glance, the Blooper appears simple: a small device with two USB-C ports. Internally, however, it enables something surprisingly powerful. When connected, the computer sees two independent USB serial devices.&lt;/p&gt;
&lt;p data-start="1267" data-end="1284"&gt;As Clem explains:&lt;/p&gt;
&lt;blockquote data-start="1286" data-end="1410"&gt;
&lt;p data-start="1288" data-end="1410"&gt;&amp;ldquo;The blooper appears as two independent devices&amp;hellip; they both just talk to each other.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1412" data-end="1662"&gt;This means a single computer can communicate with itself as if it were talking to an external embedded system. From the OS perspective, the data looks like it is coming from another device entirely, even though it&amp;rsquo;s looped back through the hardware.&lt;/p&gt;
&lt;p data-start="1664" data-end="1796"&gt;This hardware loopback is central to why the tool exists. While software loopback can be simulated, Clem points out the limitations:&lt;/p&gt;
&lt;blockquote data-start="1798" data-end="1970"&gt;
&lt;p data-start="1800" data-end="1970"&gt;&amp;ldquo;You could emulate this in software, but the setup is not as easy&amp;hellip; and I don&amp;rsquo;t think it works on any computer. And this thing does.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1972" data-end="2027"&gt;This reliability and portability is the key difference.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs1" data-start="2034" data-end="2076"&gt;Logging Serial Output Like a Real Device&lt;/h2&gt;
&lt;p data-start="2078" data-end="2194"&gt;One of Clem&amp;rsquo;s first demonstrations focuses on logging serial data to a file, a task common in embedded development.&lt;/p&gt;
&lt;p data-start="2196" data-end="2229"&gt;He explains the scenario clearly:&lt;/p&gt;
&lt;blockquote data-start="2231" data-end="2395"&gt;
&lt;p data-start="2233" data-end="2395"&gt;&amp;ldquo;For the computer, it was exactly the same as if the data was coming from an external device. It can&amp;rsquo;t make any difference.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="2397" data-end="2586"&gt;The supporting Python script shows exactly how this is achieved. The logging workflow is implemented in logfile.py, which timestamps incoming serial data and writes it directly to disk:&lt;/p&gt;
&lt;p data-start="2397" data-end="2586"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.readline().decode(&amp;#39;utf-8&amp;#39;).strip()
timestamp = time.strftime(&amp;#39;%Y-%m-%d %H:%M:%S&amp;#39;)
log_entry = f&amp;quot;{timestamp} - {incoming_data}\n&amp;quot;
f.write(log_entry)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;&lt;/span&gt;&lt;/code&gt;This reinforces a major use case: testing software that normally expects real hardware output. Because the Blooper behaves like real external hardware, tools such as Arduino IDE, terminal monitors, and custom serial apps can be tested safely and repeatedly.&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="3068" data-end="3117"&gt;Clem highlights how widely he uses this workflow:&lt;/p&gt;
&lt;blockquote data-start="3119" data-end="3249"&gt;
&lt;p data-start="3121" data-end="3249"&gt;&amp;ldquo;I use this to log stuff from Arduinos or out of computers or Raspberry Pi&amp;rsquo;s or whatever.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs2" data-start="3256" data-end="3297"&gt;Revisiting the Null Modem Cable Concept&lt;/h2&gt;
&lt;p data-start="3299" data-end="3361"&gt;The Blooper&amp;rsquo;s inspiration comes directly from older workflows.&lt;/p&gt;
&lt;p data-start="3363" data-end="3377"&gt;Clem reflects:&lt;/p&gt;
&lt;blockquote data-start="3379" data-end="3523"&gt;
&lt;p data-start="3381" data-end="3523"&gt;&amp;ldquo;Back in the early 2000, my means of transporting files from one computer to another was&amp;hellip; floppy disks.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3525" data-end="3683"&gt;Before networking was ubiquitous, null modem cables allowed direct PC-to-PC communication over UART. The Blooper recreates this idea with modern USB hardware:&lt;/p&gt;
&lt;blockquote data-start="3685" data-end="3792"&gt;
&lt;p data-start="3687" data-end="3792"&gt;&amp;ldquo;USB ports are kind of a serial port hidden inside a USB protocol.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3794" data-end="3952"&gt;Internally, the Blooper converts USB to UART on both sides. The result is two hosts communicating directly, bypassing traditional USB host-device constraints.&lt;/p&gt;
&lt;p data-start="3954" data-end="4060"&gt;This is what allows two computers, or even one computer with two terminals &amp;mdash; to chat over a single cable.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs3" data-start="4067" data-end="4114"&gt;Building a Full-Duplex Chat Between Computers&lt;/h2&gt;
&lt;p data-start="4116" data-end="4264"&gt;To demonstrate full duplex communication, Clem runs a simple Python chat application. This behaviour is implemented in chat.py and chat2.py.&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;The scripts use two threads: one for reading serial input and one for writing. This enables real-time two-way communication:&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;&lt;pre class="ui-code" data-mode="python"&gt;threading.Thread(target=read_from_serial, args=(ser,), daemon=True).start()
write_to_serial(ser)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="4504" data-end="4717"&gt;This simple threading approach makes the serial link behave like a messaging app, demonstrating how easily developers can test command protocols or debug communication stacks.&lt;/p&gt;
&lt;p data-start="4719" data-end="4760"&gt;Clem summarises the usefulness perfectly:&lt;/p&gt;
&lt;blockquote data-start="4762" data-end="4915"&gt;
&lt;p data-start="4764" data-end="4915"&gt;&amp;ldquo;This also works if you plug both ends into the same computer&amp;hellip; which is very handy for debugging applications.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs4" data-start="4922" data-end="4960"&gt;Transferring Files Without a Network&lt;/h2&gt;
&lt;p data-start="4962" data-end="5056"&gt;Another demonstration recreates a classic use case: transferring files without network access.&lt;/p&gt;
&lt;p data-start="5058" data-end="5086"&gt;Clem explains the relevance:&lt;/p&gt;
&lt;blockquote data-start="5088" data-end="5245"&gt;
&lt;p data-start="5090" data-end="5245"&gt;&amp;ldquo;While transferring data without a network is not as common today&amp;hellip; this can still be useful in air-gapped systems.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="5247" data-end="5320"&gt;The Python tools behind this are filesender.py and filereader.p&lt;strong data-start="5302" data-end="5319"&gt;y&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;Sending a file is straightforward:&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;&lt;pre class="ui-code" data-mode="python"&gt;with open(&amp;#39;log_file.txt&amp;#39;, &amp;#39;r&amp;#39;) as file:
    data = file.read()
ser.write(data.encode())&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5461" data-end="5520"&gt;Receiving and saving the data uses continuous serial reads:&lt;/p&gt;
&lt;p data-start="5461" data-end="5520"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.read(ser.in_waiting).decode()
file.write(incoming_data)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;These scripts mirror how firmware is often uploaded to embedded systems.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5687" data-end="5721"&gt;Clem explicitly connects the dots:&lt;/p&gt;
&lt;blockquote data-start="5723" data-end="5866"&gt;
&lt;p data-start="5725" data-end="5866"&gt;&amp;ldquo;This is the same way that you would upload firmware over serial&amp;hellip; or configure industrial machinery.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs5" data-start="5873" data-end="5920"&gt;Hardware Design Choices That Make It Reliable&lt;/h2&gt;
&lt;p data-start="5922" data-end="6048"&gt;The transcript adds substantial technical depth beyond the original write-up, especially around the hardware design decisions.&lt;/p&gt;
&lt;p data-start="6050" data-end="6118"&gt;One of the most important details is the use of FTDI USB-UART chips:&lt;/p&gt;
&lt;blockquote data-start="6120" data-end="6285"&gt;
&lt;p data-start="6122" data-end="6285"&gt;&amp;ldquo;They always enumerate perfectly&amp;hellip; they don&amp;rsquo;t need any external crystals. This has to be reliable and bootable at any time.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6287" data-end="6414"&gt;This is a key engineering decision: the Blooper is meant to be a tool, not an experiment. Reliability takes priority over cost.&lt;/p&gt;
&lt;p data-start="6416" data-end="6456"&gt;Other critical hardware details include:&lt;/p&gt;
&lt;p data-start="6458" data-end="6712"&gt;&amp;bull; USB-C CC pull-downs (5.1k&amp;Omega;) to ensure correct power negotiation&lt;br data-start="6523" data-end="6526" /&gt; &amp;bull; Schottky diode to prevent reverse powering&lt;br data-start="6570" data-end="6573" /&gt; &amp;bull; Ground stitching vias to prevent crosstalk&lt;br data-start="6617" data-end="6620" /&gt; &amp;bull; Shared reset circuit with pull-up resistor&lt;br data-start="6664" data-end="6667" /&gt; &amp;bull; Dual LED indicators for traffic direction&lt;/p&gt;
&lt;p data-start="6714" data-end="6737"&gt;Clem emphasises safety:&lt;/p&gt;
&lt;blockquote data-start="6739" data-end="6860"&gt;
&lt;p data-start="6741" data-end="6860"&gt;&amp;ldquo;If you don&amp;rsquo;t do that, you get weird behavior&amp;hellip; and this could damage the port.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6862" data-end="7002"&gt;These considerations ensure the device is safe to connect between two computers, something normally discouraged with USB-A-to-USB-A cables.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs6" data-start="7009" data-end="7045"&gt;Assembly and Practical Build Notes&lt;/h2&gt;
&lt;p data-start="7047" data-end="7118"&gt;The assembly process introduces several practical lessons for builders.&lt;/p&gt;
&lt;p data-start="7120" data-end="7166"&gt;Clem notes the challenges of USB-C connectors:&lt;/p&gt;
&lt;blockquote data-start="7168" data-end="7301"&gt;
&lt;p data-start="7170" data-end="7301"&gt;&amp;ldquo;Be aware that USB-C ports that have pins underneath them&amp;hellip; might be really hard to rework.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7303" data-end="7415"&gt;He deliberately chose USB-C connectors limited to USB 2.0 to simplify assembly and avoid unnecessary complexity.&lt;/p&gt;
&lt;p data-start="7417" data-end="7462"&gt;For enclosure, he chose a pragmatic approach:&lt;/p&gt;
&lt;blockquote data-start="7464" data-end="7605"&gt;
&lt;p data-start="7466" data-end="7605"&gt;&amp;ldquo;Heat shrink is the absolute easiest way to make a case&amp;hellip; it&amp;rsquo;s completely functional and compliant.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7607" data-end="7659"&gt;This reinforces the project&amp;rsquo;s focus on practicality.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs7" data-start="7666" data-end="7689"&gt;Why This Tool Matters&lt;/h2&gt;
&lt;p data-start="7691" data-end="7746"&gt;Perhaps the most telling reflection comes near the end:&lt;/p&gt;
&lt;blockquote data-start="7748" data-end="7873"&gt;
&lt;p data-start="7750" data-end="7873"&gt;&amp;ldquo;A lot of my projects would not work out as good as they actually do without this.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7875" data-end="7963"&gt;The Blooper is not just a demonstration device. It&amp;rsquo;s a daily workflow tool that enables:&lt;/p&gt;
&lt;p data-start="7965" data-end="8103"&gt;&amp;bull; Device emulation&lt;br data-start="7983" data-end="7986" /&gt; &amp;bull; Protocol testing&lt;br data-start="8004" data-end="8007" /&gt; &amp;bull; Serial debugging&lt;br data-start="8025" data-end="8028" /&gt; &amp;bull; File transfer without networking&lt;br data-start="8062" data-end="8065" /&gt; &amp;bull; Reliable UART testing environments&lt;/p&gt;
&lt;p data-start="8105" data-end="8156"&gt;Clem also highlights one of the most powerful uses:&lt;/p&gt;
&lt;blockquote data-start="8158" data-end="8276"&gt;
&lt;p data-start="8160" data-end="8276"&gt;&amp;ldquo;I could pretend that I&amp;rsquo;m an Arduino&amp;hellip; and see if the command parsing works.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8278" data-end="8384"&gt;This ability to emulate hardware responses opens up a wide range of development and testing possibilities.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs8" data-start="8391" data-end="8425"&gt;Open Source and Future Potential&lt;/h2&gt;
&lt;p data-start="8427" data-end="8565"&gt;The project is fully open source and available for the community to build and modify. Clem encourages others to adapt and extend the tool:&lt;/p&gt;
&lt;blockquote data-start="8567" data-end="8681"&gt;
&lt;p data-start="8569" data-end="8681"&gt;&amp;ldquo;Do you have any tools that you made yourself to make your life easier?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8683" data-end="8842"&gt;The Blooper may have started as a personal helper, but it now stands as a practical tool for developers working with embedded systems and serial communication.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;It brings an old idea, the null modem cable, firmly into modern development workflows.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlpnguf" data-start="8844" data-end="8932"&gt;Supporting Links and Files&lt;/h2&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;-&amp;nbsp;&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcc"&gt;Bill of Materials&lt;/h2&gt;
&lt;table class="e14-product-bom-main"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;&lt;a id="e14-product-link-28a4e" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2&amp;nsku=83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_BUY_KIT" class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('28a4e'));" data-farnell="2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2" data-newark="83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Kit&lt;/a&gt; &lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FT230XS-R&lt;/td&gt;
&lt;td&gt;FTDI&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-73b67" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2&amp;nsku=83T7087~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('73b67'));" data-farnell="2081321~2" data-newark="83T7087~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usb-c port&lt;/td&gt;
&lt;td&gt;Molex&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-cf25e" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3702965~2&amp;nsku=30AK0565~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('cf25e'));" data-farnell="3702965~2" data-newark="30AK0565~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Led 0603&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-040a2" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3796321~2&amp;nsku=73AJ8834~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('040a2'));" data-farnell="3796321~2" data-newark="73AJ8834~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5k1 resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-784a0" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447404~4&amp;nsku=94X1664~4&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('784a0'));" data-farnell="2447404~4" data-newark="94X1664~4" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;68Ohm resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-c419d" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447422~2&amp;nsku=94X1713~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('c419d'));" data-farnell="2447422~2" data-newark="94X1713~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;schottky diode&lt;/td&gt;
&lt;td&gt;bourns&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-35e4e" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2807974~2&amp;nsku=43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('35e4e'));" data-farnell="2807974~2" data-newark="43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="xs-hide"&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcd"&gt;Additional Parts&lt;/h2&gt;
&lt;table class="e14-product-bom-additional"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCB made by Aisler&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heatshrink tubing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mcetoc_1jhqlp2dce"&gt;&lt;/h3&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: open source hardware usb, hardware debugging tools, serial device emulation, serial loopback testing, uart file transfer, usb null modem, embedded serial debugging, usb looper, usb uart project, usb serial logging, ftdi uart bridge, usb host to host communication, usb serial chat application, uart debugging tool, friday_release, air gapped file transfer&lt;/div&gt;
</description></item><item><title>Build Your Own USB Looper for Serial Debugging and File Transfer -- Episode 702</title><link>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702/revision/6</link><pubDate>Thu, 19 Feb 2026 10:26:32 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ac0e986d-170b-4d78-b9a0-ce61d4a7b5bb</guid><dc:creator>cstanton</dc:creator><comments>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702#comments</comments><description>Revision 6 posted to Documents by cstanton on 2/19/2026 10:26:32 AM&lt;br /&gt;
&lt;p&gt;&lt;span&gt;Clem introduces the &amp;quot;Blooper&amp;quot;, USB Looper, a modern null-modem style tool for UART debugging, device emulation and file transfer without a network. See how it logs serial data, enables full-duplex chat between computers, and safely connects two USB hosts.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqmd0ec0"&gt;&lt;span&gt;Watch&amp;nbsp;Clem Build the Blooper&lt;/span&gt;&lt;/h2&gt;
&lt;p data-start="267" data-end="671"&gt;&amp;lt;embed video&amp;gt;&lt;/p&gt;
&lt;p data-start="267" data-end="671"&gt;Some tools begin as personal workflow helpers and quietly become essential to multiple projects. Clem&amp;rsquo;s USB Looper. nicknamed the &lt;strong data-start="398" data-end="411"&gt;&amp;ldquo;&lt;/strong&gt;Blooper&lt;strong data-start="398" data-end="411"&gt;&amp;rdquo;,&lt;/strong&gt;&amp;nbsp;clearly falls into that category. What started as a practical debugging aid has grown into a fully documented, open-source hardware tool designed to solve real development problems around UART, USB and device emulation.&lt;/p&gt;
&lt;p data-start="673" data-end="720"&gt;Early in the video, Clem sets the tone clearly:&lt;/p&gt;
&lt;blockquote data-start="722" data-end="835"&gt;
&lt;p data-start="724" data-end="835"&gt;&amp;ldquo;This tool has saved so many projects&amp;hellip; and guess what? I made it myself.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="837" data-end="1004"&gt;The Blooper is best understood as a modern reinterpretation of the classic null modem cable, but built for today&amp;rsquo;s USB-centric workflows and development environments.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqmt2l30" data-start="1011" data-end="1043"&gt;&lt;/h2&gt;
&lt;h2 id="mcetoc_1jhqloafs0" data-start="1011" data-end="1043"&gt;What the Blooper Actually Does&lt;/h2&gt;
&lt;p data-start="1045" data-end="1265"&gt;At first glance, the Blooper appears simple: a small device with two USB-C ports. Internally, however, it enables something surprisingly powerful. When connected, the computer sees two independent USB serial devices.&lt;/p&gt;
&lt;p data-start="1267" data-end="1284"&gt;As Clem explains:&lt;/p&gt;
&lt;blockquote data-start="1286" data-end="1410"&gt;
&lt;p data-start="1288" data-end="1410"&gt;&amp;ldquo;The blooper appears as two independent devices&amp;hellip; they both just talk to each other.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1412" data-end="1662"&gt;This means a single computer can communicate with itself as if it were talking to an external embedded system. From the OS perspective, the data looks like it is coming from another device entirely, even though it&amp;rsquo;s looped back through the hardware.&lt;/p&gt;
&lt;p data-start="1664" data-end="1796"&gt;This hardware loopback is central to why the tool exists. While software loopback can be simulated, Clem points out the limitations:&lt;/p&gt;
&lt;blockquote data-start="1798" data-end="1970"&gt;
&lt;p data-start="1800" data-end="1970"&gt;&amp;ldquo;You could emulate this in software, but the setup is not as easy&amp;hellip; and I don&amp;rsquo;t think it works on any computer. And this thing does.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1972" data-end="2027"&gt;This reliability and portability is the key difference.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs1" data-start="2034" data-end="2076"&gt;Logging Serial Output Like a Real Device&lt;/h2&gt;
&lt;p data-start="2078" data-end="2194"&gt;One of Clem&amp;rsquo;s first demonstrations focuses on logging serial data to a file, a task common in embedded development.&lt;/p&gt;
&lt;p data-start="2196" data-end="2229"&gt;He explains the scenario clearly:&lt;/p&gt;
&lt;blockquote data-start="2231" data-end="2395"&gt;
&lt;p data-start="2233" data-end="2395"&gt;&amp;ldquo;For the computer, it was exactly the same as if the data was coming from an external device. It can&amp;rsquo;t make any difference.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="2397" data-end="2586"&gt;The supporting Python script shows exactly how this is achieved. The logging workflow is implemented in logfile.py, which timestamps incoming serial data and writes it directly to disk:&lt;/p&gt;
&lt;p data-start="2397" data-end="2586"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.readline().decode(&amp;#39;utf-8&amp;#39;).strip()
timestamp = time.strftime(&amp;#39;%Y-%m-%d %H:%M:%S&amp;#39;)
log_entry = f&amp;quot;{timestamp} - {incoming_data}\n&amp;quot;
f.write(log_entry)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;&lt;/span&gt;&lt;/code&gt;This reinforces a major use case: testing software that normally expects real hardware output. Because the Blooper behaves like real external hardware, tools such as Arduino IDE, terminal monitors, and custom serial apps can be tested safely and repeatedly.&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="3068" data-end="3117"&gt;Clem highlights how widely he uses this workflow:&lt;/p&gt;
&lt;blockquote data-start="3119" data-end="3249"&gt;
&lt;p data-start="3121" data-end="3249"&gt;&amp;ldquo;I use this to log stuff from Arduinos or out of computers or Raspberry Pi&amp;rsquo;s or whatever.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs2" data-start="3256" data-end="3297"&gt;Revisiting the Null Modem Cable Concept&lt;/h2&gt;
&lt;p data-start="3299" data-end="3361"&gt;The Blooper&amp;rsquo;s inspiration comes directly from older workflows.&lt;/p&gt;
&lt;p data-start="3363" data-end="3377"&gt;Clem reflects:&lt;/p&gt;
&lt;blockquote data-start="3379" data-end="3523"&gt;
&lt;p data-start="3381" data-end="3523"&gt;&amp;ldquo;Back in the early 2000, my means of transporting files from one computer to another was&amp;hellip; floppy disks.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3525" data-end="3683"&gt;Before networking was ubiquitous, null modem cables allowed direct PC-to-PC communication over UART. The Blooper recreates this idea with modern USB hardware:&lt;/p&gt;
&lt;blockquote data-start="3685" data-end="3792"&gt;
&lt;p data-start="3687" data-end="3792"&gt;&amp;ldquo;USB ports are kind of a serial port hidden inside a USB protocol.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3794" data-end="3952"&gt;Internally, the Blooper converts USB to UART on both sides. The result is two hosts communicating directly, bypassing traditional USB host-device constraints.&lt;/p&gt;
&lt;p data-start="3954" data-end="4060"&gt;This is what allows two computers, or even one computer with two terminals &amp;mdash; to chat over a single cable.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs3" data-start="4067" data-end="4114"&gt;Building a Full-Duplex Chat Between Computers&lt;/h2&gt;
&lt;p data-start="4116" data-end="4264"&gt;To demonstrate full duplex communication, Clem runs a simple Python chat application. This behaviour is implemented in chat.py and chat2.py.&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;The scripts use two threads: one for reading serial input and one for writing. This enables real-time two-way communication:&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;&lt;pre class="ui-code" data-mode="python"&gt;threading.Thread(target=read_from_serial, args=(ser,), daemon=True).start()
write_to_serial(ser)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="4504" data-end="4717"&gt;This simple threading approach makes the serial link behave like a messaging app, demonstrating how easily developers can test command protocols or debug communication stacks.&lt;/p&gt;
&lt;p data-start="4719" data-end="4760"&gt;Clem summarises the usefulness perfectly:&lt;/p&gt;
&lt;blockquote data-start="4762" data-end="4915"&gt;
&lt;p data-start="4764" data-end="4915"&gt;&amp;ldquo;This also works if you plug both ends into the same computer&amp;hellip; which is very handy for debugging applications.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs4" data-start="4922" data-end="4960"&gt;Transferring Files Without a Network&lt;/h2&gt;
&lt;p data-start="4962" data-end="5056"&gt;Another demonstration recreates a classic use case: transferring files without network access.&lt;/p&gt;
&lt;p data-start="5058" data-end="5086"&gt;Clem explains the relevance:&lt;/p&gt;
&lt;blockquote data-start="5088" data-end="5245"&gt;
&lt;p data-start="5090" data-end="5245"&gt;&amp;ldquo;While transferring data without a network is not as common today&amp;hellip; this can still be useful in air-gapped systems.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="5247" data-end="5320"&gt;The Python tools behind this are filesender.py and filereader.p&lt;strong data-start="5302" data-end="5319"&gt;y&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;Sending a file is straightforward:&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;&lt;pre class="ui-code" data-mode="python"&gt;with open(&amp;#39;log_file.txt&amp;#39;, &amp;#39;r&amp;#39;) as file:
    data = file.read()
ser.write(data.encode())&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5461" data-end="5520"&gt;Receiving and saving the data uses continuous serial reads:&lt;/p&gt;
&lt;p data-start="5461" data-end="5520"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.read(ser.in_waiting).decode()
file.write(incoming_data)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;These scripts mirror how firmware is often uploaded to embedded systems.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5687" data-end="5721"&gt;Clem explicitly connects the dots:&lt;/p&gt;
&lt;blockquote data-start="5723" data-end="5866"&gt;
&lt;p data-start="5725" data-end="5866"&gt;&amp;ldquo;This is the same way that you would upload firmware over serial&amp;hellip; or configure industrial machinery.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs5" data-start="5873" data-end="5920"&gt;Hardware Design Choices That Make It Reliable&lt;/h2&gt;
&lt;p data-start="5922" data-end="6048"&gt;The transcript adds substantial technical depth beyond the original write-up, especially around the hardware design decisions.&lt;/p&gt;
&lt;p data-start="6050" data-end="6118"&gt;One of the most important details is the use of FTDI USB-UART chips:&lt;/p&gt;
&lt;blockquote data-start="6120" data-end="6285"&gt;
&lt;p data-start="6122" data-end="6285"&gt;&amp;ldquo;They always enumerate perfectly&amp;hellip; they don&amp;rsquo;t need any external crystals. This has to be reliable and bootable at any time.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6287" data-end="6414"&gt;This is a key engineering decision: the Blooper is meant to be a tool, not an experiment. Reliability takes priority over cost.&lt;/p&gt;
&lt;p data-start="6416" data-end="6456"&gt;Other critical hardware details include:&lt;/p&gt;
&lt;p data-start="6458" data-end="6712"&gt;&amp;bull; USB-C CC pull-downs (5.1k&amp;Omega;) to ensure correct power negotiation&lt;br data-start="6523" data-end="6526" /&gt; &amp;bull; Schottky diode to prevent reverse powering&lt;br data-start="6570" data-end="6573" /&gt; &amp;bull; Ground stitching vias to prevent crosstalk&lt;br data-start="6617" data-end="6620" /&gt; &amp;bull; Shared reset circuit with pull-up resistor&lt;br data-start="6664" data-end="6667" /&gt; &amp;bull; Dual LED indicators for traffic direction&lt;/p&gt;
&lt;p data-start="6714" data-end="6737"&gt;Clem emphasises safety:&lt;/p&gt;
&lt;blockquote data-start="6739" data-end="6860"&gt;
&lt;p data-start="6741" data-end="6860"&gt;&amp;ldquo;If you don&amp;rsquo;t do that, you get weird behavior&amp;hellip; and this could damage the port.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6862" data-end="7002"&gt;These considerations ensure the device is safe to connect between two computers, something normally discouraged with USB-A-to-USB-A cables.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs6" data-start="7009" data-end="7045"&gt;Assembly and Practical Build Notes&lt;/h2&gt;
&lt;p data-start="7047" data-end="7118"&gt;The assembly process introduces several practical lessons for builders.&lt;/p&gt;
&lt;p data-start="7120" data-end="7166"&gt;Clem notes the challenges of USB-C connectors:&lt;/p&gt;
&lt;blockquote data-start="7168" data-end="7301"&gt;
&lt;p data-start="7170" data-end="7301"&gt;&amp;ldquo;Be aware that USB-C ports that have pins underneath them&amp;hellip; might be really hard to rework.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7303" data-end="7415"&gt;He deliberately chose USB-C connectors limited to USB 2.0 to simplify assembly and avoid unnecessary complexity.&lt;/p&gt;
&lt;p data-start="7417" data-end="7462"&gt;For enclosure, he chose a pragmatic approach:&lt;/p&gt;
&lt;blockquote data-start="7464" data-end="7605"&gt;
&lt;p data-start="7466" data-end="7605"&gt;&amp;ldquo;Heat shrink is the absolute easiest way to make a case&amp;hellip; it&amp;rsquo;s completely functional and compliant.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7607" data-end="7659"&gt;This reinforces the project&amp;rsquo;s focus on practicality.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs7" data-start="7666" data-end="7689"&gt;Why This Tool Matters&lt;/h2&gt;
&lt;p data-start="7691" data-end="7746"&gt;Perhaps the most telling reflection comes near the end:&lt;/p&gt;
&lt;blockquote data-start="7748" data-end="7873"&gt;
&lt;p data-start="7750" data-end="7873"&gt;&amp;ldquo;A lot of my projects would not work out as good as they actually do without this.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7875" data-end="7963"&gt;The Blooper is not just a demonstration device. It&amp;rsquo;s a daily workflow tool that enables:&lt;/p&gt;
&lt;p data-start="7965" data-end="8103"&gt;&amp;bull; Device emulation&lt;br data-start="7983" data-end="7986" /&gt; &amp;bull; Protocol testing&lt;br data-start="8004" data-end="8007" /&gt; &amp;bull; Serial debugging&lt;br data-start="8025" data-end="8028" /&gt; &amp;bull; File transfer without networking&lt;br data-start="8062" data-end="8065" /&gt; &amp;bull; Reliable UART testing environments&lt;/p&gt;
&lt;p data-start="8105" data-end="8156"&gt;Clem also highlights one of the most powerful uses:&lt;/p&gt;
&lt;blockquote data-start="8158" data-end="8276"&gt;
&lt;p data-start="8160" data-end="8276"&gt;&amp;ldquo;I could pretend that I&amp;rsquo;m an Arduino&amp;hellip; and see if the command parsing works.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8278" data-end="8384"&gt;This ability to emulate hardware responses opens up a wide range of development and testing possibilities.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs8" data-start="8391" data-end="8425"&gt;Open Source and Future Potential&lt;/h2&gt;
&lt;p data-start="8427" data-end="8565"&gt;The project is fully open source and available for the community to build and modify. Clem encourages others to adapt and extend the tool:&lt;/p&gt;
&lt;blockquote data-start="8567" data-end="8681"&gt;
&lt;p data-start="8569" data-end="8681"&gt;&amp;ldquo;Do you have any tools that you made yourself to make your life easier?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8683" data-end="8842"&gt;The Blooper may have started as a personal helper, but it now stands as a practical tool for developers working with embedded systems and serial communication.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;It brings an old idea, the null modem cable, firmly into modern development workflows.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlpnguf" data-start="8844" data-end="8932"&gt;Supporting Links and Files&lt;/h2&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;-&amp;nbsp;&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcc"&gt;Bill of Materials&lt;/h2&gt;
&lt;table class="e14-product-bom-main"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;&lt;a id="e14-product-link-4e197" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2&amp;nsku=83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_BUY_KIT" class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('4e197'));" data-farnell="2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2" data-newark="83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Kit&lt;/a&gt; &lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FT230XS-R&lt;/td&gt;
&lt;td&gt;FTDI&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-58248" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2&amp;nsku=83T7087~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('58248'));" data-farnell="2081321~2" data-newark="83T7087~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usb-c port&lt;/td&gt;
&lt;td&gt;Molex&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-2e42c" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3702965~2&amp;nsku=30AK0565~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('2e42c'));" data-farnell="3702965~2" data-newark="30AK0565~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Led 0603&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-f6c4e" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3796321~2&amp;nsku=73AJ8834~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('f6c4e'));" data-farnell="3796321~2" data-newark="73AJ8834~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5k1 resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-a8252" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447404~4&amp;nsku=94X1664~4&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('a8252'));" data-farnell="2447404~4" data-newark="94X1664~4" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;68Ohm resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-b1c4e" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447422~2&amp;nsku=94X1713~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('b1c4e'));" data-farnell="2447422~2" data-newark="94X1713~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;schottky diode&lt;/td&gt;
&lt;td&gt;bourns&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-39cec" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2807974~2&amp;nsku=43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('39cec'));" data-farnell="2807974~2" data-newark="43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="xs-hide"&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcd"&gt;Additional Parts&lt;/h2&gt;
&lt;table class="e14-product-bom-additional"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCB made by Aisler&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heatshrink tubing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mcetoc_1jhqlp2dce"&gt;&lt;/h3&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: open source hardware usb, hardware debugging tools, serial device emulation, serial loopback testing, uart file transfer, usb null modem, embedded serial debugging, usb looper, usb uart project, usb serial logging, ftdi uart bridge, usb host to host communication, usb serial chat application, uart debugging tool, friday_release, air gapped file transfer&lt;/div&gt;
</description></item><item><title>Build Your Own USB Looper for Serial Debugging and File Transfer -- Episode 702</title><link>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702/revision/5</link><pubDate>Thu, 19 Feb 2026 10:19:39 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ac0e986d-170b-4d78-b9a0-ce61d4a7b5bb</guid><dc:creator>cstanton</dc:creator><comments>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702#comments</comments><description>Revision 5 posted to Documents by cstanton on 2/19/2026 10:19:39 AM&lt;br /&gt;
&lt;p&gt;&lt;span&gt;Clem introduces the &amp;quot;Blooper&amp;quot;, USB Looper, a modern null-modem style tool for UART debugging, device emulation and file transfer without a network. See how it logs serial data, enables full-duplex chat between computers, and safely connects two USB hosts.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqmd0ec0"&gt;&lt;span&gt;Watch&amp;nbsp;Clem Build the Blooper&lt;/span&gt;&lt;/h2&gt;
&lt;p data-start="267" data-end="671"&gt;&amp;lt;embed video&amp;gt;&lt;/p&gt;
&lt;p data-start="267" data-end="671"&gt;Some tools begin as personal workflow helpers and quietly become essential to multiple projects. Clem&amp;rsquo;s USB Looper. nicknamed the &lt;strong data-start="398" data-end="411"&gt;&amp;ldquo;&lt;/strong&gt;Blooper&lt;strong data-start="398" data-end="411"&gt;&amp;rdquo;,&lt;/strong&gt;&amp;nbsp;clearly falls into that category. What started as a practical debugging aid has grown into a fully documented, open-source hardware tool designed to solve real development problems around UART, USB and device emulation.&lt;/p&gt;
&lt;p data-start="673" data-end="720"&gt;Early in the video, Clem sets the tone clearly:&lt;/p&gt;
&lt;blockquote data-start="722" data-end="835"&gt;
&lt;p data-start="724" data-end="835"&gt;&amp;ldquo;This tool has saved so many projects&amp;hellip; and guess what? I made it myself.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="837" data-end="1004"&gt;The Blooper is best understood as a modern reinterpretation of the classic null modem cable, but built for today&amp;rsquo;s USB-centric workflows and development environments.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs0" data-start="1011" data-end="1043"&gt;What the Blooper Actually Does&lt;/h2&gt;
&lt;p data-start="1045" data-end="1265"&gt;At first glance, the Blooper appears simple: a small device with two USB-C ports. Internally, however, it enables something surprisingly powerful. When connected, the computer sees two independent USB serial devices.&lt;/p&gt;
&lt;p data-start="1267" data-end="1284"&gt;As Clem explains:&lt;/p&gt;
&lt;blockquote data-start="1286" data-end="1410"&gt;
&lt;p data-start="1288" data-end="1410"&gt;&amp;ldquo;The blooper appears as two independent devices&amp;hellip; they both just talk to each other.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1412" data-end="1662"&gt;This means a single computer can communicate with itself as if it were talking to an external embedded system. From the OS perspective, the data looks like it is coming from another device entirely, even though it&amp;rsquo;s looped back through the hardware.&lt;/p&gt;
&lt;p data-start="1664" data-end="1796"&gt;This hardware loopback is central to why the tool exists. While software loopback can be simulated, Clem points out the limitations:&lt;/p&gt;
&lt;blockquote data-start="1798" data-end="1970"&gt;
&lt;p data-start="1800" data-end="1970"&gt;&amp;ldquo;You could emulate this in software, but the setup is not as easy&amp;hellip; and I don&amp;rsquo;t think it works on any computer. And this thing does.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1972" data-end="2027"&gt;This reliability and portability is the key difference.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs1" data-start="2034" data-end="2076"&gt;Logging Serial Output Like a Real Device&lt;/h2&gt;
&lt;p data-start="2078" data-end="2194"&gt;One of Clem&amp;rsquo;s first demonstrations focuses on logging serial data to a file, a task common in embedded development.&lt;/p&gt;
&lt;p data-start="2196" data-end="2229"&gt;He explains the scenario clearly:&lt;/p&gt;
&lt;blockquote data-start="2231" data-end="2395"&gt;
&lt;p data-start="2233" data-end="2395"&gt;&amp;ldquo;For the computer, it was exactly the same as if the data was coming from an external device. It can&amp;rsquo;t make any difference.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="2397" data-end="2586"&gt;The supporting Python script shows exactly how this is achieved. The logging workflow is implemented in logfile.py, which timestamps incoming serial data and writes it directly to disk:&lt;/p&gt;
&lt;p data-start="2397" data-end="2586"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.readline().decode(&amp;#39;utf-8&amp;#39;).strip()
timestamp = time.strftime(&amp;#39;%Y-%m-%d %H:%M:%S&amp;#39;)
log_entry = f&amp;quot;{timestamp} - {incoming_data}\n&amp;quot;
f.write(log_entry)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;&lt;/span&gt;&lt;/code&gt;This reinforces a major use case: testing software that normally expects real hardware output. Because the Blooper behaves like real external hardware, tools such as Arduino IDE, terminal monitors, and custom serial apps can be tested safely and repeatedly.&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="3068" data-end="3117"&gt;Clem highlights how widely he uses this workflow:&lt;/p&gt;
&lt;blockquote data-start="3119" data-end="3249"&gt;
&lt;p data-start="3121" data-end="3249"&gt;&amp;ldquo;I use this to log stuff from Arduinos or out of computers or Raspberry Pi&amp;rsquo;s or whatever.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs2" data-start="3256" data-end="3297"&gt;Revisiting the Null Modem Cable Concept&lt;/h2&gt;
&lt;p data-start="3299" data-end="3361"&gt;The Blooper&amp;rsquo;s inspiration comes directly from older workflows.&lt;/p&gt;
&lt;p data-start="3363" data-end="3377"&gt;Clem reflects:&lt;/p&gt;
&lt;blockquote data-start="3379" data-end="3523"&gt;
&lt;p data-start="3381" data-end="3523"&gt;&amp;ldquo;Back in the early 2000, my means of transporting files from one computer to another was&amp;hellip; floppy disks.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3525" data-end="3683"&gt;Before networking was ubiquitous, null modem cables allowed direct PC-to-PC communication over UART. The Blooper recreates this idea with modern USB hardware:&lt;/p&gt;
&lt;blockquote data-start="3685" data-end="3792"&gt;
&lt;p data-start="3687" data-end="3792"&gt;&amp;ldquo;USB ports are kind of a serial port hidden inside a USB protocol.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3794" data-end="3952"&gt;Internally, the Blooper converts USB to UART on both sides. The result is two hosts communicating directly, bypassing traditional USB host-device constraints.&lt;/p&gt;
&lt;p data-start="3954" data-end="4060"&gt;This is what allows two computers, or even one computer with two terminals &amp;mdash; to chat over a single cable.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs3" data-start="4067" data-end="4114"&gt;Building a Full-Duplex Chat Between Computers&lt;/h2&gt;
&lt;p data-start="4116" data-end="4264"&gt;To demonstrate full duplex communication, Clem runs a simple Python chat application. This behaviour is implemented in chat.py and chat2.py.&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;The scripts use two threads: one for reading serial input and one for writing. This enables real-time two-way communication:&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;&lt;pre class="ui-code" data-mode="python"&gt;threading.Thread(target=read_from_serial, args=(ser,), daemon=True).start()
write_to_serial(ser)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="4504" data-end="4717"&gt;This simple threading approach makes the serial link behave like a messaging app, demonstrating how easily developers can test command protocols or debug communication stacks.&lt;/p&gt;
&lt;p data-start="4719" data-end="4760"&gt;Clem summarises the usefulness perfectly:&lt;/p&gt;
&lt;blockquote data-start="4762" data-end="4915"&gt;
&lt;p data-start="4764" data-end="4915"&gt;&amp;ldquo;This also works if you plug both ends into the same computer&amp;hellip; which is very handy for debugging applications.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs4" data-start="4922" data-end="4960"&gt;Transferring Files Without a Network&lt;/h2&gt;
&lt;p data-start="4962" data-end="5056"&gt;Another demonstration recreates a classic use case: transferring files without network access.&lt;/p&gt;
&lt;p data-start="5058" data-end="5086"&gt;Clem explains the relevance:&lt;/p&gt;
&lt;blockquote data-start="5088" data-end="5245"&gt;
&lt;p data-start="5090" data-end="5245"&gt;&amp;ldquo;While transferring data without a network is not as common today&amp;hellip; this can still be useful in air-gapped systems.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="5247" data-end="5320"&gt;The Python tools behind this are filesender.py and filereader.p&lt;strong data-start="5302" data-end="5319"&gt;y&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;Sending a file is straightforward:&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;&lt;pre class="ui-code" data-mode="python"&gt;with open(&amp;#39;log_file.txt&amp;#39;, &amp;#39;r&amp;#39;) as file:
    data = file.read()
ser.write(data.encode())&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5461" data-end="5520"&gt;Receiving and saving the data uses continuous serial reads:&lt;/p&gt;
&lt;p data-start="5461" data-end="5520"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.read(ser.in_waiting).decode()
file.write(incoming_data)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;These scripts mirror how firmware is often uploaded to embedded systems.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5687" data-end="5721"&gt;Clem explicitly connects the dots:&lt;/p&gt;
&lt;blockquote data-start="5723" data-end="5866"&gt;
&lt;p data-start="5725" data-end="5866"&gt;&amp;ldquo;This is the same way that you would upload firmware over serial&amp;hellip; or configure industrial machinery.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs5" data-start="5873" data-end="5920"&gt;Hardware Design Choices That Make It Reliable&lt;/h2&gt;
&lt;p data-start="5922" data-end="6048"&gt;The transcript adds substantial technical depth beyond the original write-up, especially around the hardware design decisions.&lt;/p&gt;
&lt;p data-start="6050" data-end="6118"&gt;One of the most important details is the use of FTDI USB-UART chips:&lt;/p&gt;
&lt;blockquote data-start="6120" data-end="6285"&gt;
&lt;p data-start="6122" data-end="6285"&gt;&amp;ldquo;They always enumerate perfectly&amp;hellip; they don&amp;rsquo;t need any external crystals. This has to be reliable and bootable at any time.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6287" data-end="6414"&gt;This is a key engineering decision: the Blooper is meant to be a tool, not an experiment. Reliability takes priority over cost.&lt;/p&gt;
&lt;p data-start="6416" data-end="6456"&gt;Other critical hardware details include:&lt;/p&gt;
&lt;p data-start="6458" data-end="6712"&gt;&amp;bull; USB-C CC pull-downs (5.1k&amp;Omega;) to ensure correct power negotiation&lt;br data-start="6523" data-end="6526" /&gt; &amp;bull; Schottky diode to prevent reverse powering&lt;br data-start="6570" data-end="6573" /&gt; &amp;bull; Ground stitching vias to prevent crosstalk&lt;br data-start="6617" data-end="6620" /&gt; &amp;bull; Shared reset circuit with pull-up resistor&lt;br data-start="6664" data-end="6667" /&gt; &amp;bull; Dual LED indicators for traffic direction&lt;/p&gt;
&lt;p data-start="6714" data-end="6737"&gt;Clem emphasises safety:&lt;/p&gt;
&lt;blockquote data-start="6739" data-end="6860"&gt;
&lt;p data-start="6741" data-end="6860"&gt;&amp;ldquo;If you don&amp;rsquo;t do that, you get weird behavior&amp;hellip; and this could damage the port.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6862" data-end="7002"&gt;These considerations ensure the device is safe to connect between two computers, something normally discouraged with USB-A-to-USB-A cables.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs6" data-start="7009" data-end="7045"&gt;Assembly and Practical Build Notes&lt;/h2&gt;
&lt;p data-start="7047" data-end="7118"&gt;The assembly process introduces several practical lessons for builders.&lt;/p&gt;
&lt;p data-start="7120" data-end="7166"&gt;Clem notes the challenges of USB-C connectors:&lt;/p&gt;
&lt;blockquote data-start="7168" data-end="7301"&gt;
&lt;p data-start="7170" data-end="7301"&gt;&amp;ldquo;Be aware that USB-C ports that have pins underneath them&amp;hellip; might be really hard to rework.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7303" data-end="7415"&gt;He deliberately chose USB-C connectors limited to USB 2.0 to simplify assembly and avoid unnecessary complexity.&lt;/p&gt;
&lt;p data-start="7417" data-end="7462"&gt;For enclosure, he chose a pragmatic approach:&lt;/p&gt;
&lt;blockquote data-start="7464" data-end="7605"&gt;
&lt;p data-start="7466" data-end="7605"&gt;&amp;ldquo;Heat shrink is the absolute easiest way to make a case&amp;hellip; it&amp;rsquo;s completely functional and compliant.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7607" data-end="7659"&gt;This reinforces the project&amp;rsquo;s focus on practicality.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs7" data-start="7666" data-end="7689"&gt;Why This Tool Matters&lt;/h2&gt;
&lt;p data-start="7691" data-end="7746"&gt;Perhaps the most telling reflection comes near the end:&lt;/p&gt;
&lt;blockquote data-start="7748" data-end="7873"&gt;
&lt;p data-start="7750" data-end="7873"&gt;&amp;ldquo;A lot of my projects would not work out as good as they actually do without this.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7875" data-end="7963"&gt;The Blooper is not just a demonstration device. It&amp;rsquo;s a daily workflow tool that enables:&lt;/p&gt;
&lt;p data-start="7965" data-end="8103"&gt;&amp;bull; Device emulation&lt;br data-start="7983" data-end="7986" /&gt; &amp;bull; Protocol testing&lt;br data-start="8004" data-end="8007" /&gt; &amp;bull; Serial debugging&lt;br data-start="8025" data-end="8028" /&gt; &amp;bull; File transfer without networking&lt;br data-start="8062" data-end="8065" /&gt; &amp;bull; Reliable UART testing environments&lt;/p&gt;
&lt;p data-start="8105" data-end="8156"&gt;Clem also highlights one of the most powerful uses:&lt;/p&gt;
&lt;blockquote data-start="8158" data-end="8276"&gt;
&lt;p data-start="8160" data-end="8276"&gt;&amp;ldquo;I could pretend that I&amp;rsquo;m an Arduino&amp;hellip; and see if the command parsing works.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8278" data-end="8384"&gt;This ability to emulate hardware responses opens up a wide range of development and testing possibilities.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs8" data-start="8391" data-end="8425"&gt;Open Source and Future Potential&lt;/h2&gt;
&lt;p data-start="8427" data-end="8565"&gt;The project is fully open source and available for the community to build and modify. Clem encourages others to adapt and extend the tool:&lt;/p&gt;
&lt;blockquote data-start="8567" data-end="8681"&gt;
&lt;p data-start="8569" data-end="8681"&gt;&amp;ldquo;Do you have any tools that you made yourself to make your life easier?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8683" data-end="8842"&gt;The Blooper may have started as a personal helper, but it now stands as a practical tool for developers working with embedded systems and serial communication.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;It brings an old idea, the null modem cable, firmly into modern development workflows.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlpnguf" data-start="8844" data-end="8932"&gt;Supporting Links and Files&lt;/h2&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;-&amp;nbsp;&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcc"&gt;Bill of Materials&lt;/h2&gt;
&lt;table class="e14-product-bom-main"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;&lt;a id="e14-product-link-0974b" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2&amp;nsku=83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_BUY_KIT" class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('0974b'));" data-farnell="2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2" data-newark="83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Kit&lt;/a&gt; &lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FT230XS-R&lt;/td&gt;
&lt;td&gt;FTDI&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-ddac0" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2&amp;nsku=83T7087~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('ddac0'));" data-farnell="2081321~2" data-newark="83T7087~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usb-c port&lt;/td&gt;
&lt;td&gt;Molex&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-25f58" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3702965~2&amp;nsku=30AK0565~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('25f58'));" data-farnell="3702965~2" data-newark="30AK0565~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Led 0603&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-8d039" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3796321~2&amp;nsku=73AJ8834~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('8d039'));" data-farnell="3796321~2" data-newark="73AJ8834~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5k1 resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-c11c8" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447404~4&amp;nsku=94X1664~4&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('c11c8'));" data-farnell="2447404~4" data-newark="94X1664~4" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;68Ohm resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-21749" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447422~2&amp;nsku=94X1713~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('21749'));" data-farnell="2447422~2" data-newark="94X1713~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;schottky diode&lt;/td&gt;
&lt;td&gt;bourns&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-fc518" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2807974~2&amp;nsku=43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('fc518'));" data-farnell="2807974~2" data-newark="43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="xs-hide"&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcd"&gt;Additional Parts&lt;/h2&gt;
&lt;table class="e14-product-bom-additional"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCB made by Aisler&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heatshrink tubing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mcetoc_1jhqlp2dce"&gt;&lt;/h3&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;

&lt;div style="font-size: 90%;"&gt;Tags: open source hardware usb, hardware debugging tools, serial device emulation, serial loopback testing, uart file transfer, usb null modem, embedded serial debugging, usb looper, usb uart project, usb serial logging, ftdi uart bridge, usb host to host communication, usb serial chat application, uart debugging tool, friday_release, air gapped file transfer&lt;/div&gt;
</description></item><item><title>Build Your Own USB Looper for Serial Debugging and File Transfer -- Episode 702</title><link>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702/revision/4</link><pubDate>Thu, 19 Feb 2026 10:18:34 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ac0e986d-170b-4d78-b9a0-ce61d4a7b5bb</guid><dc:creator>cstanton</dc:creator><comments>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702#comments</comments><description>Revision 4 posted to Documents by cstanton on 2/19/2026 10:18:34 AM&lt;br /&gt;
&lt;p&gt;&lt;span&gt;Clem introduces the &amp;quot;Blooper&amp;quot;, USB Looper, a modern null-modem style tool for UART debugging, device emulation and file transfer without a network. See how it logs serial data, enables full-duplex chat between computers, and safely connects two USB hosts.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqmd0ec0"&gt;&lt;span&gt;Watch&amp;nbsp;Clem Build the Blooper&lt;/span&gt;&lt;/h2&gt;
&lt;p data-start="267" data-end="671"&gt;&amp;lt;embed video&amp;gt;&lt;/p&gt;
&lt;p data-start="267" data-end="671"&gt;Some tools begin as personal workflow helpers and quietly become essential to multiple projects. Clem&amp;rsquo;s USB Looper. nicknamed the &lt;strong data-start="398" data-end="411"&gt;&amp;ldquo;&lt;/strong&gt;Blooper&lt;strong data-start="398" data-end="411"&gt;&amp;rdquo;,&lt;/strong&gt;&amp;nbsp;clearly falls into that category. What started as a practical debugging aid has grown into a fully documented, open-source hardware tool designed to solve real development problems around UART, USB and device emulation.&lt;/p&gt;
&lt;p data-start="673" data-end="720"&gt;Early in the video, Clem sets the tone clearly:&lt;/p&gt;
&lt;blockquote data-start="722" data-end="835"&gt;
&lt;p data-start="724" data-end="835"&gt;&amp;ldquo;This tool has saved so many projects&amp;hellip; and guess what? I made it myself.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="837" data-end="1004"&gt;The Blooper is best understood as a modern reinterpretation of the classic null modem cable, but built for today&amp;rsquo;s USB-centric workflows and development environments.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs0" data-start="1011" data-end="1043"&gt;What the Blooper Actually Does&lt;/h2&gt;
&lt;p data-start="1045" data-end="1265"&gt;At first glance, the Blooper appears simple: a small device with two USB-C ports. Internally, however, it enables something surprisingly powerful. When connected, the computer sees two independent USB serial devices.&lt;/p&gt;
&lt;p data-start="1267" data-end="1284"&gt;As Clem explains:&lt;/p&gt;
&lt;blockquote data-start="1286" data-end="1410"&gt;
&lt;p data-start="1288" data-end="1410"&gt;&amp;ldquo;The blooper appears as two independent devices&amp;hellip; they both just talk to each other.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1412" data-end="1662"&gt;This means a single computer can communicate with itself as if it were talking to an external embedded system. From the OS perspective, the data looks like it is coming from another device entirely, even though it&amp;rsquo;s looped back through the hardware.&lt;/p&gt;
&lt;p data-start="1664" data-end="1796"&gt;This hardware loopback is central to why the tool exists. While software loopback can be simulated, Clem points out the limitations:&lt;/p&gt;
&lt;blockquote data-start="1798" data-end="1970"&gt;
&lt;p data-start="1800" data-end="1970"&gt;&amp;ldquo;You could emulate this in software, but the setup is not as easy&amp;hellip; and I don&amp;rsquo;t think it works on any computer. And this thing does.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1972" data-end="2027"&gt;This reliability and portability is the key difference.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs1" data-start="2034" data-end="2076"&gt;Logging Serial Output Like a Real Device&lt;/h2&gt;
&lt;p data-start="2078" data-end="2194"&gt;One of Clem&amp;rsquo;s first demonstrations focuses on logging serial data to a file, a task common in embedded development.&lt;/p&gt;
&lt;p data-start="2196" data-end="2229"&gt;He explains the scenario clearly:&lt;/p&gt;
&lt;blockquote data-start="2231" data-end="2395"&gt;
&lt;p data-start="2233" data-end="2395"&gt;&amp;ldquo;For the computer, it was exactly the same as if the data was coming from an external device. It can&amp;rsquo;t make any difference.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="2397" data-end="2586"&gt;The supporting Python script shows exactly how this is achieved. The logging workflow is implemented in logfile.py, which timestamps incoming serial data and writes it directly to disk:&lt;/p&gt;
&lt;p data-start="2397" data-end="2586"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.readline().decode(&amp;#39;utf-8&amp;#39;).strip()
timestamp = time.strftime(&amp;#39;%Y-%m-%d %H:%M:%S&amp;#39;)
log_entry = f&amp;quot;{timestamp} - {incoming_data}\n&amp;quot;
f.write(log_entry)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;&lt;/span&gt;&lt;/code&gt;This reinforces a major use case: testing software that normally expects real hardware output. Because the Blooper behaves like real external hardware, tools such as Arduino IDE, terminal monitors, and custom serial apps can be tested safely and repeatedly.&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="3068" data-end="3117"&gt;Clem highlights how widely he uses this workflow:&lt;/p&gt;
&lt;blockquote data-start="3119" data-end="3249"&gt;
&lt;p data-start="3121" data-end="3249"&gt;&amp;ldquo;I use this to log stuff from Arduinos or out of computers or Raspberry Pi&amp;rsquo;s or whatever.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs2" data-start="3256" data-end="3297"&gt;Revisiting the Null Modem Cable Concept&lt;/h2&gt;
&lt;p data-start="3299" data-end="3361"&gt;The Blooper&amp;rsquo;s inspiration comes directly from older workflows.&lt;/p&gt;
&lt;p data-start="3363" data-end="3377"&gt;Clem reflects:&lt;/p&gt;
&lt;blockquote data-start="3379" data-end="3523"&gt;
&lt;p data-start="3381" data-end="3523"&gt;&amp;ldquo;Back in the early 2000, my means of transporting files from one computer to another was&amp;hellip; floppy disks.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3525" data-end="3683"&gt;Before networking was ubiquitous, null modem cables allowed direct PC-to-PC communication over UART. The Blooper recreates this idea with modern USB hardware:&lt;/p&gt;
&lt;blockquote data-start="3685" data-end="3792"&gt;
&lt;p data-start="3687" data-end="3792"&gt;&amp;ldquo;USB ports are kind of a serial port hidden inside a USB protocol.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3794" data-end="3952"&gt;Internally, the Blooper converts USB to UART on both sides. The result is two hosts communicating directly, bypassing traditional USB host-device constraints.&lt;/p&gt;
&lt;p data-start="3954" data-end="4060"&gt;This is what allows two computers, or even one computer with two terminals &amp;mdash; to chat over a single cable.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs3" data-start="4067" data-end="4114"&gt;Building a Full-Duplex Chat Between Computers&lt;/h2&gt;
&lt;p data-start="4116" data-end="4264"&gt;To demonstrate full duplex communication, Clem runs a simple Python chat application. This behaviour is implemented in chat.py and chat2.py.&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;The scripts use two threads: one for reading serial input and one for writing. This enables real-time two-way communication:&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;&lt;pre class="ui-code" data-mode="python"&gt;threading.Thread(target=read_from_serial, args=(ser,), daemon=True).start()
write_to_serial(ser)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="4504" data-end="4717"&gt;This simple threading approach makes the serial link behave like a messaging app, demonstrating how easily developers can test command protocols or debug communication stacks.&lt;/p&gt;
&lt;p data-start="4719" data-end="4760"&gt;Clem summarises the usefulness perfectly:&lt;/p&gt;
&lt;blockquote data-start="4762" data-end="4915"&gt;
&lt;p data-start="4764" data-end="4915"&gt;&amp;ldquo;This also works if you plug both ends into the same computer&amp;hellip; which is very handy for debugging applications.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs4" data-start="4922" data-end="4960"&gt;Transferring Files Without a Network&lt;/h2&gt;
&lt;p data-start="4962" data-end="5056"&gt;Another demonstration recreates a classic use case: transferring files without network access.&lt;/p&gt;
&lt;p data-start="5058" data-end="5086"&gt;Clem explains the relevance:&lt;/p&gt;
&lt;blockquote data-start="5088" data-end="5245"&gt;
&lt;p data-start="5090" data-end="5245"&gt;&amp;ldquo;While transferring data without a network is not as common today&amp;hellip; this can still be useful in air-gapped systems.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="5247" data-end="5320"&gt;The Python tools behind this are filesender.py and filereader.p&lt;strong data-start="5302" data-end="5319"&gt;y&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;Sending a file is straightforward:&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;&lt;pre class="ui-code" data-mode="python"&gt;with open(&amp;#39;log_file.txt&amp;#39;, &amp;#39;r&amp;#39;) as file:
    data = file.read()
ser.write(data.encode())&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5461" data-end="5520"&gt;Receiving and saving the data uses continuous serial reads:&lt;/p&gt;
&lt;p data-start="5461" data-end="5520"&gt;&lt;pre class="ui-code" data-mode="python"&gt;incoming_data = ser.read(ser.in_waiting).decode()
file.write(incoming_data)&lt;/pre&gt;&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;These scripts mirror how firmware is often uploaded to embedded systems.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5687" data-end="5721"&gt;Clem explicitly connects the dots:&lt;/p&gt;
&lt;blockquote data-start="5723" data-end="5866"&gt;
&lt;p data-start="5725" data-end="5866"&gt;&amp;ldquo;This is the same way that you would upload firmware over serial&amp;hellip; or configure industrial machinery.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs5" data-start="5873" data-end="5920"&gt;Hardware Design Choices That Make It Reliable&lt;/h2&gt;
&lt;p data-start="5922" data-end="6048"&gt;The transcript adds substantial technical depth beyond the original write-up, especially around the hardware design decisions.&lt;/p&gt;
&lt;p data-start="6050" data-end="6118"&gt;One of the most important details is the use of FTDI USB-UART chips:&lt;/p&gt;
&lt;blockquote data-start="6120" data-end="6285"&gt;
&lt;p data-start="6122" data-end="6285"&gt;&amp;ldquo;They always enumerate perfectly&amp;hellip; they don&amp;rsquo;t need any external crystals. This has to be reliable and bootable at any time.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6287" data-end="6414"&gt;This is a key engineering decision: the Blooper is meant to be a tool, not an experiment. Reliability takes priority over cost.&lt;/p&gt;
&lt;p data-start="6416" data-end="6456"&gt;Other critical hardware details include:&lt;/p&gt;
&lt;p data-start="6458" data-end="6712"&gt;&amp;bull; USB-C CC pull-downs (5.1k&amp;Omega;) to ensure correct power negotiation&lt;br data-start="6523" data-end="6526" /&gt; &amp;bull; Schottky diode to prevent reverse powering&lt;br data-start="6570" data-end="6573" /&gt; &amp;bull; Ground stitching vias to prevent crosstalk&lt;br data-start="6617" data-end="6620" /&gt; &amp;bull; Shared reset circuit with pull-up resistor&lt;br data-start="6664" data-end="6667" /&gt; &amp;bull; Dual LED indicators for traffic direction&lt;/p&gt;
&lt;p data-start="6714" data-end="6737"&gt;Clem emphasises safety:&lt;/p&gt;
&lt;blockquote data-start="6739" data-end="6860"&gt;
&lt;p data-start="6741" data-end="6860"&gt;&amp;ldquo;If you don&amp;rsquo;t do that, you get weird behavior&amp;hellip; and this could damage the port.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6862" data-end="7002"&gt;These considerations ensure the device is safe to connect between two computers, something normally discouraged with USB-A-to-USB-A cables.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs6" data-start="7009" data-end="7045"&gt;Assembly and Practical Build Notes&lt;/h2&gt;
&lt;p data-start="7047" data-end="7118"&gt;The assembly process introduces several practical lessons for builders.&lt;/p&gt;
&lt;p data-start="7120" data-end="7166"&gt;Clem notes the challenges of USB-C connectors:&lt;/p&gt;
&lt;blockquote data-start="7168" data-end="7301"&gt;
&lt;p data-start="7170" data-end="7301"&gt;&amp;ldquo;Be aware that USB-C ports that have pins underneath them&amp;hellip; might be really hard to rework.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7303" data-end="7415"&gt;He deliberately chose USB-C connectors limited to USB 2.0 to simplify assembly and avoid unnecessary complexity.&lt;/p&gt;
&lt;p data-start="7417" data-end="7462"&gt;For enclosure, he chose a pragmatic approach:&lt;/p&gt;
&lt;blockquote data-start="7464" data-end="7605"&gt;
&lt;p data-start="7466" data-end="7605"&gt;&amp;ldquo;Heat shrink is the absolute easiest way to make a case&amp;hellip; it&amp;rsquo;s completely functional and compliant.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7607" data-end="7659"&gt;This reinforces the project&amp;rsquo;s focus on practicality.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs7" data-start="7666" data-end="7689"&gt;Why This Tool Matters&lt;/h2&gt;
&lt;p data-start="7691" data-end="7746"&gt;Perhaps the most telling reflection comes near the end:&lt;/p&gt;
&lt;blockquote data-start="7748" data-end="7873"&gt;
&lt;p data-start="7750" data-end="7873"&gt;&amp;ldquo;A lot of my projects would not work out as good as they actually do without this.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7875" data-end="7963"&gt;The Blooper is not just a demonstration device. It&amp;rsquo;s a daily workflow tool that enables:&lt;/p&gt;
&lt;p data-start="7965" data-end="8103"&gt;&amp;bull; Device emulation&lt;br data-start="7983" data-end="7986" /&gt; &amp;bull; Protocol testing&lt;br data-start="8004" data-end="8007" /&gt; &amp;bull; Serial debugging&lt;br data-start="8025" data-end="8028" /&gt; &amp;bull; File transfer without networking&lt;br data-start="8062" data-end="8065" /&gt; &amp;bull; Reliable UART testing environments&lt;/p&gt;
&lt;p data-start="8105" data-end="8156"&gt;Clem also highlights one of the most powerful uses:&lt;/p&gt;
&lt;blockquote data-start="8158" data-end="8276"&gt;
&lt;p data-start="8160" data-end="8276"&gt;&amp;ldquo;I could pretend that I&amp;rsquo;m an Arduino&amp;hellip; and see if the command parsing works.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8278" data-end="8384"&gt;This ability to emulate hardware responses opens up a wide range of development and testing possibilities.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs8" data-start="8391" data-end="8425"&gt;Open Source and Future Potential&lt;/h2&gt;
&lt;p data-start="8427" data-end="8565"&gt;The project is fully open source and available for the community to build and modify. Clem encourages others to adapt and extend the tool:&lt;/p&gt;
&lt;blockquote data-start="8567" data-end="8681"&gt;
&lt;p data-start="8569" data-end="8681"&gt;&amp;ldquo;Do you have any tools that you made yourself to make your life easier?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8683" data-end="8842"&gt;The Blooper may have started as a personal helper, but it now stands as a practical tool for developers working with embedded systems and serial communication.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;It brings an old idea, the null modem cable, firmly into modern development workflows.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlpnguf" data-start="8844" data-end="8932"&gt;Supporting Links and Files&lt;/h2&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;-&amp;nbsp;&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcc"&gt;Bill of Materials&lt;/h2&gt;
&lt;table class="e14-product-bom-main"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;&lt;a id="e14-product-link-f06b9" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2&amp;nsku=83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_BUY_KIT" class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('f06b9'));" data-farnell="2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2" data-newark="83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Kit&lt;/a&gt; &lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FT230XS-R&lt;/td&gt;
&lt;td&gt;FTDI&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-8e7ae" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2&amp;nsku=83T7087~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('8e7ae'));" data-farnell="2081321~2" data-newark="83T7087~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usb-c port&lt;/td&gt;
&lt;td&gt;Molex&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-1af8c" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3702965~2&amp;nsku=30AK0565~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('1af8c'));" data-farnell="3702965~2" data-newark="30AK0565~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Led 0603&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-d5648" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3796321~2&amp;nsku=73AJ8834~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('d5648'));" data-farnell="3796321~2" data-newark="73AJ8834~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5k1 resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-1f046" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447404~4&amp;nsku=94X1664~4&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('1f046'));" data-farnell="2447404~4" data-newark="94X1664~4" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;68Ohm resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-29469" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447422~2&amp;nsku=94X1713~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('29469'));" data-farnell="2447422~2" data-newark="94X1713~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;schottky diode&lt;/td&gt;
&lt;td&gt;bourns&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-8f093" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2807974~2&amp;nsku=43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('8f093'));" data-farnell="2807974~2" data-newark="43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="xs-hide"&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcd"&gt;Additional Parts&lt;/h2&gt;
&lt;table class="e14-product-bom-additional"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCB made by Aisler&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heatshrink tubing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mcetoc_1jhqlp2dce"&gt;&lt;/h3&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Build Your Own USB Looper for Serial Debugging and File Transfer -- Episode 702</title><link>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702/revision/3</link><pubDate>Thu, 19 Feb 2026 10:12:01 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ac0e986d-170b-4d78-b9a0-ce61d4a7b5bb</guid><dc:creator>cstanton</dc:creator><comments>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702#comments</comments><description>Revision 3 posted to Documents by cstanton on 2/19/2026 10:12:01 AM&lt;br /&gt;
&lt;p&gt;&lt;span&gt;Clem introduces the &amp;quot;Blooper&amp;quot;, USB Looper, a modern null-modem style tool for UART debugging, device emulation and file transfer without a network. See how it logs serial data, enables full-duplex chat between computers, and safely connects two USB hosts.&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;&lt;span&gt;Watch&amp;nbsp;Clem Build the Blooper&lt;/span&gt;&lt;/h2&gt;
&lt;p data-start="267" data-end="671"&gt;&amp;lt;embed video&amp;gt;&lt;/p&gt;
&lt;p data-start="267" data-end="671"&gt;Some tools begin as personal workflow helpers and quietly become essential to multiple projects. Clem&amp;rsquo;s USB Looper. nicknamed the &lt;strong data-start="398" data-end="411"&gt;&amp;ldquo;&lt;/strong&gt;Blooper&lt;strong data-start="398" data-end="411"&gt;&amp;rdquo;,&lt;/strong&gt;&amp;nbsp;clearly falls into that category. What started as a practical debugging aid has grown into a fully documented, open-source hardware tool designed to solve real development problems around UART, USB and device emulation.&lt;/p&gt;
&lt;p data-start="673" data-end="720"&gt;Early in the video, Clem sets the tone clearly:&lt;/p&gt;
&lt;blockquote data-start="722" data-end="835"&gt;
&lt;p data-start="724" data-end="835"&gt;&amp;ldquo;This tool has saved so many projects&amp;hellip; and guess what? I made it myself.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="837" data-end="1004"&gt;The Blooper is best understood as a modern reinterpretation of the classic null modem cable, but built for today&amp;rsquo;s USB-centric workflows and development environments.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs0" data-start="1011" data-end="1043"&gt;What the Blooper Actually Does&lt;/h2&gt;
&lt;p data-start="1045" data-end="1265"&gt;At first glance, the Blooper appears simple: a small device with two USB-C ports. Internally, however, it enables something surprisingly powerful. When connected, the computer sees two independent USB serial devices.&lt;/p&gt;
&lt;p data-start="1267" data-end="1284"&gt;As Clem explains:&lt;/p&gt;
&lt;blockquote data-start="1286" data-end="1410"&gt;
&lt;p data-start="1288" data-end="1410"&gt;&amp;ldquo;The blooper appears as two independent devices&amp;hellip; they both just talk to each other.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1412" data-end="1662"&gt;This means a single computer can communicate with itself as if it were talking to an external embedded system. From the OS perspective, the data looks like it is coming from another device entirely, even though it&amp;rsquo;s looped back through the hardware.&lt;/p&gt;
&lt;p data-start="1664" data-end="1796"&gt;This hardware loopback is central to why the tool exists. While software loopback can be simulated, Clem points out the limitations:&lt;/p&gt;
&lt;blockquote data-start="1798" data-end="1970"&gt;
&lt;p data-start="1800" data-end="1970"&gt;&amp;ldquo;You could emulate this in software, but the setup is not as easy&amp;hellip; and I don&amp;rsquo;t think it works on any computer. And this thing does.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1972" data-end="2027"&gt;This reliability and portability is the key difference.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs1" data-start="2034" data-end="2076"&gt;Logging Serial Output Like a Real Device&lt;/h2&gt;
&lt;p data-start="2078" data-end="2194"&gt;One of Clem&amp;rsquo;s first demonstrations focuses on logging serial data to a file, a task common in embedded development.&lt;/p&gt;
&lt;p data-start="2196" data-end="2229"&gt;He explains the scenario clearly:&lt;/p&gt;
&lt;blockquote data-start="2231" data-end="2395"&gt;
&lt;p data-start="2233" data-end="2395"&gt;&amp;ldquo;For the computer, it was exactly the same as if the data was coming from an external device. It can&amp;rsquo;t make any difference.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="2397" data-end="2586"&gt;The supporting Python script shows exactly how this is achieved. The logging workflow is implemented in logfile.py, which timestamps incoming serial data and writes it directly to disk:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;incoming_data = ser.readline().decode(&lt;span class="hljs-string"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;).strip()
timestamp = time.strftime(&lt;span class="hljs-string"&gt;&amp;#39;%Y-%m-%d %H:%M:%S&amp;#39;&lt;/span&gt;)
log_entry = &lt;span class="hljs-string"&gt;f&amp;quot;&lt;span class="hljs-subst"&gt;{timestamp}&lt;/span&gt;&lt;/span&gt; - &lt;span class="hljs-subst"&gt;{incoming_data}&lt;/span&gt;\n&amp;quot;
f.write(log_entry)
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="2771" data-end="3066"&gt;This reinforces a major use case: testing software that normally expects real hardware output. Because the Blooper behaves like real external hardware, tools such as Arduino IDE, terminal monitors, and custom serial apps can be tested safely and repeatedly. &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;code&lt;/p&gt;
&lt;p data-start="3068" data-end="3117"&gt;Clem highlights how widely he uses this workflow:&lt;/p&gt;
&lt;blockquote data-start="3119" data-end="3249"&gt;
&lt;p data-start="3121" data-end="3249"&gt;&amp;ldquo;I use this to log stuff from Arduinos or out of computers or Raspberry Pi&amp;rsquo;s or whatever.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs2" data-start="3256" data-end="3297"&gt;Revisiting the Null Modem Cable Concept&lt;/h2&gt;
&lt;p data-start="3299" data-end="3361"&gt;The Blooper&amp;rsquo;s inspiration comes directly from older workflows.&lt;/p&gt;
&lt;p data-start="3363" data-end="3377"&gt;Clem reflects:&lt;/p&gt;
&lt;blockquote data-start="3379" data-end="3523"&gt;
&lt;p data-start="3381" data-end="3523"&gt;&amp;ldquo;Back in the early 2000, my means of transporting files from one computer to another was&amp;hellip; floppy disks.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3525" data-end="3683"&gt;Before networking was ubiquitous, null modem cables allowed direct PC-to-PC communication over UART. The Blooper recreates this idea with modern USB hardware:&lt;/p&gt;
&lt;blockquote data-start="3685" data-end="3792"&gt;
&lt;p data-start="3687" data-end="3792"&gt;&amp;ldquo;USB ports are kind of a serial port hidden inside a USB protocol.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3794" data-end="3952"&gt;Internally, the Blooper converts USB to UART on both sides. The result is two hosts communicating directly, bypassing traditional USB host-device constraints.&lt;/p&gt;
&lt;p data-start="3954" data-end="4060"&gt;This is what allows two computers, or even one computer with two terminals &amp;mdash; to chat over a single cable.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs3" data-start="4067" data-end="4114"&gt;Building a Full-Duplex Chat Between Computers&lt;/h2&gt;
&lt;p data-start="4116" data-end="4264"&gt;To demonstrate full duplex communication, Clem runs a simple Python chat application. This behaviour is implemented in chat.py and chat2.py.&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;The scripts use two threads: one for reading serial input and one for writing. This enables real-time two-way communication:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;threading.Thread(target=read_from_serial, args=(ser,), daemon=&lt;span class="hljs-literal"&gt;True&lt;/span&gt;).start()
write_to_serial(ser)
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="4504" data-end="4717"&gt;This simple threading approach makes the serial link behave like a messaging app, demonstrating how easily developers can test command protocols or debug communication stacks. &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;code&lt;/p&gt;
&lt;p data-start="4719" data-end="4760"&gt;Clem summarises the usefulness perfectly:&lt;/p&gt;
&lt;blockquote data-start="4762" data-end="4915"&gt;
&lt;p data-start="4764" data-end="4915"&gt;&amp;ldquo;This also works if you plug both ends into the same computer&amp;hellip; which is very handy for debugging applications.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs4" data-start="4922" data-end="4960"&gt;Transferring Files Without a Network&lt;/h2&gt;
&lt;p data-start="4962" data-end="5056"&gt;Another demonstration recreates a classic use case: transferring files without network access.&lt;/p&gt;
&lt;p data-start="5058" data-end="5086"&gt;Clem explains the relevance:&lt;/p&gt;
&lt;blockquote data-start="5088" data-end="5245"&gt;
&lt;p data-start="5090" data-end="5245"&gt;&amp;ldquo;While transferring data without a network is not as common today&amp;hellip; this can still be useful in air-gapped systems.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;blog&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="5247" data-end="5320"&gt;The Python tools behind this are filesender.py and filereader.p&lt;strong data-start="5302" data-end="5319"&gt;y&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;Sending a file is straightforward:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;&lt;span class="hljs-keyword"&gt;with&lt;/span&gt; &lt;span class="hljs-built_in"&gt;open&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#39;log_file.txt&amp;#39;&lt;/span&gt;, &lt;span class="hljs-string"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;) &lt;span class="hljs-keyword"&gt;as&lt;/span&gt; file:
    data = file.read()
ser.write(data.encode())
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5461" data-end="5520"&gt;Receiving and saving the data uses continuous serial reads:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;incoming_data = ser.read(ser.in_waiting).decode()
file.write(incoming_data)
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5613" data-end="5685"&gt;These scripts mirror how firmware is often uploaded to embedded systems.&lt;/p&gt;
&lt;p data-start="5687" data-end="5721"&gt;Clem explicitly connects the dots:&lt;/p&gt;
&lt;blockquote data-start="5723" data-end="5866"&gt;
&lt;p data-start="5725" data-end="5866"&gt;&amp;ldquo;This is the same way that you would upload firmware over serial&amp;hellip; or configure industrial machinery.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs5" data-start="5873" data-end="5920"&gt;Hardware Design Choices That Make It Reliable&lt;/h2&gt;
&lt;p data-start="5922" data-end="6048"&gt;The transcript adds substantial technical depth beyond the original write-up, especially around the hardware design decisions.&lt;/p&gt;
&lt;p data-start="6050" data-end="6118"&gt;One of the most important details is the use of FTDI USB-UART chips:&lt;/p&gt;
&lt;blockquote data-start="6120" data-end="6285"&gt;
&lt;p data-start="6122" data-end="6285"&gt;&amp;ldquo;They always enumerate perfectly&amp;hellip; they don&amp;rsquo;t need any external crystals. This has to be reliable and bootable at any time.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6287" data-end="6414"&gt;This is a key engineering decision: the Blooper is meant to be a tool, not an experiment. Reliability takes priority over cost.&lt;/p&gt;
&lt;p data-start="6416" data-end="6456"&gt;Other critical hardware details include:&lt;/p&gt;
&lt;p data-start="6458" data-end="6712"&gt;&amp;bull; USB-C CC pull-downs (5.1k&amp;Omega;) to ensure correct power negotiation&lt;br data-start="6523" data-end="6526" /&gt; &amp;bull; Schottky diode to prevent reverse powering&lt;br data-start="6570" data-end="6573" /&gt; &amp;bull; Ground stitching vias to prevent crosstalk&lt;br data-start="6617" data-end="6620" /&gt; &amp;bull; Shared reset circuit with pull-up resistor&lt;br data-start="6664" data-end="6667" /&gt; &amp;bull; Dual LED indicators for traffic direction&lt;/p&gt;
&lt;p data-start="6714" data-end="6737"&gt;Clem emphasises safety:&lt;/p&gt;
&lt;blockquote data-start="6739" data-end="6860"&gt;
&lt;p data-start="6741" data-end="6860"&gt;&amp;ldquo;If you don&amp;rsquo;t do that, you get weird behavior&amp;hellip; and this could damage the port.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6862" data-end="7002"&gt;These considerations ensure the device is safe to connect between two computers &amp;mdash; something normally discouraged with USB-A-to-USB-A cables.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs6" data-start="7009" data-end="7045"&gt;Assembly and Practical Build Notes&lt;/h2&gt;
&lt;p data-start="7047" data-end="7118"&gt;The assembly process introduces several practical lessons for builders.&lt;/p&gt;
&lt;p data-start="7120" data-end="7166"&gt;Clem notes the challenges of USB-C connectors:&lt;/p&gt;
&lt;blockquote data-start="7168" data-end="7301"&gt;
&lt;p data-start="7170" data-end="7301"&gt;&amp;ldquo;Be aware that USB-C ports that have pins underneath them&amp;hellip; might be really hard to rework.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7303" data-end="7415"&gt;He deliberately chose USB-C connectors limited to USB 2.0 to simplify assembly and avoid unnecessary complexity.&lt;/p&gt;
&lt;p data-start="7417" data-end="7462"&gt;For enclosure, he chose a pragmatic approach:&lt;/p&gt;
&lt;blockquote data-start="7464" data-end="7605"&gt;
&lt;p data-start="7466" data-end="7605"&gt;&amp;ldquo;Heat shrink is the absolute easiest way to make a case&amp;hellip; it&amp;rsquo;s completely functional and compliant.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7607" data-end="7659"&gt;This reinforces the project&amp;rsquo;s focus on practicality.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs7" data-start="7666" data-end="7689"&gt;Why This Tool Matters&lt;/h2&gt;
&lt;p data-start="7691" data-end="7746"&gt;Perhaps the most telling reflection comes near the end:&lt;/p&gt;
&lt;blockquote data-start="7748" data-end="7873"&gt;
&lt;p data-start="7750" data-end="7873"&gt;&amp;ldquo;A lot of my projects would not work out as good as they actually do without this.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7875" data-end="7963"&gt;The Blooper is not just a demonstration device. It&amp;rsquo;s a daily workflow tool that enables:&lt;/p&gt;
&lt;p data-start="7965" data-end="8103"&gt;&amp;bull; Device emulation&lt;br data-start="7983" data-end="7986" /&gt; &amp;bull; Protocol testing&lt;br data-start="8004" data-end="8007" /&gt; &amp;bull; Serial debugging&lt;br data-start="8025" data-end="8028" /&gt; &amp;bull; File transfer without networking&lt;br data-start="8062" data-end="8065" /&gt; &amp;bull; Reliable UART testing environments&lt;/p&gt;
&lt;p data-start="8105" data-end="8156"&gt;Clem also highlights one of the most powerful uses:&lt;/p&gt;
&lt;blockquote data-start="8158" data-end="8276"&gt;
&lt;p data-start="8160" data-end="8276"&gt;&amp;ldquo;I could pretend that I&amp;rsquo;m an Arduino&amp;hellip; and see if the command parsing works.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8278" data-end="8384"&gt;This ability to emulate hardware responses opens up a wide range of development and testing possibilities.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs8" data-start="8391" data-end="8425"&gt;Open Source and Future Potential&lt;/h2&gt;
&lt;p data-start="8427" data-end="8565"&gt;The project is fully open source and available for the community to build and modify. Clem encourages others to adapt and extend the tool:&lt;/p&gt;
&lt;blockquote data-start="8567" data-end="8681"&gt;
&lt;p data-start="8569" data-end="8681"&gt;&amp;ldquo;Do you have any tools that you made yourself to make your life easier?&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8683" data-end="8842"&gt;The Blooper may have started as a personal helper, but it now stands as a practical tool for developers working with embedded systems and serial communication.&lt;/p&gt;
&lt;p data-start="8683" data-end="8842"&gt;&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;It brings an old idea &amp;mdash; the null modem cable &amp;mdash; firmly into modern development workflows.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlpnguf" data-start="8844" data-end="8932"&gt;Supporting Links and Files&lt;/h2&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;-&amp;nbsp;&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcc"&gt;Bill of Materials&lt;/h2&gt;
&lt;table class="e14-product-bom-main"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;&lt;a id="e14-product-link-b0767" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2&amp;nsku=83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_BUY_KIT" class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('b0767'));" data-farnell="2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2" data-newark="83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Kit&lt;/a&gt; &lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FT230XS-R&lt;/td&gt;
&lt;td&gt;FTDI&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-db489" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2&amp;nsku=83T7087~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('db489'));" data-farnell="2081321~2" data-newark="83T7087~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usb-c port&lt;/td&gt;
&lt;td&gt;Molex&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-029b6" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3702965~2&amp;nsku=30AK0565~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('029b6'));" data-farnell="3702965~2" data-newark="30AK0565~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Led 0603&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-b0261" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3796321~2&amp;nsku=73AJ8834~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('b0261'));" data-farnell="3796321~2" data-newark="73AJ8834~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5k1 resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-5c6bf" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447404~4&amp;nsku=94X1664~4&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('5c6bf'));" data-farnell="2447404~4" data-newark="94X1664~4" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;68Ohm resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-eb968" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447422~2&amp;nsku=94X1713~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('eb968'));" data-farnell="2447422~2" data-newark="94X1713~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;schottky diode&lt;/td&gt;
&lt;td&gt;bourns&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-1c3ee" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2807974~2&amp;nsku=43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('1c3ee'));" data-farnell="2807974~2" data-newark="43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="xs-hide"&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcd"&gt;Additional Parts&lt;/h2&gt;
&lt;table class="e14-product-bom-additional"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCB made by Aisler&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heatshrink tubing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mcetoc_1jhqlp2dce"&gt;&lt;/h3&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Build Your Own USB Looper for Serial Debugging and File Transfer -- Episode 702</title><link>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702/revision/2</link><pubDate>Thu, 19 Feb 2026 10:06:54 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ac0e986d-170b-4d78-b9a0-ce61d4a7b5bb</guid><dc:creator>cstanton</dc:creator><comments>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702#comments</comments><description>Revision 2 posted to Documents by cstanton on 2/19/2026 10:06:54 AM&lt;br /&gt;
&lt;p data-start="267" data-end="671"&gt;Some tools begin as personal workflow helpers and quietly become essential to multiple projects. Clem&amp;rsquo;s USB Looper &amp;mdash; nicknamed the &lt;strong data-start="398" data-end="411"&gt;&amp;ldquo;Blooper&amp;rdquo;&lt;/strong&gt; &amp;mdash; clearly falls into that category. What started as a practical debugging aid has grown into a fully documented, open-source hardware tool designed to solve real development problems around UART, USB and device emulation. &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;blog&lt;/p&gt;
&lt;p data-start="673" data-end="720"&gt;Early in the video, Clem sets the tone clearly:&lt;/p&gt;
&lt;blockquote data-start="722" data-end="835"&gt;
&lt;p data-start="724" data-end="835"&gt;&amp;ldquo;This tool has saved so many projects&amp;hellip; and guess what? I made it myself.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="837" data-end="1004"&gt;The Blooper is best understood as a modern reinterpretation of the classic null modem cable &amp;mdash; but built for today&amp;rsquo;s USB-centric workflows and development environments.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs0" data-start="1011" data-end="1043"&gt;What the Blooper Actually Does&lt;/h2&gt;
&lt;p data-start="1045" data-end="1265"&gt;At first glance, the Blooper appears simple: a small device with two USB-C ports. Internally, however, it enables something surprisingly powerful. When connected, the computer sees &lt;strong data-start="1226" data-end="1264"&gt;two independent USB serial devices&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="1267" data-end="1284"&gt;As Clem explains:&lt;/p&gt;
&lt;blockquote data-start="1286" data-end="1410"&gt;
&lt;p data-start="1288" data-end="1410"&gt;&amp;ldquo;The blooper appears as two independent devices&amp;hellip; they both just talk to each other.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1412" data-end="1662"&gt;This means a single computer can communicate with itself as if it were talking to an external embedded system. From the OS perspective, the data looks like it is coming from another device entirely &amp;mdash; even though it&amp;rsquo;s looped back through the hardware.&lt;/p&gt;
&lt;p data-start="1664" data-end="1796"&gt;This hardware loopback is central to why the tool exists. While software loopback can be simulated, Clem points out the limitations:&lt;/p&gt;
&lt;blockquote data-start="1798" data-end="1970"&gt;
&lt;p data-start="1800" data-end="1970"&gt;&amp;ldquo;You could emulate this in software, but the setup is not as easy&amp;hellip; and I don&amp;rsquo;t think it works on any computer. And this thing does.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1972" data-end="2027"&gt;This reliability and portability is the key difference.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs1" data-start="2034" data-end="2076"&gt;Logging Serial Output Like a Real Device&lt;/h2&gt;
&lt;p data-start="2078" data-end="2194"&gt;One of Clem&amp;rsquo;s first demonstrations focuses on logging serial data to a file &amp;mdash; a task common in embedded development.&lt;/p&gt;
&lt;p data-start="2196" data-end="2229"&gt;He explains the scenario clearly:&lt;/p&gt;
&lt;blockquote data-start="2231" data-end="2395"&gt;
&lt;p data-start="2233" data-end="2395"&gt;&amp;ldquo;For the computer, it was exactly the same as if the data was coming from an external device. It can&amp;rsquo;t make any difference.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="2397" data-end="2586"&gt;The supporting Python script shows exactly how this is achieved. The logging workflow is implemented in &lt;strong data-start="2501" data-end="2515"&gt;logfile.py&lt;/strong&gt;, which timestamps incoming serial data and writes it directly to disk:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;incoming_data = ser.readline().decode(&lt;span class="hljs-string"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;).strip()
timestamp = time.strftime(&lt;span class="hljs-string"&gt;&amp;#39;%Y-%m-%d %H:%M:%S&amp;#39;&lt;/span&gt;)
log_entry = &lt;span class="hljs-string"&gt;f&amp;quot;&lt;span class="hljs-subst"&gt;{timestamp}&lt;/span&gt;&lt;/span&gt; - &lt;span class="hljs-subst"&gt;{incoming_data}&lt;/span&gt;\n&amp;quot;
f.write(log_entry)
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="2771" data-end="3066"&gt;This reinforces a major use case: testing software that normally expects real hardware output. Because the Blooper behaves like real external hardware, tools such as Arduino IDE, terminal monitors, and custom serial apps can be tested safely and repeatedly. &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;code&lt;/p&gt;
&lt;p data-start="3068" data-end="3117"&gt;Clem highlights how widely he uses this workflow:&lt;/p&gt;
&lt;blockquote data-start="3119" data-end="3249"&gt;
&lt;p data-start="3121" data-end="3249"&gt;&amp;ldquo;I use this to log stuff from Arduinos or out of computers or Raspberry Pi&amp;rsquo;s or whatever.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs2" data-start="3256" data-end="3297"&gt;Revisiting the Null Modem Cable Concept&lt;/h2&gt;
&lt;p data-start="3299" data-end="3361"&gt;The Blooper&amp;rsquo;s inspiration comes directly from older workflows.&lt;/p&gt;
&lt;p data-start="3363" data-end="3377"&gt;Clem reflects:&lt;/p&gt;
&lt;blockquote data-start="3379" data-end="3523"&gt;
&lt;p data-start="3381" data-end="3523"&gt;&amp;ldquo;Back in the early 2000, my means of transporting files from one computer to another was&amp;hellip; floppy disks.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3525" data-end="3683"&gt;Before networking was ubiquitous, null modem cables allowed direct PC-to-PC communication over UART. The Blooper recreates this idea with modern USB hardware:&lt;/p&gt;
&lt;blockquote data-start="3685" data-end="3792"&gt;
&lt;p data-start="3687" data-end="3792"&gt;&amp;ldquo;USB ports are kind of a serial port hidden inside a USB protocol.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3794" data-end="3952"&gt;Internally, the Blooper converts USB to UART on both sides. The result is two hosts communicating directly, bypassing traditional USB host-device constraints.&lt;/p&gt;
&lt;p data-start="3954" data-end="4060"&gt;This is what allows two computers &amp;mdash; or even one computer with two terminals &amp;mdash; to chat over a single cable.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs3" data-start="4067" data-end="4114"&gt;Building a Full-Duplex Chat Between Computers&lt;/h2&gt;
&lt;p data-start="4116" data-end="4264"&gt;To demonstrate full duplex communication, Clem runs a simple Python chat application. This behaviour is implemented in &lt;strong data-start="4235" data-end="4246"&gt;chat.py&lt;/strong&gt; and &lt;strong data-start="4251" data-end="4263"&gt;chat2.py&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;The scripts use two threads: one for reading serial input and one for writing. This enables real-time two-way communication:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;threading.Thread(target=read_from_serial, args=(ser,), daemon=&lt;span class="hljs-literal"&gt;True&lt;/span&gt;).start()
write_to_serial(ser)
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="4504" data-end="4717"&gt;This simple threading approach makes the serial link behave like a messaging app, demonstrating how easily developers can test command protocols or debug communication stacks. &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;code&lt;/p&gt;
&lt;p data-start="4719" data-end="4760"&gt;Clem summarises the usefulness perfectly:&lt;/p&gt;
&lt;blockquote data-start="4762" data-end="4915"&gt;
&lt;p data-start="4764" data-end="4915"&gt;&amp;ldquo;This also works if you plug both ends into the same computer&amp;hellip; which is very handy for debugging applications.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs4" data-start="4922" data-end="4960"&gt;Transferring Files Without a Network&lt;/h2&gt;
&lt;p data-start="4962" data-end="5056"&gt;Another demonstration recreates a classic use case: transferring files without network access.&lt;/p&gt;
&lt;p data-start="5058" data-end="5086"&gt;Clem explains the relevance:&lt;/p&gt;
&lt;blockquote data-start="5088" data-end="5245"&gt;
&lt;p data-start="5090" data-end="5245"&gt;&amp;ldquo;While transferring data without a network is not as common today&amp;hellip; this can still be useful in air-gapped systems.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;blog&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="5247" data-end="5320"&gt;The Python tools behind this are &lt;strong data-start="5280" data-end="5297"&gt;filesender.py&lt;/strong&gt; and &lt;strong data-start="5302" data-end="5319"&gt;filereader.py&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;Sending a file is straightforward:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;&lt;span class="hljs-keyword"&gt;with&lt;/span&gt; &lt;span class="hljs-built_in"&gt;open&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#39;log_file.txt&amp;#39;&lt;/span&gt;, &lt;span class="hljs-string"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;) &lt;span class="hljs-keyword"&gt;as&lt;/span&gt; file:
    data = file.read()
ser.write(data.encode())
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5461" data-end="5520"&gt;Receiving and saving the data uses continuous serial reads:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;incoming_data = ser.read(ser.in_waiting).decode()
file.write(incoming_data)
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5613" data-end="5685"&gt;These scripts mirror how firmware is often uploaded to embedded systems.&lt;/p&gt;
&lt;p data-start="5687" data-end="5721"&gt;Clem explicitly connects the dots:&lt;/p&gt;
&lt;blockquote data-start="5723" data-end="5866"&gt;
&lt;p data-start="5725" data-end="5866"&gt;&amp;ldquo;This is the same way that you would upload firmware over serial&amp;hellip; or configure industrial machinery.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mcetoc_1jhqloafs5" data-start="5873" data-end="5920"&gt;Hardware Design Choices That Make It Reliable&lt;/h2&gt;
&lt;p data-start="5922" data-end="6048"&gt;The transcript adds substantial technical depth beyond the original write-up, especially around the hardware design decisions.&lt;/p&gt;
&lt;p data-start="6050" data-end="6118"&gt;One of the most important details is the use of FTDI USB-UART chips:&lt;/p&gt;
&lt;blockquote data-start="6120" data-end="6285"&gt;
&lt;p data-start="6122" data-end="6285"&gt;&amp;ldquo;They always enumerate perfectly&amp;hellip; they don&amp;rsquo;t need any external crystals. This has to be reliable and bootable at any time.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6287" data-end="6414"&gt;This is a key engineering decision: the Blooper is meant to be a tool, not an experiment. Reliability takes priority over cost.&lt;/p&gt;
&lt;p data-start="6416" data-end="6456"&gt;Other critical hardware details include:&lt;/p&gt;
&lt;p data-start="6458" data-end="6712"&gt;&amp;bull; USB-C CC pull-downs (5.1k&amp;Omega;) to ensure correct power negotiation&lt;br data-start="6523" data-end="6526" /&gt; &amp;bull; Schottky diode to prevent reverse powering&lt;br data-start="6570" data-end="6573" /&gt; &amp;bull; Ground stitching vias to prevent crosstalk&lt;br data-start="6617" data-end="6620" /&gt; &amp;bull; Shared reset circuit with pull-up resistor&lt;br data-start="6664" data-end="6667" /&gt; &amp;bull; Dual LED indicators for traffic direction&lt;/p&gt;
&lt;p data-start="6714" data-end="6737"&gt;Clem emphasises safety:&lt;/p&gt;
&lt;blockquote data-start="6739" data-end="6860"&gt;
&lt;p data-start="6741" data-end="6860"&gt;&amp;ldquo;If you don&amp;rsquo;t do that, you get weird behavior&amp;hellip; and this could damage the port.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6862" data-end="7002"&gt;These considerations ensure the device is safe to connect between two computers &amp;mdash; something normally discouraged with USB-A-to-USB-A cables.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs6" data-start="7009" data-end="7045"&gt;Assembly and Practical Build Notes&lt;/h2&gt;
&lt;p data-start="7047" data-end="7118"&gt;The assembly process introduces several practical lessons for builders.&lt;/p&gt;
&lt;p data-start="7120" data-end="7166"&gt;Clem notes the challenges of USB-C connectors:&lt;/p&gt;
&lt;blockquote data-start="7168" data-end="7301"&gt;
&lt;p data-start="7170" data-end="7301"&gt;&amp;ldquo;Be aware that USB-C ports that have pins underneath them&amp;hellip; might be really hard to rework.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7303" data-end="7415"&gt;He deliberately chose USB-C connectors limited to USB 2.0 to simplify assembly and avoid unnecessary complexity.&lt;/p&gt;
&lt;p data-start="7417" data-end="7462"&gt;For enclosure, he chose a pragmatic approach:&lt;/p&gt;
&lt;blockquote data-start="7464" data-end="7605"&gt;
&lt;p data-start="7466" data-end="7605"&gt;&amp;ldquo;Heat shrink is the absolute easiest way to make a case&amp;hellip; it&amp;rsquo;s completely functional and compliant.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7607" data-end="7659"&gt;This reinforces the project&amp;rsquo;s focus on practicality.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs7" data-start="7666" data-end="7689"&gt;Why This Tool Matters&lt;/h2&gt;
&lt;p data-start="7691" data-end="7746"&gt;Perhaps the most telling reflection comes near the end:&lt;/p&gt;
&lt;blockquote data-start="7748" data-end="7873"&gt;
&lt;p data-start="7750" data-end="7873"&gt;&amp;ldquo;A lot of my projects would not work out as good as they actually do without this.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7875" data-end="7963"&gt;The Blooper is not just a demonstration device. It&amp;rsquo;s a daily workflow tool that enables:&lt;/p&gt;
&lt;p data-start="7965" data-end="8103"&gt;&amp;bull; Device emulation&lt;br data-start="7983" data-end="7986" /&gt; &amp;bull; Protocol testing&lt;br data-start="8004" data-end="8007" /&gt; &amp;bull; Serial debugging&lt;br data-start="8025" data-end="8028" /&gt; &amp;bull; File transfer without networking&lt;br data-start="8062" data-end="8065" /&gt; &amp;bull; Reliable UART testing environments&lt;/p&gt;
&lt;p data-start="8105" data-end="8156"&gt;Clem also highlights one of the most powerful uses:&lt;/p&gt;
&lt;blockquote data-start="8158" data-end="8276"&gt;
&lt;p data-start="8160" data-end="8276"&gt;&amp;ldquo;I could pretend that I&amp;rsquo;m an Arduino&amp;hellip; and see if the command parsing works.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8278" data-end="8384"&gt;This ability to emulate hardware responses opens up a wide range of development and testing possibilities.&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqloafs8" data-start="8391" data-end="8425"&gt;Open Source and Future Potential&lt;/h2&gt;
&lt;p data-start="8427" data-end="8565"&gt;The project is fully open source and available for the community to build and modify. Clem encourages others to adapt and extend the tool:&lt;/p&gt;
&lt;blockquote data-start="8567" data-end="8681"&gt;
&lt;p data-start="8569" data-end="8681"&gt;&amp;ldquo;Do you have any tools that you made yourself to make your life easier?&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8683" data-end="8842"&gt;The Blooper may have started as a personal helper, but it now stands as a practical tool for developers working with embedded systems and serial communication.&lt;/p&gt;
&lt;p data-start="8683" data-end="8842"&gt;&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;It brings an old idea &amp;mdash; the null modem cable &amp;mdash; firmly into modern development workflows.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlpnguf" data-start="8844" data-end="8932"&gt;Supporting Links and Files&lt;/h2&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;-&amp;nbsp;&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcc"&gt;Bill of Materials&lt;/h2&gt;
&lt;table class="e14-product-bom-main"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;th&gt;&lt;a id="e14-product-link-2e6cb" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2&amp;nsku=83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_BUY_KIT" class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('2e6cb'));" data-farnell="2081321~2,3702965~2,3796321~2,2447404~4,2447422~2,2807974~2" data-newark="83T7087~2,30AK0565~2,73AJ8834~2,94X1664~4,94X1713~2,43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Kit&lt;/a&gt; &lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FT230XS-R&lt;/td&gt;
&lt;td&gt;FTDI&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-c868a" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2081321~2&amp;nsku=83T7087~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('c868a'));" data-farnell="2081321~2" data-newark="83T7087~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usb-c port&lt;/td&gt;
&lt;td&gt;Molex&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-3540e" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3702965~2&amp;nsku=30AK0565~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('3540e'));" data-farnell="3702965~2" data-newark="30AK0565~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Led 0603&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-82fc1" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=3796321~2&amp;nsku=73AJ8834~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('82fc1'));" data-farnell="3796321~2" data-newark="73AJ8834~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5k1 resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-c7f4f" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447404~4&amp;nsku=94X1664~4&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('c7f4f'));" data-farnell="2447404~4" data-newark="94X1664~4" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;68Ohm resistor&lt;/td&gt;
&lt;td&gt;multicomp&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-40b19" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2447422~2&amp;nsku=94X1713~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('40b19'));" data-farnell="2447422~2" data-newark="94X1713~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;schottky diode&lt;/td&gt;
&lt;td&gt;bourns&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;a id="e14-product-link-715a2" data-at-areainteracted="rte-content" data-at-type="click" data-at-link-type="button" href="https://referral.element14.com/OrderCodeView?fsku=2807974~2&amp;nsku=43AC9106~2&amp;COM=e14c-noscript&amp;CMP=e14c-noscript&amp;osetc=e14-noscript-tracking-loss" data-at-label="PRODUCT_POPUP_OPEN"class="e14-embedded e14_shopping-cart-far e14-button" onclick="event.preventDefault();e14.func.displayProduct(e14.meta.user.country, this, 'embedded-link', e14.func.getProductLinkJSON('715a2'));" data-farnell="2807974~2" data-newark="43AC9106~2" data-comoverride="" data-cmpoverride="" data-cpc="" data-avnetemea="" data-avnetema="" data-avnetasia="" &gt;Buy Now&lt;/a&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="xs-hide"&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2 id="mcetoc_1jhqlp2dcd"&gt;Additional Parts&lt;/h2&gt;
&lt;table class="e14-product-bom-additional"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;Manufacturer&lt;/th&gt;
&lt;th&gt;Quantity&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCB made by Aisler&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heatshrink tubing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mcetoc_1jhqlp2dce"&gt;&lt;/h3&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Build Your Own USB Looper for Serial Debugging and File Transfer -- Episode 702</title><link>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702/revision/1</link><pubDate>Wed, 18 Feb 2026 13:26:26 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ac0e986d-170b-4d78-b9a0-ce61d4a7b5bb</guid><dc:creator>cstanton</dc:creator><comments>https://community.element14.com/challenges-projects/element14-presents/project-videos/w/documents/72033/build-your-own-usb-looper-for-serial-debugging-and-file-transfer----episode-702#comments</comments><description>Revision 1 posted to Documents by cstanton on 2/18/2026 1:26:26 PM&lt;br /&gt;
&lt;p data-start="267" data-end="671"&gt;Some tools begin as personal workflow helpers and quietly become essential to multiple projects. Clem&amp;rsquo;s USB Looper &amp;mdash; nicknamed the &lt;strong data-start="398" data-end="411"&gt;&amp;ldquo;Blooper&amp;rdquo;&lt;/strong&gt; &amp;mdash; clearly falls into that category. What started as a practical debugging aid has grown into a fully documented, open-source hardware tool designed to solve real development problems around UART, USB and device emulation. &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;blog&lt;/p&gt;
&lt;p data-start="673" data-end="720"&gt;Early in the video, Clem sets the tone clearly:&lt;/p&gt;
&lt;blockquote data-start="722" data-end="835"&gt;
&lt;p data-start="724" data-end="835"&gt;&amp;ldquo;This tool has saved so many projects&amp;hellip; and guess what? I made it myself.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="837" data-end="1004"&gt;The Blooper is best understood as a modern reinterpretation of the classic null modem cable &amp;mdash; but built for today&amp;rsquo;s USB-centric workflows and development environments.&lt;/p&gt;
&lt;hr data-start="1006" data-end="1009" /&gt;
&lt;h1 data-start="1011" data-end="1043"&gt;What the Blooper Actually Does&lt;/h1&gt;
&lt;p data-start="1045" data-end="1265"&gt;At first glance, the Blooper appears simple: a small device with two USB-C ports. Internally, however, it enables something surprisingly powerful. When connected, the computer sees &lt;strong data-start="1226" data-end="1264"&gt;two independent USB serial devices&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="1267" data-end="1284"&gt;As Clem explains:&lt;/p&gt;
&lt;blockquote data-start="1286" data-end="1410"&gt;
&lt;p data-start="1288" data-end="1410"&gt;&amp;ldquo;The blooper appears as two independent devices&amp;hellip; they both just talk to each other.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1412" data-end="1662"&gt;This means a single computer can communicate with itself as if it were talking to an external embedded system. From the OS perspective, the data looks like it is coming from another device entirely &amp;mdash; even though it&amp;rsquo;s looped back through the hardware.&lt;/p&gt;
&lt;p data-start="1664" data-end="1796"&gt;This hardware loopback is central to why the tool exists. While software loopback can be simulated, Clem points out the limitations:&lt;/p&gt;
&lt;blockquote data-start="1798" data-end="1970"&gt;
&lt;p data-start="1800" data-end="1970"&gt;&amp;ldquo;You could emulate this in software, but the setup is not as easy&amp;hellip; and I don&amp;rsquo;t think it works on any computer. And this thing does.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="1972" data-end="2027"&gt;This reliability and portability is the key difference.&lt;/p&gt;
&lt;hr data-start="2029" data-end="2032" /&gt;
&lt;h1 data-start="2034" data-end="2076"&gt;Logging Serial Output Like a Real Device&lt;/h1&gt;
&lt;p data-start="2078" data-end="2194"&gt;One of Clem&amp;rsquo;s first demonstrations focuses on logging serial data to a file &amp;mdash; a task common in embedded development.&lt;/p&gt;
&lt;p data-start="2196" data-end="2229"&gt;He explains the scenario clearly:&lt;/p&gt;
&lt;blockquote data-start="2231" data-end="2395"&gt;
&lt;p data-start="2233" data-end="2395"&gt;&amp;ldquo;For the computer, it was exactly the same as if the data was coming from an external device. It can&amp;rsquo;t make any difference.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="2397" data-end="2586"&gt;The supporting Python script shows exactly how this is achieved. The logging workflow is implemented in &lt;strong data-start="2501" data-end="2515"&gt;logfile.py&lt;/strong&gt;, which timestamps incoming serial data and writes it directly to disk:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;incoming_data = ser.readline().decode(&lt;span class="hljs-string"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;).strip()
timestamp = time.strftime(&lt;span class="hljs-string"&gt;&amp;#39;%Y-%m-%d %H:%M:%S&amp;#39;&lt;/span&gt;)
log_entry = &lt;span class="hljs-string"&gt;f&amp;quot;&lt;span class="hljs-subst"&gt;{timestamp}&lt;/span&gt;&lt;/span&gt; - &lt;span class="hljs-subst"&gt;{incoming_data}&lt;/span&gt;\n&amp;quot;
f.write(log_entry)
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="2771" data-end="3066"&gt;This reinforces a major use case: testing software that normally expects real hardware output. Because the Blooper behaves like real external hardware, tools such as Arduino IDE, terminal monitors, and custom serial apps can be tested safely and repeatedly. &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;code&lt;/p&gt;
&lt;p data-start="3068" data-end="3117"&gt;Clem highlights how widely he uses this workflow:&lt;/p&gt;
&lt;blockquote data-start="3119" data-end="3249"&gt;
&lt;p data-start="3121" data-end="3249"&gt;&amp;ldquo;I use this to log stuff from Arduinos or out of computers or Raspberry Pi&amp;rsquo;s or whatever.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-start="3251" data-end="3254" /&gt;
&lt;h1 data-start="3256" data-end="3297"&gt;Revisiting the Null Modem Cable Concept&lt;/h1&gt;
&lt;p data-start="3299" data-end="3361"&gt;The Blooper&amp;rsquo;s inspiration comes directly from older workflows.&lt;/p&gt;
&lt;p data-start="3363" data-end="3377"&gt;Clem reflects:&lt;/p&gt;
&lt;blockquote data-start="3379" data-end="3523"&gt;
&lt;p data-start="3381" data-end="3523"&gt;&amp;ldquo;Back in the early 2000, my means of transporting files from one computer to another was&amp;hellip; floppy disks.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3525" data-end="3683"&gt;Before networking was ubiquitous, null modem cables allowed direct PC-to-PC communication over UART. The Blooper recreates this idea with modern USB hardware:&lt;/p&gt;
&lt;blockquote data-start="3685" data-end="3792"&gt;
&lt;p data-start="3687" data-end="3792"&gt;&amp;ldquo;USB ports are kind of a serial port hidden inside a USB protocol.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="3794" data-end="3952"&gt;Internally, the Blooper converts USB to UART on both sides. The result is two hosts communicating directly, bypassing traditional USB host-device constraints.&lt;/p&gt;
&lt;p data-start="3954" data-end="4060"&gt;This is what allows two computers &amp;mdash; or even one computer with two terminals &amp;mdash; to chat over a single cable.&lt;/p&gt;
&lt;hr data-start="4062" data-end="4065" /&gt;
&lt;h1 data-start="4067" data-end="4114"&gt;Building a Full-Duplex Chat Between Computers&lt;/h1&gt;
&lt;p data-start="4116" data-end="4264"&gt;To demonstrate full duplex communication, Clem runs a simple Python chat application. This behaviour is implemented in &lt;strong data-start="4235" data-end="4246"&gt;chat.py&lt;/strong&gt; and &lt;strong data-start="4251" data-end="4263"&gt;chat2.py&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="4266" data-end="4390"&gt;The scripts use two threads: one for reading serial input and one for writing. This enables real-time two-way communication:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;threading.Thread(target=read_from_serial, args=(ser,), daemon=&lt;span class="hljs-literal"&gt;True&lt;/span&gt;).start()
write_to_serial(ser)
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="4504" data-end="4717"&gt;This simple threading approach makes the serial link behave like a messaging app, demonstrating how easily developers can test command protocols or debug communication stacks. &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;code&lt;/p&gt;
&lt;p data-start="4719" data-end="4760"&gt;Clem summarises the usefulness perfectly:&lt;/p&gt;
&lt;blockquote data-start="4762" data-end="4915"&gt;
&lt;p data-start="4764" data-end="4915"&gt;&amp;ldquo;This also works if you plug both ends into the same computer&amp;hellip; which is very handy for debugging applications.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-start="4917" data-end="4920" /&gt;
&lt;h1 data-start="4922" data-end="4960"&gt;Transferring Files Without a Network&lt;/h1&gt;
&lt;p data-start="4962" data-end="5056"&gt;Another demonstration recreates a classic use case: transferring files without network access.&lt;/p&gt;
&lt;p data-start="5058" data-end="5086"&gt;Clem explains the relevance:&lt;/p&gt;
&lt;blockquote data-start="5088" data-end="5245"&gt;
&lt;p data-start="5090" data-end="5245"&gt;&amp;ldquo;While transferring data without a network is not as common today&amp;hellip; this can still be useful in air-gapped systems.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;blog&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="5247" data-end="5320"&gt;The Python tools behind this are &lt;strong data-start="5280" data-end="5297"&gt;filesender.py&lt;/strong&gt; and &lt;strong data-start="5302" data-end="5319"&gt;filereader.py&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-start="5322" data-end="5356"&gt;Sending a file is straightforward:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;&lt;span class="hljs-keyword"&gt;with&lt;/span&gt; &lt;span class="hljs-built_in"&gt;open&lt;/span&gt;(&lt;span class="hljs-string"&gt;&amp;#39;log_file.txt&amp;#39;&lt;/span&gt;, &lt;span class="hljs-string"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;) &lt;span class="hljs-keyword"&gt;as&lt;/span&gt; file:
    data = file.read()
ser.write(data.encode())
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5461" data-end="5520"&gt;Receiving and saving the data uses continuous serial reads:&lt;/p&gt;
&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;
&lt;div&gt;
&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;
&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-python"&gt;&lt;span&gt;incoming_data = ser.read(ser.in_waiting).decode()
file.write(incoming_data)
&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start="5613" data-end="5685"&gt;These scripts mirror how firmware is often uploaded to embedded systems.&lt;/p&gt;
&lt;p data-start="5687" data-end="5721"&gt;Clem explicitly connects the dots:&lt;/p&gt;
&lt;blockquote data-start="5723" data-end="5866"&gt;
&lt;p data-start="5725" data-end="5866"&gt;&amp;ldquo;This is the same way that you would upload firmware over serial&amp;hellip; or configure industrial machinery.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-start="5868" data-end="5871" /&gt;
&lt;h1 data-start="5873" data-end="5920"&gt;Hardware Design Choices That Make It Reliable&lt;/h1&gt;
&lt;p data-start="5922" data-end="6048"&gt;The transcript adds substantial technical depth beyond the original write-up, especially around the hardware design decisions.&lt;/p&gt;
&lt;p data-start="6050" data-end="6118"&gt;One of the most important details is the use of FTDI USB-UART chips:&lt;/p&gt;
&lt;blockquote data-start="6120" data-end="6285"&gt;
&lt;p data-start="6122" data-end="6285"&gt;&amp;ldquo;They always enumerate perfectly&amp;hellip; they don&amp;rsquo;t need any external crystals. This has to be reliable and bootable at any time.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6287" data-end="6414"&gt;This is a key engineering decision: the Blooper is meant to be a tool, not an experiment. Reliability takes priority over cost.&lt;/p&gt;
&lt;p data-start="6416" data-end="6456"&gt;Other critical hardware details include:&lt;/p&gt;
&lt;p data-start="6458" data-end="6712"&gt;&amp;bull; USB-C CC pull-downs (5.1k&amp;Omega;) to ensure correct power negotiation&lt;br data-start="6523" data-end="6526" /&gt; &amp;bull; Schottky diode to prevent reverse powering&lt;br data-start="6570" data-end="6573" /&gt; &amp;bull; Ground stitching vias to prevent crosstalk&lt;br data-start="6617" data-end="6620" /&gt; &amp;bull; Shared reset circuit with pull-up resistor&lt;br data-start="6664" data-end="6667" /&gt; &amp;bull; Dual LED indicators for traffic direction&lt;/p&gt;
&lt;p data-start="6714" data-end="6737"&gt;Clem emphasises safety:&lt;/p&gt;
&lt;blockquote data-start="6739" data-end="6860"&gt;
&lt;p data-start="6741" data-end="6860"&gt;&amp;ldquo;If you don&amp;rsquo;t do that, you get weird behavior&amp;hellip; and this could damage the port.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="6862" data-end="7002"&gt;These considerations ensure the device is safe to connect between two computers &amp;mdash; something normally discouraged with USB-A-to-USB-A cables.&lt;/p&gt;
&lt;hr data-start="7004" data-end="7007" /&gt;
&lt;h1 data-start="7009" data-end="7045"&gt;Assembly and Practical Build Notes&lt;/h1&gt;
&lt;p data-start="7047" data-end="7118"&gt;The assembly process introduces several practical lessons for builders.&lt;/p&gt;
&lt;p data-start="7120" data-end="7166"&gt;Clem notes the challenges of USB-C connectors:&lt;/p&gt;
&lt;blockquote data-start="7168" data-end="7301"&gt;
&lt;p data-start="7170" data-end="7301"&gt;&amp;ldquo;Be aware that USB-C ports that have pins underneath them&amp;hellip; might be really hard to rework.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7303" data-end="7415"&gt;He deliberately chose USB-C connectors limited to USB 2.0 to simplify assembly and avoid unnecessary complexity.&lt;/p&gt;
&lt;p data-start="7417" data-end="7462"&gt;For enclosure, he chose a pragmatic approach:&lt;/p&gt;
&lt;blockquote data-start="7464" data-end="7605"&gt;
&lt;p data-start="7466" data-end="7605"&gt;&amp;ldquo;Heat shrink is the absolute easiest way to make a case&amp;hellip; it&amp;rsquo;s completely functional and compliant.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7607" data-end="7659"&gt;This reinforces the project&amp;rsquo;s focus on practicality.&lt;/p&gt;
&lt;hr data-start="7661" data-end="7664" /&gt;
&lt;h1 data-start="7666" data-end="7689"&gt;Why This Tool Matters&lt;/h1&gt;
&lt;p data-start="7691" data-end="7746"&gt;Perhaps the most telling reflection comes near the end:&lt;/p&gt;
&lt;blockquote data-start="7748" data-end="7873"&gt;
&lt;p data-start="7750" data-end="7873"&gt;&amp;ldquo;A lot of my projects would not work out as good as they actually do without this.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="7875" data-end="7963"&gt;The Blooper is not just a demonstration device. It&amp;rsquo;s a daily workflow tool that enables:&lt;/p&gt;
&lt;p data-start="7965" data-end="8103"&gt;&amp;bull; Device emulation&lt;br data-start="7983" data-end="7986" /&gt; &amp;bull; Protocol testing&lt;br data-start="8004" data-end="8007" /&gt; &amp;bull; Serial debugging&lt;br data-start="8025" data-end="8028" /&gt; &amp;bull; File transfer without networking&lt;br data-start="8062" data-end="8065" /&gt; &amp;bull; Reliable UART testing environments&lt;/p&gt;
&lt;p data-start="8105" data-end="8156"&gt;Clem also highlights one of the most powerful uses:&lt;/p&gt;
&lt;blockquote data-start="8158" data-end="8276"&gt;
&lt;p data-start="8160" data-end="8276"&gt;&amp;ldquo;I could pretend that I&amp;rsquo;m an Arduino&amp;hellip; and see if the command parsing works.&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8278" data-end="8384"&gt;This ability to emulate hardware responses opens up a wide range of development and testing possibilities.&lt;/p&gt;
&lt;hr data-start="8386" data-end="8389" /&gt;
&lt;h1 data-start="8391" data-end="8425"&gt;Open Source and Future Potential&lt;/h1&gt;
&lt;p data-start="8427" data-end="8565"&gt;The project is fully open source and available for the community to build and modify. Clem encourages others to adapt and extend the tool:&lt;/p&gt;
&lt;blockquote data-start="8567" data-end="8681"&gt;
&lt;p data-start="8569" data-end="8681"&gt;&amp;ldquo;Do you have any tools that you made yourself to make your life easier?&amp;rdquo; &lt;span class="" data-state="closed"&gt;&lt;span class="relative inline-flex items-center"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="not-prose mt-0! mb-0! flex-auto truncate"&gt;Blooper&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-start="8683" data-end="8842"&gt;The Blooper may have started as a personal helper, but it now stands as a practical tool for developers working with embedded systems and serial communication.&lt;/p&gt;
&lt;p data-start="8844" data-end="8932" data-is-last-node="" data-is-only-node=""&gt;It brings an old idea &amp;mdash; the null modem cable &amp;mdash; firmly into modern development workflows.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item></channel></rss>