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

<channel>
	<title>Robotics Archives | Paul Bupe Jr, PhD</title>
	<atom:link href="https://paulbupejr.com/category/projects/robotics/feed/" rel="self" type="application/rss+xml" />
	<link>https://paulbupejr.com/category/projects/robotics/</link>
	<description>Hardware, software, and everything in between</description>
	<lastBuildDate>Thu, 18 Apr 2024 16:50:16 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://paulbupejr.com/wp-content/uploads/2019/07/cropped-paul_logo@2x-32x32.png</url>
	<title>Robotics Archives | Paul Bupe Jr, PhD</title>
	<link>https://paulbupejr.com/category/projects/robotics/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>R&#038;D Case Study: Developing the OptiGap Sensor System</title>
		<link>https://paulbupejr.com/developing-the-optigap-sensor-system/</link>
					<comments>https://paulbupejr.com/developing-the-optigap-sensor-system/#comments</comments>
		
		<dc:creator><![CDATA[paulbupe]]></dc:creator>
		<pubDate>Wed, 10 Apr 2024 18:30:19 +0000</pubDate>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Robotics]]></category>
		<category><![CDATA[Theory]]></category>
		<category><![CDATA[3d printer filament]]></category>
		<category><![CDATA[air gap]]></category>
		<category><![CDATA[bend localization]]></category>
		<category><![CDATA[fiber]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[localization]]></category>
		<category><![CDATA[microcontroller]]></category>
		<category><![CDATA[optigap]]></category>
		<category><![CDATA[optigap sensor system]]></category>
		<category><![CDATA[raspberry pi]]></category>
		<category><![CDATA[research]]></category>
		<category><![CDATA[robotics]]></category>
		<category><![CDATA[sensor]]></category>
		<category><![CDATA[Serial]]></category>
		<category><![CDATA[soft robotics]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[zeromq]]></category>
		<guid isPermaLink="false">https://paulbupejr.com/?p=890</guid>

					<description><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 9</span> <span class="rt-label rt-postfix">minutes</span></span>Update: You can follow the discussion of this article around the web on HN, Adafruit, Hackaday, and Hackster.io! This article explores the research and development journey behind my new sensor system, OptiGap, a key component of my PhD research. I&#8217;m writing this in a storytelling format to offer insights into my decision-making process and the &#8230; <a href="https://paulbupejr.com/developing-the-optigap-sensor-system/" class="more-link">Continue reading <span class="screen-reader-text">R&#38;D Case Study: Developing the OptiGap Sensor System</span></a></p>
<p>The post <a href="https://paulbupejr.com/developing-the-optigap-sensor-system/">R&amp;D Case Study: Developing the OptiGap Sensor System</a> appeared first on <a href="https://paulbupejr.com">Paul Bupe Jr, PhD</a>.</p>
]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 9</span> <span class="rt-label rt-postfix">minutes</span></span>
<p><strong>Update</strong>: You can follow the discussion of this article around the web on <a href="https://news.ycombinator.com/item?id=40003710" target="_blank" rel="noreferrer noopener">HN</a>, <a href="https://blog.adafruit.com/2024/04/12/making-sensors-for-soft-robotic-applications/" target="_blank" rel="noreferrer noopener">Adafruit</a>, <a href="https://hackaday.com/2024/04/13/__trashed-9/" target="_blank" rel="noreferrer noopener">Hackaday</a>, and <a href="https://www.hackster.io/news/optigap-turns-3d-printer-filament-into-a-bend-sensing-and-localization-system-for-soft-robots-e3352509838d" target="_blank" rel="noreferrer noopener">Hackster.io</a>!</p>



<p>This article explores the research and development journey behind my new sensor system, <a href="https://ieeexplore.ieee.org/document/10161357" target="_blank" rel="noreferrer noopener">OptiGap</a>, a key component of my PhD research. I&#8217;m writing this in a storytelling format to offer insights into my decision-making process and the evolution leading to the final implementation. It should hopefully provide a glimpse into the sometimes-shrouded world of PhD research and may appeal to those curious about the process. For a deeper dive into technical specifics, simulations, and existing research on this subject, my dissertation is <a href="https://ir.library.louisville.edu/etd/4213/" target="_blank" rel="noreferrer noopener">available online here</a>.</p>



<span id="more-890"></span>



<h3 class="wp-block-heading">What does it do?</h3>



<p>In very general terms, this sensor is basically a rope that if bent can tell you where along its length you bent it. The fancy term for that is &#8220;bend localization.&#8221;</p>



<p>OptiGap&#8217;s application is mainly within the realm of soft robotics, which typically involves compliant (or &#8216;squishy&#8217;) systems, where the use of<a href="https://paulbupejr.com/autonomous-robot-design/"> traditional sensors</a> is often not practical. The name OptiGap, a fusion of &#8220;optical&#8221; and &#8220;gap,&#8221; reflects its core principle of utilizing air gaps within flexible optical light pipes to generate coded patterns essential for bend localization. </p>



<h2 class="wp-block-heading">How the OptiGap Sensor System Started</h2>



<p>The idea for OptiGap came about while I was experimenting with light transmission through various light pipes (optical cables) for use as a bend detection sensor. I was initially trying to see how I could effectively &#8220;slow down&#8221; light through the fiber&#8230;a seemingly straightforward task, right?</p>



<p>During this process, I attached a section of clear 3D printer filament (1.75mm TPU) to a piece of tape measure for an experiment and incidentally discovered that when I bent the tape measure (and filament) at the spot where the electrical tape was attached, there was a significant drop in light transmission. I hypothesized that this was because the sticky residue of the electrical tape was causing the filament to stretch, which in turn reduced the light transmission.</p>



<p>To verify this hypothesis, I attached a longer piece of TPU to a tape measure and began bending it at various points to observe how light transmission would change.</p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac23250&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac23250" class="aligncenter size-large wp-lightbox-container"><img fetchpriority="high" decoding="async" width="768" height="1024" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/black_tape-768x1024.jpg" alt="Tape measure experiment for OptiGap" class="wp-image-891" style="aspect-ratio:4/3;object-fit:cover" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/black_tape-768x1024.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/black_tape-225x300.jpg 225w, https://paulbupejr.com/wp-content/uploads/2024/04/black_tape-1152x1536.jpg 1152w, https://paulbupejr.com/wp-content/uploads/2024/04/black_tape-1536x2048.jpg 1536w, https://paulbupejr.com/wp-content/uploads/2024/04/black_tape-scaled.jpg 1920w" sizes="(max-width: 768px) 100vw, 768px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Tape measure experiment with clear TPU filament.</figcaption></figure>
</div>


<p>I wrote a small Linux I2C driver for the <a href="https://www.st.com/en/imaging-and-photonics-solutions/vl53l0x.html">VL53L0X </a>ToF sensor to run on a <a href="https://zeromq.org/" target="_blank" rel="noreferrer noopener">Raspberry Pi</a> and push the data to a socket using <a href="https://zeromq.org/">ZeroMQ</a>. I then created a rough GUI in Python to pull the sensor data from the socket and visualize the light transmission data in realtime, shown in the GIF below, which very quickly validated my hypothesis. This validation marked the &#8220;Eureka!&#8221; moment that sparked the eventual development of the OptiGap sensor.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="800" height="450" src="https://paulbupejr.com/wp-content/uploads/2024/04/tape.gif" alt="Initial OptiGap discovery" class="wp-image-893"/><figcaption class="wp-element-caption">My excited face while validating my discovery.</figcaption></figure>



<h2 class="wp-block-heading">The OptiGap Realization</h2>



<p>I realized that since I could control where the light was being attenuated, I could use this to encode information about the position of the bend on the sensor. Using electrical tape was not a practical solution, so I started looking for a more reliable and consistent way to create these attenuations. This led me to the idea of cutting the filament and then reattaching it together using a flexible rubber (silicone) sleeve, leaving a small air gap, as shown in the image below.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac23b74&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac23b74" class="wp-block-image size-large wp-lightbox-container"><img decoding="async" width="1024" height="337" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/tpu_gap-1024x337.jpg" alt="Proof-of-concept showing a light pipe with an air in a silicone sleeve." class="wp-image-895" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/tpu_gap-1024x337.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/tpu_gap-300x99.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/tpu_gap-768x252.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/tpu_gap-1536x505.jpg 1536w, https://paulbupejr.com/wp-content/uploads/2024/04/tpu_gap.jpg 1600w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Proof-of-concept showing a light pipe with an air gap in a silicone sleeve.</figcaption></figure>



<p>The main working principle of the air gap is that translation and/or rotation of one light pipe face relative to the other changes the fraction of light transmitted across the gap. The greater the bend angle, the more light escapes across the gap. The resulting change in intensity of the optical signal can then be correlated with known patterns for use as a sensor.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac23f05&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac23f05" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="633" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/operating_principle-1024x633.png" alt="OptiGap operating principle" class="wp-image-896" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/operating_principle-1024x633.png 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/operating_principle-300x185.png 300w, https://paulbupejr.com/wp-content/uploads/2024/04/operating_principle-768x474.png 768w, https://paulbupejr.com/wp-content/uploads/2024/04/operating_principle-1536x949.png 1536w, https://paulbupejr.com/wp-content/uploads/2024/04/operating_principle-825x510.png 825w, https://paulbupejr.com/wp-content/uploads/2024/04/operating_principle.png 1693w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">This image is from a COMSOL simulation I made.</figcaption></figure>



<h2 class="wp-block-heading">The Big Idea</h2>



<p>I then proceeded to test this idea by creating multiple air gaps in a row and bending the filament to measure the attenuation.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac242e7&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac242e7" class="wp-block-image size-large is-style-default wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="631" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/tpu_tof-1-1024x631.jpg" alt="Multiple air gaps along a single TPU lightpipe" class="wp-image-898" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/tpu_tof-1-1024x631.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/tpu_tof-1-300x185.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/tpu_tof-1-768x474.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/tpu_tof-1-1536x947.jpg 1536w, https://paulbupejr.com/wp-content/uploads/2024/04/tpu_tof-1-2048x1263.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Multiple air gaps along a single TPU lightpipe.</figcaption></figure>



<p>As depicted in the GIF below, the optical intensity decreases at each air gap, with a more noticeable decrease as the bend angle increases. This initial experimentation served as proof of concept, demonstrating the feasibility of the idea. It led to the formulation of my final hypothesis of <strong>utilizing a pattern of these air gaps to encode information regarding the sensor&#8217;s bending and employing a naive Bayes classifier on a microcontroller to decode the bend location.</strong></p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="800" height="450" src="https://paulbupejr.com/wp-content/uploads/2024/04/gaps.gif" alt="Validating the attenuation at the air gaps." class="wp-image-899"/><figcaption class="wp-element-caption">Validating the attenuation at the air gaps.</figcaption></figure>



<p>This concept resembles the functionality of a linear encoder. Linear encoders gauge an object&#8217;s linear movement, typically comprising a slider rail with a coded scale akin to a measuring ruler and a sensing head that moves across this scale to read it. Linear (absolute) encoders emit a distinct code at each position, ensuring consistent identification of displacement.</p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac24765&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac24765" class="aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="519" height="417" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/block_diagram.png" alt="OptiGap system overview." class="wp-image-900" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/block_diagram.png 519w, https://paulbupejr.com/wp-content/uploads/2024/04/block_diagram-300x241.png 300w" sizes="auto, (max-width: 519px) 100vw, 519px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">OptiGap system overview.</figcaption></figure>
</div>


<p>The OptiGap system, functioning like an absolute encoder, would encode absolute positions using patterns of bend-sensitive air gaps along parallel light pipes, effectively serving as a singular fiber optic sensor.</p>



<h3 class="wp-block-heading"><strong>Encoding the Bend Location using Inverse Gray Code</strong></h3>



<p>Absolute encoders commonly employ Gray code, a binary system where two successive values differ in only one bit. This property allows for various applications, including error checking. However, Gray code isn&#8217;t optimal for the OptiGap sensor system. Here, we aim for consecutive values to differ by the maximum number of bits to facilitate easier differentiation. This necessity gave rise to Inverse Gray code.</p>


<div class="wp-block-image">
<figure class="aligncenter size-medium"><img loading="lazy" decoding="async" width="300" height="180" src="https://paulbupejr.com/wp-content/uploads/2024/04/Gray-Code-300x180.jpg" alt="" class="wp-image-902" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/Gray-Code-300x180.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/Gray-Code-1024x615.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/Gray-Code-768x461.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/Gray-Code.jpg 1176w" sizes="auto, (max-width: 300px) 100vw, 300px" /></figure>
</div>


<p>Inverse Gray code is a binary code where two successive values differ by the maximum (n-1) number of bits. To implement this, I simply create cuts in the filament wherever there&#8217;s a &#8220;1&#8221; in the Inverse Gray code sequence. This approach can scale to any bit number. For the prototype, I utilized 3 bits, providing 8 possible positions.</p>



<h3 class="wp-block-heading">Visualization of the OptiGap Sensor System</h3>



<p>The illustration below depicts the signal patterns of the OptiGap sensor system for each bend position using three fibers. By employing a naive Bayes classifier, the sensor system can discern bend positions based on signal patterns. The third graph represents actual sensor data from the prototype system, utilized for training the classifier on the microcontroller.</p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac24cd1&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac24cd1" class="aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="519" height="448" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/signal_patterns.png" alt="OptiGap bending patterns." class="wp-image-903" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/signal_patterns.png 519w, https://paulbupejr.com/wp-content/uploads/2024/04/signal_patterns-300x259.png 300w" sizes="auto, (max-width: 519px) 100vw, 519px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">OptiGap bending patterns.</figcaption></figure>
</div>


<h2 class="wp-block-heading">The OptiGap Prototype</h2>



<p>I proceeded to construct a prototype of the OptiGap sensor system, utilizing 3 strands of clear TPU 3D printer filament, each featuring a distinct pattern of air gaps. The image below showcases the filament just before cutting, with the cut pattern indicated on a piece of tape.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac250b3&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac250b3" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="156" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/making_cuts-1024x156.jpg" alt="Beginning stages of an OptiGap sensor prototype." class="wp-image-905" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/making_cuts-1024x156.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/making_cuts-300x46.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/making_cuts-768x117.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/making_cuts-1536x234.jpg 1536w, https://paulbupejr.com/wp-content/uploads/2024/04/making_cuts-2048x312.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Beginning stages of an OptiGap sensor prototype.</figcaption></figure>



<p>For the prototype, I employed a commercial 3:1 fiber optic coupler to merge the light from the 3 strands into a single fiber optic cable, resulting in the completion of the sensor prototype, as depicted below.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac2543b&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac2543b" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="842" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/first_assembled_prototype-1024x842.jpg" alt="Assembled sensing head of an OptiGap sensor." class="wp-image-906" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/first_assembled_prototype-1024x842.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/first_assembled_prototype-300x247.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/first_assembled_prototype-768x632.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/first_assembled_prototype-1536x1264.jpg 1536w, https://paulbupejr.com/wp-content/uploads/2024/04/first_assembled_prototype-2048x1685.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Assembled sensing head of an OptiGap sensor.</figcaption></figure>



<p>This marked the final phase of validating the hypothesis and operational theory behind the OptiGap sensor.</p>



<h3 class="wp-block-heading">Reducing the Physical Size</h3>



<p>The initial prototype proved to be large and bulky, primarily due to the size of the 3D printer filament used. Drawing from previous experience, I recognized that PMMA (plastic) optical fiber offered a smaller and more flexible alternative suitable for this application. Consequently, I assessed 500, 750, and 1000 micron unjacketed PMMA optical fibers from Industrial Fiber Optics, Inc. for the sensor strands, resulting in a significant reduction in sensor size.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac2582f&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac2582f" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="544" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/fiber_label-1024x544.jpg" alt="500 micron PMMA fiber spool." class="wp-image-907" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/fiber_label-1024x544.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/fiber_label-300x159.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/fiber_label-768x408.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/fiber_label-1536x815.jpg 1536w, https://paulbupejr.com/wp-content/uploads/2024/04/fiber_label-2048x1087.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">500 micron PMMA fiber spool.</figcaption></figure>



<p>I conducted tests on all three types of fibers to evaluate their light transmission and flexibility. Among them, the 500 micron fiber emerged as the optimal choice overall, although all three exhibited sufficient flexibility for this application.</p>



<h3 class="wp-block-heading"><strong>Reducing the Optical Transceiver Complexity</strong></h3>



<p>I decided to switch from using the complex VL53L0X ToF sensor to a simple photodiode and IR LED setup to reduce the complexity of the system and to increase modularity. This also allowed me to use a &nbsp;microcontroller to read the sensor data, which was a significant improvement over the initial prototype.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac25c28&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac25c28" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="792" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/new_fiber_tx-1024x792.jpg" alt="IR LED prototype board." class="wp-image-908" style="aspect-ratio:4/3;object-fit:cover" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/new_fiber_tx-1024x792.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/new_fiber_tx-300x232.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/new_fiber_tx-768x594.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/new_fiber_tx-1536x1188.jpg 1536w, https://paulbupejr.com/wp-content/uploads/2024/04/new_fiber_tx-2048x1584.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">IR LED prototype board with 1000 micron PMMA fiber.</figcaption></figure>



<p>I then created a demo system for the sensor based around an STM32 microcontroller and a photodiode/IR LED setup.</p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac26049&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac26049" class="aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="519" height="298" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/demo_system.png" alt="Full OptiGap demo system using 500 micron PMMA fiber." class="wp-image-909" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/demo_system.png 519w, https://paulbupejr.com/wp-content/uploads/2024/04/demo_system-300x172.png 300w" sizes="auto, (max-width: 519px) 100vw, 519px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Full OptiGap demo system using 500 micron PMMA fiber.</figcaption></figure>
</div>


<h2 class="wp-block-heading"><strong>Realtime Machine Learning on a Microcontroller</strong></h2>



<p>The final stage in developing the OptiGap sensor system involved integrating a naive Bayes classifier onto the STM32 microcontroller to decode the bend location from the sensor data. <strong><em>I opted for a naive Bayes classifier due to its efficiency compared to if-statements or lookup tables, its capability to handle new or previously unseen data, and its potential for increased accuracy by considering relationships between multiple input variables.</em></strong></p>



<p>Implementing the naive Bayes classifier proved to be relatively straightforward. This classifier is a probabilistic model based on applying Bayes&#8217; theorem to determine how a measurement can be assigned to a particular class, with the class representing the bend location in this context. I utilized the <a href="https://www.arm.com/technologies/cmsis">Arm CMSIS-DSP library</a> for the classifier implementation.</p>



<h3 class="wp-block-heading">Fitting the Sensor Data</h3>



<p>The initial step in integrating the classifier was to fit the sensor data to a Gaussian distribution for each air gap pattern. To expedite this process, I developed a Python GUI for rapid labeling and fitting of the data using GNB (Gaussian Naive Bayes) from the scikit-learn library.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac2653b&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac2653b" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="452" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/ui_2-1024x452.jpg" alt="Initial data labeling and fitting UI." class="wp-image-910" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/ui_2-1024x452.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/ui_2-300x132.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/ui_2-768x339.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/ui_2.jpg 1431w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Initial data labeling and fitting UI.</figcaption></figure>



<p>I later improved this UI to be more general and to allow for more complex data fitting.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac268e9&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac268e9" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="511" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/ui-1024x511.jpg" alt="Improved UI." class="wp-image-911" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/ui-1024x511.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/ui-300x150.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/ui-768x383.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/ui.jpg 1453w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Improved UI.</figcaption></figure>



<p>The probabilities for each class were computed and saved as a header for use on the microcontroller.</p>



<h3 class="wp-block-heading">Filtering the Sensor Data</h3>



<p>To enhance the accuracy of the classifier, I implemented a two-stage filtering process on the STM32 . The initial stage involved a basic moving average filter, followed by a Kalman filter in the second stage. </p>


<div class="wp-block-image">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac26d41&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac26d41" class="aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="554" height="190" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/dsp.jpg" alt="Signal filtering stages." class="wp-image-913" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/dsp.jpg 554w, https://paulbupejr.com/wp-content/uploads/2024/04/dsp-300x103.jpg 300w" sizes="auto, (max-width: 554px) 100vw, 554px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Signal filtering stages. Noise reduction relative to input signal.</figcaption></figure>
</div>


<h2 class="wp-block-heading">The OptiGap Sensor System Demo</h2>



<p>The GIFs provided below illustrate various stages of the OptiGap sensor system, encompassing assembly and the operational demonstration of the final sensor system.</p>



<h4 class="wp-block-heading has-text-align-center">System Overview</h4>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="800" height="450" src="https://paulbupejr.com/wp-content/uploads/2024/04/System_Overview.gif" alt="" class="wp-image-914"/></figure>



<h4 class="wp-block-heading has-text-align-center">Assembly of an OptiGap Sensor using TPU Filament</h4>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="800" height="450" src="https://paulbupejr.com/wp-content/uploads/2024/04/Assembly.gif" alt="" class="wp-image-915"/></figure>



<h4 class="wp-block-heading has-text-align-center">Attenuation of Light through the OptiGap Sensor</h4>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="800" height="450" src="https://paulbupejr.com/wp-content/uploads/2024/04/Attenuation.gif" alt="" class="wp-image-916"/></figure>



<h4 class="wp-block-heading has-text-align-center"><strong>Fitting of the Sensor Data</strong></h4>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="800" height="450" src="https://paulbupejr.com/wp-content/uploads/2024/04/Training.gif" alt="" class="wp-image-918"/></figure>



<h4 class="wp-block-heading has-text-align-center"><strong>Segment Classification using PMMA Optical Fiber</strong></h4>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="800" height="450" src="https://paulbupejr.com/wp-content/uploads/2024/04/Segment_Classification.gif" alt="" class="wp-image-919"/></figure>



<h4 class="wp-block-heading has-text-align-center"><strong>Segment Classification using TPU Filament</strong></h4>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="800" height="450" src="https://paulbupejr.com/wp-content/uploads/2024/04/Validation.gif" alt="" class="wp-image-920"/></figure>



<h4 class="wp-block-heading has-text-align-center"><strong>Underwater Operation</strong></h4>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="800" height="450" src="https://paulbupejr.com/wp-content/uploads/2024/04/Underwater_Validation.gif" alt="" class="wp-image-921"/></figure>



<h2 class="wp-block-heading">OptiGap Design Specifications</h2>



<h3 class="wp-block-heading has-text-align-center">Key Properties &amp; Parameters</h3>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="191" src="https://paulbupejr.com/wp-content/uploads/2024/04/properties-1024x191.png" alt="" class="wp-image-979" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/properties-1024x191.png 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/properties-300x56.png 300w, https://paulbupejr.com/wp-content/uploads/2024/04/properties-768x143.png 768w, https://paulbupejr.com/wp-content/uploads/2024/04/properties.png 1176w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<h3 class="wp-block-heading has-text-align-center">Material Recommendations</h3>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="636" src="https://paulbupejr.com/wp-content/uploads/2024/04/materails-1024x636.png" alt="" class="wp-image-980" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/materails-1024x636.png 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/materails-300x186.png 300w, https://paulbupejr.com/wp-content/uploads/2024/04/materails-768x477.png 768w, https://paulbupejr.com/wp-content/uploads/2024/04/materails.png 1174w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<h2 class="wp-block-heading">Next Steps</h2>



<p>I&#8217;ve made significant progress on the OptiGap system beyond what&#8217;s documented here, including its integration into another modular actuation and sensing system I developed called EneGate.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac27981&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac27981" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="814" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://paulbupejr.com/wp-content/uploads/2024/04/enegate_optigap-1024x814.jpg" alt="" class="wp-image-922" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/enegate_optigap-1024x814.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/enegate_optigap-300x239.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/enegate_optigap-768x611.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/enegate_optigap-1536x1221.jpg 1536w, https://paulbupejr.com/wp-content/uploads/2024/04/enegate_optigap-2048x1628.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">My EneGate PCB integrating an OptiGap sensor.</figcaption></figure>



<p>This has involved custom PCB design and systems integration, detailed in my dissertation. Additionally, I&#8217;ve prototyped miniature PCB versions of the optics to interface with the PCBs for the EneGate system.</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac27d47&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac27d47" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="768" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" data-id="924" src="https://paulbupejr.com/wp-content/uploads/2024/04/daughterboard-1024x768.jpg" alt="" class="wp-image-924" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/daughterboard-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2024/04/daughterboard-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/daughterboard-768x576.jpg 768w, https://paulbupejr.com/wp-content/uploads/2024/04/daughterboard-1536x1152.jpg 1536w, https://paulbupejr.com/wp-content/uploads/2024/04/daughterboard.jpg 1600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Mini OptiGap PCB</figcaption></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69dfc7ac28082&quot;}" data-wp-interactive="core/image" data-wp-key="69dfc7ac28082" class="wp-block-image size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="907" height="599" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" data-id="923" src="https://paulbupejr.com/wp-content/uploads/2024/04/enegate_optigap_pcb.jpg" alt="" class="wp-image-923" srcset="https://paulbupejr.com/wp-content/uploads/2024/04/enegate_optigap_pcb.jpg 907w, https://paulbupejr.com/wp-content/uploads/2024/04/enegate_optigap_pcb-300x198.jpg 300w, https://paulbupejr.com/wp-content/uploads/2024/04/enegate_optigap_pcb-768x507.jpg 768w" sizes="auto, (max-width: 907px) 100vw, 907px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Enlarge"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Another mini OptiGap PCB</figcaption></figure>
</figure>



<p>I&#8217;ve also validated OptiGap on a real-world soft robotic system, with full details set to be presented in an upcoming RoboSoft paper titled &#8220;<strong><em>Embedded Optical Waveguide Sensors for Dynamic Behavior Monitoring in Twisted-Beam Structures.</em></strong>&#8220;</p>



<h3 class="wp-block-heading"><strong>Commercialization</strong></h3>



<p>There&#8217;s an ongoing commercialization aspect to this research as well. Feel free to reach out if you&#8217;re interested in further details.</p>



<h2 class="wp-block-heading">That&#8217;s it for now!</h2>



<p>I don&#8217;t want to make this too long so I&#8217;ll end here. I hope this provided some insight into the research and development process involved in something like this. If you have any questions or would like to learn more, don&#8217;t hesitate to contact me!</p>
<p>The post <a href="https://paulbupejr.com/developing-the-optigap-sensor-system/">R&amp;D Case Study: Developing the OptiGap Sensor System</a> appeared first on <a href="https://paulbupejr.com">Paul Bupe Jr, PhD</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://paulbupejr.com/developing-the-optigap-sensor-system/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Designing an Advanced Autonomous Robot: Goose</title>
		<link>https://paulbupejr.com/autonomous-robot-design/</link>
					<comments>https://paulbupejr.com/autonomous-robot-design/#comments</comments>
		
		<dc:creator><![CDATA[paulbupe]]></dc:creator>
		<pubDate>Tue, 30 Jul 2019 23:37:01 +0000</pubDate>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Robotics]]></category>
		<category><![CDATA[lidar]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[raspberry pi]]></category>
		<category><![CDATA[robotics]]></category>
		<category><![CDATA[solidworks]]></category>
		<guid isPermaLink="false">http://paulbupejr.com/?p=363</guid>

					<description><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 10</span> <span class="rt-label rt-postfix">minutes</span></span>Update: This article was featured on Hackaday.com and on SDP/SI&#8217;s &#8220;Featured People and Organizations&#8221; page. Goose is a mobile autonomous robot I designed and built over 6 months in my spare time for a robotics competition. This was a fully custom and challenging build that tested my competence in electrical engineering, mechanical engineering, control systems, &#8230; <a href="https://paulbupejr.com/autonomous-robot-design/" class="more-link">Continue reading <span class="screen-reader-text">Designing an Advanced Autonomous Robot: Goose</span></a></p>
<p>The post <a href="https://paulbupejr.com/autonomous-robot-design/">Designing an Advanced Autonomous Robot: Goose</a> appeared first on <a href="https://paulbupejr.com">Paul Bupe Jr, PhD</a>.</p>
]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 10</span> <span class="rt-label rt-postfix">minutes</span></span>
<p><strong>Update</strong>: This article was featured on <a href="https://hackaday.com/2019/08/08/designing-an-advanced-autonomous-robot-goose/" target="_blank" rel="noreferrer noopener">Hackaday.com</a> and on SDP/SI&#8217;s <a href="https://sdp-si.com/features/sdpsi-features.php" target="_blank" rel="noreferrer noopener">&#8220;Featured People and Organizations&#8221; page</a>.</p>



<p>Goose is a mobile autonomous robot I designed and built over 6 months in my spare time for a robotics competition. This was a fully custom and challenging build that tested my competence in electrical engineering, mechanical engineering, control systems, and computer science.  </p>



<p>Instead of focusing heavily on the competition, the goal of this article is to <em>briefly</em> go through the system design process. I&#8217;ll touch on my various design choices and discuss how I chose to address some of the common issues in designing an autonomous robot. This is not a tutorial (those will be coming later) but more of a case study. </p>



<figure class="wp-block-gallery columns-2 is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-19-1024x733.jpg"><img loading="lazy" decoding="async" width="1024" height="733" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-19-1024x733.jpg" alt="" data-id="367" data-link="http://paulbupejr.com/goose-19/" class="wp-image-367" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-19-1024x733.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-19-300x215.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-19-768x550.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure></li><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-20-1024x768.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-20-1024x768.jpg" alt="" data-id="366" data-link="http://paulbupejr.com/goose-20/" class="wp-image-366" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-20-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-20-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-20-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure></li></ul></figure>



<span id="more-363"></span>



<h2 class="wp-block-heading">Competition and Results</h2>



<p>The basic premise of the competition was to have an autonomous robot  navigate a square arena (enclosed by four walls) and collect / sort&nbsp; multi-colored cubes and balls. It had to avoid fixed obstacles and had a 3-minute time limit. The robot was also required to &#8220;orbit&#8221; around the center of the arena in a counterclockwise fashion while performing the aforementioned tasks. </p>



<p>Goose was in second place after the first round then suffered a catastrophic reverse polarity condition at my hands (<a href="https://en.wikipedia.org/wiki/Murphy%27s_law">thanks Murphy</a>) prior to the second run. I made two critical mistakes:</p>



<ol class="wp-block-list"><li>I daisy-chained the power rail going to my two motor controllers instead of tying each directly to my power bus. This set me up for the upcoming cascading failure.</li><li>After being awake for over 24 hour I somehow reverse polarized the power rail going to my motor controllers, which destroyed them both. </li></ol>



<p>Even without a second round run, Goose did well enough in the first round to finish fourth overall in the Open competition.</p>



<h2 class="wp-block-heading">Hardware Design</h2>



<figure class="wp-block-image"><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-12.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-12-1024x768.jpg" alt="" class="wp-image-374" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-12-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-12-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-12-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption>The underside of the machined base with wiring harnesses connected </figcaption></figure>



<p>The first hardware decision I made was selecting the type of drive system the robot would employ.  Since the robot was constrained to a  9&#8243; x 9&#8243; x 11&#8243; box, and once I realized that I was just building a glorified vacuum cleaner, my design ideas converged towards a very compact <a href="https://en.wikipedia.org/wiki/WALL-E">Wall-E</a> type chassis.  </p>



<p>Based on experience I chose a tracked differential drive system, i.e., <a href="https://en.wikipedia.org/wiki/Holonomic_(robotics)">non-holonomic</a> like a tank. As a general rule you want to avoid using omnidirectional wheels an autonomous robot unless you have a localization system that gives you an accurate pose. Using a two-motor differential drive system allowed me to achieve a compact design by placing the geared motors in the rear and directly driving the tracks.  </p>



<p><a href="https://sdp-si.com/">SDP/SI</a> was gracious enough to provide me with the timing belts and pulleys I used in my custom drivebase (shown in the image above) so thanks to them!  I also would not have been able to build this robot without the amazing engineering/manufacturing facilities at <a href="https://cec.georgiasouthern.edu/">Georgia Southern University</a> that have state of the art equipment (such as the waterjet and laser cutter I used) available to students.</p>



<h3 class="wp-block-heading">Prototyping and Base Build</h3>



<p>After getting a rough idea of the physical design of the robot I started prototyping using SolidWorks, my 3D printer, and a laser cutter. My prototyping workflow involved first sketching out parts on paper, creating them in SolidWorks, then 3D printing or laser cutting them as needed. In total I ended up creating around 232 SolidWorks parts by the end of the build.</p>



<figure class="wp-block-image"><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-2.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-2-1024x768.jpg" alt="Rapid prototyping robot base" class="wp-image-384" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-2-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-2-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-2-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption>Rapid prototyping with wood and acrylic</figcaption></figure>



<figure class="wp-block-gallery columns-2 is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-21-1024x546.jpg"><img loading="lazy" decoding="async" width="1024" height="546" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-21-1024x546.jpg" alt="" data-id="365" data-link="http://paulbupejr.com/goose-21/" class="wp-image-365" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-21-1024x546.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-21-300x160.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-21-768x410.jpg 768w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-21.jpg 1919w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="blocks-gallery-item__caption">Partial SolidWorks 3D model</figcaption></figure></li><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-3-1024x768.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-3-1024x768.jpg" alt="" data-id="383" data-link="http://paulbupejr.com/goose-3/" class="wp-image-383" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-3-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-3-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-3-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="blocks-gallery-item__caption">Track prototype</figcaption></figure></li></ul></figure>



<p>The biggest issue I ran into was figuring out how to remove play from the shaft in the bearing. The inner race of the bearing would move when under tension which caused alignment issues with the belt.  The shaft was anchored at one end only&nbsp;because there was no room to add a second bearing (even a sleeve bearing) on the outer plate end due to the competition size constraints. </p>



<figure class="wp-block-gallery columns-2 is-cropped wp-block-gallery-4 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-7-1024x768.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-7-1024x768.jpg" alt="" data-id="379" data-link="http://paulbupejr.com/goose-7/" class="wp-image-379" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-7-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-7-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-7-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="blocks-gallery-item__caption">Bearing assembly with shaft</figcaption></figure></li><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-8-1024x768.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-8-1024x768.jpg" alt="" data-id="378" data-link="http://paulbupejr.com/goose-8/" class="wp-image-378" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-8-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-8-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-8-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="blocks-gallery-item__caption">3D printed bearing sleeves mounted on brackets</figcaption></figure></li></ul></figure>



<p>I was able to overcome this issue by designing a sturdy bearing mount that I mounted on the inside of the bracket then added a smaller acrylic mount with a sleeve bearing on the outside. This, along with shortening the shaft, was able to remove any play from the shaft under tension. I also added a very small lip to the pulleys to prevent the belt from slipping. The final base used aluminum which was machined using a <a href="https://www.omax.com/maxiem-waterjet/1515">MAXIEM 1515 waterjet cutter</a>. </p>



<figure class="wp-block-gallery columns-2 is-cropped wp-block-gallery-5 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-4-1024x768.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-4-1024x768.jpg" alt="" data-id="382" data-link="http://paulbupejr.com/goose-4/" class="wp-image-382" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-4-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-4-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-4-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="blocks-gallery-item__caption">Cutting aluminum on a waterjet</figcaption></figure></li><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-13-1024x768.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-13-1024x768.jpg" alt="" data-id="373" data-link="http://paulbupejr.com/goose-13/" class="wp-image-373" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-13-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-13-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-13-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="blocks-gallery-item__caption">The finished drivebase</figcaption></figure></li></ul></figure>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Goose &quot;Static Fire&quot; Test" width="660" height="371" src="https://www.youtube.com/embed/LapK2Nf0OVU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div><figcaption>Testing the right drive assembly at full power</figcaption></figure>



<p>The remaining parts were created using wood with the help of a laser cutter. </p>



<figure class="wp-block-gallery columns-3 is-cropped wp-block-gallery-6 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-25-1024x711.jpg"><img loading="lazy" decoding="async" width="1024" height="711" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-25-1024x711.jpg" alt="" data-id="403" data-link="http://paulbupejr.com/goose-25/" class="wp-image-403" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-25-1024x711.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-25-300x208.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-25-768x534.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="blocks-gallery-item__caption">Cutting out wood</figcaption></figure></li><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-15-1024x768.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-15-1024x768.jpg" alt="" data-id="371" data-link="http://paulbupejr.com/goose-15/" class="wp-image-371" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-15-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-15-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-15-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="blocks-gallery-item__caption">First test fit</figcaption></figure></li><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-17-1024x768.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-17-1024x768.jpg" alt="" data-id="369" data-link="http://paulbupejr.com/goose-17/" class="wp-image-369" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-17-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-17-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-17-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="blocks-gallery-item__caption">Staining the wood</figcaption></figure></li></ul></figure>



<h2 class="wp-block-heading">Electronics</h2>



<figure class="wp-block-image"><a href="http://paulbupejr.com/wp-content/uploads/2019/06/IEEEbot-Electronics-1.png"><img loading="lazy" decoding="async" width="878" height="727" src="http://paulbupejr.com/wp-content/uploads/2019/06/IEEEbot-Electronics-1.png" alt="" class="wp-image-388" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/IEEEbot-Electronics-1.png 878w, https://paulbupejr.com/wp-content/uploads/2019/06/IEEEbot-Electronics-1-300x248.png 300w, https://paulbupejr.com/wp-content/uploads/2019/06/IEEEbot-Electronics-1-768x636.png 768w" sizes="auto, (max-width: 878px) 100vw, 878px" /></a></figure>



<p>The electronics subsystem of Goose utilized an architecture that I have been tweaking for my autonomous robot designs over many years. The main idea is to minimize the cost of failure by isolating as many systems as possible and using generalized interfaces to connect the systems, i.e., modularization. All the supply rails are also individually fused with on/off switches and indicators. </p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="687" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-24-1024x687.jpg" alt="" class="wp-image-404" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-24-1024x687.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-24-300x201.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-24-768x515.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Control panel</figcaption></figure>



<p>Some core safety features of my architecture include:</p>



<ul class="wp-block-list"><li>Proper fusing for overcurrent protection.</li><li><a href="https://en.wikipedia.org/wiki/Crowbar_(circuit)">Crowbar circuits</a> for overvoltage protection. Crowbar circuits require very careful design in order to avoid false triggers due to noise or a narrow operating band.  </li><li>High current <a href="https://www.analog.com/en/technical-articles/primer-on-powerpath-controllers-ideal-diodes-prioritizers.html">ideal diodes</a> for reverse polarity protection. <strong>I did not include this in Goose and of course suffered a competition ending reverse-polarity condition so I won&#8217;t skip it again</strong>!</li></ul>



<p>All these concepts are nothing new in electronics but striking the right balance between complexity and functionality for any one particular application can be tricky, especially when creating an autonomous robot.  </p>



<p>Even though this system did not contain any sensitive analog circuitry, I still isolated the noisy motor power rail from the rest of the circuitry, eventually tying everything together at a single point at the battery in the <a href="https://www.analog.com/en/analog-dialogue/articles/staying-well-grounded.html">&#8220;star ground&#8221;</a> configuration. It&#8217;s always important to have a good idea of the major current paths in your circuits so you can spot any potential issues like ground loops &#8212; this does not require advanced knowledge of mesh analysis! </p>



<h3 class="wp-block-heading">Mainboard</h3>



<figure class="wp-block-image"><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-18-e1560883236583.jpg"><img loading="lazy" decoding="async" width="1024" height="925" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-18-e1560883236583-1024x925.jpg" alt="" class="wp-image-368" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-18-e1560883236583-1024x925.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-18-e1560883236583-300x271.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-18-e1560883236583-768x694.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption>Custom circuit with various sensor interfaces and drivers.</figcaption></figure>



<p>I have made it a habit to always use soldered PCBs for my projects. While breadboards are useful in the very initial stages of prototyping, they should not be used for anything past initial testing and brainstorming &#8212; they are too unreliable and can be difficult to troubleshoot due to issues like intermittent connections. Depending on your level of experience most analog circuits can be designed using a <a href="https://www.analog.com/en/design-center/design-tools-and-calculators/ltspice-simulator.html">SPICE</a> simulator and some basic math.</p>



<p>I designed the board for GOOSE using a stripboard. Stripboards are easier to use than regular solderable PCBs for more complicated circuits because they have connected strips (thus the name) that you cut to break the circuit at a desired point. This means you don&#8217;t have to solder a lot of holes in order to make a power bus or run a signal to multiple pins. Just don&#8217;t forget to cut the traces or you&#8217;ll have a pretty bad day!</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="880" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-9-1024x880.jpg" alt="" class="wp-image-377" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-9-1024x880.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-9-300x258.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-9-768x660.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>The bottom of the stripboard before I cut the traces</figcaption></figure>



<p>The board contained the 5V and 3.3V power rails rated up to 2.5A, two PWM MOSFET driver circuits, a logic level converter, 9 DoF IMU, and the Teensy microcontroller. There are also a few other assorted supporting components. </p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="866" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-10-1024x866.jpg" alt="" class="wp-image-376" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-10-1024x866.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-10-300x254.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-10-768x650.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Unpopulated stripboard</figcaption></figure>



<h3 class="wp-block-heading">Cabling and Wiring Harnesses</h3>



<p>One of the most important and necessary skills in robotics is being able to make cables and wiring harnesses that are custom to the robot. While the process can be tedious, it results in a more reliable and professional end product. I typically use 2.54mm JST-XH connectors and &#8220;Dupont&#8221; connectors for my wiring when working with prototype boards. There&#8217;s quite a lot behind the names of connectors so I encourage you to read <a href="http://tech.mattmillman.com/info/crimpconnectors/">this article</a> which does a great job summarizing most of what you&#8217;ll need to know about crimpers and connectors. For high current applications I used regular spade connectors and <a href="https://www.amazon.com/221-412-2-Conductor-Compact-Splicing-Connectors/dp/B00JB3U7Y6/ref=pd_lpo_sbs_60_t_1?_encoding=UTF8&amp;psc=1&amp;refRID=Z81BSPGB7V3S030DB7XS">Wago 221 connectors</a> for creating power busses. You can get generic versions of these on eBay and similar sites. </p>



<p>When creating long runs on this project I cannibalized a CAT5 cable and crimped on my own connectors to the ends. This was especially ideal because the twisted pairs meant I could effectively run differential signals if needed. </p>



<figure class="wp-block-gallery columns-2 is-cropped wp-block-gallery-7 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-16-1024x768.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-16-1024x768.jpg" alt="" data-id="370" data-link="http://paulbupejr.com/goose-16/" class="wp-image-370" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-16-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-16-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-16-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="blocks-gallery-item__caption">Properly crimped and insulated connectors</figcaption></figure></li><li class="blocks-gallery-item"><figure><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-23-1024x768.jpg"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-23-1024x768.jpg" alt="" data-id="405" data-link="http://paulbupejr.com/goose-23/" class="wp-image-405" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-23-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-23-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-23-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="blocks-gallery-item__caption">Wire harnesses from CAT5 cable</figcaption></figure></li></ul></figure>



<p>The <a href="https://standards.nasa.gov/standard/nasa/nasa-std-87394">NASA Standard for Crimping, Interconnecting Cables, Harnesses, And Wiring</a> is a great resource for learning from the pros. While most of the crimping tools they use cost in the hundreds of dollars on the low end, the information is still relevant and quite useful!</p>



<h3 class="wp-block-heading">Processing Subsystem</h3>



<p>I used two processing cores for Goose: a <a href="https://www.pjrc.com/teensy/techspecs.html">Teensy 3.2</a> (32 bit ARM Cortex-M4) microcontroller to handle all the deterministic logic, and a Debian-based <a href="https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus/">Raspberry Pi 3B+</a> for the more heavy computational work dealing with mapping and image processing. The Raspberry Pi was running the <a href="https://www.ros.org/">Robot Operating System</a> (ROS) and the Teensy communicated to the Pi via USB serial.</p>



<figure class="wp-block-image"><a href="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-22.jpg"><img loading="lazy" decoding="async" width="1024" height="766" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-22-1024x766.jpg" alt="" class="wp-image-406" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-22-1024x766.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-22-300x224.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-22-768x574.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption>The two &#8220;brains&#8221; of Goose connected together.</figcaption></figure>



<p>Running at 96 MHz, the Teensy was fast enough to process data from two quadrature encoders and perform real-time odometry calculations; run an AHRS fusion algorithm from a 9 DoF IMU at about 2.1 kHz; run multiple PID loops; monitor two ultrasonic sensors at a high refresh rate, and send all this data to the Pi at a baud rate of 500,000. I had several ROS nodes running on the Teensy which communicated to the ROS Master on the Pi. As an example, I used the handler below to process messages from the Pi to the Teensy and then command the setpoint of the PID controllers:</p>



<pre class="wp-block-code"><code>void process_velocities(const geometry_msgs::Twist&amp; cmd_msg)
{
	double x = cmd_msg.linear.x;	// forward velocity
	double z = cmd_msg.angular.z;	// rotational velocity

	if (z == 0) { // going straight
		left_motor_setpoint = x * 60 / (PI*wheel_diameter);
		right_motor_setpoint = left_motor_setpoint;
	}
	else if (x == 0) // turning in place
	{
		left_motor_setpoint = z * track_width * 60 / (wheel_diameter* PI * 2);
		right_motor_setpoint = -left_motor_setpoint;
	}
	else 
	{
		left_motor_setpoint = x * 60 / (PI * wheel_diameter) - z * track_width * 60 / (wheel_diameter * PI * 2);
		right_motor_setpoint = x * 60 / (PI * wheel_diameter) + z * track_width * 60 / (wheel_diameter * PI * 2);
	}
} // process_velocities()</code></pre>



<p class="has-text-align-center has-small-font-size"><em>Handler used to process velocity messages from the Pi and command the PID setpoints</em></p>



<div style="height:20px" aria-hidden="true" class="wp-block-spacer"></div>



<p>I initially considered and prototyped using a <a href="https://beagleboard.org/black">BeagleBone Black</a> since it contains two deterministic 32-bit PRU processing cores that can be accessed from the Linux system but I found the development overhead not worth it for one person with limited time. I wrote a few articles based on that experience <a href="http://paulbupejr.com/beaglebone-black-internet-over-usb/">here</a>, <a href="http://paulbupejr.com/change-cloud9-workspace/">here</a>, and <a href="http://paulbupejr.com/adding-swap-memory-to-the-beaglebone-black/">here</a>.</p>



<h3 class="wp-block-heading">Localization and Navigation Subsystem</h3>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2019/06/Goose-14-1024x768.jpg" alt="" class="wp-image-372" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/Goose-14-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-14-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2019/06/Goose-14-768x576.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The competition rules required the robot to move in large circles for the duration of the run which meant I couldn&#8217;t use encoder-based dead reckoning; the act of turning introduces errors due to drift and slippage which would accumulate to unacceptable levels over the course of the 3 minute run. </p>



<p>To counter this issue, I took advantage of the fact that the arena was enclosed by four walls in a square to develop a navigation system that used encoder odometry, IMU feedback, and LiDAR point cloud data to effectively pinpoint the location of the robot at all times.</p>



<figure class="wp-block-image"><a href="http://paulbupejr.com/wp-content/uploads/2019/06/IEEEbot-Localization.png"><img loading="lazy" decoding="async" width="868" height="665" src="http://paulbupejr.com/wp-content/uploads/2019/06/IEEEbot-Localization.png" alt="" class="wp-image-387" srcset="https://paulbupejr.com/wp-content/uploads/2019/06/IEEEbot-Localization.png 868w, https://paulbupejr.com/wp-content/uploads/2019/06/IEEEbot-Localization-300x230.png 300w, https://paulbupejr.com/wp-content/uploads/2019/06/IEEEbot-Localization-768x588.png 768w" sizes="auto, (max-width: 868px) 100vw, 868px" /></a></figure>



<p>As shown in the figure above, the basic idea was to use a pre-made map of the environment and then use point cloud data from the LiDAR in addition to the pose esitmate from to localize using a particle filter algorithm. I created the map in Adobe Illustrator and then converted it to a pgm file for use in ROS. </p>



<div class="wp-block-image"><figure class="aligncenter"><img loading="lazy" decoding="async" width="300" height="300" src="http://paulbupejr.com/wp-content/uploads/2019/07/map-300x300.png" alt="" class="wp-image-469" srcset="https://paulbupejr.com/wp-content/uploads/2019/07/map-300x300.png 300w, https://paulbupejr.com/wp-content/uploads/2019/07/map-150x150.png 150w, https://paulbupejr.com/wp-content/uploads/2019/07/map-768x768.png 768w, https://paulbupejr.com/wp-content/uploads/2019/07/map-1024x1024.png 1024w, https://paulbupejr.com/wp-content/uploads/2019/07/map-45x45.png 45w, https://paulbupejr.com/wp-content/uploads/2019/07/map.png 1802w" sizes="auto, (max-width: 300px) 100vw, 300px" /><figcaption>Map used to generate an occupancy grid for navigation in ROS</figcaption></figure></div>



<p>Localization inside a square would be difficult using LiDAR only (since all corners look the same and corner matching would fail) so I incorporated the pose estimate generated by fusing the encoder odometry data and the 9 DoF IMU using an unscented Kalman filter. I used an unscented Kalman filter (as opposed to the extended Kalman filter) for handling the nonlinear data because it is <em>generally</em> more accurate and has less computational complexity since there&#8217;s no need to calculate the Jacobian matrix.</p>



<figure class="wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Differential Drive PID Test" width="660" height="371" src="https://www.youtube.com/embed/TZl-nySItxE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div><figcaption>Testing the tuning of the two motor PID loops</figcaption></figure>



<h4 class="wp-block-heading">Side note:</h4>



<p>I have written a paper that includes some experimentation on developing a computationally efficient 2D navigation algorithm (for a microcontroller-based autonomous robot) which I might revise and release when I have the time. The algorithm I developed had a time complexity of O(n). Below is a page from the paper showing part of my experimental setup and a mapping / vector generated by the algorithm. I used a <a href="http://en.benewake.com/product/detail/5c345e26e5b3a844c472329c.html">TFmini</a> short-range LiDAR module for these experiments. </p>



<figure class="wp-block-image"><a href="http://paulbupejr.com/wp-content/uploads/2019/07/paul_tfmini_experiments.png"><img loading="lazy" decoding="async" width="810" height="1013" src="http://paulbupejr.com/wp-content/uploads/2019/07/paul_tfmini_experiments.png" alt="" class="wp-image-433" srcset="https://paulbupejr.com/wp-content/uploads/2019/07/paul_tfmini_experiments.png 810w, https://paulbupejr.com/wp-content/uploads/2019/07/paul_tfmini_experiments-240x300.png 240w, https://paulbupejr.com/wp-content/uploads/2019/07/paul_tfmini_experiments-768x960.png 768w" sizes="auto, (max-width: 810px) 100vw, 810px" /></a></figure>



<h2 class="wp-block-heading">Final Thoughts</h2>



<p>This project was certainly fun and a lot of work! There&#8217;s so much more to this robot I haven&#8217;t even touched on in this article but for the sake of keeping it &#8220;brief&#8221; I will have to end it here. </p>



<p>If time permits I may write a separate article on each system of the robot along with any associated source code and hardware info; possibly a series on building an advanced autonomous robot. I would like to go into more details on the software side and the workflow I came up with for working easily with ROS on a Raspberry Pi and a Teensy microcontroller. </p>



<p>Let me know your thoughts on this build or if you&#8217;d like to see any tutorials based on what&#8217;s in this build or robotics in general!</p>
<p>The post <a href="https://paulbupejr.com/autonomous-robot-design/">Designing an Advanced Autonomous Robot: Goose</a> appeared first on <a href="https://paulbupejr.com">Paul Bupe Jr, PhD</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://paulbupejr.com/autonomous-robot-design/feed/</wfw:commentRss>
			<slash:comments>19</slash:comments>
		
		
			</item>
		<item>
		<title>ModBot:  A Modular Robotics  Test Platform</title>
		<link>https://paulbupejr.com/robotics-platform/</link>
					<comments>https://paulbupejr.com/robotics-platform/#respond</comments>
		
		<dc:creator><![CDATA[paulbupe]]></dc:creator>
		<pubDate>Thu, 24 May 2018 03:47:33 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Robotics]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[raspberry pi]]></category>
		<category><![CDATA[robotics]]></category>
		<category><![CDATA[Serial]]></category>
		<guid isPermaLink="false">http://paulbupejr.com/?p=82</guid>

					<description><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 4</span> <span class="rt-label rt-postfix">minutes</span></span>ModBot is a simple robotics platform created for testing sensors, algorithms, vision systems, and everything else in between</p>
<p>The post <a href="https://paulbupejr.com/robotics-platform/">ModBot:  A Modular Robotics  Test Platform</a> appeared first on <a href="https://paulbupejr.com">Paul Bupe Jr, PhD</a>.</p>
]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 4</span> <span class="rt-label rt-postfix">minutes</span></span>
<p>ModBot is a simple robotics platform created for testing sensors, algorithms, vision systems, and everything else in between. I designed this platform with modularity in mind (thus the name) which requires the compartmentalization of behaviors and functions into discrete and, ideally, interchangeable modules.  Since this is an experimental platform I opted not tie it to ROS (even though it still uses a Linux environment so ROS can be used) and created a very simple ASCII protocol for communication between modules. Lastly, I added teleoperation capabilities using a PlayStation DualShock 4 controller.</p>



<span id="more-82"></span>



<h2 class="wp-block-heading">Robotics Platform Block Diagram and Design</h2>



<p>The base is the fairly standard four-wheel differential drive design. A Raspberry Pi controls the motors via a dedicated Arduino Nano microcontroller that has motion profiles/velocity curves for each motor. </p>



<div class="wp-block-image"><figure class="aligncenter"><a href="http://paulbupejr.com/wp-content/uploads/2018/05/StackMod-1.png"><img loading="lazy" decoding="async" width="1024" height="722" src="http://paulbupejr.com/wp-content/uploads/2018/05/StackMod-1-1024x722.png" alt="" class="wp-image-165" srcset="https://paulbupejr.com/wp-content/uploads/2018/05/StackMod-1-1024x722.png 1024w, https://paulbupejr.com/wp-content/uploads/2018/05/StackMod-1-300x211.png 300w, https://paulbupejr.com/wp-content/uploads/2018/05/StackMod-1-768x541.png 768w, https://paulbupejr.com/wp-content/uploads/2018/05/StackMod-1.png 1152w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption>ModBot Block Diagram</figcaption></figure></div>



<p>I utilized standard sockets and connectors so that controllers and other components could be swapped out without full disassembly of the robot. Notably, I used RJ45 Keystone jacks so that I can use standard Cat 5 cables as module interconnects. Multiple microcontrollers can be added to the system using the I2C protocol I created for communication.  </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-4-1024x768.jpg" alt="" class="wp-image-590" srcset="https://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-4-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-4-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-4-768x576.jpg 768w, https://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-4-1536x1152.jpg 1536w, https://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-4-2048x1536.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>All the core components of this robotics platform are kept under the upper deck, which is used to hold whatever component or sensor is being tested. The ports for the Raspberry Pi and other components are oriented such that cables can be plugged in or removed without removing the cover.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="768" src="http://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-6-1024x768.jpg" alt="" class="wp-image-592" srcset="https://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-6-1024x768.jpg 1024w, https://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-6-300x225.jpg 300w, https://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-6-768x576.jpg 768w, https://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-6-1536x1152.jpg 1536w, https://paulbupejr.com/wp-content/uploads/2020/01/modbot_web-6-2048x1536.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Serial Communication Protocol</h2>



<p>To help facilitate modularity, I created a simple serial protocol to abstract the transfer of data between modules. </p>



<h3 class="wp-block-heading">Why Create a Custom Protocol?</h3>



<p>As I started building more complex systems with multiple “brains” working together (Raspberry Pis, BeagleBones, and Arduinos), I founding myself needing a simple protocol that could be used to more easily facilitate communication to all these controllers over I2C. Over various projects I standardized formalized the following protocol.</p>



<p><em>There are a lot of full-featured and extensive protocols and libraries out there (<a rel="noreferrer noopener" href="https://github.com/firmata/protocol" target="_blank">Firmata</a>&nbsp;being at the top)&nbsp;and this does not attempt to replace or compete with those. It’s a simple single-purpose protocol with the sole focus of use for simple robotic systems with no overhead or fancy features.</em></p>



<h3 class="wp-block-heading">Robotics Platform Communication Protocol</h3>



<p>This I2C protocol is designed to be simple, human-readable, and is suitable for transmission over a serial bus. All data are passed as ASCII characters between 0x24 (36) and 0x7D (125).  The protocol is simple enough that it can be debugged without any special decoding as show in the screenshot from my oscilloscope below.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="800" height="480" src="http://paulbupejr.com/wp-content/uploads/2020/01/DS1Z_QuickPrint3.png" alt="" class="wp-image-587" srcset="https://paulbupejr.com/wp-content/uploads/2020/01/DS1Z_QuickPrint3.png 800w, https://paulbupejr.com/wp-content/uploads/2020/01/DS1Z_QuickPrint3-300x180.png 300w, https://paulbupejr.com/wp-content/uploads/2020/01/DS1Z_QuickPrint3-768x461.png 768w" sizes="auto, (max-width: 800px) 100vw, 800px" /><figcaption>Protocol as captured on oscilloscope</figcaption></figure>



<p><strong><em>This is just a basic overview and not meant to be full documentation of the protocol.</em></strong> </p>



<h4 class="wp-block-heading"><strong>Packet Structure</strong></h4>



<p class="has-text-align-center has-small-font-size">&lt;START&gt;&lt;SRC_ADDRESS&gt;&lt;DST_ADDRESS&gt;&lt;ACTION&gt;&lt;COMMAND&gt;&lt;DATA&gt;&lt;END&gt;&lt;CHECKSUM&gt;</p>



<ul class="wp-block-list"><li>The <strong><code>START </code></strong>byte is ASCII &#8220;<code>{</code>&#8221; (123 decimal, 0x7B).</li><li>The <strong><code>SRC_ADDRESS </code></strong>byte is any value from 64 to 95 decimal (0x40 to 0x5F, ASCII “<code>@</code>” to “<code>_</code>”).</li><li>The <strong><code>DST_ADDRESS </code></strong>byte is any value from 64 to 95 decimal (0x40 to 0x5F, ASCII “<code>@</code>” to “<code>_</code>”).</li><li>The <strong><code>ACTION </code></strong>byte is an ASCII “<code>?</code>” for <code>GET</code> and ASCII “$” for <code>SET</code>.</li><li>The <strong><code>COMMAND </code></strong>bytes are three characters.</li><li>The <strong><code>DATA</code> </strong>bytes are variable length and are described in the Data section.</li><li>The <strong><code>END</code> </strong>byte is ASCII &#8220;<code>}</code>&#8221; (125 decimal, 0x7D).</li><li>The <strong><code>CHECKSUM </code></strong>is calculated by subtracting 32 from all the characters in the packet (excluding the start and end bytes) and summing them. The modulo 95 of this value is then calculated and 32 is added back to that value.</li></ul>



<h2 class="wp-block-heading">Checksum Calculation</h2>



<pre class="wp-block-code"><code>int calculate_checksum(String packet) {
   int sum = 0;
   int c = packet.length();
   for (int i = 0; i &lt; c; i++) { sum += packet&#91;i] - 32;}
   return (sum % 95) + 32;
}</code></pre>



<h3 class="wp-block-heading">Example Commands</h3>



<p>The available commands for this revision are listed in the table below.</p>



<figure class="wp-block-table"><table><tbody><tr><th>Command</th><th>Description</th></tr><tr><td><code>ARM</code></td><td>Arm / Disarm System</td></tr><tr><td><code>MTR</code></td><td>Motor Speed</td></tr><tr><td><code>SRV</code></td><td>Servo Position / Speed</td></tr><tr><td><code>ULT</code></td><td>Ultrasonic Distance</td></tr><tr><td><code>IRS</code></td><td>IR Value</td></tr><tr><td><code>DGT</code></td><td>Digital Pin</td></tr><tr><td><code>ANL</code></td><td>Analog Pin</td></tr></tbody></table></figure>



<h4 class="wp-block-heading">Example <code>MTR&nbsp;GET</code> Command and Response</h4>



<p><code>MTR GET</code> command.&nbsp;This packet requests the speed of motor number 2.</p>



<pre class="wp-block-preformatted">{@e?MTR02}X</pre>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><th>Character</th><th>Description</th></tr><tr><td>{</td><td>Start byte</td></tr><tr><td>@</td><td>Source address</td></tr><tr><td>e</td><td>Destination address</td></tr><tr><td>?</td><td>GET action</td></tr><tr><td>M</td><td>Command byte 1</td></tr><tr><td>T</td><td>Command byte 2</td></tr><tr><td>R</td><td>Command byte 3</td></tr><tr><td>0</td><td>Motor number byte 1</td></tr><tr><td>2</td><td>Motor number byte 2</td></tr><tr><td>}</td><td>End byte</td></tr><tr><td>X</td><td>Checksum</td></tr></tbody></table></figure>



<p><code>MTR GET</code> response.&nbsp;This packet returns the speed of motor number 2.</p>



<pre class="wp-block-preformatted">{e@?MTR02+078}C
</pre>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><th>Character</th><th>Description</th></tr><tr><td>{</td><td>Start byte</td></tr><tr><td>e</td><td>Source address</td></tr><tr><td>@</td><td>Destination address</td></tr><tr><td>?</td><td>GET action</td></tr><tr><td>M</td><td>Command byte 1</td></tr><tr><td>T</td><td>Command byte 2</td></tr><tr><td>R</td><td>Command byte 3</td></tr><tr><td>0</td><td>Motor number byte 1</td></tr><tr><td>2</td><td>Motor number byte 2</td></tr><tr><td>+</td><td>Motor speed sign byte</td></tr><tr><td>0</td><td>Motor speed byte 1</td></tr><tr><td>7</td><td>Motor speed byte 2</td></tr><tr><td>8</td><td>Motor speed byte 3</td></tr><tr><td>}</td><td>End byte</td></tr><tr><td>C</td><td>Checksum</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Teleoperation Test Run</h2>



<p>Here&#8217;s a short clip of me testing the motion profiles and mixing of the inputs from the controller joystick. As you can probably tell there was still a bit of tweaking to be done when I took this video but overall the robotics platform was quite responsive. </p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="ModBot Teleop Test with DualShock 4 Controller" width="660" height="371" src="https://www.youtube.com/embed/hoT0-weHZBw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://paulbupejr.com/robotics-platform/">ModBot:  A Modular Robotics  Test Platform</a> appeared first on <a href="https://paulbupejr.com">Paul Bupe Jr, PhD</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://paulbupejr.com/robotics-platform/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 
Lazy Loading (feed)

Served from: paulbupejr.com @ 2026-04-15 13:15:24 by W3 Total Cache
-->