<?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>Photons, Electrons, and Dirt &#187; PIC18</title>
	<atom:link href="https://bikerglen.com/blog/category/microchip/pic18/feed/" rel="self" type="application/rss+xml" />
	<link>https://bikerglen.com/blog</link>
	<description>A blog by Glen Akins</description>
	<lastBuildDate>Mon, 16 Feb 2026 00:47:00 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.2.38</generator>
	<item>
		<title>Building a Simple RFID Door Access Controller</title>
		<link>https://bikerglen.com/blog/building-a-simple-rfid-door-access-controller/</link>
		<comments>https://bikerglen.com/blog/building-a-simple-rfid-door-access-controller/#comments</comments>
		<pubDate>Wed, 11 Aug 2021 00:43:25 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[Microchip]]></category>
		<category><![CDATA[PIC18]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">https://bikerglen.com/blog/?p=3338</guid>
		<description><![CDATA[In this project, I build what is quite possibly the world&#8217;s simplest (and least intelligent) door access controller to let me open and close my garage door using my mountain bike helmet. We&#8217;ll take a look at my motivation for &#8230; <a href="https://bikerglen.com/blog/building-a-simple-rfid-door-access-controller/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><iframe title="YouTube video player" src="https://www.youtube.com/embed/BHS816K3yuk" width="630" height="355" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p>In this project, I build what is quite possibly the world&#8217;s simplest (and least intelligent) door access controller to let me open and close my garage door using my mountain bike helmet. We&#8217;ll take a look at my motivation for the project, review some available RFID readers, pick a reader, then design and program the simple access controller. The simple access controller will receive the card ID from the RFID reader, compare the ID against a list of authorized cards, and make the decision to activate the garage door opener or not. Afterwards, we&#8217;ll briefly talk about the security of the system and include some ideas on how to improve the project.</p>
<p><span id="more-3338"></span></p>
<h2>Motivation</h2>
<div id="attachment_3356" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/hf-helmet-sticker-2.jpg"><img class="size-large wp-image-3356" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/hf-helmet-sticker-2-1024x576.jpg" alt="The 13.56 MHz NTAG203 RFID sticker on the back of my helmet." width="640" height="360" /></a><p class="wp-caption-text">The 13.56 MHz NTAG203 RFID sticker on the back of my helmet.</p></div>
<p>My primary motivation for this project was to have a quick way to get into the garage after riding my bike in the hills and around town. Most of my neighbors have simple keypads where you type in a numeric code and the garage door opens or closes. This would be the easy route and I could have gone down this route too. But, just like with mountain biking, the major downside to picking the easy route is you don&#8217;t improve your skills.</p>
<p>As usual, I decided to go down the gnarly route. My first thought was to put an RFID card in my hydration pack so I could hold my pack up against a reader and open or close the door. After pondering this for a while, I discovered they make thin RFID stickers. Inspired by dirt bike enduro races that use barcodes on helmets to time racers, I had the thought to stick an RFID sticker to my helmet to open or close the door, and, voila, the project was born!</p>
<h2>RFID Technology</h2>
<p>The first step in an RFID project is to pick the RFID technology to use. RFID technology is primarily divided into categories by the frequencies used to communicate between the RFID reader and the RFID token. These frequencies are 125 kHz, 13.56 MHz, and UHF frequencies between 860 MHz and 960 MHz.</p>
<p>Regardless of frequency, they all work on the same basic concept whereby the reader uses a coil to induce a current in a token that powers a chip that can receive a signal, decode the signal, process the signal, encode a response, and transmit the response back to the reader. The simplest RFID chips just transmit their serial number back to the reader. Other chips can perform complex cryptographic operations to establish an encrypted and authenticated link between the reader and the token and then use the data exchanged back and forth to update their non-volatile memory.</p>
<h3>125 kHz Tech</h3>
<div id="attachment_3367" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/125khz-reader-and-tokens.jpg"><img class="size-large wp-image-3367" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/125khz-reader-and-tokens-1024x682.jpg" alt="A Parallax reader and cards, an old SciAtl work badge, and a HID Global keyfob." width="640" height="426" /></a><p class="wp-caption-text">Some examples of 125 kHz RFID technology: a Parallax reader and cards, an old SciAtl work badge, and an HID Global keyfob.</p></div>
<p>125 kHz RFID technology is the oldest technology in common use. The read range is limited to a few centimeters. These RFID tokens are often used for getting into corporate office buildings, parking garages, and apartment common areas. These tokens transmit a fixed 26, 32, or 37 bit code.</p>
<p>The HID Global cards used for access to office buildings typically transmit 26 bits or 37 bits. Some other cards, like the Parallax card in the photo above, transmit 32 bits. All of the 125 kHz cards are inexpensive but they&#8217;re not secure. A quick perusal of Amazon, eBay, or AliExpress shows all sorts of devices for cloning and duplicating these cards.</p>
<h3>13.56 MHz Tech</h3>
<div id="attachment_3379" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/13.56MHz-cards.jpg"><img class="size-large wp-image-3379" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/13.56MHz-cards-1024x682.jpg" alt="Some example 13.56 MHz RFID cards, stickers, key fobs, and tokens." width="640" height="426" /></a><p class="wp-caption-text">Some example 13.56 MHz RFID cards, stickers, key fobs, and tokens.</p></div>
<p>13.56 MHz RFID tags are <a href="https://rfid4u.com/rfid-frequency/">the most widely used tags</a>. They have a read range from a few centimeter to about half a meter. They&#8217;re used for hotel room keys, traditional proximity-based access control cards, stored value cards, asset tracking, and transit fare cards. The 13.56 MHz tags I have are divided into two groups: HID Global&#8217;s iClass cards and cards that follow the ISO14443 standard.</p>
<p>The iClass cards can be read only by HID multiClass or iClass readers (more on these readers later). The ISO14443 cards can be read on most readers including some but not all HID multiClass and iClass readers.</p>
<p>Some examples of ISO14443 standard cards include cards sold under the names MIFARE, NTAG, and DESFire. This <a href="https://rfid4u.com/rfid-standards-mandates/">page has some details</a> on the various RFID card standards. The HID cards have 26 or 37 bit unique IDs. The ISO14443 cards have either 4 or 7 byte unique IDs (UIDs).</p>
<h4>13.56 MHz Tech Security</h4>
<p>The security of 13.56 MHz RFID cards runs the gamut from very little like the 125 kHz RFID cards to very sophisticated with encrypted tunnels and mutual authentication of the reader and card. Applications that only use the ISO14443 UID for authentication basically have the same security as the 125 kHz technology RFID tokens. &#8220;Magic&#8221; 13.56 MHz RFID chips are available that permit re-writing their UID. These chips allow the UID from one card to be cloned into the &#8220;magic&#8221; card. These chips are used in the <a href="https://dangerousthings.com/">Dangerous Things</a> RFID implants.</p>
<p>At the other end of  the security scale are technologies like HID Global&#8217;s iClass SEOS readers and cards. A customer&#8217;s key is embedded in a hardware security element inside the reader. Each card contains a <a href="https://www.ibm.com/docs/en/zos/2.1.0?topic=keys-diversifying">diversified key</a> that is derived from the customer&#8217;s key and the card&#8217;s UID. The reader computes its own value of the diversified key then that common key is used to mutually authenticate the card and reader to each other. If the authentication check passes, the reader beeps twice instead of once and the UID of the card is forwarded to the access controller.</p>
<p>The NXP MIFARE DESFire cards are capable of similar authentication and encryption as HID Global&#8217;s iClass SEOS card but are usually used for applications like stored value cards and transit fare cards. Using a reader breakout board like Adafruit&#8217;s PN532 or M5Stack&#8217;s MFRC522 miniature reader (both discussed in the next section) along with the NXP TapLink SDK or the open source libnfc library, it should be possible for even a hobbyist to build their own application with the same level of security as the HID Global iClass SEOS system. That project, however, is currently left to the reader.</p>
<h3>UHF Tech</h3>
<div id="attachment_3353" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/uhf-toll-sticker.jpg"><img class="size-large wp-image-3353" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/uhf-toll-sticker-1024x576.jpg" alt="A UHF RFID toll transponder stuck to the inside of my windshield for Colorado's E-470 toll road." width="640" height="360" /></a><p class="wp-caption-text">A UHF RFID toll transponder sticker on the the inside of my windshield for E-470&#8217;s ExpressToll system.</p></div>
<p>The last type of tag I looked at were EPC Global Class1 Gen2 UHF RFID tags. These are available in sticker form and are typically used for <a href="https://www.labelandnarrowweb.com/contents/view_breaking-news/2013-12-05/confidex-rfid-labels-to-be-used-in-toll-collecting-system/">toll roads</a>, race timing, and capital asset inventory applications. The stickers can be read at high speeds and at a distance of several meters with the right antennas. For inventory applications, hundreds of stickers within the read area can be read simultaneously. I ruled these out due to the cost of the readers and that I didn&#8217;t want to trigger my garage door from more than a few centimeters.</p>
<h2>RFID Readers</h2>
<p>After learning about the available RFID tag technology and available products, I decided to use a 13.56 MHz ISO14443 sticker for the back of my bicycle helmet. They&#8217;re cheap, readily available from multiple sources, and compatible with most 13.56 MHz RFID readers. The next step was to pick a reader.</p>
<h3>Impinj UHF Readers</h3>
<div id="attachment_3358" style="width: 610px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/Reader-Speedway-Series-Spotlight-600x400.jpg"><img class="size-full wp-image-3358" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/Reader-Speedway-Series-Spotlight-600x400.jpg" alt="Impinj Raceway UHF RFID readers from https://www.impinj.com/products/readers/impinj-speedway" width="600" height="400" /></a><p class="wp-caption-text">Impinj Raceway UHF RFID readers. Photo from https://www.impinj.com/products/readers/impinj-speedway</p></div>
<p>Let&#8217;s start with the highest end and most expensive readers. Readers like the Impinj reader shown above operate in the UHF frequency band. These readers are used for high-speed, long-distance applications. They use external antennas that can be focused to precisely define the read area and they can read multiple tags within in the read area simultaneously. The Impinj readers start at about $1000 without antennas. I don&#8217;t have one. It wouldn&#8217;t work with the 13.56 MHz sticker I chose for my helmet anyway. Maybe someday.</p>
<h3>Adafruit PN532 NFC/RFID Controller Breakout Board</h3>
<div id="attachment_3369" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/adafruit-pn532.jpg"><img class="size-large wp-image-3369" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/adafruit-pn532-1024x682.jpg" alt="The Adafruit PN532 breakout board." width="640" height="426" /></a><p class="wp-caption-text">The Adafruit PN532 breakout board.</p></div>
<p>Next up is the <a href="https://www.adafruit.com/product/364">Adafruit PN532 NFC/RFID controller breakout board</a>. It&#8217;s a versatile breakout board for experimenting with the NXP PN532 RFID reader/writer IC. It lets you read and write 13.56 MHz ISO14443-compliant contactless cards from any system supporting 3.3V I2C, SPI, or UART communications.</p>
<div id="attachment_3380" style="width: 761px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/gnfc.png"><img class="size-full wp-image-3380" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/gnfc.png" alt="The main screen of the GNFC app for Windows and the PN532 reader IC." width="751" height="682" /></a><p class="wp-caption-text">The main screen of the GNFC app for Windows and the PN532 reader IC.</p></div>
<p>Adafruit has a <a href="https://learn.adafruit.com/adafruit-pn532-rfid-nfc/overview">guide to using their breakout board</a> with Arduino or CircuitPython. I didn&#8217;t want to develop another embedded system just for testing so I dug around and found an app called <a href="https://github.com/JiapengLi/GNFC">GNCF</a> on Github that was adequate for testing the board and reading a few cards using a UART connection from a PC.</p>
<p>I decided not to use this board for my project because it&#8217;s physically large and I needed something that would be easy to waterproof and place on the exterior of the house. Some day I&#8217;d like to revisit this board to see if I can get mutual authentication and encryption working using MIFARE DESFire cards and <a href="https://github.com/nfc-tools/libnfc">libnfc</a>. It also looks like this board may be able to read HID iClass cards (but not iClass SE cards) using libnfc.</p>
<h3>M5Stack MFRC522 Mini RFID Reader/Writer Unit</h3>
<div id="attachment_3370" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/m5stack-atom-reader-relays.jpg"><img class="size-large wp-image-3370" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/m5stack-atom-reader-relays-1024x682.jpg" alt="caption" width="640" height="426" /></a><p class="wp-caption-text">With an M5Stack Atom, an M5Stack four relay board, and an M5Stack RFID reader, a complete RFID control project can be built with no soldering.</p></div>
<p>The second RFID reader I researched and experimented with is the <a href="https://shop.m5stack.com/products/rfid-sensor-unit">M5Stack MFRC522 mini RFID reader/writer unit</a>. It&#8217;s small and inexpensive at $12.50. It&#8217;s based on the RC522 RFID module and uses I2C to communicate with a host microprocessor. M5Stack has an Arduino library and example Arduino sketch on their website to demonstrate reading of 13.56 MHz ISO14443 card UIDs using the module.</p>
<div id="attachment_3371" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/m5stack-waterproof-enclosure.jpg"><img class="size-large wp-image-3371" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/m5stack-waterproof-enclosure-1024x682.jpg" alt="caption" width="640" height="426" /></a><p class="wp-caption-text">The M5Stack RFID reader is small enough to place in a waterproof enclosure and mount outside.</p></div>
<p>What I really like about the M5Stack RFID reader is that with only the M5Stack RFID reader, an M5Stack Atom Lite ESP32-pico based development kit, an M5Stack relay board and a SEEED Grove I2C hub board, you can build a complete RFID system that can control external gadgets for about $35 with zero soldering.</p>
<p>The reader is also small enough to fit in a small waterproof enclosure like the one from Hammond Manufacturing shown in the photo above. Ultimately, I decided against using the M5Stack RFID reader for my project though.</p>
<h3>HID Global multiClass and iClass Readers</h3>
<div id="attachment_3429" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/hid-global-readers.jpg"><img class="size-large wp-image-3429" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/hid-global-readers-1024x682.jpg" alt="Various flavors of HID Global RFID proximity card readers." width="640" height="426" /></a><p class="wp-caption-text">Various flavors of HID Global RFID proximity card readers.</p></div>
<p>Next up were various versions of the HID Global readers we&#8217;re all familiar with from badging into the office in the mornings. These seemed ideal for my application because they&#8217;re designed specifically for access control and they&#8217;re also designed to be mounted on the exteriors of buildings. What I didn&#8217;t know until I purchased a few to experiment with was exactly what type of cards they would or would not read.</p>
<div id="attachment_3386" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/reader-credential-support.png"><img class="size-large wp-image-3386" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/reader-credential-support-1024x582.png" alt="caption" width="640" height="364" /></a><p class="wp-caption-text">Credential support options from the HID reader configuration guide.</p></div>
<p>The table above from the <a href="https://www.hidglobal.com/sites/default/files/resource_files/plt-02630-c.0-readers-and-credentials-htog.pdf">HID reader configuration guide</a> (PDF) shows the available credential support options when ordering a basic iClass SE reader. After reading the guide, I decided I wanted a reader that supported 125 kHz credentials and I wanted a reader that would support credentials with an ISO14443 UID like the sticker I chose for the back of my helmet.</p>
<p>SIO is a secure identity object that provides higher security when using MIFARE cards than just using the MIFARE card&#8217;s ISO14443 UID. With the right software, card writer, and licenses, it&#8217;s possible to embed an SIO in a generic MIFARE card. This seems rather complicated and likely not possible for a hobbyist.</p>
<p>I also decided I wanted a Standard v1 keyset reader with Wiegand output. I searched eBay for used readers with part numbers matching these four criteria and ordered a few to experiment with to make sure they&#8217;d read the sticker I chose for my helmet.</p>
<h2>Wiegand Protocol</h2>
<div id="attachment_3430" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/reader-color-codes.jpg"><img class="size-large wp-image-3430" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/reader-color-codes-1024x634.jpg" alt="All the readers use the same color code. I'm only interested in the red, black, green, and white wires." width="640" height="396" /></a><p class="wp-caption-text">All the readers use the same color code. I&#8217;m only interested in the red, black, green, and white wires.</p></div>
<p>The reader I selected uses the Wiegand protocol for communicating with the rest of the access control system. The Wiegand protocol traces its history to early access control cards that used the <a href="https://en.wikipedia.org/wiki/Wiegand_effect">Wiegand effect</a>.</p>
<p>This protocol sends one bit at a time using a two wire interface. Both wires are normally high. For each bit sent, one of the two wires is pulled low. If the green wire is pulled low, the bit is a zero. If the white wire is pulled low, the bit is a one. Both wires return to high between bits. I had no idea of the timing of the bits or voltage of the interface though.</p>
<p>When one of the readers arrived, I connected it to a bench supply and an oscilloscope to observe the Wiegand protocol output from the reader. I needed to know the time between each bit, the duration of each bit, and the voltage used by the interface so that I could design hardware and software to receive and decode the card numbers sent from the reader.</p>
<div id="attachment_3392" style="width: 810px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/scope_3.png"><img class="wp-image-3392 size-full" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/scope_3.png" alt="scope_3" width="800" height="632" /></a><p class="wp-caption-text">Complete 32-bit ISO14443 UID from a HID Global reader. The yellow trace on top is connected to the green &#8216;0&#8217; wire and the green trace on bottom is connected to the white &#8216;1&#8217; wire.</p></div>
<p>The scope trace above shows the Wiegand output from the reader when a MIFARE classic card that was previously used as part of a hotel&#8217;s door lock system is presented to the reader. Looking at the voltage range of the traces, it&#8217;s clear that the Wiegand interface is a five volt interface. The 32 bits transmitted correspond to the cards ISO14443 UID, 9D:F2:11:78 (UID bytes are transmitted lowest byte first).</p>
<div id="attachment_3393" style="width: 810px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/scope_4.png"><img class="wp-image-3393 size-full" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/scope_4.png" alt="scope_4" width="800" height="632" /></a><p class="wp-caption-text">Time between bits from the same card and reader.</p></div>
<p>Next, the scope trace above shows the time between bits. I&#8217;m going to call it 2 milliseconds.</p>
<div id="attachment_3394" style="width: 810px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/scope_5.png"><img class="wp-image-3394 size-full" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/scope_5.png" alt="scope_5" width="800" height="632" /></a><p class="wp-caption-text">Time of a single bit from the same card and reader.</p></div>
<p>Finally, the scope trace above shows the duration of a single bit. It&#8217;s only 40 microseconds! It might be good to use an interrupt to detect the zero&#8217;s and one&#8217;s rather than trying to poll them from the software&#8217;s main loop. I measured several other cards. The number of bits transmitted varied based on the card type but the time between bits and the duration of each bit remained the same for all cards.</p>
<h2>Design Requirements</h2>
<p>With the measurement of the voltages and timing of the Wiegand protocol from the reader completed, I could begin designing the hardware and software for my simple access controller. The simple access controller will capture the UID from the card reader and make the decision to activate the garage door opener based on the received UID. The requirements:</p>
<ul>
<li>Two general purpose input pins preferably with interrupt capability for handling the Wiegand interface to the card reader. These lines must be protected against electrostatic discharge.</li>
<li>The number of bits transmitted by the Wiegand protocol varies depending on the type of card presented and there&#8217;s no end of data signal so a timer must be available on the selected microcontroller to determine when the transmission of the card UID is complete.</li>
<li>Use a simple 8-bit microcontroller. The microcontroller must run from 5 volts or have 5 volt tolerant inputs since 5 volts is the voltage of the Wiegand interface.</li>
<li>At least two LEDs to indicate that the main loop of the software is running and to indicate if the UID received from the card reader is authorized or not.</li>
<li>At least one relay to control the garage door opener when an authorized card is presented to the reader.</li>
<li>The relay contacts must not activate the garage door opener at reset, at power up, at power down, or at anytime other than when an authorized card is presented to the reader.</li>
<li>A few pushbutton switches might be useful but are not strictly necessary.</li>
<li>Use an external 12 volt power input with an on-board 5 volt power supply for the selected microcontroller.</li>
<li>Supply a 12 volt power passthrough for the card reader from the external supply.</li>
<li>UID&#8217;s of authorized cards will be hardcoded and compiled into the software.</li>
<li>All parts are either immediately available or I have them on-hand.</li>
</ul>
<p>With the design requirements finalized, it was time to select components and start the schematic design.</p>
<h2>Schematic Design</h2>
<div id="attachment_3399" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/schematic.png"><img class="size-large wp-image-3399" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/schematic-1024x664.png" alt="The final schematic for the simple door access controller." width="640" height="415" /></a><p class="wp-caption-text">The final schematic for the simple door access controller.</p></div>
<p>As I started design of the schematic, my preference was for parts that I had on hand and parts that I had used before. The only parts I had trouble sourcing were the relays. I had to make a late design change to use relays with 12 volt coils instead of 5 volt coils because the 5 volt versions just weren&#8217;t available. Fortunately, I already planned to use a 12 volt power supply to power this project and therefore 12 volts was already available in the design.</p>
<h3>Microcontroller</h3>
<p>A small PIC microcontroller like a PIC18F1320 would be more than sufficient for this project. The PIC18F1320 has interrupt on change capability for a few of its pins when they&#8217;re configured as inputs and numerous timers so it meets the requirements for the project.</p>
<p>Unfortunately, the only PIC microcontroller I had ready access to due to the ongoing semiconductor shortage was a PIC18F45K50. It&#8217;s overkill for this application. Just like its smaller sibling, the PIC18F45K50 has interrupt on change capabilities and numerous timers. I will not be using its USB functionality for this project.</p>
<p>The PIC18F45K50 has an internal oscillator that is accurate enough for our application so an external crystal or oscillator is not needed. In addition to the usual 0.1 uF decoupling capacitors close to the VDD pins, the PIC18F45K50 requires a low-ESR 0.47 uF capacitor between its VUSB3V3 pin and ground. This is C9 in the schematic.</p>
<p>The data sheet also recommends 1 uF in parallel to each of the 0.1 uF capacitors if the PIC is located more than a few inches from its 5V power supply. Our is not so the 1 uF caps are not strictly necessary in this design.</p>
<h3>Card Reader Wiegand Interface</h3>
<div id="attachment_3410" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/schematic-wiegand-interface.png"><img class="size-large wp-image-3410" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/schematic-wiegand-interface-1024x647.png" alt="The Wiegand interface portion of the schematic." width="640" height="404" /></a><p class="wp-caption-text">The Wiegand interface portion of the schematic.</p></div>
<p>The card reader connects to the simple access controller via a four position, 3.81 mm pitch Phoenix pluggable terminal block. Pin 1 is +12 volts to power the reader, pin 2 is ground, pin 3 connects to the reader&#8217;s green &#8216;0&#8217; output and pin 4 connects to the reader&#8217;s white &#8216;1&#8217; output. 12 volts from the external power supply is passed through from the power input connector the reader connector.</p>
<p>Pins 3 and 4 from the reader connector connect to the microcontroller&#8217;s RC0 and RC1 pins. RC0 and RC1 have interrupt on change capabilities when configured as inputs. D3 and D4 provide ESD protection and R11 and R12 limit current into the microcontroller during ESD events and short circuits and reduce reflections back to the reader. R9 and R10 are optional 5 volt pull-up resistors because some Wiegand readers do not have internal pull-up resistors. The reader I will be using does so R9 and R10 are not stuffed on the board.</p>
<h3>Relays and Drivers</h3>
<div id="attachment_3411" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/schematic-relay-output.png"><img class="size-large wp-image-3411" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/schematic-relay-output-1024x761.png" alt="Schematic of the first of two of the relay outputs." width="640" height="476" /></a><p class="wp-caption-text">Schematic of the first of two of the relay outputs.</p></div>
<p>The 12 volt relay coils are switched using basic transistor switch circuits connected to the microcontroller&#8217;s RA2 and RA3 pins. R5 and R6 limit the current into the base of the transistors. R7 and R8 keep the transistors from turning on while the PIC microcontroller is in reset and during software initialization. Once the software is initialized, the micro drives the pins low to keep the relays from turning on.</p>
<p>When an authorized card is detected, the microcontroller drives RA2 high for about one half second. This turns on transistor Q1 and energizes relay K1&#8217;s coil. This in turn closes the relay&#8217;s contacts which then activate the garage door opener. Connections to the relays are made using a pair of 2 position, 3.81 mm pitch Phoenix pluggable terminal blocks. D1 and D2 protect the transistors from back EMF when the relays are switched off. Relay K2 is presently unused.</p>
<h3>LEDs and Switches</h3>
<div id="attachment_3406" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/MFG_GB15JVF.jpg"><img class="size-full wp-image-3406" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/MFG_GB15JVF.jpg" alt="Photo of an NKK GB15JVC / GB15JVF switch from digikey.com." width="640" height="449" /></a><p class="wp-caption-text">Photo of an NKK GB15JVC / GB15JVF switch from digikey.com.</p></div>
<p>For the pushbutton switches and LEDs, I&#8217;m using one red NKK GB15JVC switch and one green NKK GB15JVF switch. The stock photo of one of these switches from digikey.com is shown above. These switches have built in LED illumination and light pipes, look great, and don&#8217;t occupy much board or front panel space.</p>
<h3>Power Supply</h3>
<div id="attachment_3412" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/schematic-power-supply.png"><img class="size-large wp-image-3412" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/schematic-power-supply-1024x372.png" alt="The 5V power supply for the microcontroller." width="640" height="233" /></a><p class="wp-caption-text">The 5V power supply for the microcontroller.</p></div>
<p>The simple access controller requires an external 12 volt power supply connected to a 2 position, 3.81 mm pitch Phoenix pluggable terminal block. An internal 5V DC/DC converter from CUI steps the 12 volts down to 5 volts to power the microcontroller. The 12V from the external power supply is made available on the reader connector to simplify and clean up the external wiring to the simple access controller.</p>
<h3>Programming and Debugging</h3>
<p>I&#8217;m using a Tag-Connect footprint with Microchip&#8217;s recommended debug circuit to program and debug the microcontroller.</p>
<h2>Board Design</h2>
<div id="attachment_3400" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/board-design.png"><img class="size-large wp-image-3400" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/board-design-1024x622.png" alt="The completed board design." width="640" height="389" /></a><p class="wp-caption-text">The completed board design.</p></div>
<p>The board is designed to fit in a Hammond 1455C801 extruded aluminum enclosure using the supplied black plastic bezels between the enclosure and end panels. If using the flanged 1455CF801 version of the enclosure, the connectors and switches need to be moved inward by 1.4 mm on each end of the board or a set of bezels needs to be modified to fit on the flanged enclosure.</p>
<p>Guides on the documentation layers indicate where the board slides into the card guides on the chassis. No components or vias are allowed in this region. A second set of guides indicate where the board intersects with the enclosure&#8217;s screw holes as it&#8217;s slid into the chassis. No tall components are allowed inside this region. On either end of the board design are a final set of guides that show where the end panels on the enclosure intersect with the components that extend past the edges of the board.</p>
<p>The power and relay connectors are on one end of the board. The switches and reader connector are on the other end of the board. There&#8217;s lots of space left on the board for other components if needed for future design iterations.</p>
<div id="attachment_3433" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/unstuffed-boards1.jpg"><img class="size-large wp-image-3433" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/unstuffed-boards1-1024x682.jpg" alt="The front and back of the fabricated boards." width="640" height="426" /></a><p class="wp-caption-text">The front and back of the fabricated boards.</p></div>
<p>The photo above shows the fabricated boards.</p>
<div id="attachment_3448" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/assembled-board.jpg"><img class="size-large wp-image-3448" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/assembled-board-1024x683.jpg" alt="The assembled board." width="640" height="427" /></a><p class="wp-caption-text">The assembled board.</p></div>
<p>The photo above shows an assembled board.</p>
<h2>Enclosure Design</h2>
<div id="attachment_3414" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/enclosure-end-panels.png"><img class="size-large wp-image-3414" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/enclosure-end-panels-1024x595.png" alt="The completed enclosure design." width="640" height="372" /></a><p class="wp-caption-text">The completed enclosure design.</p></div>
<p>I designed the end panels for the enclosure using Front Panel Express&#8217;s design software. After the panels were designed, I exported the board and panels to Fusion 360 to verify their fit. Once I was happy with how everything fit together, I ordered the panels from Front Panel Express.</p>
<div id="attachment_3446" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/end-panels-2.jpg"><img class="size-large wp-image-3446" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/end-panels-2-1024x575.jpg" alt="The fabricated end panels." width="640" height="359" /></a><p class="wp-caption-text">The fabricated end panels.</p></div>
<p>The photo above shows the fabricated end panels.</p>
<h2>Software</h2>
<div id="attachment_3417" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/PXL_20210804_024007514.jpg"><img class="size-large wp-image-3417" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/PXL_20210804_024007514-1024x576.jpg" alt="The debug setup for writing and testing the software for the simple access controller." width="640" height="360" /></a><p class="wp-caption-text">The debug setup for testing the hardware and writing the software for the simple access controller.</p></div>
<p>After assembling the board, it was time to start on the software. I wrote the software in three phases. The first phase was getting a timed main loop running that would blink a heartbeat LED periodically. The second phase was writing the interrupt driven code to receive and decode the Wiegand protocol. The third phase was comparing the received Wiegand data to a list of authorized cards and turning on the red LED if the card was not authorized and turning on the green LED and first relay if the card was authorized.</p>
<h3>Main loop and Heartbeat LED</h3>
<p>One of the first steps to bringing up just about any board is to get an LED blinking. This proves the debugger can talk to the microcontroller and that the oscillator and microcontroller are running. I like to blink the LED from the main loop and use a timer interrupt to control the rate of the main loop execution. This shows me that the main loop executes, interrupts work, and, by comparing the actual LED period to the expected LED period, I can ensure the oscillator is running at the correct frequency.</p>
<p>My code usually looks a bit like this early in the bring up phase:</p>
<pre>...

// 250 Hz timer 2 period value
// dec2hex(12e6/16/12/250-1)
#define TMR2_PERIOD 0xF9

// led states
#define LED_ON   0
#define LED_OFF  1

volatile uint8_t flag250 = 0;  

void main(void)
{
    // set up clocks and oscillators
    SYSTEM_Initialize ();

    // no analog I/O
    ANSELB = 0;
   
    // initialize LEDs to off
    LATBbits.LATB2 = LED_OFF;
    LATBbits.LATB4 = LED_OFF;
    TRISBbits.TRISB2 = 0;
    TRISBbits.TRISB4 = 0;
    
    // enable priority interrupts
    RCONbits.IPEN = 1;

    // configure TMR2
    TMR2_Initialize ();
    
    // enable interrupts
    INTCONbits.GIEH = 1;
    INTCONbits.GIEL = 1;

    while(1)
    {
        // run 250 Hz tasks
        if (flag250) {
            // clear flag
            flag250 = 0;
            
            // blink led or turn on for a while if not authorized
            if (ledTimer == 0) {
                LED1 = LED_ON;
            } else if (ledTimer == 25) {
                LED1 = LED_OFF;
            }

            // increment led timer counter, 1.0 second period
            if (++ledTimer &gt;= 250) {
                ledTimer = 0;
            }
        }
    } //end while
} //end main


void TMR2_Initialize (void)
{
    PR2 = TMR2_PERIOD;
    TMR2 = 0x00;
    IPR1bits.TMR2IP = 0;
    PIR1bits.TMR2IF = 0;
    PIE1bits.TMR2IE = 1;
    T2CON = 0x5E;
}


void __interrupt(low_priority) SYS_InterruptLow(void)
{
    if (PIE1bits.TMR2IE == 1 &amp;&amp; PIR1bits.TMR2IF == 1)
    {
        TMR2_InterruptHandler();
    }
}


void TMR2_InterruptHandler (void)
{
    PIR1bits.TMR2IF = 0;
    flag250 = 1;
}

...</pre>
<p>This code initializes the GPIO for the LED, turns the LED off, initializes a timer to generate an interrupt every 4 ms, then waits for flag250 to be set by the timer interrupt service routine. Once the flag is set, the main loop uses a the led_timer counter to turn on the led for 100 ms every second. Blink, blink!</p>
<h3>Decoding Wiegand Using the Interrupt on Change Pins and a Timer Interrupt</h3>
<div id="attachment_3365" style="width: 810px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/scope_2.png"><img class="size-full wp-image-3365" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/scope_2.png" alt="Scope traces while decoding Wiegand protocol. Yellow is a '0', green is a '1', blue is the decoded data, magenta is the timer expiring signalling the end of the data." width="800" height="632" /></a><p class="wp-caption-text">Scope traces while decoding Wiegand protocol. Yellow is a &#8216;0&#8217;, green is a &#8216;1&#8217;, blue is the decoded data, magenta is the timer expiring signalling the end of the data.</p></div>
<p>The next step in the project was to write the software to receive and decode the Wiegand data from the card reader. I&#8217;m using the PIC18&#8217;s interrupt on change feature and timer 0 to receive and decode the Wiegand data inside a few interrupt service routines. Once the complete card ID is received from the reader, the ISR sets a flag and gives the main loop a copy of the card ID to check.</p>
<p>The first step was to allocate some global variables for use by the interrupt service routines. The first four variables are used exclusively by the ISRs. The last two variables are used to pass the received card ID from the ISR to the main loop for checking against the list of authorized card IDs.</p>
<pre>// work variables for constructing card UID from card reader
uint8_t cbits = 0;
uint8_t newUidBit = 0;
uint8_t uidBits = 0;
uint8_t uidData[8];
uint8_t mainUidBits = 0;
uint8_t mainUidData[8];</pre>
<p>The next step was to add code inside main to initialize RC0 and RC1 as inputs and enable the interrupt on change interrupts on these two inputs:</p>
<pre>    // no analog I/O
    ANSELC = 0;
   
    // initialize W0, W1 as inputs
    TRISCbits.TRISC0 = 1;
    TRISCbits.TRISC1 = 1;
    
    // clear uid from card
    uidBits = 0;
    for (i = 0; i &lt; 8; i++) {
        uidData[i] = 0;
    }

    // enable iocc0 and iocc1
    IOCCbits.IOCC0 = 1;    // enable IOCC0
    IOCCbits.IOCC1 = 1;    // enable IOCC1
    cbits = PORTC;         // latch state
    INTCON2bits.IOCIP = 0; // low priority
    INTCONbits.IOCIF = 0;  // clear flag
    INTCONbits.IOCIE = 1;  // enable interrupt</pre>
<p>Then I needed to add some code to the low priority interrupt interrupt handler to dispatch to the IOC and TMR0 interrupt handlers based on the state of the interrupt enable and interrupt flag bits:</p>
<pre>    if (INTCONbits.IOCIE == 1 &amp;&amp; INTCONbits.IOCIF == 1) {
        IOC_InterruptHandler();
    }
    
    if (INTCONbits.TMR0IE == 1 &amp;&amp; INTCONbits.TMR0IF == 1) {
        TMR0_InterruptHandler();
    }</pre>
<p>Things start to get interesting inside the IOC interrupt handler. When an IOC interrupt occurs, the code reads PORTC and checks the state of the lower two bits. If RC1 and RC0 are both low, something is wrong because both lines should never be low in the Wiegand protocol. If they are low, we reset the UID receive routine and start over. If RC1 and RC0 are both high, that&#8217;s just the Wiegand protocol returning to the idle state between bits and we can safely ignore it. If only RC1 is low (it&#8217;s connected to the white &#8216;1&#8217; wire), we shift in a &#8216;1&#8217; bit into the current UID. If only RC0 is low (it&#8217;s connected to the green &#8216;0&#8217; wire), we shift in a &#8216;0&#8217; bit into the current UID. Finally, we clear the IOC interrupt flag bit.</p>
<pre>void IOC_InterruptHandler (void)
{
    cbits = PORTC;

    switch (cbits &amp; 3) {
        case 0:
            // both low is an error, reset the UID and start over
            ResetUID ();
            break;
        case 1: 
            // W1 is low and W0 is high, that's a '1'
            newUidBit = 1;
            ShiftUID ();
            break;
        case 2:
            // W1 is high and W0 is low, that's a '0'
            newUidBit = 0;
            ShiftUID ();
            break;
        case 3:
            // both high is a no operation
            break;
    }

    INTCONbits.IOCIF = 0;  // clear flag
}</pre>
<p>The UID reset routine sets the number of received bits to zero and clears the received UID.</p>
<pre>void ResetUID (void)
{
    uint8_t i;
    
    uidBits = 0;
    for (i = 0; i &lt; 8; i++) {
        uidData[i] = 0;
    }
}</pre>
<p>The shift routine increments the count of bits received and shifts the new UID bit into the 8 byte array holding the current UID. If the number of bits received exceeds 64, it clears the bit count, clears the UID, and starts over. After any bit is shifted in, the shift routine sets timer 0 to timeout at 4 ms. Since bits are received every 2 ms, the timeout timer will be restarted before timing out after every bit except for the last bit. After the last bit is received, the timer will time out after 4 ms and generate an interrupt.</p>
<pre>void ShiftUID (void)
{
    if (uidBits &gt;= 64) {
        ResetUID ();
    } else {
        uidBits++;
        
        uidData[7] = uidData[7] &lt;&lt; 1;
        uidData[7] |= (uidData[6] &amp; 0x80) ? 1 : 0;

        uidData[6] = uidData[6] &lt;&lt; 1;
        uidData[6] |= (uidData[5] &amp; 0x80) ? 1 : 0;

        uidData[5] = uidData[5] &lt;&lt; 1;
        uidData[5] |= (uidData[4] &amp; 0x80) ? 1 : 0;

        uidData[4] = uidData[4] &lt;&lt; 1;
        uidData[4] |= (uidData[3] &amp; 0x80) ? 1 : 0;

        uidData[3] = uidData[3] &lt;&lt; 1;
        uidData[3] |= (uidData[2] &amp; 0x80) ? 1 : 0;

        uidData[2] = uidData[2] &lt;&lt; 1;
        uidData[2] |= (uidData[1] &amp; 0x80) ? 1 : 0;

        uidData[1] = uidData[1] &lt;&lt; 1;
        uidData[1] |= (uidData[0] &amp; 0x80) ? 1 : 0;

        uidData[0] = uidData[0] &lt;&lt; 1;
        uidData[0] |= newUidBit ? 1 : 0;
    }
    
    // set data timeout timer to 4 milliseconds
    TMR0_Initialize ();
}</pre>
<p>Here&#8217;s the code to reset timer 0 to 4 ms and enable it and its interrupt if they&#8217;re not already enabled:</p>
<pre>// 4 ms timer 0 load / reload value
// dec2hex(65535-12e6/16/250) = 0xF447
#define TMR0_RELOAD_VALUE 0xF447

void TMR0_Initialize (void)
{
    T0CONbits.T08BIT = 0;
    TMR0H = TMR0_RELOAD_VALUE &gt;&gt; 8;
    TMR0L = TMR0_RELOAD_VALUE &amp; 0xFF;
    INTCON2bits.TMR0IP = 0;
    INTCONbits.TMR0IF = 0;
    INTCONbits.TMR0IE = 1;
    T0CON = 0x93;
}</pre>
<p>Finally, here&#8217;s the timer 0 interrupt handler. It clears the interrupt flag, disables the interrupt, disables the timer, and copies the received number of bits and the received UID into a second set of variables that are accessed by the main loop:</p>
<pre>void TMR0_InterruptHandler (void)
{
    uint8_t i;
    
    // clear flag, disable interrupt, and stop timer
    INTCONbits.TMR0IF = 0;
    INTCONbits.TMR0IE = 0;
    T0CONbits.TMR0ON = 0;

    if (uidBits &gt;= 26) {
        // forward UID to main loop for checking
        mainUidBits = uidBits;
        for (i = 0; i &lt; 8; i++) {
            mainUidData[i] = uidData[i];
        }
    }
    
    // get ready for next card scan
    ResetUID ();
}</pre>
<p>I&#8217;m not worried about race conditions between the ISR and the main loop code. When connected to a legitimate reader, the ISR code will take a minimum of 56 ms (2*26 for bits + 4 for timeout) to receive a UID. The main loop will always be done processing its copy of the UID within 4 ms.</p>
<div id="attachment_3365" style="width: 810px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/scope_2.png"><img class="size-full wp-image-3365" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/scope_2.png" alt="Scope traces while decoding Wiegand protocol. Yellow is a '0', green is a '1', blue is the decoded data, magenta is the timer expiring signalling the end of the data." width="800" height="632" /></a><p class="wp-caption-text">Scope traces while decoding Wiegand protocol. Yellow is a &#8216;0&#8217;, green is a &#8216;1&#8217;, blue is the decoded data, magenta is the timer expiring signalling the end of the data.</p></div>
<p>To debug the Wiegand receive routine, I used a four channel scope connected to the two Wiegand data lines and two unused output pins on the PIC. A screen capture from the scope after receiving a 32 bit UID from the reader is shown in the image above.</p>
<ul>
<li>Channel 1 is the yellow trace and was connected to the Wiegand &#8216;0&#8217; signal.</li>
<li>Channel 2 is the green trace and was connected to the Wiegand &#8216;1&#8217; signal.</li>
<li>Channel 3 is the blue trace. This trace was connected to the first unused output pin. It was set to a zero or a one based on the value of newUidBit inside ShiftUID. This allowed me to see when the IOC interrupt occurred and that the ShiftUID routine was shifting the correct bit value into the UID array.</li>
<li>Channel 4 is the magenta trace. This trace was connected to the second unused output pin. It was set high inside the timer 0 interrupt handler routine after the 4 ms timeout occured. This allowed me to verify the timeout was only occurring after the end of the UID data and it was happening in a timely fashion after the end of the UID data.</li>
</ul>
<h3>Checking Card Authorization and Controlling the LEDs and Relays</h3>
<p>The next step was to compare the received UID against a list of authorized UID&#8217;s compiled into the software. I defined a value with the number of authorized UID&#8217;s then added an array with 8 bytes for each authorized UID. I initialized the array with the UID&#8217;s of a sticker on my bike helmet and another sticker on my skateboard helmet. Both of these UID&#8217;s are only 32 bits.</p>
<pre>#define N_CARDS 2

const uint8_t authedUids[N_CARDS][8] = {
    { 0x12, 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00 }, // bike helmet
    { 0x12, 0x34, 0x56, 0x79, 0x00, 0x00, 0x00, 0x00 }  // skate helmet
};</pre>
<p>I added some code to the main loop that is executed every 4 ms. When the ISR sets the main loop&#8217;s copy of the received number of UID bits to a non-zero value, the code executes and looks for a match. If a match is found, the UID is authorized and the code:</p>
<ul>
<li style="text-align: left;">turns on the green LED</li>
<li style="text-align: left;">sets a timer to turn off the green LED after 1 second</li>
<li style="text-align: left;">turns on relay 1</li>
<li style="text-align: left;">sets a timer to turn off relay 1 after 1 second.</li>
</ul>
<p>If a match is not found, the UID is not authorized and the code:</p>
<ul>
<li>turns on the red LED</li>
<li>sets a timer to turn off the red LED after 1 second</li>
<li>the relay remains off.</li>
</ul>
<p>After checking for a match, the code clears its copy of the number of UID bits to zero so that it does not execute again until the next card number is received.</p>
<pre>            if (mainUidBits != 0) {
                // check card against valid cards
                notAuthorized = 1;
                for (card = 0; card &lt; N_CARDS; card++) {
                    uidAuthorized = 1;
                    for (i = 0; i &lt; 8; i++) {
                        if (mainUidData[i] != authedUids[card][i]) {
                            uidAuthorized = 0;
                        }
                    }
                    if (uidAuthorized) {
                        notAuthorized = 0;
                        RELAY1 = RELAY_ON;
                        LED2 = LED_ON;
                        relayTimer1 = 125;
                        goodUidTimer = 250;
                    }
                }
                mainUidBits = 0;
                if (notAuthorized) {
                    badUidTimer = 250;
                }
            }</pre>
<p>Finally here&#8217;s the code to control the red LED, the code to turn off the green LED after 1 second, and the code to turn off relay 0 after 0.5 seconds. The red LED normally blinks once per second except when an unauthorized card is presented in which case it lights steady for 1 second.</p>
<pre>            // blink led or turn on for a while if not authorized
            if (badUidTimer != 0) {
                LED1 = LED_ON;
                badUidTimer--;
            } else if (ledTimer == 0) {
                LED1 = LED_ON;
            } else if (ledTimer == 25) {
                LED1 = LED_OFF;
            }
            
            // turn on green led for a while if authorized
            if (goodUidTimer != 0) {
                LED2 = LED_ON;
                goodUidTimer--;
            } else {
                LED2 = LED_OFF;
            }
           
            // decrement relay 1 timer until it hits zero then turn off the relay
            if (relayTimer1 == 0) {
                RELAY1 = RELAY_OFF;
            } else {
                relayTimer1--;
            }</pre>
<h2>Assembly and Installation</h2>
<div id="attachment_3449" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/enclosure-unassembled.jpg"><img class="size-large wp-image-3449" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/enclosure-unassembled-1024x683.jpg" alt="All the part required to assembled the simple access controller." width="640" height="427" /></a><p class="wp-caption-text">All the part required to assembled the simple access controller.</p></div>
<p>With all the parts and pieces in house and the software finished, it was time to assemble the project. The big question is if the cut outs on the panels would align perfectly with the components on the circuit board.</p>
<div id="attachment_3450" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/enclosure-reader-side.jpg"><img class="size-large wp-image-3450" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/enclosure-reader-side-1024x683.jpg" alt="The reader side of the assembled project." width="640" height="427" /></a><p class="wp-caption-text">The reader side of the assembled project.</p></div>
<p>Tah-dah! The cut outs for the Phoenix connectors are maybe a bit high but the cut outs for the small circular illuminated pushbuttons are perfect. I could probably bend the connectors up a bit too but everything is close enough.</p>
<div id="attachment_3451" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/enclosure-power-side.jpg"><img class="size-large wp-image-3451" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/enclosure-power-side-1024x683.jpg" alt="The power and relay side of the assembled project." width="640" height="427" /></a><p class="wp-caption-text">The power and relay side of the assembled project.</p></div>
<p>The other end of the project. The connectors are for relay 1, relay 2, and power.</p>
<h3>Connecting to a Garage Door Opener Remote</h3>
<div id="attachment_3454" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/opener.jpg"><img class="size-large wp-image-3454" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/opener-1024x576.jpg" alt="The wireless garage door opener with a set of wires soldered across the pushbutton." width="640" height="360" /></a><p class="wp-caption-text">The wireless garage door opener with a set of wires soldered across the pushbutton.</p></div>
<p>I had two options for connecting to the garage door opener and controlling the garage door. The first would be to run a cable between the door opener and the simple access controller. The second would be to hack a door opener remote to allow it to be controlled by an external relay. I went with the latter. I&#8217;m out of cable staples and I was trying to minimize the amount of time spent on a latter in the garage.</p>
<p>I took apart the opener and tacked two bodge wires in parallel with the pushbutton switch inside the opener. I routed those wires outside the opener then connected them to a larger gauge and more robust wire. Once I confirmed the hack worked, I taped the whole thing up with black electrical tape to keep the wires from coming loose or breaking. The larger gauge wire is connected to a Phoenix pluggable screw terminal block that is plugged into the relay 1 connector on the simple access controller.</p>
<h3>Mounting Everything in the Garage</h3>
<div id="attachment_3453" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/installed.jpg"><img class="size-large wp-image-3453" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/installed-1024x576.jpg" alt="The assembled project installed inside the garage." width="640" height="360" /></a><p class="wp-caption-text">The assembled project installed inside the garage.</p></div>
<p>With everything tested, I mounted the garage door opener remote and the simple access controller to the wall just inside the garage and connected it to the HID Global card reader I previously mounted on the exterior of the house.</p>
<p>If you watch the video at the top of this post, you can see where I mounted the reader. I do not recommend mounting a reader in this location because it takes quite a bit of work to snake the reader&#8217;s pigtail through the headers around the garage door. In the case of my house, it was go through the headers or go through the brick. For better or worse, I went through the headers.</p>
<h2>Security</h2>
<p>Garage doors with openers are inherently insecure. They have both electronic and mechanical weaknesses. The rolling code remote control systems have long been hacked. Thieves know to reach in with a hanger and pull the emergency door release lever. The 24 to 37 bits of entropy provided by the typical RFID access control card is pretty good in comparison as long as you can prevent the card from being cloned. Newer RFID access control cards and readers address the eavesdropping and cloning issues with the older systems.</p>
<p>In the future, I could upgrade my system to use HID Global&#8217;s iClass SEOS cards and readers. This would prevent eavesdropping and cloning attacks but I&#8217;d have to trade the RFID sticker on the back of my helmet for a SEOS card or keyfob stuffed in my pack. If I wanted to stick with the cool helmet sticker, I&#8217;d have to implement my own authentication scheme with a PN532 reader and DESFire sticker which actually sounds like a pretty good future project. Speaking of which…</p>
<h2>Future Upgrades</h2>
<p>In the future, I might upgrade the reader and card to higher security devices. I&#8217;d also like to add some networking capabilities—either Ethernet with PoE or Wi-Fi. If the device were placed on the network, MQTT could be used to report scanned cards (both rejected and acceepted) to a logging system. A web browser interface could be used to enroll and delete authorized cards from memory. Finally, it&#8217;d be useful to have inputs to sense and report over MQTT when the door was closed, when the door was fully open, and when the door was somewhere between the two states.</p>
<h2>Final Word</h2>
<p>The goal with this project was to build something cool and useful and keep it as simple as possible. Achievement unlocked!</p>
<p><a href="https://bikerglen.com/wp/wp-content/uploads/2021/08/achievement-unlocked.png"><img class="alignnone size-full wp-image-3439" src="https://bikerglen.com/wp/wp-content/uploads/2021/08/achievement-unlocked.png" alt="achievement unlocked" width="820" height="154" /></a></p>
<h2>Design Files</h2>
<p>The design files for this project are on <a href="https://github.com/bikerglen/simple-access-controller">Github</a>.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/building-a-simple-rfid-door-access-controller/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PoE-Powered RGB LED Floodlight</title>
		<link>https://bikerglen.com/blog/poe-powered-led-floodlight/</link>
		<comments>https://bikerglen.com/blog/poe-powered-led-floodlight/#comments</comments>
		<pubDate>Sun, 02 Feb 2020 18:38:05 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[DMX / Art-Net]]></category>
		<category><![CDATA[Ethernet]]></category>
		<category><![CDATA[Lighting]]></category>
		<category><![CDATA[Microchip]]></category>
		<category><![CDATA[PIC18]]></category>
		<category><![CDATA[Power over Ethernet (PoE)]]></category>
		<category><![CDATA[RGB LED]]></category>

		<guid isPermaLink="false">https://bikerglen.com/blog/?p=2169</guid>
		<description><![CDATA[This project uses a Silvertel 802.3at Ag5300 PoE+ module with a built-in isolated 24 V DC/DC converter to power  a 10 W ColorKinetics ColorBurst 4 RGB LED floodlight. The Ethernet cable and light plug into a small power / control board and PoE+ powers the floodlight and Art-Net UDP packets control the light.  <a href="https://bikerglen.com/blog/poe-powered-led-floodlight/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div id="attachment_1977" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/IMG_20191217_224903-2000.jpg"><img class="size-large wp-image-1977" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/IMG_20191217_224903-2000-1024x682.jpg" alt="Philip Color Kinetics ColorBurst 4 10 watt RGB LED flood light controlled and powered over the network." width="640" height="426" /></a><p class="wp-caption-text">Philip Color Kinetics ColorBurst 4 10 watt RGB LED flood light controlled and powered over the network.</p></div>
<p>Time for another PoE project! This project uses a Silvertel 802.3at Ag5300 PoE+ module with a built-in isolated 24 V DC/DC converter to power  a 10 W ColorKinetics ColorBurst 4 RGB LED floodlight. The Ethernet cable and light plug into a small power / control board and PoE+ powers the floodlight and Art-Net UDP packets control the light. If this were a real product, the power / control board would be integrated into the fixture and the Ethernet cable would then plug directly into the back of the light.</p>
<p><span id="more-2169"></span></p>
<h2>The Silvertel Ag5300 PoE+ Module</h2>
<div id="attachment_2229" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/02/silvertel-module.jpg"><img class="size-large wp-image-2229" src="https://bikerglen.com/wp/wp-content/uploads/2020/02/silvertel-module-1024x683.jpg" alt="Silvertel Ag5324 PoE PD module with integrated isolated 24 V DC/DC converter." width="640" height="427" /></a><p class="wp-caption-text">Silvertel Ag5324 PoE PD module with integrated isolated 24 V DC/DC converter.</p></div>
<p>My previous PoE projects <a href="https://bikerglen.com/blog/ethernet-powered-pixels/">here</a> and <a href="https://bikerglen.com/blog/poe-vfd-tube-clock/">here</a> used a discrete Texas Instruments TPS2378 PoE+ classification IC and a Molex Ethernet jack with integrated magnetics and PoE+ classification circuitry. The TI TPS2378 is the lowest cost solution. The downside is it requires quite a other components to operate. The Molex jack is the highest cost solution but requires very few external components to operate.</p>
<div id="attachment_2224" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/02/three-solutions.png"><img class="size-large wp-image-2224" src="https://bikerglen.com/wp/wp-content/uploads/2020/02/three-solutions-1024x792.png" alt="Three different isolated PoE PD designs. The top left design uses a Molex Ethernet jack with integrated magnetics and PoE PD classification circuitry." width="640" height="495" /></a><p class="wp-caption-text">Three different isolated PoE PD designs. The top left design uses a Molex Ethernet jack with integrated magnetics and PoE PD classification circuitry. The bottom design uses an Ethernet jack, separate magnetics, and a TI PoE PD classification IC. The top right design, which is the design used in this project, uses an Ethernet jack, separate magnetics, and a Silvertel PoE module. The Silvertel module lies somewhere in the middle in terms of complexity. In the two more complicated designs, the transformer and Bob Smith termination network could be replaced with an Ethernet jack with integrated magnetics.</p></div>
<p>The Silvertel module sits somewhere in the middle of these other two solutions. It still requires a jack, magnetics, two bridge rectifiers, and a transient suppressor like the discrete TI solution, but, unlike the TI and Molex solutions, it includes an isolated 12 V or 24 V DC/DC converter. The integrated DC/DC converter can be a big cost savings and help to reduce the overall parts count.</p>
<h2>The Plan</h2>
<p>I have a box of Color Kinetics ColorBurst 4 lights sitting in my basement. These lights run from 24 volts, draw a maximum of 10 watts, and use a funky 24 volt version of the DMX-512 protocol. I tore down a larger <a href="https://bikerglen.com/blog/color-kinetics-colorburst-6-teardown/">ColorBurst 6 fixture a few years ago</a> which is very similar in design and operation to the ColorBurst 4.</p>
<div id="attachment_2232" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/02/pds-150e-cb4-setup.jpg"><img class="size-large wp-image-2232" src="https://bikerglen.com/wp/wp-content/uploads/2020/02/pds-150e-cb4-setup-1024x682.jpg" alt="A Color Kinetics PDS-150e power data supply next to a single ColorBurst 4 fixture." width="640" height="426" /></a><p class="wp-caption-text">A Color Kinetics PDS-150e power data supply next to a single ColorBurst 4 fixture.</p></div>
<p>These lights are normally powered and controlled using a Color Kinetics power data supply like the PDS-150e shown in the photograph above. The PDS-150e contains a 24 volt, 150 watt DC power supply powered from the AC mains and a microprocessor that can control the lights using a Color Kinetics proprietary Ethernet-based protocol or DMX-512. This power data supply can power and control up to 12 ColorBurst 4 lights.</p>
<div id="attachment_2217" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/giant-neopixels.jpg"><img class="size-large wp-image-2217" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/giant-neopixels-1024x576.jpg" alt="With enough of these fixtures in a row, they're almost like giant Neopixels!" width="640" height="360" /></a><p class="wp-caption-text">With enough of these fixtures in a row, they&#8217;re almost like giant Neopixels!</p></div>
<p>For this project, I&#8217;m going to replace the PDS-150e with a small power / control board that can directly power and control a single 10 watt ColorBurst 4 fixture from any 802.3at / PoE+ capable switch and an industry-standard Art-Net controller sitting anywhere on the network. I&#8217;ll use Synthe-FX&#8217;s Luminair 3 software running on an iPad Mini to send Art-Net packets to the board and control the light.</p>
<p>A Silvertel PoE module will handle the 802.3at classification and supply a regulated and isolated 24 volts for powering the fixture. A PIC18F67J60 will handle the data side of the project by accepting Art-Net packets and converting them to a serial DMX-512 stream to control the light. Finally, the project will use a line driver to step up the inverted 3.3 volt DMX-512 serial bitstream to a 24 volt version that is compatible with the fixture.</p>
<h2>The Schematic</h2>
<div id="attachment_2220" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/02/giant-pixpoe-schematic-page-1.png"><img class="size-large wp-image-2220" src="https://bikerglen.com/wp/wp-content/uploads/2020/02/giant-pixpoe-schematic-page-1-1024x681.png" alt="Schematic page one." width="640" height="426" /></a><p class="wp-caption-text">Schematic page one.</p></div>
<p>Page one of the schematic is shown above. It&#8217;s basically the same as page one of the schematic for the Ethernet-powered pixels project except the Texas Instrument PoE classification IC and the Cui 5 volt DC/DC converter have been replaced by the Silvertel Ag5324 PoE module.</p>
<div id="attachment_2221" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/02/giant-pixpoe-schematic-page-2.png"><img class="size-large wp-image-2221" src="https://bikerglen.com/wp/wp-content/uploads/2020/02/giant-pixpoe-schematic-page-2-1024x681.png" alt="Schematic page two." width="640" height="426" /></a><p class="wp-caption-text">Schematic page two.</p></div>
<p>Page two of the schematic is shown above. It&#8217;s basically the same as page two of the schematic for the Ethernet-powered pixels project except the WS2812 5 volt level shifter and ESD protection circuitry has been removed. In its place is a circuit reverse engineered from a Color Kinetics PDS-60 24 volt power supply to drive the 24 volt inverted DMX protocol to the ColorBurst 4 fixture from the microcontrollers&#8217; 3.3 volt output.</p>
<p>If you have questions about the parts used on this project, I highly recommend reviewing the <a href="https://bikerglen.com/blog/ethernet-powered-pixels/">Ethernet-powered pixels project</a>. It goes in-depth on the selection of parts used for that project, most of which are also used on this project.</p>
<h2>The Board Layout</h2>
<div id="attachment_2222" style="width: 949px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/02/giant-pixpoe-board-layout.png"><img class="size-full wp-image-2222" src="https://bikerglen.com/wp/wp-content/uploads/2020/02/giant-pixpoe-board-layout.png" alt="Finished board layout." width="939" height="562" /></a><p class="wp-caption-text">Finished board layout.</p></div>
<p>After finishing the schematic, I designed the circuit board. I attempted to place the components a bit closer together on this project versus the Ethernet-powered pixels project.</p>
<p>A primary concern while designing this board was to maintain at least 50 to 60 mils separation between the PoE power circuitry and the microcontroller circuitry. I don&#8217;t have the equipment to test whether this board layout successfully passes the 802.3 isolation requirements but with this separation, it at least stands a chance.</p>
<p>I ordered the boards from OSH Park and put together a bill-of-materials with their corresponding Digi-Key part numbers. Once I received notification that the boards had shipped from OSH Park, I ordered the parts from Digi-Key. This way I&#8217;d get the boards and the parts around the same time.</p>
<h2>Power Supply Bring Up</h2>
<div id="attachment_1971" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/more-poe-adventures.jpg"><img class="size-large wp-image-1971" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/more-poe-adventures-1024x575.jpg" alt="blah, blah, blah" width="640" height="359" /></a><p class="wp-caption-text">The PoE-powered RGB LED floodlight controller with the PoE and power supply circuitry populated.</p></div>
<p>After receiving the boards back from OSH Park, I brought up the PoE and power supply circuitry first. Since I learned on the Ethernet-powered pixels project not to put an LED across the rectified power from the Ethernet transformer, this board came up immediately. I used a DMM to verify the output of the Silvertel PoE module was 24 volts and I verified the board showed up as an unknown 802.3at / PoE+ device on my switch port.</p>
<h2>Microcontroller Bring Up</h2>
<div id="attachment_1960" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/GiantPixPoE-Top-2000.jpg"><img class="wp-image-1960 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/GiantPixPoE-Top-2000-1024x682.jpg" alt="circuit board with ethernet jack, magnetics, power supply, micrcontroller, and line driver stuffed." width="640" height="426" /></a><p class="wp-caption-text">The fully populated PoE-powered RGB LED floodlight controller board.</p></div>
<p>My parts order for the rest of the board arrived a bit late but I had enough parts on hand to populate the 3.3 volt power supply and the PIC18F67J60 microcontroller. I did not have the parts for the Ethernet signals or the 25 MHz oscillator so the Ethernet bring up would have to wait for later.</p>
<p>I created a new XC8 project in MPLAB X IDE that used the internal oscillator on the PIC to blink the four LEDs slowly in succession. This was enough software to verify the microcontroller could be programmed and debugged. I downloaded the software and the lights blinked exactly as expected.</p>
<p>Once the rest of the parts arrived, I populated the remainder of the board including the Ethernet circuitry, the SiTime MEMS 25 MHz oscillator, the EUI-48 serial EEPROM, and the 3.3 volt inverted serial to 24 volt inverted serial driver.</p>
<p>To verify the Ethernet circuitry worked, I downloaded the build of the software for the Ethernet-powered pixels project to this board. This build could not control the ColorBurst 4 LED floodlight but it would attempt to get an IP address using DHCP from my router which was enough functionality to verify the Ethernet circuitry functioned correctly.</p>
<p>When I plugged the board into my switch, the board powered up and received an IP address from my router. I noted that a new MAC address had appeared on my network and this MAC address was the same MAC address as the one programmed in the EUI-48. The Ethernet circuitry works!</p>
<p>The next step was to clone the software for the Ethernet-powered pixels project to a new project and modify the Art-Net UDP receive routine to send the first three channels of level data to the ColorBurst 4 fixture as DMX data. I wrote the quick DMX send routine shown below then downloaded the code to the board.</p>
<pre>        INTERRUPT_GlobalInterruptDisable();
        INTERRUPT_PeripheralInterruptDisable();
        
        // send break
        TRISCbits.TRISC6 = 0;
        LATCbits.LATC6 = 0;
        RCSTA1bits.SPEN = 0;

        __delay_us (88);

        // send mark after break
        RCSTA1bits.SPEN = 1;

        __delay_us (8);
        
        // send 0x00 followed by three art-net data bytes
        EUSART1_Write (0x00);
        EUSART1_Write (giantR);
        EUSART1_Write (giantG);
        EUSART1_Write (giantB);
        
        INTERRUPT_GlobalInterruptEnable();
        INTERRUPT_PeripheralInterruptEnable();</pre>
<p>I used an oscilloscope to verify the serial data ranged from 0 to 24 volts and the baud rate was correct. After that, I connected the ColorBurst 4 fixture to the board. The light powered up but did not respond to the levels set on my Art-Net controller. Using the scope I could see DMX packets being sent to the light with transmitted levels corresponding to the levels set by the Art-Net controller but the light did not respond.</p>
<p>Finally, I looked at the DMX-512 spec again. It requires two stop bits. The PIC18F67J60 doesn&#8217;t support two stop bits but it does support a 9-bit data transmission mode. I enabled the mode and set the 9th bit to always be a &#8216;1&#8217;. That generates a signal identical to a signal with two stop bits.</p>
<pre>        // enable 9 bit mode
        TXSTA1bits.TX9 = 1;
        TXSTA1bits.TX9D = 1;</pre>
<p>I downloaded the code to the board again and this time, success! The ColorBurst 4 responded as I varied the level sliders on my Art-Net controller software.</p>
<h2>Putting It All Together</h2>
<div id="attachment_1974" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/IMG_20191217_224700-2000.jpg"><img class="size-large wp-image-1974" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/IMG_20191217_224700-2000-1024x682.jpg" alt="blah, blah, blah" width="640" height="426" /></a><p class="wp-caption-text">The RGB LED floodlight being powered and controlled over the network. I&#8217;m using Luminair 3 by Synthe-FX on an iPad mini to send the Art-Net packets and control the LED fixture.</p></div>
<p>This project was successful. I could use software running on my iPad Mini to control the brightness and color of the light emitted by the ColorBurst 4 LED fixture and the fixture was powered using 802.3at PoE+ from my Ethernet switch.</p>
<p>A possible future iteration of this project might be to build my own RGB LED fixture, integrate the PoE+ power supply and Art-Net control circuitry in to the fixture, and design an enclosure to hold and cool everything. The enclosure would need to have a means for aiming it and securing it in position, a transparent or frosted window for the light, and an Ethernet jack on the back or bottom for powering and controlling the light.</p>
<div id="attachment_332" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2014/06/DSC_0824_2560.jpg"><img class="size-large wp-image-332" src="https://bikerglen.com/wp/wp-content/uploads/2014/06/DSC_0824_2560-1024x683.jpg" alt="Color Kinetics C200 RGB LED track fixtures hacked to be usable without the track." width="640" height="427" /></a><p class="wp-caption-text">Color Kinetics C200 RGB LED track fixtures hacked to be usable without the track.</p></div>
<p>Another thought would be to replace the control board in one of the older style Color Kinetics C-200 fixtures shown above with a board of my own design that includes PoE and controller functionality then cut a new rear panel for the light with just an opening for an Ethernet jack on it. This could be tricky depending on the amount of space available in the fixture.</p>
<h2>Design Files</h2>
<p>The design files for this project are on <a href="https://github.com/bikerglen/poe-ckcb4-floodlight">Github</a>. You can reach me about any missing files or other questions on Twitter <a href="https://twitter.com/bikerglen">@bikerglen</a>.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/poe-powered-led-floodlight/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PoE-Powered VFD Tube Clock</title>
		<link>https://bikerglen.com/blog/poe-vfd-tube-clock/</link>
		<comments>https://bikerglen.com/blog/poe-vfd-tube-clock/#comments</comments>
		<pubDate>Sat, 25 Jan 2020 00:54:24 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[Ethernet]]></category>
		<category><![CDATA[Microchip]]></category>
		<category><![CDATA[PIC18]]></category>
		<category><![CDATA[Power over Ethernet (PoE)]]></category>

		<guid isPermaLink="false">https://bikerglen.com/blog/?p=2079</guid>
		<description><![CDATA[This is a vintage VFD tube clock that uses Ethernet for both power and data. The power is provided using 802.3at PoE+ and a Molex PD Jack that contains both integrated magnetics and a PoE Type 2 PD controller. The IP stack runs on a Microchip PIC18F67J60 microcontroller that has an integrated Ethernet MAC and PHY. The IP stack includes DHCP, DNS, NTP, and LLDP functionality. <a href="https://bikerglen.com/blog/poe-vfd-tube-clock/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div id="attachment_2083" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/5.jpg"><img class="size-large wp-image-2083" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/5-1024x682.jpg" alt="The completed and assembled PoE-powered vintage VFD tube clock." width="640" height="426" /></a><p class="wp-caption-text">The completed and assembled PoE-powered vintage VFD tube clock.</p></div>
<p>This is a vintage VFD tube clock that uses Ethernet for both power and data. The power is provided using 802.3at PoE+ and a Molex PD Jack that contains both integrated magnetics and a PoE Type 2 PD controller. The IP stack runs on a Microchip PIC18F67J60 microcontroller that has an integrated Ethernet MAC and PHY. The IP stack includes DHCP, DNS, NTP, and LLDP functionality.</p>
<p><span id="more-2079"></span></p>
<p>The clock powers up and receives its IP address and a DNS server address via DHCP. LLDP is used to negotiate 7.5 Watts of power. The clock performs a DNS lookup to get an NTP server address from <a href="http://pool.ntp.org" target="_blank" rel="noopener noreferrer">pool.ntp.org</a>. Once the clock has the address of an NTP server, it uses NTP to set the date and time. With the date and time set, the clock displays the time using the 6 VFD tubes and three MIcrochip HV5812 high-voltage display drivers. Once an hour, the clock corrects any drift using NTP.</p>
<h2>Vacuum Fluorescent Displays</h2>
<div id="attachment_2096" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/DSC01131_2000px.jpg"><img class="size-large wp-image-2096" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/DSC01131_2000px-1024x682.jpg" alt="A modern vacuum fluorescent dot matrix character display module. Circa 2008." width="640" height="426" /></a><p class="wp-caption-text">A modern vacuum fluorescent dot matrix character display module circa 2008.</p></div>
<p><a href="https://en.wikipedia.org/wiki/Vacuum_fluorescent_display">Vacuum fluorescent displays</a> occupy a niche in history between their high-voltage Nixie predecessors and their expensive-at-the-time LED successors. They can be identified by their relatively fast response times, wide viewing angles, and characteristic blue-green glow.</p>
<p>The dual-axis inclinometer photo above shows a relatively modern vacuum fluorescent display. This display is a drop-in replacement for a character LCD module. It&#8217;s visible at night, in bright sunlight, and from any angle unlike the LCD it replaced. This display module is circa 2008. Thisinclinometer was built to show the pitch and roll of my Jeep long before vehicles included this features in their instrument clusters.</p>
<div id="attachment_2094" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/DSC01124_2000px.jpg"><img class="wp-image-2094 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/DSC01124_2000px-1024x682.jpg" alt="An IV-11 VFD tube from 1989 on the left and an IV-12 VFD tube from 1992 on the right." width="640" height="426" /></a><p class="wp-caption-text">An IV-11 VFD tube from 1989 on the left and an IV-12 VFD tube from 1992 on the right.</p></div>
<p>This clock project uses even older VFD tubes. The tubes are available in a variety of formats. In the photo above are two styles of VFD tubes. The tube on the left is an IV-11 display tube from 1989. The tube on the right is an IV-12 display tube from 1991. The only real difference between these tubes is the IV-11 on the left has a right-hand decimal point and wire leads while the IV-12 tube on the right lacks a decimal point altogether and has pins to mount the tube in a socket.</p>
<p>A Nixie tube requires 170 V DC to drive the tube&#8217;s anode. Vacuum fluorescent display tubes only require 25 V DC. As a result, they&#8217;re much easier to drive. Both tubes have a grid, a heater, and an anode per display segment. The electrical requirements for each are displayed in the table below:</p>
<table>
<tbody>
<tr>
<th></th>
<th>Volts</th>
<th>Minimum Current</th>
<th>Nominal Current</th>
<th>Maximum Current</th>
</tr>
<tr>
<td>Heater</td>
<td>1.5 V</td>
<td>90 mA</td>
<td>100 mA</td>
<td>110 mA</td>
</tr>
<tr>
<td>Grid</td>
<td>25 V</td>
<td>12 mA</td>
<td>&#8212;</td>
<td>17 mA</td>
</tr>
<tr>
<td>Anode / Display Segment</td>
<td>25 V</td>
<td>3 mA</td>
<td>&#8212;</td>
<td>5 mA</td>
</tr>
</tbody>
</table>
<p>With six tubes, the worst case heater current consumption is 6 tubes * 1.5 V * 0.110 A = 0.99 W. With six tubes, the worst case grid power consumption is 6 tubes * 25 V * 0.017 A = 2.55 W. With six tubes, the worst case segment power consumption is 6 tubes * 7 segments * 25 V * 0.005 A = 5.25 W. A six digit clock is then going to need a 1.5 V power supply capable of supplying 0.99 Watts and a 25 V power supply capable of supplying 7.8 Watts.</p>
<p>I decided to use the IV-12 tubes with the pins for sockets on their base. In the event of a mistake on one of my PCBs, I could unplug the tubes and re-use them on a corrected board. In the event of a failed tube, I could swap tubes on the project without significant PCB rework.</p>
<h2>VFD Tube PCB Footprint</h2>
<div id="attachment_2086" style="width: 528px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/iv-12_s.jpg"><img class="size-full wp-image-2086" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/iv-12_s.jpg" alt="This is the only IV-12 tube diagram I could find showing the positions of the pins on the bottom of the tube." width="518" height="478" /></a><p class="wp-caption-text">This is the only IV-12 tube diagram I could find showing the positions of the pins on the bottom of the tube.</p></div>
<p>After deciding on a tube to use for the clock project, the next step was to generate a schematic symbol and PCB footprint for the tube. I had a very hard time finding the diameter and spacing of the tube&#8217;s pins. I finally found a single low resolution image (reproduced above) on an eBay listing for the tubes. Of course, it doesn&#8217;t say if that&#8217;s a top or bottom view of the tube or which direction the front of the tube faces.</p>
<div id="attachment_2088" style="width: 600px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/iv-12-symbol.png"><img class="wp-image-2088 size-full" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/iv-12-symbol.png" alt="iv-12 symbol" width="590" height="284" /></a><p class="wp-caption-text">IV-12 VFD tube schematic symbol. I have no idea which anode pin corresponds to which display segment but I will be able to remap them in software so it doesn&#8217;t really matter.</p></div>
<p>I created a schematic symbol for the VFD tube. The left pin is the grid anode, the bottom two pins are the heater pins, and the top seven pins are the segment anodes.</p>
<p>After creating the schematic symbol, I created a PCB footprint for the part. I used the geometry from the data sheet and visual inspection of the base of the tube to create a Matlab / Octave script that creates an Eagle script to place the 11 pins and label them with their pin numbers. Here&#8217;s the Matlab / Octave code:</p>
<pre>first = -(180-(360-306)/2);
increment = +34;
count = 10;
radius = 11.9 / 2;
text_radius = radius - 2;
drill = 1.95;

fprintf (1, 'grid mm;\n');
fprintf (1, 'change align bottom-center;\n');
fprintf (1, 'change size 32mil;\n');
fprintf (1, 'change font vector;\n');
fprintf (1, 'change ratio 16;\n');
fprintf (1, 'change drill %5.2f;\n', drill);

for i=1:count
  angle = first + (i-1) * increment;
  x = cos (angle / 180 * pi);
  y = sin (angle / 180 * pi);
  xp = x * radius;
  yp = y * radius;
  xt = x * text_radius;
  yt = y * text_radius;
  at = 90 + angle;
  %fprintf (1, "%4d %8.4f %8.4f\n", angle, x, y);
  fprintf (1, "pad '%d' round 0 (%8.4f %8.4f);\n", i, xp, yp);
  if (angle &gt;= 0) 
    fprintf (1, "text '%d' sr%d (%8.4f %8.4f);\n", i, round(at), xt, yt);
  else
    fprintf (1, "text '%d' r%d (%8.4f %8.4f);\n", i, round(at), xt, yt);
  endif
endfor</pre>
<p>Running this code produces the following Eagle script:</p>
<pre>grid mm;
change align bottom-center;
change size 32mil;
change font vector;
change ratio 16;
change drill  1.95;
pad '1' round 0 ( -5.3015  -2.7012);
text '1' r-63 ( -3.5195  -1.7933);
pad '2' round 0 ( -2.8846  -5.2040);
text '2' r-29 ( -1.9150  -3.4547);
pad '3' round 0 (  0.5186  -5.9274);
text '3' r5 (  0.3443  -3.9350);
pad '4' round 0 (  3.7445  -4.6240);
text '4' r39 (  2.4858  -3.0697);
pad '5' round 0 (  5.6900  -1.7396);
text '5' r73 (  3.7774  -1.1549);
pad '6' round 0 (  5.6900   1.7396);
text '6' sr107 (  3.7774   1.1549);
pad '7' round 0 (  3.7445   4.6240);
text '7' sr141 (  2.4858   3.0697);
pad '8' round 0 (  0.5186   5.9274);
text '8' sr175 (  0.3443   3.9350);
pad '9' round 0 ( -2.8846   5.2040);
text '9' sr209 ( -1.9150   3.4547);
pad '10' round 0 ( -5.3015   2.7012);
text '10' sr243 ( -3.5195   1.7933);</pre>
<p>Running this script in the Eagle PCB library editor produced the bulk of the following footprint:</p>
<div id="attachment_2089" style="width: 479px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/iv-12-package.png"><img class="wp-image-2089 size-full" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/iv-12-package.png" alt="iv-12 package" width="469" height="479" /></a><p class="wp-caption-text">Finished IV-12 VFD tube PCB footprint.</p></div>
<p>After running the script,  I added an outline of the tube, labeled the front, and added some notes about which pins should be connected to which supplies. While researching this project, I came across one note that said the displays appeared brighter when 1.5 V is connected to pin 2 and ground is connected to pin 3 rather than the other way around. I did not verify that guidance but decided to follow it anyway.</p>
<p>The drills for the pads are 1.95 or 2.00 mm in diameter. These holes accommodate Harwin H3161-01 pin sockets for 1 mm pins. These are press fit into the holes in the PCB then soldered into place. The tube pins are 1 mm in diameter and fit in these pins easily. I used 1.95 mm drills on the clock but would use 2.00 mm drills on future versions.</p>
<h2>VFD Tube Socket Test Board</h2>
<div id="attachment_2091" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/IMG_20200102_180018_2000px.jpg"><img class="wp-image-2091 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/IMG_20200102_180018_2000px-1024x576.jpg" alt="IMG_20200102_180018_2000px" width="640" height="360" /></a><p class="wp-caption-text">Test board to verify the placement of the sockets and how well the tube fits in the sockets.</p></div>
<p>After designing the schematic symbol and PCB footprint, I created a small test board to verify the placement of the sockets and how well the tube fits in the sockets. I powered on a segment on the tube to verify the location of the ground, heater, grid, and segment pins. Everything fit so I knew I had a good PCB footprint to use on the final clock board.</p>
<p>I included a <a href="https://www.microchip.com/wwwproducts/en/HV5812">Microchip HV5812</a> high-voltage display driver and <a href="http://Texas Instruments SN74LVC8T245">Texas Instruments SN74LVC8T245</a> level shifter on the test board to test my circuit for controlling the tube but ultimately skipped testing the circuit before releasing the real boards.</p>
<h2>Designing the Clock</h2>
<h3>Mechanical Design</h3>
<div id="attachment_2105" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/DSC_2115_2000px.jpg"><img class="size-large wp-image-2105" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/DSC_2115_2000px-1024x681.jpg" alt="My six tube IN-18 Nixie tube clock from 2018." width="640" height="426" /></a><p class="wp-caption-text">My six tube IN-18 Nixie tube clock from 2018.</p></div>
<p>With the ground work out of the way, it was time to start designing the clock. I wanted to give it a similar aesthetic to the six-digit IN-18 Nixie tube clock shown above that I designed in 2018. The IN-18 clock uses a <a href="https://www.frontpanelexpress.com/housings">CNC&#8217;d anodized aluminum enclosure with some extruded aluminum profiles</a> on either end to hold everything together. The dimensions of the end profiles are shown in the diagram below.</p>
<div id="attachment_2110" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/profile1.png"><img class="size-large wp-image-2110" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/profile1-1024x593.png" alt="Front Panel Express enclosure profile #1 dimensions." width="640" height="371" /></a><p class="wp-caption-text">Front Panel Express enclosure profile #1 dimensions.</p></div>
<p>The &#8220;A&#8221; slots in the profiles are designed to hold 1.6 mm thick circuit boards. I wanted to decrease the depth and width of the VFD clock versus the Nixie clock. This would require using the slots in the profiles to hold the circuit board versus using screws through the top panel like I did on the Nixie clock. You can see the four screws to be eliminated on the top panel in the photo of the Nixie clock above.</p>
<h3>Electrical Design</h3>
<p>Next I turned my attention to the electrical hardware. The clock would require a microcontroller with Ethernet capable of using NTP to set the date and time, a display driver capable of sourcing 25 Volts, a bunch of power supplies, and use 802.3af/at for PoE/PoE+ for power.</p>
<h4>Microcontroller</h4>
<div id="attachment_2028" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/minimal-ethernet-circuit.png"><img class="size-large wp-image-2028" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/minimal-ethernet-circuit-1024x771.png" alt="PIC18F67J60 minimal Ethernet circuit." width="640" height="482" /></a><p class="wp-caption-text">PIC18F67J60 minimal Ethernet circuit.</p></div>
<p>I decided to use the <a href="https://www.microchip.com/wwwproducts/en/PIC18F67J60">Microchip PIC18F67J60</a> for a microcontroller. The Microchip PIC18F67J60 includes both an internal Ethernet MAC and PHY and the Microchip Code Configurator includes software libraries for NTP. Most importantly, I had good luck with this microcontroller on my <a href="https://bikerglen.com/blog/ethernet-powered-pixels/">Ethernet-Powered Pixels project</a>. This microcontroller requires a 3.3 V supply.</p>
<h4>Display Segment Driver</h4>
<div id="attachment_2112" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/hv5812-high-voltage-outputs.png"><img class="size-large wp-image-2112" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/hv5812-high-voltage-outputs-1024x931.png" alt="HV5812 high-voltage output configuration." width="640" height="582" /></a><p class="wp-caption-text">HV5812 high-voltage output configuration.</p></div>
<p>To drive the segments on the VFD tubes, I used a <a href="https://www.microchip.com/wwwproducts/en/HV5812">Microchip HV5812</a> 20-channel serial-input display driver. These display drivers have full totem-pole outputs and are rated for 80 V. The data sheet implies each output is capable of sourcing at least 25 mA. Since each segment requires only 3 to 5 mA at 25 V, these parts are more than adequate for driving the VFD tube segments. One HV5812 would be used for every two tubes.</p>
<p>The only downside is these parts require a 5 V supply and their inputs are referenced to this supply. If these parts were capable of running from 3.3 V, that would have eliminated the need for a 5 V power supply and level translator in this design.</p>
<h4>Power Supplies</h4>
<p>This design requires four power supply voltages. The tubes require 25 V and 1.5 V, the HV5812 drivers require 5 V, and the microcontroller requires 3.3 V. The 1.5 V, 3.3 V, and 5 V supplies will be powered from the 25 V supply. The 25 V supply will be powered from the 37 to 57 volt PoE supply.</p>
<p>I used CUI point-of-load, non-isolated DC/DC converters for the 1.5 V, 3.3 V, and 5 V supplies. The 3.3 V supply is a through-hole V7805-500 module. For the 1.5 V and 5 V supplies, I needed a shorter package than the V780x-500 and V780x-1000 modules so that the modules could fit between two boards separated by 11 mm. I used a V78E01-1000-SMT and V7805-500-SMT for the 1.5 V and 5 V supplies respectively. These are only 8.25 mm tall so they&#8217;ll easily fit between the two boards.</p>
<p>For the 25 V supply, I used a CUI PDQE20-Q48-S24-D isolated DC/DC converter. This module is a 24 V, 20 W converter and has a wide input voltage range of 18 to 75 V that will work with the PoE supply voltage of 37 to 57 V. This supply also has an adjustment input for fine tuning the voltage output. I ran through the math on the data sheet and figured with a resistor somewhere in the range of 55k, I could adjust the voltage output up to 25 V.</p>
<h4> 802.3af PoE / 802.3at PoE+ Power</h4>
<div id="attachment_2057" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-pd-devices.jpg"><img class="size-large wp-image-2057" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-pd-devices-1024x684.jpg" alt="A bunch of different PoE+ PD components including two Molex PD jacks, two TI TPS2378 ICs, a TI TPS2378 evaluation board, and a Silvertel PoE+ PD 24 VDC module." width="640" height="428" /></a><p class="wp-caption-text">A bunch of different PoE+ PD components including two Molex PD jacks, two TI TPS2378 ICs, a TI TPS2378 evaluation board, and a Silvertel PoE+ PD 24 VDC module.</p></div>
<p>For this project, I decided to use a <a href="https://www.molex.com/molex/products/datasheet.jsp;jsessionid=iF_MJ_iUK_6EHRKKXtnSSxIiYIpPB7SB6O8dgCzx.molex1?part=active/0857914020_MODULAR_JACKS_PLUG.xml">Molex 85791-4020 PD Jack</a> for the 802.3at / PoE+ functionality. This Ethernet jack contains both integrated magnetics and Type 2 / Class 4 PoE+ classification circuitry. This one jack, shown on the left in the photo above, replaces most of the components on the evaluation board shown in the top-right of the photo.</p>
<div id="attachment_2125" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/pd-jack-block-diagram.png"><img class="size-large wp-image-2125" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/pd-jack-block-diagram-1024x278.png" alt="Molex 85791-x020 PD Jack block diagram." width="640" height="174" /></a><p class="wp-caption-text">Molex 85791-x020 PD Jack block diagram.</p></div>
<p>The jack, in addition to the integrated Ethernet magnetics, contains all the circuitry required to perform 802.3at / PoE+ classification. This includes the bridge rectifiers, transient suppression diodes, detection capacitance, detection resistance, and an integrated <a href="https://www.microsemi.com/product-directory/poe-pd-front-end-w-pwm-controller/4783-pd70200">Microchip PD70200 PoE classification IC</a>. The block diagram from the datasheet is shown above. These jacks are bulky and expensive but for a one-off, hand-built prototype like this VFD clock, the reduction in parts count and assembly time was worth it to me.</p>
<h2>Power / Control Board Function Split</h2>
<div id="attachment_2123" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/block-diagram.png"><img class="size-large wp-image-2123" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/block-diagram-1024x521.png" alt="Block diagram of the clock project. The power / controller board contains the functions left of the dotted line. The tube / driver board contains the functions right of the dotted line." width="640" height="326" /></a><p class="wp-caption-text">Block diagram of the clock project. The power / controller board contains the functions left of the dotted line. The tube / driver board contains the functions right of the dotted line.</p></div>
<p>Based on my experience designing the Nixie IN-18 clock, I knew the tube sockets, segment drivers, microcontroller, and power supplies would not fit on a single board and a two board stack would be required to hold all the components.</p>
<p>I decided to place the PoE and microcontroller circuitry and the 25 V and 3.3 V power supplies on a power / controller board and the level translator, segment drivers, tube sockets, and 1.5 V and 5 V power supplies on a tube / driver board. The boards are connected together using headers. The headers supply 25 V, a SPI interface, and the reference voltage for the SPI interface from the power / controller board to the tube / driver board.</p>
<p>This split would prove advantageous during board bring up because the power / controller board contains everything needed to run the microcontroller and the tube / driver board contains everything needed to power and control the tubes with a single 25 V supply and a SPI interface.</p>
<h2>Tube / Driver Board Design</h2>
<h3>Schematic</h3>
<div id="attachment_2127" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/tube-board-page-1.png"><img class="size-large wp-image-2127" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/tube-board-page-1-1024x681.png" alt="Schematic of the tube / driver board." width="640" height="426" /></a><p class="wp-caption-text">Schematic of the tube / driver board.</p></div>
<p>The schematic for the tube / driver board is shown above. It consists of three main sections: power input, data input, and the tubes and drivers.</p>
<p>The main power input is 25 VDC on J1. This voltage feeds the 1.5 V and 5 V converters to generate the voltages needed for the tubes&#8217; heaters and the display drivers.</p>
<p>The data input on J2 consists of clock, data, latch, and blank signals. The logic levels of these signals are referenced to the voltage on J2-6 which can range from 1.8 to 5 V. In the case of our design, this is 3.3 V. This board could be used unmodified with a 5 V output microcontroller like the one on an Arduino by connecting J2-6 to +5 V instead of +3.3 V.</p>
<p>The tube drivers are Microchip HV5812 serial input high-voltage display drivers. The data signals are daisy chained between the three parts while the clock, latch, and blank signals are connected in parallel to all the parts. The tubes use the tube library symbol and footprint previously designed and tested on the tube socket test board.</p>
<h3>Board</h3>
<div id="attachment_2131" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/tube-board.png"><img class="size-large wp-image-2131" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/tube-board-1024x245.png" alt="Finished tube / driver board layout." width="640" height="153" /></a><p class="wp-caption-text">Finished tube / driver board layout.</p></div>
<p>Once the schematic was done, I designed a board in Eagle PCB. The tube pin sockets are located on the bottom of the board and the tubes extend into the screen with their fronts facing toward the bottom of the screen. The power supplies, display drivers, connectors and passives are located on the top of the board. After the design was done, the board&#8217;s width was extended to mount the board in the slots on the extruded aluminum profiles that form the sides of the enclosure.</p>
<div id="attachment_2132" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/e9bcbd5fe15f64bbe79c2febc33f3669.png"><img class="size-large wp-image-2132" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/e9bcbd5fe15f64bbe79c2febc33f3669-1024x207.png" alt="Tube board top." width="640" height="129" /></a><p class="wp-caption-text">Tube board top.</p></div>
<p>I uploaded the design files to OSH Park and checked the board renders. Above is a render of the top side of the board.</p>
<div id="attachment_2134" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/1319b0c1de78b8adad725ed08438f4dc.png"><img class="size-large wp-image-2134" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/1319b0c1de78b8adad725ed08438f4dc-1024x207.png" alt="Tube board bottom." width="640" height="129" /></a><p class="wp-caption-text">Tube board bottom.</p></div>
<p>Above is a render of the bottom side of the board. Once I was happy with the renders and had verified the boards and their components fit in the enclosure using Fusion 360, I placed an order for the boards at OSH Park.</p>
<h2>A Complication and Another Test Board</h2>
<div id="attachment_2139" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/pgood-test-board.jpg"><img class="size-large wp-image-2139" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/pgood-test-board-1024x683.jpg" alt="Open-drain, active-low power good to open-drain, active-low converter disable test board. Rated for 60 V operation." width="640" height="427" /></a><p class="wp-caption-text">Open-drain, active-low power good to open-drain, active-low converter disable test board. Rated for 60 V operation.</p></div>
<p>One wrinkle to be solved before designing the power / control board was how to connect the Molex PD jack&#8217;s open-drain, active-low power good signal to the 24 V DC/DC converter&#8217;s active-low converter disable input.</p>
<p>The PD jack pulls its power good output low to indicate that the power is good and the external DC/DC converter should be enabled. The DC/DC converter has a converter disable input that disables the converter when it is pulled low.</p>
<p>I needed a circuit that will hold the converter disable input low while the power good signal is not pulled low and will release the converter disable input when the power good signal is pulled low. And the only power supply rail available is the 37 to 57 V PoE power.</p>
<div id="attachment_2140" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/power-good-test-board-schematic.png"><img class="size-large wp-image-2140" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/power-good-test-board-schematic-1024x363.png" alt="Open-drain, active-low power good to open-drain, active-low converter disable test board schematic. Rated for 60 V operation." width="640" height="227" /></a><p class="wp-caption-text">Open-drain, active-low power good to open-drain, active-low converter disable test board schematic. Rated for 60 V operation.</p></div>
<p>I solved this problem by designing the circuit shown in the schematic above. Ignore R1, D1, C1, D3, and R4. When /PGOOD is open, it&#8217;s pulled high by R2. Zener diode D2 limits the voltage when /PGOOD is pulled high to 5.1 V so as not exceed Q1&#8217;s maximum VGS. In this case, Q1 conducts and connects the /CDB output to ground thus disabling the DC/DC converter. When /PGOOD is pulled low, the gate of Q1 is pulled low and Q1 stops conducting. The allows the /CDB output to float high and enables the DC/DC converter.</p>
<p>To test the circuit, I built a small test board. Only D2, R2, R3, and Q1 were stuffed on the test board. I connected the V+ and V- rails on the test board (TP1 and TP3 respectively) to a bench power supply set for 60 V. I connected the power outputs (TP4 and TP6) to the converter&#8217;s DC input and the /CDB output (TP5) to the converter&#8217;s converter disable input.</p>
<p>I then turned on the bench power supply and verified the converter&#8217;s output was disabled. After placing a jumper between /PGOOD (TP2) and V- (TP3), I verified the converter&#8217;s output was enabled. I disconnected and connected the jumper a few more times to verified the converter&#8217;s output was on only when the /PGOOD signal was connected to V-.</p>
<h2>Power / Controller Board Design</h2>
<h3>Schematic</h3>
<div id="attachment_2128" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/control-board-page-1.png"><img class="size-large wp-image-2128" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/control-board-page-1-1024x681.png" alt="First page of the schematic for the power / control board." width="640" height="426" /></a><p class="wp-caption-text">First page of the schematic for the power / control board.</p></div>
<p>After designing the tube board and verifying the converter enable/disable circuit, I designed the schematic for the power / control board. Page 1 of the schematic is shown above and page 2 of the schematic is shown below.</p>
<div id="attachment_2129" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/control-board-page-2.png"><img class="size-large wp-image-2129" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/control-board-page-2-1024x681.png" alt="Second page of the schematic for the power / control board." width="640" height="426" /></a><p class="wp-caption-text">Second page of the schematic for the power / control board.</p></div>
<p>This is basically the same circuit that I used for the <a href="https://bikerglen.com/blog/ethernet-powered-pixels/">Ethernet-powered pixels</a> project but with the following changes:</p>
<ol>
<li>Ethernet jack, magnetics, and PoE classification circuitry have been replaced by the Molex PD Jack.</li>
<li>The addition of the /PGOOD to /CDB active-low, open-drain inverter circuit.</li>
<li>The 5 V, 20 W converter is now a 24 V, 20 W converter and its adjustment pin is connected to a variable resistor to permit adjustment of the output voltage up to 25 V.</li>
<li>The 25 V and 3.3 V power rails, the SPI data and clock, and two GPIO signals are routed to header sockets that connect to the tube / driver board.</li>
</ol>
<p>After the schematic was complete I moved on to designing the board.</p>
<h3>Board</h3>
<div id="attachment_2136" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/control-board.png"><img class="size-large wp-image-2136" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/control-board-1024x317.png" alt="Finished control board layout." width="640" height="198" /></a><p class="wp-caption-text">Finished control board layout.</p></div>
<p>On the initial revision of the board, I had the power supply circuitry next to the Ethernet jack and the microcontroller on the right hand side of the board. I decided the Ethernet traces between the jack and the microcontroller were too long so I moved the microcontroller to the center of the board and moved the power supply circuitry to the right-hand side of the board.</p>
<p>The thick dashed white line is a 56 mil isolation gap between the PoE power circuitry and the isolated microcontroller circuitry. This board is less wide than the tube / driver board because it needs to fit between the extruded aluminum side profiles rather in the slots on the profiles.</p>
<div id="attachment_2135" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/ce289e122b221a78ad8664e465654bac.png"><img class="size-large wp-image-2135" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/ce289e122b221a78ad8664e465654bac-1024x236.png" alt="Controller board top." width="640" height="148" /></a><p class="wp-caption-text">Controller board top.</p></div>
<p>I uploaded the design files to OSH Park and checked the board renders. Above is a render of the top side of the board.</p>
<div id="attachment_2133" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/825885b0465ec7412896a6f7fe7fa5b8.png"><img class="size-large wp-image-2133" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/825885b0465ec7412896a6f7fe7fa5b8-1024x236.png" alt="Controller board bottom." width="640" height="148" /></a><p class="wp-caption-text">Controller board bottom.</p></div>
<p>Above is a render of the bottom side of the board. Once I was happy with the renders and had verified the boards and their components fit in the enclosure using Fusion 360, I placed an order for the boards at OSH Park.</p>
<h2>Enclosure Design</h2>
<div id="attachment_2066" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/clock-2-v11-cropped-jpg.jpg"><img class="size-large wp-image-2066" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/clock-2-v11-cropped-jpg-1024x683.jpg" alt="Rear view of the PoE-powered VFD tube clock enclosure." width="640" height="427" /></a><p class="wp-caption-text">Rear view of the PoE-powered VFD tube clock enclosure.</p></div>
<p>The enclosure was designed using Front Panel Express&#8217;s software, their enclosure design manual, and the side profile enclosure macros built into the software. Once the enclosure was designed, I exported DXF files from their software and imported them into Fusion 360.</p>
<p>Inside Fusion 360, I extruded the shapes in the DXF files into bodies with their actual thicknesses and assembled the enclosure. I used Eagle PCB&#8217;s integration with Fusion 360 to import my empty circuit boards into Fusion 360 and placed the boards in the enclosure. Rather than model all the components on the board, I placed only the larger components that I thought might cause interference with the boards or the enclosure.</p>
<div id="attachment_2148" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/clock-2-v11.png"><img class="size-large wp-image-2148" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/clock-2-v11-1024x819.png" alt="Enclosure design showing boards and their position in the enclosure." width="640" height="512" /></a><p class="wp-caption-text">Enclosure design showing boards and their position in the enclosure.</p></div>
<p>Above is an image captured in Fusion 360 showing the enclosure, the placement of the boards inside the enclosure, and the placement of the lager components on the boards. Once I was happy with the enclosure design, I ordered the panels from Front Panel Express.</p>
<h2>Enclosure Test Fit</h2>
<div id="attachment_2138" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/DSC01051-cropped.jpg"><img class="size-large wp-image-2138" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/DSC01051-cropped-1024x682.jpg" alt="Test fit of the enclosure panels, boards, and Ethernet jack." width="640" height="426" /></a><p class="wp-caption-text">Test fit of the enclosure panels, boards, and Ethernet jack.</p></div>
<p>After what seemed like an eternity, my enclosure panels and circuit boards arrived. I assembled the enclosure but left the front panel off then bolted the two boards together using M3 x 11 mm spacers and placed the Ethernet jack in its footprint on the power / control board. I slid the boards into the top slot of the enclosure and the Ethernet jack aligned perfectly with the cut out in the rear panel.</p>
<p>I failed to account for the tabs that OSH Park uses to panelize their customers&#8217; boards together though. I had to use a file to file down the tabs to get a smooth edge on all the boards for them to fit in the enclosure. Next time I would bring each of the two long edges in 0.25 mm (0.5 mm narrower total) to cut down on the amount of filing I had to do and account for OSH Park&#8217;s manufacturing tolerances.</p>
<h2>Tube / Driver Board Bring Up</h2>
<p><iframe src="https://www.youtube.com/embed/TnCH3Bg95Ik" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p>I decided to stuff and bring up the tube / driver board first. I populated the ICs, followed by the DC/DC converters, passives, and pin headers. While soldering these, I taped off the pin socket holes so I wouldn&#8217;t accidentally drag the iron across them and fill any of the holes with solder. Cleaning them out well enough to insert the socket pins would be difficult.</p>
<p>Once all the other parts were soldered on the board, I pushed the 60 pin sockets through the holes on the board. I had to use a make shift tool (broken chopstick) and some force to seat them in their holes. Next time, I&#8217;d use at least a 2.00 mm drill instead of a 1.95 mm drill for the holes to make inserting the pin sockets easier. Lastly, I soldered the pins in place.</p>
<p>To bring up and test the board, I used my Keysight bench power supply and a Particle Photon board. I set the bench power supply to supply 25 V at 100 mA and 5 V at 350 mA. I connected the 25 V to the power header on the tube / driver board and the 5 V to the micro USB connector on the Particle Photon.</p>
<p>I then connected the ground, SPI clock and data lines, and two GPIOs from the Particle Photon to the data connector on the tube board. I also connected the Particle Photon&#8217;s 3.3 V output to the 3.3 V input on the data connector to supply the input side of the level translator IC on the tube / driver board.</p>
<p>With the hardware connections complete, I turned to writing some software to permit the display of numeric strings on the tubes. The hardest part of this was mapping the 64 bits sent using the SPI interface to the 42 segments of the VFD tubes.</p>
<p>After figuring out the mapping, I wrote a function to display a numeric string on the tubes and registered it with the Particle Cloud. I could then use the Particle Console to send a string like &#8220;123456,&#8221; &#8220;&#8212;&#8212;,&#8221; or &#8220;******&#8221; to display on the tubes. Any character place with a &#8216;*&#8217; shows the spinning segments animation. The result of this effort is shown in the video above. Success!</p>
<h2>Power Supply Bring Up and Adjustment</h2>
<div id="attachment_2142" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/DSC01064-cropped.jpg"><img class="size-large wp-image-2142" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/DSC01064-cropped-1024x682.jpg" alt="Power supply bring up successful!" width="640" height="426" /></a><p class="wp-caption-text">Power supply bring up successful!</p></div>
<p>After bringing up the tube / driver board successfully, I decided it was time to focus on the PoE and power supply circuitry. I stuffed the PoE and power supply components on the power / control board and attached a DMM to the +24 V and ground test points.</p>
<p>I connected the board to my Ethernet switch. After a second or two, the LEDs lit indicating the 24 V and 3.3 V supplies were operating. I used a small screwdriver to adjust the 25-turn variable resistor until the DMM read 25 volts. I then moved the DMM to the +3.3 V test point and verified the 3.3 V supply was really 3.3 volts.</p>
<h2>Power / Control Board Bring Up</h2>
<div id="attachment_2143" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/4.jpg"><img class="size-large wp-image-2143" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/4-1024x682.jpg" alt="Power / control board microcontroller bringup successful!" width="640" height="426" /></a><p class="wp-caption-text">Power / control board microcontroller bring up successful!</p></div>
<p>Finally it was time to stuff the microcontroller and Ethernet parts on the power / control board. This is a tedious process because of the sheer number of passives. To aid in the process, I put the reference designators from the schematic in the customer data field when placing my Digi-Key order. This way each of the bags of passives was labeled with where they went on the circuit board. Genius.</p>
<p>After stuffing the board, I connected my MPLAB REAL ICE programmer and a 3.3 V serial cable to the board and downloaded the software from the Ethernet-powered pixels project to the board. I watched on the serial console as the board booted and obtained an IP address via DHCP from my router.</p>
<p>This was enough to prove almost all of the hardware worked. I connected the boards together and placed them inside the enclosure. I left the front of the enclosure off so that the serial cable and debugger could stay connected. It was all software now.</p>
<h2>The Software</h2>
<p><iframe src="https://www.youtube.com/embed/RXZ56NHuO3g" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p>I used the Microchip Code Configurator to build a new project for the PIC18F67J60 microcontroller. I enabled all the Ethernet protocols this time: DHCP, DNS, UDP, TCP, NTP, and LLDP. To make the code that handles the interaction between the display tubes and the IP protocols easier to follow, I moved some of the higher-level code that deals with the sequencing of DHCP, DNS, NTP, and LLDP operations out of the network_manage function and in to the main function.</p>
<p>At boot, the software initializes the microcontroller&#8217;s peripherals, turns all the VFD tube segments off, and reads its Ethernet MAC address from a <a href="https://www.microchip.com/wwwproducts/en/25AA02E48">Microchip 25AA02E48</a> serial EEPROM with built-in globally unique Ethernet MAC address. After initialization is complete, the software spins the segments on the tubes until an IP address and DNS server IP address are assigned to the clock using DHCP. The software then displays the IP address twice and the DNS server IP address twice. The video above shows an early version of the software that gets an IP address for the clock via DHCP and displays it three times.</p>
<p>While the IP addresses are scrolling, the software is performing a DNS query to pool.ntp.org to get the IP address of an NTP time server. Once received, the NTP server IP adresss is displayed and the NTP server is queried for the current date and time. The received date and time is set then updated once per second using the 25 MHz SiTime MEMS oscillator for the time base.</p>
<p>The software applies time zone and daylight savings time correction to the received time and scrolls that across the tubes. After two scrolls of the date and time, the clock goes into &#8220;be a clock&#8221; mode where it displays the current TZ and DST corrected time on the tubes until the next reboot. Once an hour, a new NTP server is requested from pool.ntp.org and the time is re-synchronized.</p>
<h2>The Finished Clock</h2>
<div id="attachment_2144" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/1.jpg"><img class="size-large wp-image-2144" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/1-1024x682.jpg" alt="Finished and assembled clock. Front view." width="640" height="426" /></a><p class="wp-caption-text">Finished and assembled clock. Front view.</p></div>
<p>Front view of the finished clock with the Ethernet cable connected.</p>
<div id="attachment_2145" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/2.jpg"><img class="size-large wp-image-2145" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/2-1024x682.jpg" alt="Finished and assembled clock. Rear view." width="640" height="426" /></a><p class="wp-caption-text">Finished and assembled clock. Rear view.</p></div>
<p>Rear view of the finished clock with the Ethernet cable connected.</p>
<div id="attachment_2147" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2020/01/3.jpg"><img class="size-large wp-image-2147" src="https://bikerglen.com/wp/wp-content/uploads/2020/01/3-1024x682.jpg" alt="Internal view of the clock with the debugger and serial console cable still connected." width="640" height="426" /></a><p class="wp-caption-text">Internal view of the clock with the debugger and serial console cable still connected.</p></div>
<p>Interior view of the finished clock with the Ethernet cable connected.</p>
<h2>Ideas for the Future</h2>
<p>I&#8217;m thinking about upgrading the power / control board to use an ATSAMD21 with the Wiznet W5500 Ethernet PHY/MAC. This processor would have enough power to allow the clock to make RESTful queries to NOAA and the NWS to display the current temperature or forecast temperatures in addition to the time. The PIC18F67J60 could make these queries too but the XML formatted responses might be tough to parse with the limited memory on the PIC18.</p>
<h2>Design Files</h2>
<p>The design files for this project are on <a href="https://github.com/bikerglen/poe-vfd-clock">Github</a>. You can reach me about any missing files or other questions on Twitter <a href="https://twitter.com/bikerglen">@bikerglen</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/poe-vfd-tube-clock/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>It&#8217;s an Ethernet-Powered Christmas Tree!</title>
		<link>https://bikerglen.com/blog/ethernet-powered-pixels/</link>
		<comments>https://bikerglen.com/blog/ethernet-powered-pixels/#comments</comments>
		<pubDate>Sun, 29 Dec 2019 20:45:21 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[DMX / Art-Net]]></category>
		<category><![CDATA[Ethernet]]></category>
		<category><![CDATA[Lighting]]></category>
		<category><![CDATA[Microchip]]></category>
		<category><![CDATA[PIC18]]></category>
		<category><![CDATA[Power over Ethernet (PoE)]]></category>
		<category><![CDATA[RGB LED]]></category>

		<guid isPermaLink="false">https://bikerglen.com/blog/?p=1979</guid>
		<description><![CDATA[The lighted tree in the video above gets both the power and data for its RGB LED pixels using a single Ethernet cable. Power for the pixels is supplied from an Ethernet switch using the 802.3at PoE+ standard. Data for &#8230; <a href="https://bikerglen.com/blog/ethernet-powered-pixels/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><iframe src="https://www.youtube.com/embed/0Oo144LTxu4" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe><br />
The lighted tree in the video above gets both the power and data for its RGB LED pixels using a single Ethernet cable. Power for the pixels is supplied from an Ethernet switch using the 802.3at PoE+ standard. Data for the pixels comes from software running on a PC that generates Art-Net packets at 40 Hz. Each Art-Net packet contains the RGB levels for all the pixels on the tree. Let&#8217;s take a closer look at the technical details and how this tree came into existence.</p>
<p><span id="more-1979"></span></p>
<h2>Motivation</h2>
<div id="attachment_1997" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/goalz.jpg"><img class="size-large wp-image-1997" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/goalz-1024x682.jpg" alt="Philips Color Kinetics iColor Flex LMX setup with the AC power data supply, proprietary leader cable, and 50 pixels." width="640" height="426" /></a><p class="wp-caption-text">Philips Color Kinetics iColor Flex LMX setup with the AC power data supply, proprietary leader cable, and 50 pixels.</p></div>
<p>A few weeks ago, I wrote a post where I <a href="https://bikerglen.com/blog/reverse-engineering-the-icolor-flex-protocol/">reversed engineered</a> some Philips Color Kinetics iColor Flex RGB LED string lights. These lights require an AC power data supply that supplies 24 volts to power the pixels and transforms DMX or UDP packets of pixel data into the protocol used by the pixels. In addition to the power supply, the pixels require a proprietary leader cable to connect them to the power supply.</p>
<p>In a typical setup, you have to run AC mains power and Ethernet data to the power supply then run the leader cable to the pixels. To avoid having a large stack of power data supplies in larger setups, Color Kinetics makes a rack mount power supply that can power up to eight strings of lights. This rack mount power supply still requires a leader cable for each string of lights.</p>
<p>I&#8217;ve been wanting to build an 802.3af/at/bt Power over Ethernet design for a few years now and have always come up short on ideas and then it hit me, what if the Ethernet cable could connect closer to the pixels in the photo above? With a small box of electronics between the Ethernet cable and the connector on the end of the pixels, the pixels could receive both power and data from the Ethernet switch. No more AC mains wiring and no more proprietary leader cables.</p>
<h2>802.3af/at/bt Power over Ethernet</h2>
<p>Many Power over Ethernet schemes involve connecting the spare pairs in an Ethernet cable to an always-on 12 VDC or 24 VDC power supply. At the other end of the Ethernet wiring, the spare pairs are connected to a DC/DC converter that generates the voltages required by the device. This is fraught with problems and is not real Power over Ethernet!</p>
<p>802.3af/at/bt Power over Ethernet only supplies power to a device once a device detection and classification process completes. This process is a hardware handshake between the power sourcing equipment (PSE) and the powered device (PD). During the handshake, the PSE communicates its power sourcing capabilities to the PD and the PD communicates its power requirements to the PSE. If the PSE is capable of supplying the amount of power required by the PD, power is connected to the PD.</p>
<p>While the PD is powered, the PSE continuously monitors the current draw of the PD. If the current draw drops too low for too long, the PSE assumes the PD was disconnected and shuts down power to the PD. This process ensures power is only supplied to standards-compliant devices and only while those devices are connected.</p>
<p>In addition to the hardware handshake, Power over Ethernet can use Link Layer Discovery Protocol (LLDP) to communicate a PD&#8217;s power requirement to the PSE with greater resolution than permitted by the hardware handshake. For example, a device could complete the handshake indicating it is an 802.3at PoE+ compliant device but use LLDP to tell the connected switch it only requires 20 watts instead of the maximum 25.5 watts. This can potentially reduce the number of Ethernet switches required in large installations if the switches do not need to assume every device will always consume its maximum power.</p>
<table class="wikitable">
<tbody>
<tr>
<th>Property</th>
<th>802.3af <span class="nowrap">(802.3at Type 1)</span> &#8220;PoE&#8221;</th>
<th><span class="nowrap">802.3at Type 2</span> &#8220;PoE+&#8221;</th>
<th><span class="nowrap">802.3bt Type 3</span> &#8220;4PPoE&#8221;</th>
<th><span class="nowrap">802.3bt Type 4</span></th>
</tr>
<tr>
<td>Power available at PD<sup id="cite_ref-25" class="reference"><a href="https://en.wikipedia.org/wiki/Power_over_Ethernet#cite_note-25">[note 1]</a></sup></td>
<td><span class="nowrap">12.95 W</span></td>
<td><span class="nowrap">25.50 W</span></td>
<td><span class="nowrap">51 W</span></td>
<td><span class="nowrap">71 W</span></td>
</tr>
<tr>
<td>Maximum power delivered by PSE</td>
<td><span class="nowrap">15.40 W</span></td>
<td><span class="nowrap">30.0 W</span></td>
<td><span class="nowrap">60 W</span></td>
<td><span class="nowrap">100 W</span></td>
</tr>
<tr>
<td>Voltage range (at PSE)</td>
<td><span class="nowrap">44.0–57.0 V</span></td>
<td><span class="nowrap">50.0–57.0 V</span></td>
<td><span class="nowrap">50.0–57.0 V</span></td>
<td><span class="nowrap">52.0–57.0 V</span></td>
</tr>
<tr>
<td>Voltage range (at PD)</td>
<td><span class="nowrap">37.0–57.0 V</span></td>
<td><span class="nowrap">42.5–57.0 V</span></td>
<td><span class="nowrap">42.5–57.0 V</span></td>
<td><span class="nowrap">41.1–57.0 V</span></td>
</tr>
<tr>
<td>Maximum current I<sub>max</sub></td>
<td><span class="nowrap">350 mA</span></td>
<td><span class="nowrap">600 mA</span></td>
<td><span class="nowrap">600 mA</span> per pair</td>
<td><span class="nowrap">960 mA</span> per pair</td>
</tr>
</tbody>
</table>
<p>The table above is copied from the <a href="https://en.wikipedia.org/wiki/Power_over_Ethernet">Wikipedia page</a> on Power over Ethernet. It shows the 4 main types of Power over Ethernet and the amount of power each is capable of delivering to a PD. Also shown are the voltages a PD will see at its Ethernet jack based on the voltage supplied by the PSE, the maximum current draw of the PD, and the maximum resistance in 100 meters of Cat 3 (Type 1) or Cat 5 (Type 2 to 4) Ethernet cabling.</p>
<p>Type 1 and Type 2 PoE can use either the 10/100 Mbps data pairs or the 10/100 Mbps spare pairs for supplying power. It&#8217;s up to the switch to decide which set of pairs so the powered device must support using either set. Type 3 and Type 4 PoE use all four pairs for supplying power. All four PoE types work with all speeds of Ethernet, 10/100 Mbps as well as 1/2.5/5/10 Gbps.</p>
<p>For more information on Power over Ethernet, I highly recommend the Power over Ethernet <a href="https://en.wikipedia.org/wiki/Power_over_Ethernet">Wikipedia page</a>, section 7.4.1 of the Texas Instruments TPS2378 IEEE 802.3at PoE+ Interface <a href="http://www.ti.com/lit/ds/symlink/tps2378.pdf">data sheet</a> (PDF), and the Silicon Labs Si3404/06x <a href="https://www.silabs.com/documents/public/application-notes/an1130-si3404-06x-dg.pdf">PoE-PD Controller Design Guide</a> (PDF).</p>
<h2>Feasibility and Scaling Back Ambitions</h2>
<div id="attachment_2002" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/box1-v4.png"><img class="size-large wp-image-2002" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/box1-v4-1024x819.png" alt="Artist's depiction of two Ethernet to iColor Flex PoE power data supplies." width="640" height="512" /></a><p class="wp-caption-text">Artist&#8217;s depiction of two Ethernet to iColor Flex PoE power data supplies.</p></div>
<p>Getting back to my design, I pictured a small box with a waterproof Ethernet connector on one end and an Amphenol LTW waterproof connector for the pixels on the other end like the boxes in the artist&#8217;s rendering above. Inside the box would be 802.3af/at/bt classification circuitry, a power supply capable of delivering 62 watts at 24 volts, a microcontroller with Ethernet, and an FPGA to generate the Chromasic protocol data for the lights.</p>
<p>Referring to the chart of PoE capabilities in the previous section on standards-compliant Power over Ethernet, supplying 62 watts to the iColor Flex lights would require using 802.3bt Type 4 PoE and having an efficiency exceeding 87%. I felt this was certainly technically feasible but a bit too ambitious for my first PoE design. I also do not have an 802.3bt capable Ethernet switch yet. Time to scale back my ambitions a bit.</p>
<p>The next thought was to scale back to using iColor Flex MX pixels that require 22.5 watts at 7.5 volts. This could be powered using 802.3at PoE which is capable of delivering 25.5 watts to the powered device. This would require being over 88% efficient and I&#8217;d have to design a 7.5 volt wide input range buck converter too. I still felt this was a bit too ambitious.</p>
<div id="attachment_2006" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixels.jpg"><img class="size-large wp-image-2006" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixels-1024x666.jpg" alt="A string of 50 RGB pixels on the left and a strip of 60 RGB pixles on the right." width="640" height="416" /></a><p class="wp-caption-text">A string of 50 RGB pixels on the left and a strip of 60 RGB pixels on the right.</p></div>
<p>The next step down in power consumption and complexity were the ubiquitous WS2812 RGB LEDs. Adafruit sells these in <a href="https://www.adafruit.com/product/1138?length=1">one meter strips of 60 RGB LEDs</a> and Light-O-Rama sells these as <a href="http://store.lightorama.com/50sqpi5vbl.html">five meter strings of 50 RGB pixels</a>. Both of these consume 60 mA per bulb at 5 volts which is 0.3 watt per LED. A strip of 60 Neopixels consumes 18 watts maximum. The string of 50 from Light-O-Rama consumes 15 watts maximum.</p>
<p>15 and 18 watts easily falls within the 25.5 watt maximum for <span class="nowrap">802.3at</span> PoE+. In addition, the WS2812 LEDs have significantly relaxed timing requirements compared to the iColor Flex LEDs. This allows the pixels to be controlled in software and eliminates the requirement for an FPGA to drive the pixels. Finally, the pixels run from 5 VDC. Since 5 VDC isolated switching DC/DC converter modules are common, I will not need to design a custom power supply as part of the project.</p>
<p>Over the course of a few hours, I talked myself down from building an 802.3bt 62 watt PD with an FPGA in a waterproof enclosure to building a much simpler proof-of-concept that uses 802.3at PoE+ for power and controls up to 60 WS2812 pixels in software. WS2812 pixels will be a great starting point for a project that can both power and control a string or strip of lights over Ethernet.</p>
<h2>Electrical Isolation</h2>
<p>The 802.3af/at/bt PoE standards require electrical isolation between the power interface and all user-accessible conductors including the frame ground. In a large commercial building, there could be 100 meters of Ethernet cable between the switch and the powered device with the result that the grounds at each end of the Ethernet cable have a large voltage difference between them. Without isolation, current would flow over the Ethernet cable which is both a safety issue and an electrical noise issue.</p>
<p>A lot of designs like PoE-enabled network cameras, Wi-Fi access points with internal antennas, and ceiling troffer LED lights have no user accessible conductors and therefore can use a non-isolated design. In this case, the enclosure and the lack of user-accessible conductors acts as the isolation required by the standard.</p>
<p>Other designs like Wi-Fi access points with external antenna connectors or building access controls with connections for locks and card readers require an isolated design. My design is going to have a connector for the WS2812 pixels so technically it requires an isolated design.</p>
<p>For both isolated and non-isolated designs, the 802.3 Ethernet standards require a transformer between the Ethernet jack and the Ethernet PHY. For isolated PoE designs, isolation is also required in the board layout, in the feedback loop in the power supply circuit, and in any status indicators between the PoE classification circuitry and the microcontroller. Isolated designs are therefore more complicated and more expensive than non-isolated designs.</p>
<p>Isolated designs do have an advantage during development and testing though. Programmers, debuggers, logic analyzers, oscilloscopes, and other test equipment can be connected to the isolated portions of the design without risk to the user or equipment. With a non-isolated design (or to debug the power interface side of an isolated design), you might need a battery-powered laptop to connect the debugger to the microcontroller, high-voltage differential probes for an oscilloscope, or a handheld oscilloscope with isolated input channels.</p>
<h2>Design Requirements</h2>
<p>Taking into account the selected pixels and the need for an isolated PoE design, here&#8217;s the basic list of requirements for my design:</p>
<ul>
<li>Use standards-compliant 802.3at PoE+ classification circuitry.</li>
<li>Use less than 25.5 watts total power to stay within the 802.3at PoE+ power envelope.</li>
<li>Use an isolated power supply design capable of supplying 20 watts at 5 volts. 15 to 18 watts will be available for the WS2812 pixels. Two watts will be available for the support circuitry including the microcontroller.</li>
<li>Use transformers, optocouplers, and appropriate trace spacing to maintain isolation between the power interface circuitry and the remainder of the device.</li>
<li>Use an Ethernet-capable microcontroller to reduce parts count and design complexity.</li>
<li>Use easy to hand-solder SMD packages with no inaccessible pins, leads, or pads. One of these days, I&#8217;ll have to learn to solder/reflow DFN/QFN packages with exposed thermal pads, but I&#8217;m not there yet.</li>
</ul>
<h2>Selecting the PoE Controller</h2>
<div id="attachment_2057" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-pd-devices.jpg"><img class="size-large wp-image-2057" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-pd-devices-1024x684.jpg" alt="A bunch of different PoE+ PD components including two Molex PD jacks, two TI TPS2378 ICs, a TI TPS2378 evaluation board, and a Silvertel PoE+ PD 24 VDC module." width="640" height="428" /></a><p class="wp-caption-text">A bunch of different PoE+ PD components including two Molex PD jacks, two TI TPS2378 ICs, a TI TPS2378 evaluation board, and a Silvertel PoE+ PD 24 VDC module.</p></div>
<p>The 802.3af PoE standard was ratified in 2003 and the 802.3at PoE+ standard was ratified in 2009. The relative age of the standards means there&#8217;s tons of great PoE/PoE+ silicon and modules on the market.</p>
<p><a href="http://www.ti.com/power-management/power-over-ethernet-poe/overview.html">Texas Instruments</a>, <a href="https://www.analog.com/en/products/monitor-control-protection/power-over-ethernet-poe-interface-controllers/poe-powered-device.html#">Analog Devices</a>, <a href="https://www.microsemi.com/product-directory/power-over-ethernet/847-poe-pd-front-end-w-pwm-controller">Microchip Technology</a>, and <a href="https://www.silabs.com/power-over-ethernet/powered-devices">Silicon Labs</a> all make PoE PD controller silicon. All these chips handle classification. Many of these chips include integrated transistor switches to control power to the user&#8217;s circuitry. Some of these chips even include switch mode power supply controllers to step down the incoming voltage to the user&#8217;s required voltage.</p>
<p>Silvertel makes complete <a href="https://silvertel.com/poe-power-over-ethernet-html/">PoE modules</a> capable of delivering from 13W to 99W to a PD. These modules handle classification, isolation, and include a DC/DC converter to step the input voltage down to a more usable 12 or 24 volts. Molex even makes <a href="https://www.molex.com/molex/products/datasheet.jsp;jsessionid=05oiS64RT1IkXnHXuryno-eThRG8f2tOemOF-xbW.molex0?part=active/0857913020_MODULAR_JACKS_PLUG.xml">Ethernet jacks</a> with integrated magnetics and PoE/PoE+ classification circuitry. These jacks use the Microchip / Microsemi <span class=""><a href="https://www.microsemi.com/product-directory/poe-pd-front-end-w-pwm-controller/4783-pd70200">PD70200</a></span> controller.</p>
<div id="attachment_2024" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-pd-controller-circuit.png"><img class="size-large wp-image-2024" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-pd-controller-circuit-1024x227.png" alt="802.3at PoE+ powered device controller and classification circuit." width="640" height="142" /></a><p class="wp-caption-text">802.3at PoE+ powered device controller and classification circuit.</p></div>
<p>After reading datasheets for what felt like weeks, I settled on the TI TPS2378 802.3at PoE+ PD controller. It performs PoE+ detection and classification, includes an internal pass MOSFET with inrush current limiting, comes in a relatively easy to solder SOIC-8 package with an exposed thermal pad, and requires minimum external components.</p>
<p>The schematic above shows the basic circuit. Bridge rectifiers BR1 and BR2 rectify the voltage from the Ethernet jack since the input voltage is of unknown polarity. C1, L1, and L2 are an EMI/EMC filter. Zener diode D1 provides transient protection. C2 provides the minimum load capacitance required by the PoE specifications. R1 and R2 set the detection current and classification current respectively.</p>
<div id="attachment_2040" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/tps2378-startup.png"><img class="wp-image-2040 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/tps2378-startup-1024x775.png" alt="tps2378-startup" width="640" height="484" /></a><p class="wp-caption-text">TI TPS2378 startup sequence from the datasheet.</p></div>
<p>Figure 19 from section 7.4.3 of the TPS2378 datasheet (reproduced above) shows the detection, classification, inrush current limiting, and startup sequence. When the input voltage is between 1.4 and 10.9 volts, the TPS2378 generates a detection signature. Once the PSE sees the detection signature, the PSE supplies a voltage between 10.9 and 22 volts. This is the classification phase and the TPS2378 generates a classification current between 36 and 44 mA to indicate it is a 802.3at PoE+ Type 2 / Class 4 device. For 802.3at this step is performed twice with a mandatory return to the detection current between each classification pulse.</p>
<p>Once classification is complete, the PSE supplies full power to the PD and the TPS2378 turns on the internal pass MOSFET but in an inrush current limiting mode. This limits the input current to about 140 mA and allows the bulk capacitors in the downstream power supply circuit to charge. Once the current through the pass MOSFET drops below 125 mA, inrush current limiting is turned off, the converter disable pin is de-asserted, and the user&#8217;s circuitry can run.</p>
<p>If 802.3at/PoE+ classification was successful, the T2P pin will be asserted and the user&#8217;s circuitry can run at full power. If 802.3at/PoE+ classification was not successful, the T2P pin will be de-asserted and the user&#8217;s circuitry must stay within the 802.3af PoE power envelope.</p>
<h2>Selecting the Power Supplies</h2>
<div id="attachment_2026" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-power-supply-circuits.png"><img class="size-large wp-image-2026" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-power-supply-circuits-1024x568.png" alt="Isolated wide-input range to 5 VDC switching power supply module (top) and 3.3 VDC non-isolated switching power supply module (bottom)." width="640" height="355" /></a><p class="wp-caption-text">Isolated wide-input range to 5 VDC switching power supply module (top) and 3.3 VDC non-isolated switching power supply module (bottom).</p></div>
<p>The next step was to select an isolated DC/DC converter that has an input range of 37 to 57 VDC, a 5 VDC output, and a 20 watt power rating. The CUI PDQE20-Q48-S5-D meets these specifications. It has a nominal input voltage of 48 volts but works with a range from 18 to 75 volts. It is rated for 20 watts, is isolated, and has an efficiency of 90%. It comes in a 1&#8243; by 1&#8243; form factor module. The converter requires a 100 uF input capacitor and a 100 uF output capacitor for stable operation. It also has an active-low disable input that can be connected directly to the TPS2378&#8217;s CDB pin to keep the converter disabled until the bulk input capacitor is charged.</p>
<p>The microcontroller requires 3.3 VDC at about 250 mA. to operate. This is supplied by a CUI V7803-500 non-isolated switching regulator. It has an input range from 4.75 to 28 VDC and is connected to the output of the 5 VDC isolated converter. It requires a few capacitors to operate as well. I included a few LEDs to indicate the 5 VDC and 3.3 VDC power supplies are operational.</p>
<h2>Selecting the Ethernet Microcontroller</h2>
<div id="attachment_2028" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/minimal-ethernet-circuit.png"><img class="size-large wp-image-2028" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/minimal-ethernet-circuit-1024x771.png" alt="PIC18F67J60 minimal Ethernet circuit." width="640" height="482" /></a><p class="wp-caption-text">PIC18F67J60 minimal Ethernet circuit. Pay particular attention to Note 4 for Power over Ethernet applications.</p></div>
<p>The next step was to select a microcontroller to receive Art-Net UDP packets of pixel data and output the pixel data to the WS2812 LEDs. Most Ethernet microcontrollers only include Ethernet MAC functionality and require an external Ethernet PHY. The Microchip PIC18F67J60 microcontroller includes both an internal Ethernet MAC and PHY. This reduces the parts count and board area needed by the design.</p>
<p>The basic schematic from the data sheet is shown in the schematic above. I added some ESD protection circuitry as shown in the Microchip Ethernet of Everything <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/40001930A.pdf">reference design</a> (PDF). The PIC18F67J60 is limited to 10 Mbps Ethernet but sixty 24-bit WS2812 pixels updated at 40 Hz only require 57,600 bits per second of data to operate.</p>
<h2>Other Circuitry of Note</h2>
<p>Here&#8217;s a brief examination of some of the other circuitry in the design.</p>
<h3>Optically Isolated AT Classification Indicator</h3>
<div id="attachment_2044" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-t2p-isolation.png"><img class="size-large wp-image-2044" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-t2p-isolation-1024x401.png" alt="T2P flag isolation circuitry." width="640" height="251" /></a><p class="wp-caption-text">T2P flag isolation circuitry.</p></div>
<p>The TPS2378 asserts T2P low if 802.3at/PoE+ classification is successful. An optoisolator is used to isolate this signal and make it available to the microcontroller. When ISO_T2P is asserted low indicating the PD can draw up to 25.5 watts of power, the microcontroller can enable the WS2812 pixels.</p>
<h3>3.3 VDC to 5 VDC Level Translator for WS2812 LEDs</h3>
<div id="attachment_2045" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-ws2812-driver.png"><img class="size-large wp-image-2045" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-ws2812-driver-1024x485.png" alt="The 3.3 VDC to 5 VDC level translator and transient protection circuitry used to drive the WS2812 LEDs." width="640" height="303" /></a><p class="wp-caption-text">The 3.3 VDC to 5 VDC level translator and transient protection circuitry used to drive the WS2812 LEDs.</p></div>
<p>The microcontroller has 3.3 VDC outputs but the WS2812 LEDs have inputs referenced to 5 VDC. These generally work ok from 3.3 VDC but I added a Texas Instruments Little Logic single gate buffer to translate the 3.3 VDC output from the microcontroller up to 5 VDC. The resistor and diode array protect the microcontroller and buffer from transients on the WS2812 data line.</p>
<h3>SiTime MEMS Oscillator</h3>
<p>I&#8217;m using a <a href="https://www.sitime.com/products/automotive-high-temp-oscillators/sit2024">SiTime MEMS oscillator</a> to generate the 25 MHz clock for the microcontroller. This oscillator comes in a small but still easy-to-solder SOT23-5 package. Digi-Key programs them to the purchaser&#8217;s needed frequency on demand or you can buy a stock of blank parts and use the SiTime programmer to program them as needed.</p>
<h3>Globally Unique MAC Address</h3>
<p>Purchasing a block of MAC addresses for maker projects is not feasible. Instead I&#8217;m using a <a href="https://www.microchip.com/design-centers/memory/serial-eeprom/mac-address-and-unique-id-eeproms">Microchip EUI-48 serial EEPROM</a> that contains a pre-provisioned, globally-unique, and write-protected MAC address. The alternative for devices that will not be used outside your local network is to use a locally administered address from one of the <a href="https://serverfault.com/questions/40712/what-range-of-mac-addresses-can-i-safely-use-for-my-virtual-machines">locally administered address pools</a>.</p>
<h2>Finished Schematic</h2>
<p>Here is the finished schematic. It&#8217;s two pages. Page 1:</p>
<div id="attachment_2048" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixpoe-schematic-page-1.png"><img class="size-large wp-image-2048" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixpoe-schematic-page-1-1024x682.png" alt="Finished schematic, page one." width="640" height="426" /></a><p class="wp-caption-text">Finished schematic, page one.</p></div>
<p>Page 2:</p>
<div id="attachment_2049" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixpoe-schematic-page-2.png"><img class="size-large wp-image-2049" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixpoe-schematic-page-2-1024x682.png" alt="Finished schematic, page two." width="640" height="426" /></a><p class="wp-caption-text">Finished schematic, page two.</p></div>
<h2>Finished Board</h2>
<div id="attachment_2050" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixpoe-board.png"><img class="size-large wp-image-2050" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixpoe-board-1024x607.png" alt="The finished board." width="640" height="379" /></a><p class="wp-caption-text">The finished board.</p></div>
<p>The image above shows the finished board. The thick dashed line shows the 56 mil space required to isolate the power interface circuitry on the left of the line from the user circuitry on the right of the line. The only components crossing the line are a filter capacitor rated for 2000 volts, the Ethernet magnetics, the T2P optocoupler, and the isolated DC/DC converter. All these parts provide DC isolation between the two halves of the board.</p>
<p>The next step was to upload the boards to <a href="https://oshpark.com/">OSH Park</a>, check the renders, and order the boards.</p>
<div id="attachment_2052" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixpoe-top.png"><img class="size-large wp-image-2052" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixpoe-top-1024x569.png" alt="OSH Park render of the top of the board." width="640" height="356" /></a><p class="wp-caption-text">OSH Park render of the top of the board.</p></div>
<p>The image above is an OSH Park render of the top of the board.</p>
<div id="attachment_2053" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixpoe-bottom.png"><img class="size-large wp-image-2053" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/pixpoe-bottom-1024x569.png" alt="OSH Park render of the bottom of the board." width="640" height="356" /></a><p class="wp-caption-text">OSH Park render of the bottom of the board.</p></div>
<p>The image above is an OSH Park render of the bottom of the board.</p>
<h2>Future Board Revisions</h2>
<p>While these boards were being manufactured, a helpful Twitter user pointed out some revisions I could make to improve the EMI/EMC performance and some other minor changes to the board. Here&#8217;s the list of changes for future board versions:</p>
<ul>
<li>Change PIC18 ground traces to vias to 9 mil width.</li>
<li>Change all other ground traces to vias to 20 mil width.</li>
<li>Change the 3.3 V bridges between 3.3 V fills to 20 mil width.</li>
<li>Change PIC18 pin 10 (VDDCORE) and 9 (GND) traces to 9 mil width.</li>
<li>Move PIC18 pin 9 (GND) via to far side of capacitor. Make the trace 20 mil wide.</li>
<li>Change TD_CT / filtered 3.3 V traces to 8 mil width between caps and PIC18.</li>
<li>Changed 5V trace to a pour / fill.</li>
<li>Increase separation of VPPIN to RTN to 25 mil per section 7.3.9 of TPS2378 data sheet.</li>
<li>More vias on thermal pad.</li>
<li>Use schottky diodes instead of bridge rectifiers for greater efficiency.</li>
<li>Investigate routing 3.3 V power on top layer and adding a ground fill / pour on the top layer stitched to the bottom layer.</li>
<li>Use jack with integrated magnetics or integrated magnetics and PD circuitry.</li>
<li>Improve isolation / spacing between power interface circuitry and frame ground.</li>
</ul>
<h2>Software Development</h2>
<div id="attachment_2055" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/olimex-pic-web.jpg"><img class="size-large wp-image-2055" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/olimex-pic-web-1024x684.jpg" alt="The Olimex PIC-WEB board I used for software development while waiting for my boards." width="640" height="428" /></a><p class="wp-caption-text">The Olimex PIC-WEB board I used for software development while waiting for my boards.</p></div>
<p>While the boards were being manufactured, I started software development using an <a href="https://www.olimex.com/Products/PIC/Development/PIC-WEB/">Olimex PIC WEB development board</a>. The Ethernet hardware and software on this board is functionally identical to the Ethernet hardware and software on my board so it was a good platform to use for software development until my boards were available.</p>
<h3>Microchip Code Configurator</h3>
<p>I created a new PIC18F67J60 project in the MPLAB X IDE then used the Microchip Code Configurator (MCC) to generate the basic timer, EUSART, and TCP/IP Ethernet code for the project.</p>
<p>In the system tab, I enabled TMR1 interrupts, assigned the EUSART1 TX1 and RX1 pins, and configured an external 25 MHz clock on the primary OSC pins. In the libraries tab, I added the TCP/IP Lite library and enabled the UDP, DHCP, IPV4, ICMP, and ARP protocols. In the MAC tab, I selected ETHxxJ6x since I&#8217;m using the Ethernet MAC built into the device. I also configured a locally administered MAC address until I had an opportunity to enable the EUI-48 serial EEPROM. I added the TMR1 and EUSART1 peripherals then enabled the TMR1 interrupt to occur every 40 ms and the callback function to be called once per second. The EUSART was configured for 9600 bps and STDIO was redirected to USART. I clicked the generate tab to generate the initial code base.</p>
<p>Once the code was generated, I opened up main.c, removed the comments to enable interrupts, and added a call to Network_Manage () inside the while loop inside the main function. I built the project and downloaded it to the PIC-WEB board. It started running and eventually grabbed an IP address from my DHCP server. At this point I could ping the board but that&#8217;s about it.</p>
<h3>Adding Art-Net UDP Receive</h3>
<p>Next I added code to receive Art-Net packets over the network to the project. I created a udp_rx_artnet.h file with the following code:</p>
<pre>#ifndef _UDP_RX_ARTNET_H
#define _UDP_RX_ARTNET_H

void UdpRxArtNetInit (void);
void UdpRxArtNetRecv (int16_t length);

#endif    //_UDP_DEMO_H</pre>
<p>Then I created a udp_rx_artnet.c file with the following code:</p>
<pre>#include &lt;stdint.h&gt;
#include "udp_rx_artnet.h"
#include "ws2812b.h"
#include "mcc_generated_files/TCPIPLibrary/udpv4.h"
#include "mcc_generated_files/TCPIPLibrary/tcpip_config.h"
#include "mcc_generated_files/pin_manager.h"


void UdpRxArtNetInit (void)
{
    // nothing to do here
}


void UdpRxArtNetRecv (int16_t length)
{
    uint8_t i;
    uint8_t leds;
    uint8_t r, g, b;
    
    if (length &gt;= 18) {
        for (i = 0; i &lt; 18; i++) {
            UDP_Read8 ();
        }
        
        length = length - 18;
        if (length &gt; NUM_CHANS) {
            length = NUM_CHANS;
        }
        leds = length / 3;
        length = 3 * leds;
        
        for (i = 0; i &lt; length; i+=3) {
            r = UDP_Read8 ();
            g = UDP_Read8 ();
            b = UDP_Read8 ();
            ledData[i+0] = gamma8[g];
            ledData[i+1] = gamma8[r];
            ledData[i+2] = gamma8[b];
            
        }
        
        for (; i &lt; 150; i++) {
            ledData[i] = 0;
        }
        
        WS2812b_Write ();
        printf ("+");
        LATEbits.LATE4 = ~LATEbits.LATE4;
    }
}</pre>
<p>It&#8217;s not the world&#8217;s most robust Art-Net receive code but it&#8217;ll work for proof of concept purposes. Next I added the UdpRxArtNetRecv function to the UDP callback table in MCC_Generated_Files/TCPIPLibrary/udpv4_port_handler_table.c:</p>
<pre>const udp_handler_t UDP_CallBackTable[] = \
{    
    {68, DHCP_Handler},     
    {0x1936, UdpRxArtNetRecv},
};</pre>
<p>Then inside main.c I added a call to UdpRxArtNetInit () to initialize the Art-Net receiver. I rebuilt the project and downloaded the code. (The first version of the code called printf&#8217;s to display the first few bytes of received RGB data rather than calling WS2812b_Write as shown in the listing above.) I then used my PC to generate Art-Net packets with 60 LEDs (180 channels) of data and send those to the PIC-WEB board. The printf&#8217;s showed the sent levels and it was time to move on to controlling the pixels.</p>
<h3>Controlling the Pixels</h3>
<p>In the past, I&#8217;ve used an FPGA to generate perfect WS2812 LED pixel timing. I did not use an FPGA on this project and instead used software to bit bang the protocol to the LEDs. Fortunately, the LEDs are quite tolerant to deviations from the timing specified in the data sheet and I had no issues controlling them.</p>
<p>The ws2812b.h header file:</p>
<pre>#ifndef WS2812B_H
#define    WS2812B_H

#ifdef    __cplusplus
extern "C" {
#endif

#define NUM_LEDS 60
#define NUM_CHANS (3*NUM_LEDS)
    
#define WS2812b_LAT LATBbits.LB2
#define WS2812b_TRIS TRISBbits.TRISB2

void WS2812b_Init (void);
void WS2812b_Write (void);

extern uint8_t ledData[NUM_CHANS];
extern const uint8_t gamma8[256];

#ifdef    __cplusplus
}
#endif

#endif    /* WS2812B_H */</pre>
<p>The ws2812b.c source file:</p>
<pre>#include &lt;stdint.h&gt;
#include "mcc_generated_files/mcc.h"
#include "ws2812b.h"


const uint8_t gamma8[] = {
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
    1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,
    2,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  5,  5,  5,
    5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,  9,  9, 10,
   10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
   17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
   25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
   37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
   51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
   69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
   90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
  115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
  144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
  177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
  215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };

uint8_t ledData[NUM_CHANS];


void WS2812b_Init (void)
{
    WS2812b_LAT = 0;
    WS2812b_TRIS = 0;
}


void WS2812b_Write (void)
{
    uint8_t i, j, a;
    
    INTERRUPT_GlobalInterruptDisable();
    INTERRUPT_PeripheralInterruptDisable();

    for (i = 0; i &lt; NUM_CHANS; i++) {
        a = ledData[i];

        // 7
        if (a &amp; 0x80) {
            WS2812b_LAT = 1;
            NOP();
            NOP();
            NOP();
            NOP();
        } else {
            WS2812b_LAT = 1;
            NOP();
        }
        WS2812b_LAT = 0;

        // 6
        if (a &amp; 0x40) {
            WS2812b_LAT = 1;
            NOP();
            NOP();
            NOP();
            NOP();
        } else {
            WS2812b_LAT = 1;
            NOP();
        }
        WS2812b_LAT = 0;

        // 5
        if (a &amp; 0x20) {
            WS2812b_LAT = 1;
            NOP();
            NOP();
            NOP();
            NOP();
        } else {
            WS2812b_LAT = 1;
            NOP();
        }
        WS2812b_LAT = 0;

        // 4
        if (a &amp; 0x10) {
            WS2812b_LAT = 1;
            NOP();
            NOP();
            NOP();
            NOP();
        } else {
            WS2812b_LAT = 1;
            NOP();
        }
        WS2812b_LAT = 0;

        // 3
        if (a &amp; 0x08) {
            WS2812b_LAT = 1;
            NOP();
            NOP();
            NOP();
            NOP();
        } else {
            WS2812b_LAT = 1;
            NOP();
        }
        WS2812b_LAT = 0;

        // 2
        if (a &amp; 0x04) {
            WS2812b_LAT = 1;
            NOP();
            NOP();
            NOP();
            NOP();
        } else {
            WS2812b_LAT = 1;
            NOP();
        }
        WS2812b_LAT = 0;

        // 1
        if (a &amp; 0x02) {
            WS2812b_LAT = 1;
            NOP();
            NOP();
            NOP();
            NOP();
        } else {
            WS2812b_LAT = 1;
            NOP();
        }
        WS2812b_LAT = 0;

        // 0
        if (a &amp; 0x01) {
            WS2812b_LAT = 1;
            NOP();
            NOP();
            NOP();
            NOP();
        } else {
            WS2812b_LAT = 1;
            NOP();
        }
        WS2812b_LAT = 0;
    }

    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();
}</pre>
<p>I placed the call to WS2812b_Write inside the Art-Net UDP receive function and a call to WS2812b_Init inside my main function. The lights did not work quite right on the first try. This code required an oscilloscope and a few tries to get the timing good enough to reliably control the LEDs. Eventually though, I could reliably control the LED colors and brightness from Art-Net UDP packets sent from either my PC or my iPad.</p>
<h3>Serial EEPROM and MAC Address</h3>
<p>The PIC-WEB board does not have an EUI-48 serial EEPROM so I had to use a locally administered MAC address for the initial software development. Once I got my boards back, I wrote some SPI code to read the MAC address from the serial EEPROM and use this address instead of the MAC address configured in the MCC generated header file.</p>
<p>spi1.h:</p>
<pre>#ifndef SPI1_H
#define    SPI1_H

#ifdef    __cplusplus
extern "C" {
#endif

void spi1_Init (void);
uint8_t spi1_ExchangeByte (uint8_t in);

#ifdef    __cplusplus
}
#endif

#endif    /* SPI1_H */</pre>
<p>spi1.c:</p>
<pre>#include &lt;xc.h&gt;
#include &lt;stdint.h&gt;
#include &lt;stdio.h&gt;
#include "spi1.h"

void spi1_Init (void)
{
    SSP1CON1bits.SSPEN1 = 0;

    TRISBbits.TRISB4 = 0; // e48 csb - output
    LATBbits.LATB4   = 1; // e48 csb - set to high / not asserted
    TRISCbits.TRISC3 = 0; // sck     - output
    TRISCbits.TRISC4 = 1; // miso    - input
    TRISCbits.TRISC5 = 0; // mosi    - output

    SSP1STATbits.CKE = 1;
    SSP1STATbits.SMP = 1;    
    SSP1CON1 = 0x02;
    SSP1CON2 = 0x00;
    SSP1CON1bits.SSPEN = 1;
}

uint8_t spi1_ExchangeByte (uint8_t data )
{
    SSP1BUF = data;
    while(!PIR1bits.SSP1IF);
    PIR1bits.SSP1IF = 0;
    return SSP1BUF;
}</pre>
<p>Finally the code to read the MAC address from the serial EEPROM.</p>
<p>mac_eeprom.h:</p>
<pre>#ifndef MAC_EEPROM_H
#define    MAC_EEPROM_H

#ifdef    __cplusplus
extern "C" {
#endif

#define MAC_ADDR_48                 0xFA
#define MAC_ADDR_64                 0xF8

/***************** 25AA02E48 Instruction Set Summary *********************/
#define MAC_EE_READ     0x03
#define MAC_EE_WRITE    0x02
#define MAC_EE_WRDI     0x04
#define MAC_EE_WREN     0x06
#define MAC_EE_RDSR     0x05
#define MAC_EE_WRSR     0x01

void e48_read_mac(uint8_t *mac);

#ifdef    __cplusplus
}
#endif

#endif    /* MAC_EEPROM_H */</pre>
<p>mac_eeprom.c:</p>
<pre>#include &lt;xc.h&gt;
#include &lt;stdint.h&gt;
#include &lt;stdio.h&gt;
#include "spi1.h"
#include "mac_eeprom.h"

// e48_Csb on RB4
// SCK on SCK1/RC3
// MISO on SDI1/RC4
// MOSI on SDO1/RC5

void e48_read_mac(uint8_t *mac)
{
    uint8_t i;
    
    // set cs low
    LATBbits.LATB4   = 0;
    
    spi1_ExchangeByte (MAC_EE_READ);
    spi1_ExchangeByte (MAC_ADDR_48);
    
    for (i = 0; i &lt; 6; i++) {
        mac[i] = spi1_ExchangeByte (0x00);
    }
    
    // set high low
    LATBbits.LATB4   = 1;
    
    // printf("macAddr:%.2X:%.2X:%.2X:%.2X:%.2X:%.2X \r\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
}</pre>
<p>That&#8217;s a brief summary of the code I have written for this project to date. Eventually, I will need to add LLDP to specify the power requirements of my board with a bit more granularity. A follow on project may require HTTP requests and NTP as well.</p>
<h2>Bring Up and Testing</h2>
<div id="attachment_1972" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-works.jpg"><img class="size-large wp-image-1972" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-works-1024x576.jpg" alt="Bringing up the PoE+ PD circuitry and power supplies." width="640" height="360" /></a><p class="wp-caption-text">Bringing up the PoE+ PD circuitry and power supplies.</p></div>
<p>Once the boards arrived, I mounted the components required for PoE+ classification and the power supplies to the board as shown in the photo above. Initially the PoE classification failed every time. The switch would try twice about every three seconds. Some LEDs on the board would light briefly but classification would fail and the power supplies would not be turned on.</p>
<p>Eventually I traced the problem to a resistor and an LED I put across the output of the bridge rectifiers to try to indicate when the switch was supplying power to the board. <strong>This does not work.</strong> The current consumed by the LED in parallel with the detection and classification currents is not within the specs required for the detection and classification currents.</p>
<p>I removed the resistor and LED then detection and classification completed successfully. The 802.3at / PoE+ T2P LED lit then the 5 VDC and 3.3 VDC power supply LEDs lit. I used a multimeter to measure the 5 VDC and 3.3 VDC outputs. They were in spec so I proceeded to mount the microcontroller and the rest of the components.</p>
<div id="attachment_2062" style="width: 866px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-alive.png"><img class="size-full wp-image-2062" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/poe-alive.png" alt="My switch indicating the board is receiving power and has a valid IP address. This was before I was using the EUI-48 serial EEPROM to configure a MAC address." width="856" height="353" /></a><p class="wp-caption-text">My switch indicating the board is receiving power and has a valid IP address. This was before I was using the EUI-48 serial EEPROM to configure a MAC address.</p></div>
<p>Once the rest of the components were mounted, I downloaded the software I developed using the Olimex PIC-WEB board to my board. Everything more or less worked perfectly! My network switch indicated the power advertised by the board, the power consumed by the board, and the IP address assigned to the board by the DHCP server.</p>
<p>There were some small tweaks to the software that came later like adding code to get a real MAC address from the serial EEPROM and adding code to turn LEDs on and off to indicate the status of the DHCP client and when an Art-Net packet was received.</p>
<div id="attachment_1973" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/IMG_20191207_120244-2000.jpg"><img class="size-large wp-image-1973" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/IMG_20191207_120244-2000-1024x682.jpg" alt="Completed board with a one meter strip of 60 WS2812 LEDs connected." width="640" height="426" /></a><p class="wp-caption-text">Completed board with a one meter strip of 60 WS2812 LEDs connected.</p></div>
<p>The photograph above shows the finished board driving a strip of 60 WS2812 LEDs. The power for the LEDs is delivered from an 802.3at / PoE+ capable network switch. The data for the LEDs comes from Art-Net packets generated by my PC.</p>
<div id="attachment_1962" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/PixPoE-Top-2000.jpg"><img class="size-large wp-image-1962" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/PixPoE-Top-2000-1024x682.jpg" alt="Photograph of the top of the completed board. " width="640" height="426" /></a><p class="wp-caption-text">Photograph of the top of the completed board.</p></div>
<p>Above is a close up photo of the top of the finished board.</p>
<div id="attachment_1961" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/PixPoE-Bottom-2000.jpg"><img class="size-large wp-image-1961" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/PixPoE-Bottom-2000-1024x682.jpg" alt="Photograph of the bottom of the completed board." width="640" height="426" /></a><p class="wp-caption-text">Photograph of the bottom of the completed board.</p></div>
<p>Above is a close up photo of the bottom of the finished board.</p>
<h2>Decorating the Tree</h2>
<div id="attachment_1963" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/LEDs.jpg"><img class="size-large wp-image-1963" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/LEDs-1024x682.jpg" alt="A circuit board in a (fake) pine tree." width="640" height="426" /></a><p class="wp-caption-text">A circuit board in a (fake) pine tree.</p></div>
<p>I initially used the one meter strip of sixty WS2812 pixels rather than the string of 50 pixels because the strip fit entirely on my desk and it was very easy to look and see if the pixels were displaying the patterns from my PC properly or not. Once the code was running properly, it was time to go bigger!</p>
<p>I grabbed the five meter string of 50 pixels and a cheap $20 fake tree from Michael&#8217;s and proceeded to string the lights on the tree. I stuffed the board in the tree then shot the quick video at the top of this post. I&#8217;m pretty sure the tree is not an ESD-safe location for the circuit board.</p>
<div id="attachment_2059" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/thumbnail.jpg"><img class="size-large wp-image-2059" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/thumbnail-1024x576.jpg" alt="The decorated tree." width="640" height="360" /></a><p class="wp-caption-text">The decorated tree.</p></div>
<p>Above is a thumbnail from the video showing the decorated tree in my home office.</p>
<h2>Future Power over Ethernet Projects</h2>
<div id="attachment_1977" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/IMG_20191217_224903-2000.jpg"><img class="size-large wp-image-1977" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/IMG_20191217_224903-2000-1024x682.jpg" alt="Philip Color Kinetics ColorBurst 4 10 watt RGB LED flood light controlled and powered over the network." width="640" height="426" /></a><p class="wp-caption-text">Philip Color Kinetics ColorBurst 4 10 watt RGB LED flood light controlled and powered over the network.</p></div>
<p>I have two more Power over Ethernet projects in progress. The first one is almost complete. It uses a Silvertel 24 volt isolated PoE+ module to power a Philips Color Kinetics ColorBurst 4 10-watt RGB LED flood light. Control data for the light comes from Synthe-Fx&#8217;s Luminair 3 software running on an iPad.</p>
<div id="attachment_2066" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/12/clock-2-v11-cropped-jpg.jpg"><img class="size-large wp-image-2066" src="https://bikerglen.com/wp/wp-content/uploads/2019/12/clock-2-v11-cropped-jpg-1024x683.jpg" alt="Rear view of the PoE-powered VFD tube clock enclosure." width="640" height="427" /></a><p class="wp-caption-text">Rear view of the PoE-powered VFD tube clock enclosure.</p></div>
<p>The second project is an IV-12 VFD tube display that gets both power and time or other data for display over the network. This second project uses one of the Molex Ethernet jacks with integrated magnetics and 802.3at PoE+ classification circuitry. This project is in progress. I&#8217;ve ordered the aluminum panels for the enclosure shown above but am waiting on my VFD tubes to arrive before ordering the circuit boards for the project.</p>
<h2>Design Files</h2>
<p>Design files for this project are in the <a href="https://github.com/bikerglen/pixpoe">PixPoE repository</a> in my github account. If anything&#8217;s missing or you have a question about something, you can find me on Twitter @bikerglen.</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/ethernet-powered-pixels/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PIC16F1459 USB Volume Knob</title>
		<link>https://bikerglen.com/blog/pic16f1459-usb-volume-knob/</link>
		<comments>https://bikerglen.com/blog/pic16f1459-usb-volume-knob/#comments</comments>
		<pubDate>Mon, 14 Oct 2019 17:18:23 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[3D Printing]]></category>
		<category><![CDATA[Microchip]]></category>
		<category><![CDATA[PIC18]]></category>
		<category><![CDATA[USB]]></category>
		<category><![CDATA[USB Human Interface Device (HID)]]></category>

		<guid isPermaLink="false">https://bikerglen.com/blog/?p=1607</guid>
		<description><![CDATA[The PIC16F1459 is proving to be quite the versatile part when it comes to building USB devices. Previously, I&#8217;ve used it to upgrade my giant keyboard, various flavors of one-key keyboards, a USB-controlled industrial stack light, and an annoying CAPS &#8230; <a href="https://bikerglen.com/blog/pic16f1459-usb-volume-knob/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div id="attachment_1600" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/usb-volume-knob-top.jpg"><img class="wp-image-1600 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/usb-volume-knob-top-1024x682.jpg" alt="The completed USB volume knob project. It uses an off-the-shelf knob and a PIC16F1459 microcontroller. The enclosure is 3D printed." width="640" height="426" /></a><p class="wp-caption-text">The completed USB volume knob. The 3D printed enclosure houses a custom board design, a PIC16F1459 microcontroller, and an optical encoder. The knob itself is an aluminum off-the-shelf component from TE Connectivity.</p></div>
<p>The PIC16F1459 is proving to be quite the versatile part when it comes to building USB devices. Previously, I&#8217;ve used it to upgrade my <a href="https://bikerglen.com/blog/building-a-giant-usb-three-key-mechanical-keyboard/">giant keyboard</a>, various flavors of <a href="https://bikerglen.com/blog/presenting-the-single-esc-key-usb-keyboard/">one-key keyboards</a>, a USB-controlled <a href="https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/">industrial stack light</a>, and an annoying CAPS LOCK <a href="https://bikerglen.com/blog/the-annoying-caps-lock-warning-buzzer/">warning buzzer</a>.  In this project, I&#8217;m going to use the PIC16F1459 to build a USB volume knob that works similarly to the volume keys on some USB keyboards. Read on to find out more about the design of the USB volume knob.</p>
<p><span id="more-1607"></span></p>
<h2>Enclosure Design</h2>
<h3>Design Inspiration and Criteria</h3>
<p>Believe it or not, I designed the enclosure for this project before I ever even thought about building a USB volume knob. A few months ago, I set out to to design a generic enclosure that was somewhat roomy that I could use for any small project. The volume knob just happened to be the first project to come along after designing the generic enclosure.</p>
<div id="attachment_1237" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/notch-connectors.jpg"><img class="size-large wp-image-1237" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/notch-connectors-1024x682.jpg" alt="Close up of the notch and connectors." width="640" height="426" /></a><p class="wp-caption-text">Close up of the notch and connectors.</p></div>
<p>I thought about enclosures I designed in the past and a few elements of two enclosures in particular struct me as unique and something I should bring forward to my generic enclosure design. The first was the round form factor and the rear panel notch on the USB <a href="https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/">stack light controller</a> base. These are shown in the photo of the stack light controller above.</p>
<div id="attachment_1147" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/side-view.jpg"><img class="size-large wp-image-1147" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/side-view-1024x683.jpg" alt="If you look closely, you can see the overlapping lips on each half of the enclosure in this photo." width="640" height="427" /></a><p class="wp-caption-text">If you look closely, you can see the overlapping lips on each half of the enclosure in this photo.</p></div>
<p>The second was the way the overlapping lips worked to seal the two halves of the <a href="https://bikerglen.com/blog/homebrew-rgb-led-light/">PIC24 DMX RGB light</a> together. If you look closely, you can see these in the photo of the light&#8217;s enclosure above.</p>
<p>After deciding on these key design elements, I narrowed down a few other design criteria:</p>
<ol>
<li>The enclosure should bolt together with 2-56 threaded black oxide screws and nuts.</li>
<li>The enclosure should be 0.75 inch tall since this was the largest commonly available 2-56 thread black oxide screw length.</li>
<li>The enclosure would be 60 mm in diameter.</li>
<li>The flat edge of the board that would accommodate any necessary connectors would be 24 mm wide. 24 mm easily allows for a micro USB connector or USB C connector plus a second small connector or reset button,</li>
<li>The enclosure walls would be 1.5 mm thick.</li>
<li>The circular overhangs above and below the notch would be 2 mm thick to imply the enclosure is thicker and sturdier than it really is.</li>
</ol>
<h3>Parametric Modeling</h3>
<div id="attachment_1625" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/parameters.png"><img class="size-large wp-image-1625" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/parameters-1024x601.png" alt="Parameters used to control the size of the enclosure." width="640" height="376" /></a><p class="wp-caption-text">Parameters used to control the size of the enclosure.</p></div>
<p>Since this was a generic enclosure being designed for a project that doesn&#8217;t exist yet, it&#8217;d be great to be able to resize the enclosure later based on the actual needs of the project. Fortunately Fusion 360 supports parametric modeling. With parametric modeling, you define a list of parameters and their values. Instead of specifying a fixed value when drawing a feature in the model, you use the name of the parameter instead. Now when you go back to the table and change the parameter&#8217;s value, the model will automatically update and resize based on the new value.</p>
<p>The list of parameters and their values I used for this enclosure is shown in the photo above. When I sketched the circle that became the base of the model, I entered &#8220;enclosure_diameter&#8221; for the diameter of the circle rather than &#8220;60 mm.&#8221; Now if I decide I want a larger enclosure, I can go back to the table and change the expression for the enclosure_diameter from &#8220;60 mm&#8221; to &#8220;70 mm&#8221; and the base will magically grow to 70 mm in diameter. Another cool thing is expressions can be chained like the calculation of the board diameter above which is based on the enclosure diameter, the wall thickness, and a small offset.</p>
<p>Parametric modeling can be difficult to get right. It takes a bit of planning and foresight to get it right. The enclosure bottom seems to work OK. For some reason, the enclosure top doesn&#8217;t move its screw holes correctly when the diameter is changed and the enclosure_height doesn&#8217;t really work at all. I may fix this in a later version of the enclosure design. I called it good enough for now though and moved on.</p>
<h3>Enclosure Bottom</h3>
<div id="attachment_1628" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/enc-bottom-top.png"><img class="size-large wp-image-1628" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/enc-bottom-top-1024x819.png" alt="Interior view of the bottom half of the enclosure." width="640" height="512" /></a><p class="wp-caption-text">Interior view of the bottom half of the enclosure.</p></div>
<p>The photo above shows the interior of the bottom half of the completed enclosure. The board rests on top of the hexagonal extrusions that hold the hex nuts.</p>
<div id="attachment_1629" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/enc-bottom-bottom.png"><img class="size-large wp-image-1629" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/enc-bottom-bottom-1024x819.png" alt="Exterior view of the bottom half of the enclosure." width="640" height="512" /></a><p class="wp-caption-text">Exterior view of the bottom half of the enclosure.</p></div>
<p>The photo above shows the exterior of the bottom half of the completed enclosure. The hexagonal holes hold the hex nuts that secure the two halves of the enclosure together.</p>
<h3>Enclosure Top</h3>
<div id="attachment_1630" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/enc-top-bottom.png"><img class="size-large wp-image-1630" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/enc-top-bottom-1024x819.png" alt="Interior view of the top half of the enclosure." width="640" height="512" /></a><p class="wp-caption-text">Interior view of the top half of the enclosure.</p></div>
<p>The photo above shows the interior of the top half of the completed enclosure. The screws that hold the enclosure together run through the center of the hollow posts. The ends of the hollow posts hold the circuit board in place. The flat portion notched out of the rear of the enclosure is very visible in this view.</p>
<div id="attachment_1631" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/enc-top-top.png"><img class="size-large wp-image-1631" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/enc-top-top-1024x819.png" alt="Exterior view of the top half of the enclosure." width="640" height="512" /></a><p class="wp-caption-text">Exterior view of the top half of the enclosure.</p></div>
<p>The photo above shows the exterior of the top half of the completed enclosure. The holes are tapered so that the flat head screws lay flush with the top of the enclosure.</p>
<p>That&#8217;s the finished generic version of the enclosure. Once we&#8217;ve selected an encoder and knob, we&#8217;ll add a hole for the encoder as well as a hole for a female micro USB B connector.</p>
<h3>Creating and Exporting a Board Outline</h3>
<div id="attachment_1634" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/bottom-with-board.png"><img class="size-large wp-image-1634" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/bottom-with-board-1024x819.png" alt="A generic circuit board located inside the enclosure. I added a 3D model of a right-angle tactile switch to see how a reset button might fit inside the enclosure." width="640" height="512" /></a><p class="wp-caption-text">A generic circuit board located inside the enclosure. I added a 3D model of a right-angle tactile switch to see how a reset button might fit inside the enclosure.</p></div>
<p>Since this was a generic enclosure design, it only made sense to have an empty board outline I could use a starting point when designing various boards to fit inside the enclosure.</p>
<p>I constructed a plane on top of the hex standoffs then created a sketch on that plane. I projected the interior of the enclosure and offset it by 0.5 mm away from the walls of the enclosure to create the board outline. I also need to create keepouts for the hex standoffs and circular posts that contact the board inside the enclosure. I projected these from the bottom and top of the enclosure into the sketch as well.</p>
<div id="attachment_1636" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/board-outline1.png"><img class="size-large wp-image-1636" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/board-outline1-1024x974.png" alt="The completed board outline in Eagle PCB. The white outline is on the Dimension (20) layer. The hex and round keep out areas are on the blue bKeepout (40) and red tKeepout (39) layers respectively." width="640" height="609" /></a><p class="wp-caption-text">The completed board outline in Eagle PCB. The white outline is on the Dimension (20) layer. The hex and round keep out areas are on the blue bKeepout (40) and red tKeepout (39) layers respectively.</p></div>
<p>Once the sketch was completed, I exported it as a DXF file from Fusion 360 then imported it into the dimension layer in Eagle PCB. I moved the hex standoff lines to the bottom keepout layer and the round standoff lines to the top keepout layer. I left the board outline on the dimension layer. The DXF export and import wasn&#8217;t perfect so I had to patch up the board outline some on the dimension layer. Finally, I added the holes for the 2-56 screws and saved the file as an Eagle BRD file to use as a starting point for any designs utilizing the enclosure.</p>
<h2>Selecting an Encoder</h2>
<p>A tweet from one my co-workers was the inspiration to build a USB volume knob based on the work I&#8217;d done on the small keyboards and caps lock warning buzzer. Turning a variable resistor would not work for a USB volume knob though because a variable resistor outputs an absolute resistance / position value and there is not a USB HID command to set the volume to a fixed level. You can turn the volume down, you can turn the volume up, and you can toggle mute with USB HID. That&#8217;s it.</p>
<p>Also, a variable resistor has fixed end points in its rotation. Even if I could hack something to detect which way the variable resistor was being turned and send the correct USB HID commands to the computer, eventually I&#8217;d hit an endpoint in the knobs rotation and that endpoint would likely not be aligned with the lowest volume or highest volume setting on the computer.</p>
<div id="attachment_1638" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/encoders.jpg"><img class="size-large wp-image-1638" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/encoders-1024x682.jpg" alt="Two different types of encoders." width="640" height="426" /></a><p class="wp-caption-text">Two fundamentally different encoder examples.</p></div>
<p>I needed a device that could signal the volume to go up when turned one direction and that could signal the volume to go down when turned the other direction. Also pushing the knob should toggle mute. Fortunately such a device exists&#8211;the rotary encoder. I&#8217;ve heard them called incremental encoders, rotary pulse generators, or simply encoders. These come in a bunch of different varieties.</p>
<p>The photo above shows two examples. The one with the ribbon cable is an optical rotary encoder with a quadrature encoded output. The smaller one is a mechanical rotary encoder that closes different switch contacts based on CW or CCW rotation of the shaft. The optical encoder is over $30. The mechanical encoder is closer to $3.</p>
<p>As an aside, the optical encoder pictured above has been in production for over 30 years. It was originally developed within the test and measurement division of HP for use on the front panels of their test equipment. When Agilent split off from HP in 2000, the production of the encoder went to Agilent. The encoder then went to Avago in the Agilent-Avago split in 2015. It&#8217;s currently sold by Broadcom after the Avago acquistion of Broadcom and their subsequent name change.</p>
<p>Here are some key parameters to be aware of when selecting an encoder:</p>
<ul>
<li>Shaft size: 1/4-inch (6.35 mm) and 6 mm are the most common sizes. Shaft size needs to match the diameter of the hole in the center of the chosen knob.</li>
<li>Shaft shape: Either round or D shaped. Round works. D shaped is easier to lock into place and prevent rotation of the knob on the shaft.</li>
<li>Shaft length: The value is all over the place. It&#8217;s important that the locking screw on the chosen knob can make solid contact with whatever length shaft is chosen. It&#8217;s also aesthetically important that the shaft is not too long otherwise the knob will bottom out and look way too far away from the chassis.</li>
<li>Smooth or with detents: Smooth encoders rotate freely. Encoders with detents click into place after each change in output state.</li>
<li>Optical or mechanical: Optical encoders have longer lifetimes, offer more pulses per revolution, and are more expensive. Mechanical encoders are the opposite.</li>
<li>Number of pulses per revolution: How many pulses does the knob generate in one revolution. 16, 32, 120, and 256 are common values. Some specialized encoders for motor shaft positioning applications generate even more.</li>
<li>Encoding: quadrature / gray scale or discrete pulse per direction. We&#8217;ll get into quadrature / gray scale encoding in the software section below.</li>
<li>Integrated switch: Some encoders have an integrated pushbutton switch; others don&#8217;t.</li>
<li>Supply voltage: Optical encoders typically run from a specific supply voltage and have open-drain / open-collector outputs. Mechanical encoders are a bit more flexible in terms of acceptable voltages.</li>
<li>Panel mount or board mount. Panel mount encoders have threaded stems and mount to the panel using a hex nut. Board mount encoders solder directly to the board. The distance between board and enclosure and encoder and knob all have to be considered during design with either type. I generally find board mount encoders to be less flexible in terms of positioning than panel mount encoders.</li>
</ul>
<div id="attachment_1591" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/2.jpg"><img class="wp-image-1591 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/2-1024x575.jpg" alt="2" width="640" height="359" /></a><p class="wp-caption-text">The Grayhill 62S11-M5-020C encoder used for this project. The sticker is leftover from another project and was used to keep the encoder from shorting to the board during software development.</p></div>
<p>I picked the Grayhill 62S11-M5-020C encoder that&#8217;s shown in the photo above. It has the following attributes:</p>
<ul>
<li>1/4&#8243; diameter D shaft.</li>
<li>Detented with 32 pulses per revolution.</li>
<li>Optical with quadrature encoding and an integrated switch.</li>
<li>Panel mount with a short ribbon cable and small connector.</li>
</ul>
<p>All this goodness was not cheap. The encoder goes for about $45 at quantity one.</p>
<h2>Selecting a Knob</h2>
<div id="attachment_1640" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/knobs.jpg"><img class="wp-image-1640 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/knobs-1024x682.jpg" alt="knobs" width="640" height="426" /></a><p class="wp-caption-text">Three alternative knob options for the USB volume knob.</p></div>
<p>After selecting an encoder, the next step was to select a knob. I need a knob to fit a 1/4&#8243; shaft and I wanted metal knob. I narrowed down to the four options shown in the picture above. The two larger knobs are made by TE Connectivity. They have a glossy finish. The two smaller knobs are made by Kilo International. They have a matte finish.</p>
<p>My favorite knob is the one front and center in the photograph but I decided it was too small compared to the enclosure. The knob I ultimately selected and is on the USB volume knob in the photo above is TE Connectivity part # KN1251B1/4 and sells for about $15. The runner up knob is Kilo International part # OEDNI-90-4-5 and sells for about $7. I&#8217;m definitely going to have to build something in the future that uses a few of the Kilo International knobs.</p>
<h2>Finishing the Enclosure Design</h2>
<div id="attachment_1642" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/section-analysis1.png"><img class="size-large wp-image-1642" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/section-analysis1-1024x819.png" alt="Section analysis showing the vertical alignment of the encoder within the enclosure." width="640" height="512" /></a><p class="wp-caption-text">Section analysis showing the vertical alignment of the encoder within the enclosure.</p></div>
<p>Now that I had a knob and encoder picked out, it was time to return to the enclosure design. The encoder has a 3/8-32 thread and <a href="https://littlemachineshop.com/images/gallery/PDF/TapDrillSizes.pdf">requires a 0.3970&#8243; hole (PDF link)</a>. I created a hole centered on the top half of the enclosure with this diameter then it was time to think about the vertical alignment of the enclosure, circuit board, encoder, and knob.</p>
<p>Fortunately Grayhill had a 3D model of their encoder and TE Connectivity had a 3D model of their knob. I imported these into the enclosure design and used the joint tool to place the encoder in the hole and to place the knob on the end of the encoder shaft. The Grayhill 3D model wasn&#8217;t an exact match so there&#8217;s a rogue connector and cable protruding outside the enclosure but that&#8217;s OK for now.</p>
<p>Fusion 360&#8217;s section analysis tool allowed me to see a cutaway view of how the knob, encoder, PCB, and enclosure fit together. I played with the alignment until I found something where there was enough clearance between the knob and the enclosure to allow the integrated push button in the encoder to be pressed.</p>
<p>This ultimately required the encoder to be recessed 4.5 mm below the top of the enclosure and the knob to be elevated 1/16&#8243; above the end of the shaft of the encoder. I could use washers to satisfy the former requirement. Instead I bulked up the 3D printed material between the encoder and enclosure to the required thickness. To satisfy the latter requirement, I placed a 1/16&#8243; spacer with an outside diameter of 1/4&#8243; into the knob before mounting it on the encoder&#8217;s shaft. Kind of a kluge but it works well.</p>
<p>I added the cutout for the micro USB B connector to the rear of the enclosure using the same technique I used when making connector cutouts on the <a href="https://bikerglen.com/blog/homebrew-rgb-led-light/">DMX-controlled RGB LED light</a>. The final version of the 3D printed enclosure with the micro USB B connector cutout and the encoder and knob mounted is shown the image below. I then generated the STL files and sent them for 3D printing at Sculpteo using <a href="https://www.sculpteo.com/blog/2017/10/25/how-to-design-for-hp-multi-jet-fusion-technology/">HP&#8217;s Multi Jet Fusion 3D</a> printing technology.</p>
<div id="attachment_1594" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/puck_v2_v16_grayhill_encoder-v7.png"><img class="size-large wp-image-1594" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/puck_v2_v16_grayhill_encoder-v7-1024x819.png" alt="Finished enclosure design." width="640" height="512" /></a><p class="wp-caption-text">Finished enclosure design.</p></div>
<h2>Designing the Electronics and Board</h2>
<div id="attachment_1643" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/schematic.png"><img class="size-large wp-image-1643" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/schematic-1024x764.png" alt="Completed schematic." width="640" height="478" /></a><p class="wp-caption-text">Completed schematic.</p></div>
<p>The schematic for the electronics is shown in the image above. It&#8217;s identical to the schematic for the updated version of the <a href="https://bikerglen.com/blog/updates-to-the-annoying-caps-lock-warning-buzzer/#more-1548">Annoying CAPS LOCK Warning Buzzer</a> except for the addition of a connector for the Grayhill optical rotary encoder and a few more LEDs.</p>
<p>The Grayhill encoder requires +5V DC to power the infrared light sources inside the encoder. It has open-drain / open-collector outputs and requires 2.2k pullup resistors on its CH A and CH B outputs to function. The encoder&#8217;s integrated push button switch uses the PIC&#8217;s internal weak pullup function so no pullup resistor is required on the switch output signal.</p>
<div id="attachment_1644" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/board.png"><img class="size-large wp-image-1644" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/board-985x1024.png" alt="Completed board." width="640" height="665" /></a><p class="wp-caption-text">Completed board.</p></div>
<p>The USB volume knob board is 56 mm in diameter. It is absolutely roomy compared to the 1&#8243; x 1&#8243; boards used for the caps lock warning buzzer and assorted one key keyboards. As a result, the layout was significantly easier and faster to finish.</p>
<p>I started with the generic board outline file I created while designing the enclosure. On that board outline I placed the critical components like the USB connector, the encoder connector, and the ESD suppression diodes first.</p>
<p>I placed the rest of the components next while leaving a big open area in the center to avoid any components making contact with the metallic base of the encoder or interfering with the folding of the encoder&#8217;s ribbon cable. After placing all the components, it was time to route the board.</p>
<p>I created a ground plane on each side of the board then connected the two ground planes using lots of vias through the board. Horizontal traces run on the front side of the board and vertical traces run on the rear. The +5V power is routed where its needed using traces. The completed and stuffed board is shown in the photo below.</p>
<div id="attachment_1646" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/board.jpg"><img class="size-large wp-image-1646" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/board-1024x682.jpg" alt="The completed and stuffed circuit board. I left the buzzer off for now." width="640" height="426" /></a><p class="wp-caption-text">The completed and stuffed circuit board. I left the buzzer off for now.</p></div>
<h2>Software</h2>
<p>I did have one slight snag while building this project: the software. Just because volume keys are on many USB keyboards doesn&#8217;t mean the volume keys function like the rest of the keys on the keyboard. The USB HID spec treats the volume keys quite differently. As a result, the software I used on the one key keyboards and caps lock warning buzzer was going to require some pretty arcane (if USB HID is not your thing) modifications to control the computer&#8217;s volume.</p>
<h3>USB HID Report Descriptors</h3>
<p>During device enumeration, the connected USB device tells the USB host what type of device it is. If it is a USB HID device, the device also has to tell the host the types and formats of reports it will send to the host and the types and formats of reports it expects from the host. This is done using a USB HID report descriptor.</p>
<p>The USB HID report descriptor is built using codes from the USB HID specification and a supplementary document called the USB HID usage tables. The USB HID report descriptor provides the host with enough information to parse USB input reports or to create USB output reports.</p>
<p>This offloads a lot of complexity from the device to the host. The host must be able to deal with arbitrarily formatted input reports from USB HID devices. It must also be able to create arbitrarily formatted output reports to send to USB HID devices. There&#8217;s no guarantee that different USB HID devices that perform similar functions will have identical or even similarly formatted input and output reports.</p>
<p>The code below shows the USB HID report descriptor that my small one key keyboards and the caps lock warning buzzer use. It asks the host to send an output report with the status of the five common LEDs (Num Lock, Scroll Lock, Caps Lock, etc.) and three padding bits. It also tell the host that the device will send the state of the eight modifier keys followed by up to six keys from the key code chart when polled by the host.</p>
<pre>const struct{uint8_t report[HID_RPT01_SIZE];}hid_rpt01={
{   0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,                    // USAGE (Keyboard)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x08,                    //   REPORT_COUNT (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
    0x95, 0x05,                    //   REPORT_COUNT (5)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x05, 0x08,                    //   USAGE_PAGE (LEDs)
    0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
    0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
    0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x03,                    //   REPORT_SIZE (3)
    0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)
    0x95, 0x06,                    //   REPORT_COUNT (6)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0xc0}                          // End Collection
};</pre>
<p>Further complicating things, the volume control keys are not a part of the keyboard usage page in the HID usage tables. They&#8217;re part of a separate usage page called the consumer control usage tables. If we want to send volume control keys to the host, we need to send some HID usage codes from a different usage table than we used for the keyboard.</p>
<p>Unfortunately, there&#8217;s no way to mix the keyboard usage with the consumer usage in a single input report. This means our device needs to send one type of input report when a keyboard key is pressed and a second, different type of input report when the volume is adjusted. (Or we could do away with sending keyboard usage input reports altogether but I wanted to keep the caps lock status and did not want to preclude sending +/- key presses instead of volume up / volume down in the future.)</p>
<p>Telling the host our device is capable of sending two different USB input reports is done using USB HID collections. There&#8217;s already one USB HID collection in the code above. The code below builds on the code above and adds a second USB HID collection. Everything up to the start of the second USB HID collection in the code below is identical to the code above.</p>
<pre>const struct{uint8_t report[HID_RPT01_SIZE];}hid_rpt01={
{   0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,                    // USAGE (Keyboard)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x01,                    //   REPORT_ID
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x08,                    //   REPORT_COUNT (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
    0x95, 0x05,                    //   REPORT_COUNT (5)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x05, 0x08,                    //   USAGE_PAGE (LEDs)
    0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
    0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
    0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x03,                    //   REPORT_SIZE (3)
    0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)
    0x95, 0x06,                    //   REPORT_COUNT (6)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0xc0,                          // End Collection

    0x05, 0x0C,                    // USAGE_PAGE (Consumer Devices)
    0x09, 0x01,                    // USAGE (Consumer Control)
    0xA1, 0x01,                    // COLLECTION (Application)
    0x85, 0x02,                    //   REPORT_ID
    0x05, 0x0C,                    //   USAGE_PAGE (Consumer Devices)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x07,                    //   REPORT_COUNT (7)
    0x09, 0xB5,                    //   USAGE (Scan Next Track)
    0x09, 0xB6,                    //   USAGE (Scan Previous Track)
    0x09, 0xB7,                    //   USAGE (Stop)
    0x09, 0xCD,                    //   USAGE (Play / Pause)
    0x09, 0xE2,                    //   USAGE (Mute)
    0x09, 0xE9,                    //   USAGE (Volume Up)
    0x09, 0xEA,                    //   USAGE (Volume Down)
    0x81, 0x02,                    //   INPUT (Data, Variable, Absolute)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x81, 0x01,                    //   INPUT (Constant)
    0xC0}                          // End Collection
};</pre>
<p>The first thing this new, second USB HID collection does is tell the host we&#8217;re going to send codes from the USB HID consumer control usage tables. This is done using the USAGE_PAGE and USAGE instructions. Next, this input report will have an ID of 0x02. Then it tells the host we&#8217;re going to send the state of the track controls and volume controls and one padding bit. Lastly, it closes the collection with the end collection instruction. This <a href="https://www.microchip.com/forums/m618147.aspx">forum post</a> on Microchip&#8217;s website was invaluable in figuring out the modifications that were required to send the volume keys in a USB input report.</p>
<p>Another slight wrinkle is that if there is only one type of input report, the input report ID is not specified in the USB input reports sent from the device to the host. If there&#8217;s more than one type of input report, however, the input report ID must be specified in the USB input report. This means our USB input reports need to be bumped in length from eight bytes to nine bytes everywhere they&#8217;re referenced in our code.</p>
<p>If you&#8217;re really curious about all the code changes to support a second type of USB HID input report, I suggest doing a diff between the annoying caps lock warning buzzer source code and the USB volume knob source code. Source code for both devices is in my Github repositories.</p>
<h3>Decoding the Encoder’s Quadrature Outputs</h3>
<div id="attachment_1683" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/quadrature-codes.png"><img class="size-large wp-image-1683" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/quadrature-codes-1024x321.png" alt="Truth table and waveform illustration from the Grayhill encoder data sheet." width="640" height="201" /></a><p class="wp-caption-text">Truth table and waveform illustration from the Grayhill encoder data sheet.</p></div>
<p>If you look at OUTPUT A and OUTPUT B in the above diagram, you can see that OUTPUT B lags OUTPUT A by 90 degrees. This is called quadrature encoding. As a result, the outputs of the encoder looks like a gray code counter and only one output signal changes per click / move of the encoder.</p>
<p>To determine the direction the encoder is moving you need to know the last state of the two outputs and the current state of the two outputs. Based on the last state and the current state, you can determine if the encoder is being turned clockwise or counterclockwise.</p>
<p>For example, let&#8217;s start at position number 3 in the diagram above. A and B are both high. We save this state to a variable. Some amount of time later, we read the encoder again. If A and B are still both high, the encoder has not been turned. If however, A is now low while B is still high, the encoder has been turned one click clockwise. If however, A is still high while B is now low, the encoder has been turned one click counterclockwise.</p>
<p>To avoid missing encoder pulses, software must read the encoder at least twice as fast as the highest expected pulse rate. My software polls the encoder at a 1 kHz rate. This allows the encoder to be turned up to 500 pulses per second without missing a pulse. With a manually turned knob with only 32 pulses per revolution, that rate is acceptable. If you have a microcontroller capable of generating interrupts on the change of state of input pins, you can handle much higher rotational speeds.</p>
<p>The code to read the encoder and determine whether the volume needs to go up or down is shown below. The variable last_knob holds the last known state of the encoder&#8217;s outputs. The variable this_knobs is assigned the current state of the encoder&#8217;s outputs. The switch statement determines which way the knob is being turned and updates the signed variable value_knob up or down based on the direction the knob is turned.</p>
<pre>#define S2_PORT  PORTBbits.RB5      // CHA
#define S3_PORT  PORTBbits.RB4      // CHB

void BUTTON_UpdateStates (void)
{
    ...
    // this_knob = { CHB, CHA }
    this_knob = (S3_PORT &lt;&lt; 1) | S2_PORT;
    switch (last_knob) {
        case 0: if (this_knob == 1) { value_knob--; } else if (this_knob == 2) { value_knob++; } break;
        case 1: if (this_knob == 0) { value_knob++; } else if (this_knob == 3) { value_knob--; } break;
        case 2: if (this_knob == 0) { value_knob--; } else if (this_knob == 3) { value_knob++; } break;
        case 3: if (this_knob == 1) { value_knob++; } else if (this_knob == 2) { value_knob--; } break;
    }
    last_knob = this_knob;
}</pre>
<p>Inside the code that responds to the USB bus&#8217;s input polling requests is code to see if value_knob is less than or greater than zero. This code is shown below. If it&#8217;s less than zero, it sets the volume_down bit in the USB input report that will be sent to the host computer. If it&#8217;s greater than zero, it sets the volume_up bit in the USB input report that will be sent to the host computer. There&#8217;s quite a bit of abstraction and redirection in this code since I did not attempt to simplify it any from the Microchip for Library Applications source code.</p>
<pre>inputReport.report_id = 0x02;
if(BUTTON_IsPressed(BUTTON_USB_DEVICE_HID_KEYBOARD_KEY_0) == true) {
    inputReport.modifiers.media.mute = 1;
}
if(BUTTON_IsPressed(BUTTON_USB_DEVICE_HID_KEYBOARD_KEY_1) == true) {
    inputReport.modifiers.media.volumeDown = 1;
}
if(BUTTON_IsPressed(BUTTON_USB_DEVICE_HID_KEYBOARD_KEY_2) == true) {
    inputReport.modifiers.media.volumeUp = 1;
}</pre>
<p>Inside the BUTTON_isPressed function below is the actual check to see if value_knob is positive or negative. The caller calls BUTTON_isPressed with the value BUTTON_S2 to see if the volume needs to be turned down. If it does, the function returns true and value_knob is incremented to mark that we&#8217;ve handled this volume down request from the user. The caller calls BUTTON_isPressed with the value BUTTON_S3 to see if the volume needs to be turned up. If it does, the function returns true and value_knob is decremented to mark that we&#8217;ve handled this volume down request from the user. BUTTON_S1 implements the mute function.</p>
<p>The incrementing and decrementing of the value_knob variable allows for the encoder to be turned faster than volume updates can be sent over the USB bus. Once the encoder stops turning, the USB bus will eventually catch up and value_knob will settle on zero. The code that generates the USB input reports might need to be updated to send a &#8216;0&#8217; for all the mute / volume keys between presses for this to work properly.</p>
<pre>bool BUTTON_IsPressed(BUTTON button)
{
    switch(button) {
        case BUTTON_S1:
            return ((state1 &gt;= 2) ? true : false);
        case BUTTON_S2:
            if (value_knob &lt; 0) {
                value_knob++;
                return true;
            }
            return false;
        case BUTTON_S3:
            if (value_knob &gt; 0) {
                value_knob--;
                return true;
            }
            return false;
        case BUTTON_NONE:
            return false;
    }
    return false;
}</pre>
<h3>Program the Bootloader</h3>
<div id="attachment_1687" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/programming-bootloader.jpg"><img class="wp-image-1687 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/programming-bootloader-1024x682.jpg" alt="An extremely staged photo of using the Tag-Connect cable to program the USB bootloader." width="640" height="426" /></a><p class="wp-caption-text">An extremely staged photo of using the Tag-Connect cable to program the USB bootloader.</p></div>
<p>Up until this point, I had been using the MPLAB X IDE and my REAL ICE debugger to program and debug the firmware directly on the PIC16F1459. Now  that the firmware was debugged, it was time to go to a more production oriented approach to programming and updating the USB volume knob firmware.</p>
<p>I used the MPLAB X IDE and my REAL ICE programmer to program a USB bootloader into the microcontroller. This allows updates to the firmware to be made directly over the USB bus without taking the USB volume knob apart and without using a dedicated programmer and programmer cable. This is the exact same USB bootloader I used on the one key keyboards and annoying caps lock warning buzzer.</p>
<h3>Program the Firmware</h3>
<div id="attachment_1567" style="width: 451px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/usb-bootloader.png"><img class="size-full wp-image-1567" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/usb-bootloader.png" alt="The main (and only) window of the Microchip Library for Applications USB Bootloader utility." width="441" height="442" /></a><p class="wp-caption-text">The main (and only) window of the Microchip Library for Applications USB Bootloader utility.</p></div>
<p>Once the bootloader was programmed into the PIC16F1459, I could update the USB volume knob firmware using the Microchip Library for Applications (MLA) USB Bootloader Utility. A screenshot of the utility is shown above. The process is as follows:</p>
<ol>
<li>Launch the MLA bootloader utility from the MLA install directory.</li>
<li>Hold down the knob while plugging the USB volume knob into the USB port on the PC.</li>
<li>Wait for the device attached and device ready messages as shown in the dialog box above.</li>
<li>Click the open button in the GUI and select the .hex file from the dist directory inside the USB volume knob firmware directory.</li>
<li>Click the program button to program the firmware into the USB volume knob.</li>
<li>Click the reset button to reset the PIC and launch the application firmware. You can also unplug the USB volume knob then plug it back into the PC. Do not hold down the knob this time.</li>
<li>Test the firmware update by turning the knob to change the volume and pressing the knob to mute / unmute the volume.</li>
</ol>
<h3>Testing</h3>
<div id="attachment_1689" style="width: 263px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/volumes.png"><img class="size-full wp-image-1689" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/volumes.png" alt="Turn the knob and you should see the volume go up and down. Press the knob and you should see the volume mute and unmute." width="253" height="185" /></a><p class="wp-caption-text">Turn the knob and you should see the volume go up and down. Press the knob and you should see the volume mute and unmute.</p></div>
<p>Test the knob before assembling the knob into the enclosure. Turn the knob to change the volume and press the knob to mute / unmute the volume.</p>
<h2>Assembly</h2>
<div id="attachment_1648" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/assembly.jpg"><img class="size-large wp-image-1648" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/assembly-1024x683.jpg" alt="Parts and tools required for assembly. Note how the encoder's ribbon cable is accordion folded into place." width="640" height="427" /></a><p class="wp-caption-text">Parts and tools required for assembly. Note how the encoder&#8217;s ribbon cable is accordion folded into place.</p></div>
<p>Assembly went pretty smoothly. First mount the encoder to the top of the enclosure using the hardware included with the encoder. Next accordion fold the ribbon cable as shown in the photograph above. Connect the encoder cable to the circuit board then press the circuit board against the top of the enclosure. While holding the circuit board in place, thread a few screws through the top of the enclosure and fit the bottom of the enclosure over the screws. Insert the nuts into their recesses on the bottom of the enclosure and tighten all four screws using a 3/64&#8243; or 0.050&#8243; hex driver.</p>
<p>A top view of the assembled USB volume knob is shown in the photo below.</p>
<div id="attachment_1600" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/usb-volume-knob-top.jpg"><img class="size-large wp-image-1600" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/usb-volume-knob-top-1024x682.jpg" alt="The completed USB volume knob project. It uses an off-the-shelf knob and a PIC16F1459 microcontroller. The enclosure is 3D printed." width="640" height="426" /></a><p class="wp-caption-text">The completed USB volume knob project. It uses an off-the-shelf knob and a PIC16F1459 microcontroller. The enclosure is 3D printed.</p></div>
<p>A side view of the rear of the assembled USB volume knob is shown in the photo below.</p>
<div id="attachment_1602" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/usb-volume-knob-rear.jpg"><img class="size-large wp-image-1602" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/usb-volume-knob-rear-1024x682.jpg" alt="Flat section on the rear of the enclosure to accommodate the micro USB connector." width="640" height="426" /></a><p class="wp-caption-text">Flat section on the rear of the enclosure to accommodate the micro USB connector.</p></div>
<p>My desk is kind of slick. I dug through the junk drawer in the kitchen to find some rubber bumpers to place on the bottom of the USB volume knob to keep it in place while turning it. I only had two bumpers left. That&#8217;d be kind of wobbly so I cut the waste material surrounding the two remaining bumpers to size then stuck it on the bottom of the USB volume knob instead:</p>
<div id="attachment_1601" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/10/usb-volume-knob-bottom.jpg"><img class="size-large wp-image-1601" src="https://bikerglen.com/wp/wp-content/uploads/2019/10/usb-volume-knob-bottom-1024x682.jpg" alt="Rubber stuck to bottom of enclosure to keep it from sliding on my desk." width="640" height="426" /></a><p class="wp-caption-text">Rubber stuck to bottom of enclosure to keep it from sliding on my desk.</p></div>
<h2>Design Files</h2>
<p>Design files are available for the enclosure, board, and software in my <a href="https://github.com/bikerglen/usb-volume-knob">Github repository</a> for the project.</p>
<h2>Resources</h2>
<p>The following online resources were helpful while figuring out the needed USB input report descriptors to report desired volume changes to the PC:</p>
<ul>
<li>This Microchip forum post:<br />
<a href="https://www.microchip.com/forums/m618147.aspx"> https://www.microchip.com/forums/m618147.aspx</a></li>
<li>This tutorial on USB HID Report Descriptors:<br />
<a href="https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/">https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/</a></li>
</ul>
<p>Readers may also find the following resources helpful:</p>
<ul>
<li>A good description of the USB HID setup process:<br />
<a href="http://kevincuzner.com/2018/02/02/cross-platform-driverless-usb-the-human-interface-device/">http://kevincuzner.com/2018/02/02/cross-platform-driverless-usb-the-human-interface-device/</a></li>
<li>The USB HID Landing Page:<br />
<a href="https://www.usb.org/hid">https://www.usb.org/hid</a></li>
<li>The USB Device Class Definition for Human Interface Devices (HID):<br />
<a href="https://www.usb.org/sites/default/files/documents/hid1_11.pdf">https://www.usb.org/sites/default/files/documents/hid1_11.pdf</a></li>
<li>The USB HID usage tables:<br />
<a href="https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf">https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/pic16f1459-usb-volume-knob/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updates to the Annoying CAPS LOCK Warning Buzzer</title>
		<link>https://bikerglen.com/blog/updates-to-the-annoying-caps-lock-warning-buzzer/</link>
		<comments>https://bikerglen.com/blog/updates-to-the-annoying-caps-lock-warning-buzzer/#comments</comments>
		<pubDate>Mon, 30 Sep 2019 04:40:56 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[3D Printing]]></category>
		<category><![CDATA[Microchip]]></category>
		<category><![CDATA[PIC18]]></category>
		<category><![CDATA[USB]]></category>
		<category><![CDATA[USB Human Interface Device (HID)]]></category>

		<guid isPermaLink="false">https://bikerglen.com/blog/?p=1548</guid>
		<description><![CDATA[In my first post on the Annoying CAPS LOCK Warning Buzzer, I concluded with a list of future improvements to make to the project. Those updates are now implemented and the Annoying CAPS LOCK Warning Buzzer is more robust than &#8230; <a href="https://bikerglen.com/blog/updates-to-the-annoying-caps-lock-warning-buzzer/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div id="attachment_1549" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/buzzer-updates.jpg"><img class="size-large wp-image-1549" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/buzzer-updates-1024x683.jpg" alt="Some minor updates to the annoying caps lock warning buzzer." width="640" height="427" /></a><p class="wp-caption-text">Some new additions to the annoying caps lock warning buzzer (circled in green).</p></div>
<p>In my <a href="https://bikerglen.com/blog/the-annoying-caps-lock-warning-buzzer/">first post on the Annoying CAPS LOCK Warning Buzzer</a>, I concluded with a list of future improvements to make to the project. Those updates are now implemented and the Annoying CAPS LOCK Warning Buzzer is more robust than ever. Read on to find out more about the improvements.</p>
<p><span id="more-1548"></span></p>
<h2>Goals for Improvements</h2>
<p>The list of new features and improvements is pretty short:</p>
<ol>
<li>Include a ground plane on both sides of the board. Route +5V as traces.</li>
<li>Add some basic ESD protection.</li>
<li>Add a button and LED to use with a USB bootloader and firmware update utility to apply firmware updates.</li>
<li>Make the button and LED accessible without disassembling the buzzer.</li>
</ol>
<p>Let&#8217;s run through each of the improvements separately.</p>
<h2>Ground Plane</h2>
<p>On the old board, the ground plane was on the component / top layer with a +5V plane on the bottom. This wasn&#8217;t causing any problems (that I know of) but the ground plane was broken by up all the pads for the surface-mount components. In the new version, both sides of the board contain a filled ground plane with lots of vias to bond the two ground planes to each other. The +5V is now routed as traces on the bottom of the board.</p>
<p>In theory this will reduce noise on the board and improve the electromagnetic compatibility of the board. One day I&#8217;ll have to bring both the old board and new board to work, find a spectrum analyzer and EMC probe set, and learn to make some EMC measurements. In the meantime, at least I didn&#8217;t break anything with the ground plane changes.</p>
<h2>ESD Protection</h2>
<div id="attachment_1558" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/esd-protection.jpg"><img class="wp-image-1558 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/esd-protection-1024x683.jpg" alt="esd-protection" width="640" height="427" /></a><p class="wp-caption-text">That&#8217;s the Nexperia PRTR5V0U2X ESD protection diode below the five millimeter mark on my Adafruit PCB ruler. It&#8217;s small but not any worse than an SOT-23 transistor to hand solder.</p></div>
<p>The second change was to add some basic ESD protection using a Nexperia <a href="https://assets.nexperia.com/documents/data-sheet/PRTR5V0U2X.pdf">PRTR5V0U2X ultra-low capacitance double rail-to-rail ESD protection diode</a>. This single device protects both USB data lines even in the absence of a supply voltage. The device needs to be located as close as possible to the USB connector and be very-well connected to the ground plane of the board.</p>
<h2>Button and LED and Resistor</h2>
<div id="attachment_1560" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/button-led-resistor.jpg"><img class="size-large wp-image-1560" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/button-led-resistor-1024x683.jpg" alt="A KMR2 tactile switch, an 0805 1k resistor, and an 0805 orange LED." width="640" height="427" /></a><p class="wp-caption-text">A KMR2 tactile switch, an 0805 1k resistor, and an 0805 orange LED.</p></div>
<p>The next improvement was to enable the use of the Microchip Library for Applications (MLA) USB bootloader to update the firmware on the Annoying CAPS LOCK Warning Buzzer. At boot time, the USB MLA bootloader checks a pushbutton switch. If the switch is pushed, the bootloader goes into a mode where the application firmware can be updated over USB. If the switch is not pressed, the USB MLA bootloader boots directly into the application firmware.</p>
<p>I needed a small pushbutton switch to use with the bootloader. I searched Digi-Key and Mouser looking for an SMD tactile switch. I found lots of candidates. I finally settled on a C&amp;K Switches KMR211NGLFS tactile switch. If you have an Adafruit Feather M0 board, this is very similar to the reset switch on that board.</p>
<p>The MLA USB bootloader can also blink an LED to indicate the state of the bootloader. I decided to take advantage of this feature. I selected a Dialight 599-0130-007F 0805 SMD orange LED. Any color would work but orange is somewhat different than the typical red or green LEDs on projects. Finally, I needed a current limiting resistor for the LED. I went with a small 1k 5% 0805 SMD resistor.</p>
<h2>Enclosure Modifications</h2>
<div id="attachment_1563" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/caps-lock-buzzer-v2-v5.png"><img class="size-large wp-image-1563" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/caps-lock-buzzer-v2-v5-1024x683.png" alt="The updated enclosure. Two two millimeter diameter holes on the bottom allow access to the tactile switch and LED." width="640" height="427" /></a><p class="wp-caption-text">The updated enclosure. Two two millimeter diameter holes on the bottom allow access to the tactile switch and LED.</p></div>
<p>To make the pushbutton and LED accessible without having to disassemble the warning buzzer, I added two 2 mm holes to the bottom of the enclosure. When the board is placed in the enclosure, one hole is directly over the pushbutton and the other hole is directly over the LED. The pushbutton can be pushed via a small screwdriver or paper clip. The LED light is visible by turning the buzzer upside down.</p>
<h2>Updated Schematic</h2>
<div id="attachment_1564" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/caps-lock-buzzer-v2-schematic.png"><img class="size-large wp-image-1564" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/caps-lock-buzzer-v2-schematic-1024x764.png" alt="Updated schematic. The U2, SW1, R2, and USER1 LED are new to this version of the design." width="640" height="478" /></a><p class="wp-caption-text">Updated schematic. The U2, SW1, R2, and USER1 LED are new to this version of the design.</p></div>
<p>The schematic above show the updates made for the second version of the warning buzzer. U2, SW1, R2, and the USER1 LED are new to this version of the design.</p>
<h2>Updated Boards</h2>
<div id="attachment_1562" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/new-vs-old-boards.jpg"><img class="size-large wp-image-1562" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/new-vs-old-boards-1024x683.jpg" alt="Old board on the left. New board on the right." width="640" height="427" /></a><p class="wp-caption-text">Old board on the left. New board on the right.</p></div>
<p>The photo above shows the old version of the design on the left and the new version of the design on the right. Most of components and traces are in the same place. The current limiting resistor for LED D2 / USER1 is on the reverse side of the board. Notice the many vias on the new design of the board. These vias connect the ground planes on each side of the board together.</p>
<h2>Updated Enclosure</h2>
<div id="attachment_1597" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/buzzer-back-1.jpg"><img class="size-large wp-image-1597" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/buzzer-back-1-1024x682.jpg" alt="The bottom of the annoying CAPS LOCK warning buzzer with the modifications to expose the LED and pushbutton." width="640" height="426" /></a><p class="wp-caption-text">The bottom of the annoying CAPS LOCK warning buzzer with the modifications to expose the LED and pushbutton.</p></div>
<p>The bottom of the updated enclosure is shown in the above photo. The hole with the orange glow is the LED. The other hole is for accessing the pushbutton swtich.</p>
<h2>Updated BOM</h2>
<p>The components that are new to the second version of the design are listed in the table below. You&#8217;ll also need a second 0805 1k 5% resistor.</p>
<table width="994">
<tbody>
<tr>
<td width="42">Line #</td>
<td width="126">Mfr. #</td>
<td width="126">Manufacturer</td>
<td width="508">Description</td>
<td width="70">Order Qty.</td>
<td width="122">Price (USD)</td>
</tr>
<tr>
<td>1</td>
<td>KMR211NGLFS</td>
<td>C&amp;K Switches</td>
<td>Tactile Switch</td>
<td>1</td>
<td>$0.52</td>
</tr>
<tr>
<td>2</td>
<td>PRTR5V0U2X,215</td>
<td>Nexperia</td>
<td>5.5V ESD Protection Diodes</td>
<td>1</td>
<td>$0.51</td>
</tr>
<tr>
<td>3</td>
<td>599-0130-007F</td>
<td>Dialight</td>
<td>0805 Orange LED</td>
<td>1</td>
<td>$0.26</td>
</tr>
</tbody>
</table>
<h2>Using the Bootloader</h2>
<div id="attachment_1567" style="width: 451px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/usb-bootloader.png"><img class="size-full wp-image-1567" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/usb-bootloader.png" alt="The main (and only) window of the Microchip Library for Applications USB Bootloader utility." width="441" height="442" /></a><p class="wp-caption-text">The main (and only) window of the Microchip Library for Applications USB Bootloader utility.</p></div>
<p>The MLA USB bootloader must be programmed using a PIC programmer such as the PICkit 4 or ICD 4 and the MPLAB X IDE or IPE. Once the bootloader is programmed, the bootloader can be used to update the application firmware. To update the firmware:</p>
<ol>
<li>Launch the MLA bootloader utility from the MLA install directory.</li>
<li>Hold down the button using a paper clip or small screwdriver while plugging the warning buzzer into the USB port on the PC. Be sure to push on the pushbbutton; not the LED.</li>
<li>Wait for the device attached and device ready messages as shown in the dialog box above.</li>
<li>Click the open button in the GUI and select the .hex file from the dist directory inside the caps lock buzzer firmware directory.</li>
<li>Click the program button to program the firmware into the warning buzzer.</li>
<li>Click the reset button to reset the PIC and launch the application firmware. You can also unplug the warning buzzer then plug it back into the PC. Do not hold down the pushbutton this time.</li>
<li>Test the firmware update by toggling the CAPS LOCK key on the keyboard to turn the warning buzzer off and on.</li>
</ol>
<h2>Design Files</h2>
<p>All design files are in my <a href="https://github.com/bikerglen/caps-lock-buzzer">caps-lock-buzzer repository on github</a>.</p>
<p>The v2 schematic and board files:</p>
<ul>
<li><a href="https://github.com/bikerglen/caps-lock-buzzer/blob/master/boards/v2/caps-lock-buzzer.sch">Schematic</a></li>
<li><a href="https://github.com/bikerglen/caps-lock-buzzer/blob/master/boards/v2/caps-lock-buzzer.brd">Board</a></li>
</ul>
<p>The Fusion 360 Archive and STL files for the enclosure:</p>
<ul>
<li><a href="https://github.com/bikerglen/caps-lock-buzzer/blob/master/enclosure/v2/caps-lock-buzzer-v2-v5.f3z">Fusion 360 Archive</a></li>
<li><a href="https://github.com/bikerglen/caps-lock-buzzer/blob/master/enclosure/v2/caps-lock-buzzer-v2-top.stl">Enclosure Top STL File</a></li>
<li><a href="https://github.com/bikerglen/caps-lock-buzzer/blob/master/enclosure/v2/caps-lock-buzzer-v2-bottom.stl">Enclosure Bottom STL File</a></li>
</ul>
<p>The updated software:</p>
<ul>
<li><a href="https://github.com/bikerglen/caps-lock-buzzer/blob/master/software/HID_Bootloader_-_PIC16F1459_-_v5.10.zip">PIC16F1459 Bootloader Project</a> for use with this Hardware</li>
<li><a href="https://github.com/bikerglen/caps-lock-buzzer/tree/master/software/caps-lock-buzzer-pic16f1459-btld.X">Caps Lock Buzzer Firmware</a> for use with the Bootloader and this Hardware</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/updates-to-the-annoying-caps-lock-warning-buzzer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Annoying CAPS LOCK Warning Buzzer</title>
		<link>https://bikerglen.com/blog/the-annoying-caps-lock-warning-buzzer/</link>
		<comments>https://bikerglen.com/blog/the-annoying-caps-lock-warning-buzzer/#comments</comments>
		<pubDate>Sun, 15 Sep 2019 16:50:46 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[3D Printing]]></category>
		<category><![CDATA[Microchip]]></category>
		<category><![CDATA[PIC18]]></category>
		<category><![CDATA[USB]]></category>
		<category><![CDATA[USB Human Interface Device (HID)]]></category>

		<guid isPermaLink="false">https://bikerglen.com/blog/?p=1395</guid>
		<description><![CDATA[The only way to make CAPS LOCK even more annoying was to make it audible! Now never type a password in all upper case, join 500 lines together in vi, or turn a harmless forum post into an ANGRY SCREED &#8230; <a href="https://bikerglen.com/blog/the-annoying-caps-lock-warning-buzzer/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><iframe src="https://www.youtube.com/embed/-V8hzF0jGLM" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p>The only way to make CAPS LOCK even more annoying was to make it audible! Now never type a password in all upper case, join 500 lines together in vi, or turn a harmless forum post into an ANGRY SCREED without warning again! This project uses a PIC16F1459 to monitor the USB output report containing the CAPS LOCK status from the connected PC. When CAPS LOCK is enabled, the PIC turns on an annoying warning buzzer. Read on to build your own.</p>
<p><span id="more-1395"></span></p>
<h2>Motivation</h2>
<div id="attachment_1407" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/buzzer.jpg"><img class="size-large wp-image-1407" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/buzzer-1024x775.jpg" alt="The completed annoying caps lock warning buzzer." width="640" height="484" /></a><p class="wp-caption-text">The completed annoying caps lock warning buzzer.</p></div>
<p>The CAPS LOCK key is the most annoying key on the keyboard. It&#8217;s always getting in the way. Ever enter a password with CAPS LOCK enabled? Enough times to get locked out of your account? Yeah, me too.</p>
<p>The only way to make CAPS LOCK even more annoying was to make it loud! As a side effect, you&#8217;ll always know when CAPS LOCK is enabled so entering the wrong password, joining lines when you&#8217;re just trying to scroll down in vi, or answering an entire email in ANGRY SCREED format should be history.</p>
<h2>Derived from the One Key USB Keyboard</h2>
<div class="mceTemp">
<div id="attachment_948" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00651_crop2.jpg"><img class="wp-image-948 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00651_crop2-1024x682.jpg" alt="The single ESC key USB keyboard." width="640" height="426" /></a><p class="wp-caption-text">The single ESC key USB keyboard.</p></div>
<p>This project is almost identical to my <a href="https://bikerglen.com/blog/presenting-the-single-esc-key-usb-keyboard/">one key USB keyboard</a> project. The key switch and LED have been replaced by a transistor and a buzzer. The enclosure has a round hole instead of a square hole. The software previously turned on an LED when CAPS LOCK was set. Now it uses a different pin to enable the buzzer instead. A few small changes yield an entirely different result. The selecting parts section below is repeated verbatim from that design. Skip forward to the schematic section if you&#8217;ve already read it.</p>
</div>
<h2>Selecting Parts</h2>
<h3>Picking a USB Microcontroller</h3>
<p>I chose a PIC16F1459 in an SSOP-20 package for the microcontroller. The PIC16F145x family provides a minimal parts count solution to implementing the USB 2.0 standard. No external oscillator is required because this micro has an internal 48MHz oscillator and uses active clock tuning to fine-tune the internal oscillator frequency to the recovered clock from the USB host. This micro, a USB connector, and three capacitors are all that are needed to implement a fully-functional USB 2.0 device.</p>
<div id="attachment_930" style="width: 1012px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/min-sch.png"><img class="wp-image-930 size-full" src="https://bikerglen.com/wp/wp-content/uploads/2018/05/min-sch.png" alt="Minimal PIC16F1459 schematic for USB 2.0 operation." width="1002" height="351" /></a><p class="wp-caption-text">Minimal PIC16F1459 schematic for USB 2.0 operation.</p></div>
<p>Once I selected the microcontroller, I needed to pick a package for the microcontroller. The PIC16F1459 is available in DIP, SOIC, SSOP, and QFN packages. I chose the SSOP-20 package. The two larger packages were too big to fit in the allocated board space and the QFN package, though smaller, would be considerably more difficult to hand solder.</p>
<h3>The USB Connector</h3>
<p>Next up was to find a suitable USB Micro-B connector. Since the entire board was to be hand soldered, I wanted a connector with locating pins to position the connector on the board while I soldered it and with enough room between the connector housing and the five signals pins that I could easily see what I was doing with a microscope. I ordered a bunch of USB Micro-B connectors, examined each of them, and finally found a Wurth Electronics connector that met my needs.</p>
<div id="attachment_937" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC_2096_crop.jpg"><img class="wp-image-937 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2018/05/DSC_2096_crop-1024x681.jpg" alt="DSC_2096_crop" width="640" height="426" /></a><p class="wp-caption-text">Wurth Electronics USB Micro-B Receptacle part number 629105136821. It has little black plastic posts to keep the connector centered while soldering and plenty of room between the shell and pins for the soldering iron, flux, solder, and inevitably, wick.</p></div>
<h2>Schematic</h2>
<div id="attachment_1408" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/buzzer-schematic.png"><img class="size-large wp-image-1408" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/buzzer-schematic-1024x764.png" alt="Schematic of the annoying caps lock warning buzzer." width="640" height="478" /></a><p class="wp-caption-text">Schematic of the annoying caps lock warning buzzer.</p></div>
<p>Pictured above is the complete schematic for the caps lock buzzer. Let&#8217;s take a closer look at the buzzer, the transistor switch, and programming the PIC16F1459.</p>
<h3>The Buzzer</h3>
<div id="attachment_1410" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/buzzers.jpg"><img class="size-large wp-image-1410" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/buzzers-1024x682.jpg" alt="Buzzer candidates. I went the smallest of the three." width="640" height="426" /></a><p class="wp-caption-text">Buzzer candidates. I went with the smallest of the three.</p></div>
<p>The buzzer needed to run from 5V since that is the USB bus voltage. The current consumption needed to be less than 1 A to prevent overloading the USB bus. I selected a through-hole buzzer to make aligning the buzzer with the board and consequently the hole in the 3D printed enclosure simpler. The final criteria was to select a buzzer that fit in the existing one-key keyboard enclosure without protruding too much. I found a buzzer that ran from 5V, consumed 35 mA, and only protruded out of the existing enclosure design by 0.42 mm. The frequency is 2.7 kHz with an SPL of 80 dBA.</p>
<h3>Designing the Transistor Switch</h3>
<p>The transistor switch circuit is a pretty basic transistor switch circuit. When the PIC drives the PWM0 signal, current flows from the base through the emitter of the transistor. This current turns on the transistor and a current conducts from the positive supply rail, through the buzzer, and from the collector to the emitter of the transistor.</p>
<p>R1 is selected to drive the transistor into the saturation region and to minimize the heat dissipation in the transistor. A 1k resistor usually works well but let&#8217;s calculate the resulting current with a 1k resistor to double check. To calculate the minimum base-emitter current, we need to know the worst-case output voltage at the output of the PIC and the worst-case base-emitter saturation voltage of the transistor.</p>
<p>From the data sheet, the V(OH) of the PIC is V(DD)-0.7 volts and the V(BE)(SAT) of the transistor is 1.0 V. The minimum base-emitter current will be (5 &#8211; 0.7 &#8211; 1.0 V) / (1 k) = 3.3 mA. The current consumption of the selected buzzer is 35 mA and the h(fe) of the transistor is 200. The base current required to drive the transistor into the saturation region is 35 mA / 200 = 0.175 mA.</p>
<p>The transistor will definitely be operating in the saturation region when the PIC turns on the PWM0 output signal. We could use a higher resistor if we want to further minimize the heat dissipation of the transistor but 3.5 mA is much less than the maximum base-emitter current of the transistor and I have a lot of 0805 1k resistors in my parts box.</p>
<p>Diode D1 is present to protect the transistor from the flyback voltage generated by the inductive load of the buzzer when the transistor is switched off. The voltage that is created at the collector of the transistor will be safely sunk to the positive supply rail rather than building up to a level that could potentially destroy the transistor.</p>
<h3>Programming the PIC16F1459</h3>
<div id="attachment_1414" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/IMG_20190310_162519.jpg"><img class="size-large wp-image-1414" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/IMG_20190310_162519-1024x576.jpg" alt="The old way of programming." width="640" height="360" /></a><p class="wp-caption-text">The old way of programming.</p></div>
<p>In previous designs, I&#8217;ve used a row of plated holes designed to make with a six-position, single-row, square-post, 0.1&#8243; pitch header to connect to the PIC programmer and debugger (shown above). This works well but takes up a lot of area on both sides of the board.</p>
<div id="attachment_1412" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/tag-connect.jpg"><img class="wp-image-1412 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/tag-connect-1024x682.jpg" alt="Tag-Connect programming cable connected to the programming pins on the circuit board,." width="640" height="426" /></a><p class="wp-caption-text">The new way: a Tag-Connect programming cable connected to the programming pins on the circuit board.</p></div>
<p>For this design, I&#8217;m using a <a href="http://www.tag-connect.com/">TAG-Connect cable</a> to connect the programmer/debugger to the board (shown above). This uses roughly half the area of the 0.1&#8243; header and only requires holes for three small alignment pins.</p>
<h2>Board</h2>
<div id="attachment_1419" style="width: 857px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/boards1.png"><img class="wp-image-1419 size-full" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/boards1.png" alt="boards" width="847" height="387" /></a><p class="wp-caption-text">A rendering of the boards from OSHPark.com.</p></div>
<p>Shown above is a rendering of the completed board design. The board outline is identical to the board outline of the one-key keyboard board outline. The layout is very similar as well. Note the footprint for the Tag-Connect programming cable to the left of the buzzer on the bottom of the board.</p>
<h2>Software</h2>
<h3>USB Output Reports and the CAPS LOCK State</h3>
<p>The CAPS LOCK state of a keyboard attached to a PC is maintained by the PC; not the keyboard. If you attach five keyboards to a PC and hit the CAPS LOCK key on one keyboard, the CAPS LOCK light on all five attached keyboards will illuminate. You can then hit the CAPS LOCK key on a different keyboard and all the CAPS LOCK lights will turn off.</p>
<p>This is implemented by the connected PC sending a periodic USB output report to all the attached keyboards. Inside this USB output report is a bit indicating the current state of the CAPS LOCK, NUM LOCK, and SCROLL LOCK keys. Attached keyboards examine these bits when the USB output report is received and turn their lights on and off according to these bits.</p>
<p>The annoying caps lock buzzer looks like a keyboard to the host PC except it doesn&#8217;t have any keys. The host sends the periodic USB output reports to our &#8220;keyboard&#8221; and when the USB output report is received, our &#8220;keyboard&#8221; turns the buzzer on or off to match the state of the CAPS LOCK bit in the USB output report.</p>
<h3>Writing the Software</h3>
<p>The software for this design is based on the <a href="https://www.microchip.com/mplab/microchip-libraries-for-applications">Microchip Library for Applications</a> (MLA) USB HID demo for low-pin count PIC micrcontrollers. In the unmodified version of the software, the software turns an LED on or off based on the USB output reports described in the previous section.</p>
<p>To make the annoying caps lock warning buzzer, I only had to change the pin used to turn the LED on or off from the default in the software to pin RC2, disable sending any pressed keys to the host PC, and recompile.</p>
<h2>Initial Bring Up</h2>
<div id="attachment_1424" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/power-supply.jpg"><img class="wp-image-1424 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/power-supply-1024x683.jpg" alt="power-supply" width="640" height="427" /></a><p class="wp-caption-text">One milliamp with an unprogrammed microcontroller and the buzzer turned off is about right. It&#8217;s now safe to connect the buzzer to the PC without worrying about damaging the PC.</p></div>
<p>For the initial bring up and programming, I used a <a href="https://www.keysight.com/us/en/products/dc-power-supplies/bench-power-supplies/e36300-series-triple-output-power-supply-80-160w.html">Keysight 36312A DC power supply</a> and a <a href="http://luislab.com/99-double-banana-plug-to-usb-a">double-banana plug to USB Type A adapter from Luislab</a> (shown above). I set the DC power supply to 5 Volts and set the current limit to 50 mA. This way if I accidentally shorted power to ground while soldering or there was a defect in the board, the power supply would go into current limit mode at a safe limit rather than causing damage to the board or my PC.</p>
<p>The USB Type A ports on a PC are required by the USB spec to have a self-resetting PTC fuse on them to protect the PC against damage if the connected USB device or cable has a short or draws too much current. The trip point for the thermal fuse is 1 A. In theory, I could plug the board into my PC for the initial bring up but the PC&#8217;s USB port is really not designed to limit current. It&#8217;s a safer option for my design and my PC to use a current-limited DC power supply for the initial bring up than to use one of my PC&#8217;s USB ports or a phone charger.</p>
<h2>Measurements</h2>
<h3>Verifying the Transistor Switch is Operating in the Saturation Region</h3>
<div id="attachment_1422" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/IMG_20190915_094831.jpg"><img class="size-large wp-image-1422" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/IMG_20190915_094831-1024x576.jpg" alt="Using my 34461A to measure V(CE)." width="640" height="360" /></a><p class="wp-caption-text">Using my 34461A to measure V(CE).</p></div>
<p>After bringing up the board and programming the microcontroller, I wanted to verify the transistor in the transistor switch was operating its saturation region. To do this, I used a <a href="https://www.keysight.com/en/pdx-2891615-pn-34461A/digital-multimeter-6-digit-truevolt-dmm?cc=US&amp;lc=eng">Keysight 34461A DMM</a> to measure the voltage between the collector and emitter of the transistor while the buzzer was on. The measurement was 4.1515 mV. The transistor is clearly operating in its saturation region. If it had not been, I would have needed to lower the value of R1 to increase the base-emitter current.</p>
<h3>Current Measurements</h3>
<div id="attachment_1513" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/probe.jpg"><img class="size-large wp-image-1513" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/probe-1024x683.jpg" alt="USB current probe board." width="640" height="427" /></a><p class="wp-caption-text">USB current probe board.</p></div>
<p>To measure the current I built a USB current probe board. This board connects the USB D+, D-, and ground lines directly from input to output. The +5V USB power from the PC is brought out to a red banana jack and the +5 power to the target is brought out to a black banana jack. A DMM in current measuring mode can then be connected to the two binding posts and used to measure the current consumption of the USB device.</p>
<div id="attachment_1512" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/on.jpg"><img class="size-large wp-image-1512" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/on-1024x670.jpg" alt="Current measurement with the buzzer on." width="640" height="419" /></a><p class="wp-caption-text">Current measurement with the buzzer on.</p></div>
<p>To measure the current, I connected the USB Type A plug on the current probe board to my PC using a USB extension. I connected the annoying CAPS LOCK warning buzzer to the the USB Type A receptacle on the current probe board using a USB A to Micro B cable. I then connected the banana jacks on the current probe board to the the low range current measurement inputs on my <a href="https://www.keysight.com/en/pdx-2882338-pn-U1272A/handheld-digital-multimeter-4-digit-ip54?cc=US&amp;lc=eng">Keysight U1272A</a> DMM.</p>
<p>With the buzzer off and the annoying CAPS LOCK warning buzzer enumerated on the USB bus on my PC, I measured a current of 8.062 mA. I then engaged CAPS LOCK on my PC and measured the current with the buzzer on. With the buzzer on, I measured a current of 35.64 mA. Both of these numbers are well below the maximum a USB Type A port on a PC can supply and reasonably match the expected values in the data sheets for the PIC16F1459 microcontroller and the buzzer.</p>
<p>(Disclaimer: I work for Keysight. The E36312A was purchased through our employee discount program. The 34461A and U1272A were purchased at full price before my employment there.)</p>
<h2>Enclosure</h2>
<div id="attachment_1429" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/09/enclosure.jpg"><img class="size-large wp-image-1429" src="https://bikerglen.com/wp/wp-content/uploads/2019/09/enclosure-1024x683.jpg" alt="The one-key USB keyboard enclosure modified for the buzzer." width="640" height="427" /></a><p class="wp-caption-text">The one-key USB keyboard enclosure modified for the buzzer.</p></div>
<p>The enclosure for this project is identical to the enclosure for the one-key USB keyboard project except the rectangular cutout has been replaced by a 10 mm diameter circular hole.</p>
<h2>Future Improvements</h2>
<p>I need to place a button and LED on the board and make them accessible from the bottom of the enclosure so that I can implement a USB bootloader for updating the buzzer firmware. I also need to add a <a href="https://www.nexperia.com/products/esd-protection-tvs-filtering-and-signal-conditioning/low-capacitance-esd-protection-for-high-speed-interfaces/PRTR5V0U2X.html">Nexperia PRTR5V0U2X ESD protection diode</a> to the USB D+ and D- data signals.</p>
<p>Breaking Update: The improvements have been made! They&#8217;re described in <a href="https://bikerglen.com/blog/updates-to-the-annoying-caps-lock-warning-buzzer/">this post</a>.</p>
<h2>BOM</h2>
<p>Here&#8217;s the BOM for this project. This BOM is also present in the design files for this project on Github. See the next section for a link.</p>
<table width="994">
<tbody>
<tr>
<td width="42">Line #</td>
<td width="126">Mfr. #</td>
<td width="126">Manufacturer</td>
<td width="508">Description</td>
<td width="70">Order Qty.</td>
<td width="122">Price (USD)</td>
</tr>
<tr>
<td>1</td>
<td>C1206C474K5RACTU</td>
<td>KEMET</td>
<td>50V 0.47uF X7R 1206 10%</td>
<td>1</td>
<td>$0.23</td>
</tr>
<tr>
<td>2</td>
<td>C1210C105K4PACTU</td>
<td>KEMET</td>
<td>16V 1uF X5R 1210 10%</td>
<td>1</td>
<td>$1.26</td>
</tr>
<tr>
<td>3</td>
<td>C1206C104J4RACTU</td>
<td>KEMET</td>
<td>16V 0.1uF X7R 1206 5%</td>
<td>1</td>
<td>$0.56</td>
</tr>
<tr>
<td>4</td>
<td>629105136821</td>
<td>Wurth Elektronik</td>
<td>USB Micro B</td>
<td>1</td>
<td>$1.21</td>
</tr>
<tr>
<td>5</td>
<td>PIC16F1459-I/SS</td>
<td>Microchip</td>
<td>8-bit MCU</td>
<td>1</td>
<td>$1.66</td>
</tr>
<tr>
<td>6</td>
<td>1N4148W-7-F</td>
<td>Diodes Incorporated</td>
<td>General Purpose Diode</td>
<td>1</td>
<td>$0.16</td>
</tr>
<tr>
<td>7</td>
<td>FMMT619TA</td>
<td>Diodes Incorporated</td>
<td>BJT NPN</td>
<td>1</td>
<td>$0.55</td>
</tr>
<tr>
<td>8</td>
<td>CR0805-JW-102ELF</td>
<td>Bourns</td>
<td>0805 1K 5%</td>
<td>1</td>
<td>$0.10</td>
</tr>
<tr>
<td>9</td>
<td>CX-0905C</td>
<td>CUI Inc.</td>
<td>Buzzer</td>
<td>1</td>
<td>$2.43</td>
</tr>
</tbody>
</table>
<h2>Design Files</h2>
<p>All of the design files for this project can be found in the <a href="https://github.com/bikerglen/caps-lock-buzzer">project&#8217;s repository</a> on Github.</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/the-annoying-caps-lock-warning-buzzer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PIC16F1459 USB Stack Light Controller</title>
		<link>https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/</link>
		<comments>https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/#comments</comments>
		<pubDate>Sun, 14 Apr 2019 02:28:34 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[3D Printing]]></category>
		<category><![CDATA[Microchip]]></category>
		<category><![CDATA[PIC18]]></category>
		<category><![CDATA[USB]]></category>

		<guid isPermaLink="false">https://bikerglen.com/blog/?p=1165</guid>
		<description><![CDATA[After using the PIC16F1459 to build numerous USB HID input devices including a giant keyboard, a tiny keyboard, and a big red button, it was time to see if the PIC16F1459 could be used to control outputs too. Sticking with &#8230; <a href="https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div id="attachment_1177" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/DSC00840-cropped-3.jpg"><img class="size-large wp-image-1177" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/DSC00840-cropped-3-1024x683.jpg" alt="    PIC16F1459-based USB industrial stack light controller. Looks pretty but will it work?" width="640" height="427" /></a><p class="wp-caption-text">PIC16F1459-based USB industrial stack light controller. Looks pretty but will it work?</p></div>
<p>After using the PIC16F1459 to build numerous USB HID input devices including a <a href="https://bikerglen.com/blog/building-a-giant-usb-three-key-mechanical-keyboard/">giant keyboard</a>, <a href="https://bikerglen.com/blog/presenting-the-single-esc-key-usb-keyboard/">a tiny keyboard</a>, and <a href="https://bikerglen.com/blog/usb-big-red-button/">a big red button</a>, it was time to see if the PIC16F1459 could be used to control outputs too. Sticking with the industrial theme, I chose to build a USB controller for a, um, stack of industrial stack lights.</p>
<p><span id="more-1165"></span></p>
<h2>Industrial Stack Lights</h2>
<div id="attachment_1174" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/DSC00814-cropped-resized.jpg"><img class="size-large wp-image-1174" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/DSC00814-cropped-resized-1024x683.jpg" alt="A variety of Allen-Bradley 855T industrial stack lights and parts I found on eBay." width="640" height="427" /></a><p class="wp-caption-text">A variety of Allen-Bradley 855T industrial stack lights and parts I found on eBay.</p></div>
<p><a href="https://en.wikipedia.org/wiki/Stack_light">Industrial stack lights</a> are usually used to indicate the status of machines on production lines. Green could indicate all is functioning normally, yellow could mean the machine is running low on input material, and red could indicate the machine jammed and needs intervention.</p>
<p>If you buy them <a href="https://www.automationdirect.com/adc/overview/catalog/stacklights">new</a>, they can be quite expensive&#8211;especially for a project you&#8217;re going to build, most likely use once, and then set on a shelf. Instead, consider eBay. It&#8217;s a great place to find slightly used to new-ish industrial buttons, indicators, and stack lights on the cheap.</p>
<p>The key parameters when searching for stack lights are operating voltage, usually either 24VDC or 120VAC, and bulb type, either incandescent or LED. I recommend the 24VDC LED versions if you can find them.</p>
<h2>Controlling Hardware with USB</h2>
<p>For a simple, quick project such as this one, one does not want to have to write a custom USB driver for a Mac, PC, or Linux box. The best way to avoid writing a custom driver is to use an existing USB device class that lends itself to controlling custom hardware. The USB Human Interface Device (HID) and USB Communication Device Class (CDC) device classes both support controlling custom hardware.</p>
<h3>USB HID Output Reports</h3>
<p><a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/introduction-to-hid-concepts#reports">USB HID output reports</a> are data blobs sent from an application running on a PC or other USB host to a USB HID device such as a keyboard or mouse or game controller. If you have a fancy gaming keyboard with tons of RGB LED lights, the application software on the PC could use USB HID output reports to control the state of the RGB LEDs on the keyboard. As another example, the Sony PS3 SixAxis DualShock controllers use USB HID output reports to activate the shaking of the controller.</p>
<p>The cool part about USB HID output reports is the USD HID device receives complete packets. There&#8217;s no parsing of a data stream required. You get a complete packet, pull the bytes out of the packet, and control the hardware as necessary. The downside is USB HID output reports need application software running on the USB host PC to send them which, of course, requires developing said application software.</p>
<h3>USB CDC</h3>
<p>Another USB device class that is suitable for controlling external hardware is the USB CDC device class. The USB CDC device class is typically used to implement <a href="https://www.ftdichip.com/Products/Cables/USBTTLSerial.htm">USB to serial converters</a> or to implement serial consoles on development boards like the <a href="https://www.adafruit.com/feather">Adafruit Feather</a> series.</p>
<p>The upside with the USB CDC device class is you can launch a serial console and immediately begin interacting with your hardware. No application development required. The downside is you have to have software on your hardware that parses the faux serial data stream to find the bytes that should control your hardware.</p>
<h3>Selected Method</h3>
<p>I decided to go with the USB CDC method for this project. I did not want to have to develop a custom application on my PC to control the hardware. Being able to launch a serial console and immediately interact with the hardware was very appealing. One day I will have to try sending a USB HID output report from a PC. Just not today. I&#8217;ve sent them from numerous embedded USB hosts; just never a PC USB host.</p>
<h2>Enclosure Design</h2>
<p>After thinking about the project some, I decided I wanted a red, amber, and green light, a cap, and the 10cm pole base. The 10cm pole base would mount to the top of an enclosure that holds the USB electronics. I found the stack light parts on eBay, ordered them, found their data sheets and 3D models on the Rockwell Automation / Allen-Bradley website, and set about designing the enclosure for the electronics using Autodesk Fusion 360.</p>
<h3>Parameterized 3D Modeling</h3>
<p>Fusion 360 supports parameterized 3D models. With a parameterized model, you create a bunch of parameters, assign the parameters default values, then use the names of those parameters in place of numeric values as you create the 3D model. It requires some planning ahead but makes changing the height or diameter or wall thickness of your model later almost trivial.</p>
<p>For this enclosure, I knew it&#8217;d have a diameter, a height, a wall thickness, four screw holes, four recesses to hold some M5 nuts, and those screw holes would be a certain distance from the center of the base. Here&#8217;s the parameters I created using the modify -&gt; change parameters command in the model view:</p>
<div id="attachment_1181" style="width: 1003px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/parameters.png"><img class="size-full wp-image-1181" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/parameters.png" alt="USB industrial stack light enclosure parameters." width="993" height="504" /></a><p class="wp-caption-text">USB industrial stack light enclosure parameters.</p></div>
<p>At this point, you&#8217;re ready to create your 3D model. Create a component, create a sketch inside the component, then as you&#8217;re laying out the initial geometry of your model on the sketch, use the parameter names from above instead of a numeric value for each dimension on the sketch. If you come back later and change a parameter, the dimensions on the sketch and the 3D bodies created from the sketch will update automatically.</p>
<p>Of all the parameters shown in the dialog box above, the enclosure height parameter was the most important and the one subject to changing the most. I did not know how tall the enclosure needed to be until I had the PCB designed and the connectors and screws for the project picked out.</p>
<h3>Initial Design of the Enclosure</h3>
<p>After creating the parameters, drawing a sketch based on the parameters, and extruding parts of the sketch, the enclosure looked like the images in the pictures below. This is not the final version of the enclosure, however, because there&#8217;s no place for the USB and power connectors.</p>
<p>Based on the dimensions in the data sheet for the 855T series 10 cm stack light base, the four posts inside the enclosure image below line up with the four screw holes in the stack light 10cm base. M5 screws are threaded through the 10 cm base, into these posts in the enclosure, then secured with a nut in the hexagonal recess in the bottom of the enclosure.</p>
<div id="attachment_1188" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-no-notch.png"><img class="size-large wp-image-1188" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-no-notch-1024x690.png" alt="An early version of the enclosure as viewed from above." width="640" height="431" /></a><p class="wp-caption-text">An early version of the enclosure as viewed from above.</p></div>
<p>Here&#8217;s the same version of the enclosure as viewed from the bottom. The hexagonal recesses each hold an M5 nut that mates with an M5 screw threaded through the stack light 10 cm base and the enclosure. The smaller posts and nut recesses are for 2-56 x 1/4&#8243; screws to hold a circuit board in the bottom of the enclosure. Based on the data sheet and 3D model for the stack light base, I decided to adjust the height of the enclosure to 17mm. This would allow the use of M5 x 20mm socket cap screws to hold everything together.</p>
<div id="attachment_1189" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-bottom-no-notch.png"><img class="size-large wp-image-1189" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-bottom-no-notch-1024x690.png" alt="An early version of the enclosure as viewed from the bottom." width="640" height="431" /></a><p class="wp-caption-text">An early version of the enclosure as viewed from the bottom.</p></div>
<h3>Electrical / Mechanical Codesign</h3>
<p>At this point, I had an enclosure that was sized to mount underneath the stack light&#8217;s base. The enclosure would be secured with four M5 x 20mm screws and M5 nuts. The next step was to design a circuit board to hold the electronics. The circuit board would also need a power connector for +24VDC to power the stack lights and a USB connector to talk to the host PC.</p>
<p>I used the inspect -&gt; measure command in the model view to measure the internal dimensions of the enclosure. The circuit board needed to be 24mm wide to fit between the posts and could be up to about 60mm long. I drew a board outline in Autodesk Eagle with these dimensions and placed a Phoenix 1803277 connector for +24VDC power and a Wurth 629105136821 connector for the USB connection to the PC on the board.</p>
<p>I then used Eagle to export a 3D model of the board into Fusion 360. I placed the board inside the enclosure and looked at the alignment of the square edge of the board, the rounded interior of the enclosure, and the placement of the connectors. They fit vertically but there was no way a USB cable could mate with the USB connector or the power input&#8217;s pluggable screw terminal block could mate with its header connector.</p>
<h3>The Connector Notch</h3>
<p>At this point it became obvious that the outside of the enclosure needed to be flat where the connectors protruded through the enclosure. Also, the inside of the enclosure had to be flat where the circuit board butted up against it. With a bit of work, I created a 1.5mm thick flat wall offset 0.5 mm from the edge of the circuit board.</p>
<p>This almost worked. The problem is that where the stack light base met the enclosure there was now a gap. The final solution was to include a 2mm tall circular portion above and below the flat portion as shown in the image below. This allowed the circuit board to butt up against a flat interior wall, it allowed the connectors to mate without interference, and it had a good fit to the stack light base when the stack light base was mounted to the top of the enclosure. The bottom 2mm circular portion is just for symmetry and aesthetics.</p>
<p>The image below shows the final notched enclosure and the circuit board with connectors mounted inside the enclosure. The cutouts for the connectors were created using the same offset plane, sketch, and extrude technique that I used to create the connector cut outs for the <a href="https://bikerglen.com/blog/homebrew-rgb-led-light/">DMX RGB light project</a>.</p>
<div id="attachment_1187" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-notch.png"><img class="wp-image-1187 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-notch-1024x690.png" alt="stack mount base v22 notch" width="640" height="431" /></a><p class="wp-caption-text">View of the model from the back which shows the notch in the enclosure and the connectors protruding through the notch.</p></div>
<p>The last item to do before ordering a 3D print was to find 3D models of the connectors, stack light base, and USB cable then assemble the stack light and enclosure in Fusion 360 to check that everything fit together without interference. The image below shows everything assembled. If the Phoenix connector had not cleared the circular part of the enclosure directly above it, I would have needed to adjust the height parameter to 19mm and used M5 x 22mm screws to assemble the project.</p>
<div id="attachment_1194" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-base.png"><img class="size-large wp-image-1194" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-base-1024x691.png" alt="Stack light base, enclosure, connectors, and cables." width="640" height="432" /></a><p class="wp-caption-text">Stack light base, enclosure, connectors, and cables.</p></div>
<p>Here&#8217;s how the notch and connectors turned out in real life:</p>
<div id="attachment_1237" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/notch-connectors.jpg"><img class="size-large wp-image-1237" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/notch-connectors-1024x682.jpg" alt="Close up of the notch and connectors." width="640" height="426" /></a><p class="wp-caption-text">Close up of the notch and connectors.</p></div>
<h3>Final Design of the Enclosure</h3>
<p>Here&#8217;s the final design of the enclosure as viewed from the top:</p>
<div id="attachment_1185" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-top.png"><img class="size-large wp-image-1185" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-top-1024x690.png" alt="Base / enclosure as viewed from the top." width="640" height="431" /></a><p class="wp-caption-text">Base / enclosure as viewed from the top.</p></div>
<p>Here&#8217;s the final design of the enclosure as viewed from the bottom:</p>
<div id="attachment_1186" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-bottom.png"><img class="size-large wp-image-1186" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/stack-mount-base-v22-bottom-1024x690.png" alt="Base / enclosure as viewed from the bottom." width="640" height="431" /></a><p class="wp-caption-text">Base / enclosure as viewed from the bottom.</p></div>
<h2>Hardware Design</h2>
<p>Now that the enclosure and PCB size were finalized it was time to design the electronics. One requirement was to be able to fade the stack lights in and out and control their brightness. The PIC16F1459 only has two hardware PWM channels though. To PWM three different colored stack light segments would require external hardware or some crafty software techniques. I decided to throw hardware at the problem.</p>
<p>The <a href="https://www.nxp.com/products/analog/interfaces/ic-bus/ic-led-controllers/16-channel-12-bit-pwm-fm-plus-ic-bus-led-controller:PCA9685">NXP PCA9685</a> is a 16-channel, 12-bit PWM I²C-bus LED controller. It can control 16 channels of 12-bit PWM over an I²C bus. The I²C bus only requires two IO pins on the PIC16F1459. A quick check of the PIC16F1459 data sheet confirms that the PIC supports I²C using two dedicated pins on the package. The I²C SCL clock signal is on pin RB6 and the I²C SDA clock signal is on pin RB4. This design will use four of the PCA9685&#8217;s 16 channels and leave the remaining channels unconnected.</p>
<p>Here&#8217; s the schematic for the design:</p>
<div id="attachment_1199" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/schematic.png"><img class="size-large wp-image-1199" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/schematic-1024x764.png" alt="USB stack light controller schematic. Needs ESD protection. Grrr." width="640" height="478" /></a><p class="wp-caption-text">USB stack light controller schematic. Needs ESD protection. Grrr.</p></div>
<p>Here&#8217;s the finished board layout:</p>
<div id="attachment_1200" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/board.png"><img class="wp-image-1200 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/board-680x1024.png" alt="board" width="640" height="964" /></a><p class="wp-caption-text">USB stack light controller board layout.</p></div>
<p>And some Oshpark renders of the board:</p>
<div id="attachment_1202" style="width: 1010px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/board-renders.png"><img class="size-full wp-image-1202" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/board-renders.png" alt="Oshpark renders of the USB stack light controller board." width="1000" height="913" /></a><p class="wp-caption-text">Oshpark renders of the USB stack light controller board.</p></div>
<p>Here&#8217;s the almost completely assembled board in the finished enclosure:</p>
<div id="attachment_1206" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/IMG_20190403_172044-cropped.jpg"><img class="size-large wp-image-1206" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/IMG_20190403_172044-cropped-1024x683.jpg" alt="Almost completely assembled board." width="640" height="427" /></a><p class="wp-caption-text">Almost completely assembled board.</p></div>
<h2>Software Design</h2>
<p>The software is based on the Microchip Library for Applications CDC Basic PIC16F1459 demonstration code. To this code, I added I²C code based on the example <a href="https://electrosome.com/i2c-pic-microcontroller-mplab-xc8/">here</a>, some PCA9685 configuration code, and a small CLI for interacting with the user in a terminal.</p>
<h3>Controlling the PCA9685</h3>
<p>The PCA9685 code has three functions defined. The first initializes the addressed PCA9685 over the I²C bus and sets all 16 channels to off:</p>
<pre>void PCA9685_Init (uint8_t addr)
{
    I2C_Master_Start ();
    I2C_Master_Write (addr);
    I2C_Master_Write (MODE1);
    I2C_Master_Write (0x30);
    I2C_Master_Stop ();
    
    I2C_Master_Start ();
    I2C_Master_Write (addr);
    I2C_Master_Write (PRESCALE);
    I2C_Master_Write (0x02);
    I2C_Master_Stop ();
    
    I2C_Master_Start ();
    I2C_Master_Write (addr);
    I2C_Master_Write (MODE1);
    I2C_Master_Write (0x20);
    I2C_Master_Stop ();
    
    for (uint8_t channel = 0; channel &lt; 16; channel++) {
        PCA9685_SetPWM (addr, channel, 0);
    }
}</pre>
<p>The second function takes an I²C address, a PCA9685 channel, and a level and converts the level to the on time and off time values needed by the PCA9685. The input level is a value from 0 for completely off to 4095 for completely on:</p>
<pre>void PCA9685_SetPWM (uint8_t address, uint8_t channel, uint16_t v)
{
    v &amp;= 0xFFF;
    if (v == 4095) {
        // fully on
        PCA9685_SetRaw (address, channel, 4096, 0);
    } else if (v == 0) {
        // fully off
        PCA9685_SetRaw (address, channel, 0, 4096);
    } else {
        PCA9685_SetRaw (address, channel, 0, v);
    }
}

</pre>
<p>This above function is based on the Adafruit code <a href="https://learn.adafruit.com/16-channel-pwm-servo-driver/downloads">here</a>.</p>
<p>The last function takes the values computed by the previous functions and sets the channel of the addressed PCA9685 to the specified levels:</p>
<pre>void PCA9685_SetRaw (uint8_t address, uint8_t channel, uint16_t on, uint16_t off)
{
    I2C_Master_Start ();
    I2C_Master_Write (PCA9685_I2C_ADDRESS);
    I2C_Master_Write (LED0_ON_L + 4 * channel);
    I2C_Master_Write (on);
    I2C_Master_Write (on &gt;&gt; 8);
    I2C_Master_Write (off);
    I2C_Master_Write (off &gt;&gt; 8);
    I2C_Master_Stop ();
}</pre>
<p>As a side note, the I²C address of the PCA9685 is really 0x40. These I²C communication routines though require the address to be in the upper 7 bits of the address byte. This is why the address is #defined as 0x80 instead of 0x40.</p>
<h3>The Command Line Interface</h3>
<p>Remember the desire to interact directly with the hardware using a serial console window? This requires that the CDC device have a command line interface (CLI). I added a very simple CLI to the APP_DeviceCDCBasicDemoTasks function inside the demo code. The CLI accepts up to 72 characters per line. It supports the printable ASCII characters, backspace, and return.</p>
<p>When the user hits the return key, the CLI attempts to parse a decimal channel number and decimal level value from the entered command line. If successful, the CLI sets the specified channel of the PCA9685 to the specified level and returns &#8220;Ok&#8221; to the user. If not successful, the CLI returns &#8220;Err&#8221; to the user. Here&#8217;s an example terminal session with the stack light controller:</p>
<div id="attachment_1212" style="width: 832px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/RGU_T3aw.png"><img class="size-full wp-image-1212" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/RGU_T3aw.png" alt="CLI Terminal Session" width="822" height="667" /></a><p class="wp-caption-text">CLI Terminal Session</p></div>
<p>The first successful command sets channel 0 to 1. The next one sets channel 0 to 4095. The last one sets channel 15 to 2000. A future improvement to the CLI would be to add commands to support blinking and fading the stack lights on and off.</p>
<h3> Testing the Software</h3>
<p>Before completely assembling everything, I did test the software with a single light:</p>
<div id="attachment_1208" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/vlcsnap-2019-04-13-19h32m28s836.png"><img class="size-large wp-image-1208" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/vlcsnap-2019-04-13-19h32m28s836-1024x576.png" alt="Another example of my most excellent ESD precautions while I test the I2C and PCA9685 software." width="640" height="360" /></a><p class="wp-caption-text">Another example of my most excellent ESD precautions while I test the I2C and PCA9685 software.</p></div>
<p>This verified the CLI, I2C, and PCA9685 were all operational.</p>
<h2>Assembly</h2>
<div id="attachment_1180" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/04/DSC00850-cropped.jpg"><img class="size-large wp-image-1180" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/DSC00850-cropped-1024x683.jpg" alt="Well, that's inconvenient. Next build gets a pluggable terminal block." width="640" height="427" /></a><p class="wp-caption-text">Well, that&#8217;s inconvenient. Next build gets a pluggable terminal block.</p></div>
<p>The final step was to assemble everything. The first time I assembled everything, I forgot the rubber gasket. It&#8217;s not really needed in my non-industrial home workshop environment it but does provide a better transition between the base and the enclosure. In a future version of this project, I should replace the screw terminal strip with a small pluggable terminal block to make assembly and disassembly easier. Here are a few more photos of the project in various stages of completion. Thanks for reading!</p>

<a href='https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/dsc00856-1/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/DSC00856-1-150x150.jpg" class="attachment-thumbnail" alt="Green" /></a>
<a href='https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/dsc00858-1/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/DSC00858-1-150x150.jpg" class="attachment-thumbnail" alt="Red" /></a>
<a href='https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/dsc00859-1/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/DSC00859-1-150x150.jpg" class="attachment-thumbnail" alt="All" /></a>
<a href='https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/dsc00860-1/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/DSC00860-1-150x150.jpg" class="attachment-thumbnail" alt="None" /></a>
<a href='https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/bench/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/bench-150x150.jpg" class="attachment-thumbnail" alt="On the bench" /></a>
<a href='https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/dsc00863-1/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/DSC00863-1-150x150.jpg" class="attachment-thumbnail" alt="Base / enclosure interface" /></a>
<a href='https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/1-3/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/1-150x150.jpg" class="attachment-thumbnail" alt="Board" /></a>
<a href='https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/2-3/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/2-150x150.jpg" class="attachment-thumbnail" alt="Board and enclosure" /></a>
<a href='https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/3-2/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/3-150x150.jpg" class="attachment-thumbnail" alt="Board and enclosure" /></a>
<a href='https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/4-2/'><img width="150" height="150" src="https://bikerglen.com/wp/wp-content/uploads/2019/04/4-150x150.jpg" class="attachment-thumbnail" alt="Board and enclosure and light" /></a>

<h2>Code and Models</h2>
<p>Code and models are available upon request. They&#8217;ll most likely end up on github.com/bikerglen at some point.</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/pic16f1459-usb-stack-light-controller/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Piggybacking USB onto an Industrial Push Button</title>
		<link>https://bikerglen.com/blog/usb-big-red-button/</link>
		<comments>https://bikerglen.com/blog/usb-big-red-button/#comments</comments>
		<pubDate>Wed, 13 Mar 2019 19:08:09 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[3D Printing]]></category>
		<category><![CDATA[Microchip]]></category>
		<category><![CDATA[PIC18]]></category>
		<category><![CDATA[USB]]></category>
		<category><![CDATA[USB Human Interface Device (HID)]]></category>

		<guid isPermaLink="false">https://bikerglen.com/blog/?p=963</guid>
		<description><![CDATA[In this project, I mount the electronics from my single-key USB keyboard project to the back of an industrial mushroom push button switch. The finished big red button now activates my screensaver with a single overly-large button press. The biggest &#8230; <a href="https://bikerglen.com/blog/usb-big-red-button/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div id="attachment_966" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_105700.jpg"><img class="size-large wp-image-966" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_105700-1024x576.jpg" alt="The completed USB-connected big red button." width="640" height="360" /></a><p class="wp-caption-text">The completed USB-connected big red button.</p></div>
<p>In this project, I mount the electronics from my <a href="https://bikerglen.com/blog/presenting-the-single-esc-key-usb-keyboard/">single-key USB keyboard</a> project to the back of an industrial mushroom push button switch. The finished big red button now activates my screensaver with a single overly-large button press. The biggest issues in this project were where to mount the USB electronics and how to connect the USB cable between the button and my computer.</p>
<p><span id="more-963"></span></p>
<h2>A Few Words About Industrial Controls</h2>
<p>Industrial push buttons and indicators are the exact opposite of today&#8217;s sleek capacitive touchscreens. They&#8217;re tactile, bulky, single-purpose, take some force to operate, and are built to take abuse from both the environment and users. When a button fails after years of abuse, they&#8217;re modular to facilitate quick repairs and get whatever process they&#8217;re controlling back online quickly. (They do make industrial-rated touchscreen controllers if you really do need to have a touchscreen, e.g., to show / control process parameters.)</p>
<div id="attachment_1038" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/buttons.jpg"><img class="size-large wp-image-1038" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/buttons-1024x669.jpg" alt="Random Omron switch parts including a shrouded red non-illuminated push button, illuminated mushroom button, a mounting collar, LED, NO contacts, illumination unit, NC contacts, and an assembled non-illuminated mushroom button." width="640" height="418" /></a><p class="wp-caption-text">Random Omron switch parts including a shrouded red non-illuminated push button, illuminated mushroom button, a mounting collar, LEDs, NO contacts, illumination unit, NC contacts, and an assembled non-illuminated mushroom button.</p></div>
<p>In the photo above are a few disassembled Omron 22mm push button switches. The typical switch consists of an actuator, a mounting collar or frame, contact blocks, and, if illuminated, an illumination unit. The actuator is the part that mounts to the panel and is exposed to the user. These vary in shape and color often depending on if they&#8217;re designed to be easy to press (emergency power off) or hard to press (start self-destruct sequence).</p>
<p>The part immediately behind the actuator is a frame that connects the contact blocks to the actuator. The contact blocks do the electrical switching and are available in a variety of configurations such as normally open, normally closed, screw terminals, quick connect terminals, etc.</p>
<p>On these Omron controls, the contact blocks snap to the frame and a plunger on the actuator presses a plunger on the contact block to change the state of the contacts. In other designs, they mount using screws. Finally, if the switch is illuminated, there&#8217;s an illumination unit that can hold an LED or incandescent bulb. Below is a page from an <a href="http://www.ia.omron.com/data_pdf/cat/a22n_m22n_a30n_a254-e1_4_5_csm1045427.pdf?id=3443.">Omron Industrial Automation catalog</a> showing some of the available configurations and how they fit together.</p>
<div id="attachment_1022" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/omron-catalog-page1.jpg"><img class="wp-image-1022 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/omron-catalog-page1-724x1024.jpg" alt="" width="640" height="905" /></a><p class="wp-caption-text">A page from the Omron industrial controls catalog.</p></div>
<p>By splitting the switch into so many pieces, the exact switch needed for a job can be built from its component parts. Also repairs can be performed quickly. For example if the actuator is broken, one can disconnect the frame, replace the actuator, reconnect the frame, and be back in business without any rewiring.</p>
<h2>Where to Mount the Electronics</h2>
<p>The immediate goals for this project were (1) to use a big red button and (2) to connect it to a computer using USB. Like any engineering project, there&#8217;s tons of ways to get to a solution and it&#8217;s my job to pick the optimum solution (where optimum is open to debate).</p>
<p>My first thought was to build a small box that had screw terminals for a contact closure input on one side and a USB connector on the other side. This box would sit between the big red button&#8217;s enclosure and the computer. A small circuit board would hold the USB electronics and I&#8217;d 3D print a case for it.</p>
<p>My second thought was to just let a loose circuit board float between the contact blocks inside the big red button&#8217;s enclosure. Things are pretty well insulated so it would be unlikely to short out. But I didn&#8217;t want this thing rattling inside my switch. Then it finally came to me, what if I could mount the electronics to the switch just like a contact block mounts to the switch?</p>
<h2>Mechanical Design</h2>
<div id="attachment_1005" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/lid-and-button.jpg"><img class="size-large wp-image-1005" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/lid-and-button-1024x576.jpg" alt="Raw materials. The lid of the enclosure and pushbutton switch with mushroom operator." width="640" height="360" /></a><p class="wp-caption-text">Raw materials. The lid of the enclosure and pushbutton switch with mushroom operator.</p></div>
<p>Omron Industrial Automation makes some relatively inexpensive industrial push buttons that are available from the usual distributors. They also make a nice bright yellow enclosure specifically for emergency stop / emergency power off / big red button mushroom switches. I went to Digi-Key and ordered an Omron A22NN-BMM-NRA-G100-NN mushroom switch for $10.97 and to Arrow and ordered an OmronA22NZ-A-B01Y single button enclosure for $12.74. These are shown in the photo above.</p>
<div id="attachment_994" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/A22NZ_S_G1A-v1.png"><img class="wp-image-994 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/A22NZ_S_G1A-v1-1024x709.png" alt="Stock Omron Contact Block 3D Model." width="640" height="443" /></a><p class="wp-caption-text">The stock Omron normally open contact block 3D model with a bit of additional color.</p></div>
<p>I needed a starting point for my PCB holder. Fortunately, Omron and most of the other industrial controls vendors publish 3D models of their devices. These models are primarily used during design of industrial control panels to make sure everything fits without interference. I downloaded Omron&#8217;s 3D model of their contact block, shown above, then used Fusion 360 to carve out an area to hold a small PCB. This most likely violates Omron&#8217;s terms of use for their models but since this is a one-off, personal, non-commercial project (aka a hack), I&#8217;m going to call it fair use and not lose any sleep over it.</p>
<div id="attachment_1001" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/contact-block-clip-in-board-knubs-v2-b.png"><img class="size-large wp-image-1001" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/contact-block-clip-in-board-knubs-v2-b-1024x709.png" alt="A render of the contact block circuit board holder and circuit board. Sometimes renders don't work out in real life." width="640" height="443" /></a><p class="wp-caption-text">A render of the contact block circuit board holder and circuit board. Sometimes renders don&#8217;t work out in real life.</p></div>
<p>With a bit of work, I carved out an area to hold the circuit board, fit the board into the model, and added some tabs to hold the board in place without screws. Be sure to scrape off the switch plunger too otherwise you&#8217;ll end up with a fixed piece of plastic on top of the contact block frame that blocks the operation of the button.</p>
<div id="attachment_1004" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/failures.jpg"><img class="size-large wp-image-1004" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/failures-1024x576.jpg" alt="Failure is good as long as you learn from it, right?" width="640" height="360" /></a><p class="wp-caption-text">Failure is good as long as you learn from it, right?</p></div>
<p>This design took a few iterations to get right. I printed the PCB holder in different materials at different 3D printing places. The SLS PA nylon process at Shapeways had different dimensions than the SLS PA nylon process at Sculpteo. The HP JetFusion process at Sculpteo had different dimensions than the SLS PA nylon process at Sculpteo. In addition, the HP JetFusion nylon is more brittle / less flexible than the SLS PA nylon. I finally got a print of a holder that would work in the SLS PA nylon process from Sculpteo.</p>
<div id="attachment_997" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/boards.jpg"><img class="size-large wp-image-997" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/boards-1024x464.jpg" alt="Three failed boards and one good board. Fails: 1) screws rather than tabs. 2) header strip hits holder. 3) slots too small to accommodate tabs. Success: slots and header strip work!" width="640" height="290" /></a><p class="wp-caption-text">Three failed boards and one good board. Fails: 1) screws rather than tabs. 2) header strip hits holder. 3) slots too small to accommodate tabs. Success: slots and header strip work!</p></div>
<p>Unfortunately, I broke the tabs off the holder trying to fit the circuit board into the holder. Rather than redesign the holder, I redesigned the circuit board to have slightly bigger notches that wouldn&#8217;t stress the tabs as much during insertion. I went through a total of four revisions of the circuit board. The post office even lost two revisions of the boards for two weeks before finally finding them and delivering them.</p>
<div id="attachment_986" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_104835.jpg"><img class="size-large wp-image-986" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_104835-1024x576.jpg" alt="The finished circuit board and 3D printed holder next to the back parts of an Omron switch." width="640" height="360" /></a><p class="wp-caption-text">The finished circuit board and 3D printed holder next to the back parts of an Omron switch.</p></div>
<p>Success. After many more weeks and iterations than it should have taken, I finally got things right. With a bit of finesse and luck, I was able to place the finished circuit board into the 3D printed holder. I didn&#8217;t test the electronics before putting the board in the holder. Luckily, they did work.</p>
<p>Finally, I did a bit of assembly in Fusion 360 to see if there was any hope of a USB cable mating with the USB connector on the PCB. I couldn&#8217;t get section analysis to work in the render view of Fusion 360 so I just lopped the bottom of the enclosure off for the render.</p>
<div id="attachment_1019" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/A22NZ_A_B01Y-v6-b.jpg"><img class="wp-image-1019 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/A22NZ_A_B01Y-v6-b-1024x709.jpg" alt="" width="640" height="443" /></a><p class="wp-caption-text">Will a USB cable connect to the board inside the enclosure? That&#8217;s a definite maybe.</p></div>
<h2>Electrical Design</h2>
<div id="attachment_987" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_105314.jpg"><img class="wp-image-987 size-large" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_105314-1024x576.jpg" alt="Board assembled into holder. i had access to isopropyl alchohol and lint-free cleaning swabs so the board is a bit cleaner than my usual boards." width="640" height="360" /></a><p class="wp-caption-text">Board assembled into holder. I had access to isopropyl alcohol and lint-free cleaning swabs during assembly so the board is a bit cleaner than my usual boards.</p></div>
<p>The electrical design on this project was easy. It&#8217;s the same electronics as on the <a href="https://bikerglen.com/blog/presenting-the-single-esc-key-usb-keyboard/">single-key USB keyboard</a> project except I added a Texas Instruments TPD2E2U06QDBZRQ1 ESD protection device to the USB data lines and replaced the Cherry MX keyboard switch with a two pin 0.1&#8243; right angle header. Next time I might try a Nexperia PRTR5V0U2X that can protect both the USB power line and USB data lines.</p>
<h2>Software Design</h2>
<div id="attachment_1007" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190310_162519.jpg"><img class="size-large wp-image-1007" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190310_162519-1024x576.jpg" alt="Programming the bootloader is a bit of a pain but thankfully it only has to be done once." width="640" height="360" /></a><p class="wp-caption-text">Programming the bootloader is a bit of a pain but thankfully it only has to be done once.</p></div>
<p>The software is divided into two parts, a bootloader and the application software. These are the same as on the <a href="https://bikerglen.com/blog/presenting-the-single-esc-key-usb-keyboard/">single-key USB keyboard</a> project too. The USB bootloader is programmed into the part using any PIC programmer such as a REAL ICE or MPLAB ICD 4. It&#8217;s a bit awkward holding the programmer adapter on the board as shown in the photo above but it only has to be done once. The bootloader then enables the application software to be updated over USB without disassembling the completed project.</p>
<p>Once the bootloader is programmed, the application software may be updated by holding down the big red button while connecting the USB cable to the computer. This action enables the bootloader then the bootloader utility from the Microchip Libaries for Applications may be run to load new application software onto the PIC16F1459.</p>
<p>Currently I have two versions of the application software. One inserts a poop emoji into Microsoft documents. The other hits right-ctrl to escape Oracle&#8217;s VirtualBox&#8217;s keyboard capture then left-ctrl &amp; left-alt &amp; l to invoke the RHEL screensaver / screen lock on my Linux box at work.</p>
<h2>Final Touches</h2>
<p>Now the only thing left to do was to assemble everything. It took a bit of finesse to get the board mounted into the holder without breaking anything.</p>
<div id="attachment_987" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_105314.jpg"><img class="size-large wp-image-987" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_105314-1024x576.jpg" alt="Board assembled into holder." width="640" height="360" /></a><p class="wp-caption-text">Board assembled into holder.</p></div>
<p>Next was a dry fit test of the assembled push button.</p>
<div id="attachment_1033" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/dry-fit.jpg"><img class="size-large wp-image-1033" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/dry-fit-1024x683.jpg" alt="Yep, everything fits!" width="640" height="427" /></a><p class="wp-caption-text">Yep, everything fits!</p></div>
<p>I used some jumper wires with a two position 0.1&#8243; socket header attached to connect the contact block to the circuit board.</p>
<div id="attachment_986" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_104835.jpg"><img class="size-large wp-image-986" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_104835-1024x576.jpg" alt="The finished circuit board and 3D printed holder next to the back parts of an Omron switch." width="640" height="360" /></a><p class="wp-caption-text">The finished circuit board and 3D printed holder next to the back parts of an Omron switch.</p></div>
<p>Then I snapped the contact block and holder into place on the switch frame and mounted the switch frame to the actuator. Sliding the little yellow lever below the USB cable locks the frame to the actuator.</p>
<div id="attachment_988" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_105452.jpg"><img class="wp-image-988 size-large" title="Assembled Switch and USB Board" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_105452-1024x576.jpg" alt="IMG_20190224_105452" width="640" height="360" /></a><p class="wp-caption-text">Here&#8217;s a view with everything assembled and mounted to the top half of the enclosure.</p></div>
<p>And voila! The finished project!</p>
<div id="attachment_966" style="width: 650px" class="wp-caption alignnone"><a href="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_105700.jpg"><img class="size-large wp-image-966" src="https://bikerglen.com/wp/wp-content/uploads/2019/03/IMG_20190224_105700-1024x576.jpg" alt="The completed USB-connected big red button." width="640" height="360" /></a><p class="wp-caption-text">The completed USB-connected big red button.</p></div>
<h2>Design Files</h2>
<p>If you&#8217;re interested in the mechanical design files for the project, let me know via Twitter and I&#8217;ll post them to github. In the meantime, check out the software and schematic for my single-key keyboards on <a href="https://github.com/bikerglen/small-keyboards">github</a>.</p>
<h2>An Important Safety Note</h2>
<p>As fun as this project may have been, please do NOT use USB for an actual safety-related emergency stop or emergency power off. USB is just not reliable enough for safety-related devices.</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/usb-big-red-button/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Presenting the Single ESC Key USB Keyboard!</title>
		<link>https://bikerglen.com/blog/presenting-the-single-esc-key-usb-keyboard/</link>
		<comments>https://bikerglen.com/blog/presenting-the-single-esc-key-usb-keyboard/#comments</comments>
		<pubDate>Tue, 15 May 2018 20:51:25 +0000</pubDate>
		<dc:creator><![CDATA[Glen]]></dc:creator>
				<category><![CDATA[3D Printing]]></category>
		<category><![CDATA[Microchip]]></category>
		<category><![CDATA[PIC18]]></category>
		<category><![CDATA[USB]]></category>
		<category><![CDATA[USB Human Interface Device (HID)]]></category>

		<guid isPermaLink="false">http://bikerglen.com/blog/?p=878</guid>
		<description><![CDATA[After building the “awesomely impractical” giant three-key keyboard, I decided it was time to build something a bit more practical—presenting the single ESC key USB keyboard! This keyboard has exactly one function which is to provide an optimal ESCing experience &#8230; <a href="https://bikerglen.com/blog/presenting-the-single-esc-key-usb-keyboard/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div id="attachment_948" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00651_crop2.jpg"><img class="size-large wp-image-948" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00651_crop2-1024x682.jpg" alt="The single ESC key USB keyboard." width="640" height="426" /></a><p class="wp-caption-text">The single ESC key USB keyboard.</p></div>
<p>After building the “<a href="https://blog.hackster.io/ginormous-3-switch-keyboard-is-awesomely-impractical-748b79e471b3">awesomely impractical</a>” giant <a href="http://bikerglen.com/blog/building-a-giant-usb-three-key-mechanical-keyboard/">three-key keyboard</a>, I decided it was time to build something a bit more practical—presenting the single ESC key USB keyboard! This keyboard has exactly one function which is to provide an optimal ESCing experience regardless of whatever keyboard you normally use. In exchange for giving up a USB port, you get a dedicated tactile, clicky Cherry MX blue ESC key.</p>
<p><span id="more-878"></span></p>
<p>The only possible target demographics for this keyboard are vi/vim users on touch strip MacBooks or those who like wasting USB ports on needless functions. On the slightly more practical side, there’s a three-key version too. With a bit of programming, these three keys can be assigned whatever functions are needed. On mine, the first key does CTRL-ALT-DEL, the second key locks the screen (META-L), and the third key is an escape key.</p>
<div id="attachment_949" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00658_crop.jpg"><img class="wp-image-949 size-large" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00658_crop-1024x683.jpg" alt="The three key USB keyboard." width="640" height="427" /></a><p class="wp-caption-text">The three key USB keyboard. The LEDs underneath the keycaps are really only useful for debugging.</p></div>
<h2>Goals</h2>
<p>The only real goal with this keyboard was to see how small I could build a functional USB keyboard with a Cherry MX key switch. The keyboard needed to have an enclosure and the enclosure needed to be easy to assemble and disassemble which meant using screws to hold it together versus snapping together.</p>
<h2>Selecting Parts</h2>
<h3>Picking a USB Microcontroller</h3>
<p>I chose a PIC16F1459 in an SSOP-20 package for the microcontroller. The PIC16F145x family provides a minimal parts count solution to implementing the USB 2.0 standard. No external oscillator is required because this micro has an internal 48MHz oscillator and uses active clock tuning to fine-tune the internal oscillator frequency to the recovered clock from the USB host. This micro, a USB connector, and three capacitors are all that are needed to implement a fully-functional USB 2.0 device.</p>
<div id="attachment_930" style="width: 1012px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/min-sch.png"><img class="size-full wp-image-930" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/min-sch.png" alt="Minimal PIC16F1459 schematic for USB 2.0 operation." width="1002" height="351" /></a><p class="wp-caption-text">Minimal PIC16F1459 schematic for USB 2.0 operation.</p></div>
<p>Once I selected the microcontroller, I needed to pick a package for the microcontroller. The PIC16F1459 is available in DIP, SOIC, SSOP, and QFN packages. I chose the SSOP-20 package. The two larger packages were too big to fit in the allocated board space and the QFN package, though smaller, would be considerably more difficult to hand solder.</p>
<h3>The USB Connector</h3>
<p>Next up was to find a suitable USB Micro-B connector. Since the entire board was to be hand soldered, I wanted a connector with locating pins to position the connector on the board while I soldered it and with enough room between the connector housing and the five signals pins that I could easily see what I was doing with a microscope. I ordered a bunch of USB Micro-B connectors, examined each of them, and finally found a Wurth Electronics connector that met my needs.</p>
<div id="attachment_937" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC_2096_crop.jpg"><img class="wp-image-937 size-large" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC_2096_crop-1024x681.jpg" alt="DSC_2096_crop" width="640" height="426" /></a><p class="wp-caption-text">Wurth Electronics USB Micro-B Receptacle part number 629105136821. It has little black plastic posts to keep the connector centered while soldering and plenty of room between the shell and pins for the soldering iron, flux, solder, and inevitably, wick.</p></div>
<h3>The Other Electrical Components</h3>
<p>The rest of the electrical components weren&#8217;t super critical—a 0.47uF capacitor on the VUSB pin, a 0.1uF capacitor on the VDD pin, 1uF of bulk capacitance on the board, an LED, and a resistor. I used 1206 packages for the caps and resistor and a 3528 package for the LED because these were parts I had on hand.</p>
<div id="attachment_932" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/final-sch.png"><img class="size-large wp-image-932" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/final-sch-1024x264.png" alt="Complete one key USB keyboard schematic." width="640" height="165" /></a><p class="wp-caption-text">Complete one key USB keyboard schematic.</p></div>
<h2>The PCB</h2>
<p>Cherry MX key switches nominally occupy a 3/4” by 3/4” square area on the PCB. I decided to try to make the PCB 1” by 1”. It would have to be double sided with the key switch and LED on one side and the rest of the components on the other.</p>
<p>I drew a 1” x 1” board outline with 0.05” radius corners then placed a 0.1” diameter hole in each of the four corners. The holes are 0.1” from the edges of the board. I also tried to keep a 0.2” square keep out in each corner, but I ended up putting one cap, C2, a bit closer to the hole than I should have. The board turned out fine, but it significantly complicated the design of the enclosure. More on that later.</p>
<p>I found Eagle PCB libraries for the PIC, the USB connector, and the Cherry MX key switch. Links to these are in the Useful Resources section at the end of the blog post. I placed these components, wired everything up, made the gerbers, and ordered boards.</p>
<div id="attachment_926" style="width: 1017px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/one-key-top-and-bottom.png"><img class="size-full wp-image-926" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/one-key-top-and-bottom.png" alt="One key USB right keyboard PCB top and bottom views." width="1007" height="501" /></a><p class="wp-caption-text">One key USB right keyboard PCB top and bottom views.</p></div>
<h2>The Enclosure</h2>
<p>While the boards were being manufactured, I turned to the design of the enclosure.</p>
<h3>PCB 3D Model</h3>
<p>The first step was to use ecad.io to turn my PCB design into a 3D model that I could use to test the fit of the enclosure.</p>
<div id="attachment_911" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/one-key-model.png"><img class="size-large wp-image-911" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/one-key-model-1024x733.png" alt="3D model of the PCB." width="640" height="458" /></a><p class="wp-caption-text">3D model of the PCB.</p></div>
<h3>Critical Dimensions</h3>
<p>The second step was to gather a list of critical dimensions. These are based on past experience and reading specs:</p>
<ul>
<li>Wall thickness: 1.5mm.</li>
<li>Space between PCB edges and walls: 0.5mm.</li>
<li>Board thickness: 1.6mm but allow 1.65mm.</li>
<li>2-56 screw free fit hole diameter: 2.54mm.</li>
<li>2-56 screw countersink diameter and angle: 5.30mm and 82 degrees.</li>
<li>2-56 nut cavity: 5mm across flats, 2mm deep.</li>
<li>Maximum USB Micro-B overmold dimensions: 10.6 by 8.5mm.</li>
<li>Minimum USB Micro-B mated clearance: 1.3mm</li>
<li>3D printer minimum wall thickness: 0.6mm, ideally 1mm.</li>
</ul>
<h3>Enclosure Bottom</h3>
<p>I started with the enclosure bottom. The PCB is 25.4mm x 25.4mm so the enclosure needed to be 29.4mm x 29.4mm to allow for the 1.5mm wall thickness and 0.5mm space around the board edges. I added screw holes and recesses for the nuts on underside of the bottom of the enclosure.</p>
<div id="attachment_913" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/enclosre-bottom-2.png"><img class="wp-image-913 size-large" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/enclosre-bottom-2-1024x682.png" alt="enclosre bottom 2" width="640" height="426" /></a><p class="wp-caption-text">Enclosure bottom (exterior view).</p></div>
<div id="attachment_912" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/enclosre-bottom.png"><img class="wp-image-912 size-large" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/enclosre-bottom-1024x682.png" alt="Enclosure Bottom" width="640" height="426" /></a><p class="wp-caption-text">Enclosure bottom (interior view).</p></div>
<p>Here I hit the first snag. I needed at least 0.6mm and, ideally, 1mm of material around the top and sides of the hex nut recesses on the bottom of the enclosure to meet my 3D printer&#8217;s minimum wall specs. If I added this material all the way to the top of the enclosure, it would have necessitated a 6mm square keepout area in each corner of the PCB. Unfortunately capacitor C2 was already in this keepout area (see illustration below).</p>
<p>Since C2 was in the way, I only brought the material up 1.5 mm from the interior of the enclosure (which is 3mm from the exterior of the enclosure). This left a 1mm wall between the top of the nut recess and the interior of the enclosure. This was was within specs for printing and provided plenty of clearance for C2. Problem solved but next time I would have tried to move the capacitor over a bit on the PCB!</p>
<div id="attachment_905" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/nut-recess-clearance.png"><img class="size-large wp-image-905" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/nut-recess-clearance-1024x666.png" alt="C2 is in the upper left hand corner. Dark blue is a face of the 6mm x 6mm cube around the nut recess. Light blue is the nut recess. The arrow indicates the 1mm wall thickness between the cube face and nut recess." width="640" height="416" /></a><p class="wp-caption-text">C2 is in the upper left hand corner. Dark blue is a face of the 6mm x 6mm cube around the nut recess. Light blue is the nut recess. The arrow indicates the 1mm wall thickness between the cube face and nut recess.</p></div>
<p>The second snag involved the the overall height of the enclosure. Initially the bottom was 5mm high making the enclosure 11.65mm high overall. I planned on using 7/16&#8243; screws to assemble the enclosure. Unfortunately, my 7/16” screws were 0.020” short and barely reached the nuts. Also, the maximum USB plug overmold thickness is 8.5mm so for thick USB plugs the keyboard could be resting on the bottom of the USB plug versus resting on its own bottom.</p>
<p>Increasing the bottom height to 6.05mm and the overall enclosure height to 12.7mm solved both these issues. First, I could use 0.5” screws to assemble everything which more than adequately reached the recessed nuts. Second, this increased the distance from the center of the USB receptacle to the bottom of the housing to 4.7mm which is greater than the 4.25mm required by the USB Micro-B max overmold dimension specification.</p>
<div id="attachment_907" style="width: 838px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/overmold-clearance.png"><img class="size-full wp-image-907" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/overmold-clearance.png" alt="6.05 mm bottom height meets 4.25mm USB overmold clearance requirement." width="828" height="439" /></a><p class="wp-caption-text">6.05 mm bottom height meets 4.25mm USB overmold clearance requirement.</p></div>
<p>The last critical dimension is the minimum mated clearance of a USB Micro-B receptacle and USB Micro-B plug. This dimension is listed as 1.3mm in the USB Micro-B connector specification. When a USB cable is plugged into the connector on the USB keyboard, they need to be fully mated. In order to support this requirement, the distance from the exterior face of the enclosure to the metal guides on the USB receptacle needs to be less than 1.3mm. In my design, they&#8217;re 0.7mm which will work.</p>
<div id="attachment_909" style="width: 889px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/mated-clearance.png"><img class="wp-image-909 size-full" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/mated-clearance.png" alt="0.7mm clearance between receptacle guides and exterior face of enclosure." width="879" height="714" /></a><p class="wp-caption-text">0.7mm clearance between receptacle guides and exterior face of enclosure.</p></div>
<h3>Enclosure Top</h3>
<div id="attachment_916" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/enclosure-top-2.png"><img class="wp-image-916 size-large" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/enclosure-top-2-1024x683.png" alt="enclosure top 2" width="640" height="427" /></a><p class="wp-caption-text">Enclosure top (exterior view).</p></div>
<div id="attachment_915" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/enclosure-top-1.png"><img class="wp-image-915 size-large" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/enclosure-top-1-1024x682.png" alt="enclosure top 1" width="640" height="426" /></a><p class="wp-caption-text">Enclosure top (interior view).</p></div>
<p>The enclosure top was significantly less challenging to design. The height needed to be the board height (1.65mm) plus the height to the bottom of the depressed key cap (about 5mm). I drew the exterior walls of the enclosure, added some cylinders around the screws, drew the countersink holes, cut out a square for the key switch, and added a bit of a notch around the USB connector. The cylinders are 1.65mm shorter than the enclosure so that the board fits completely recessed into the top of the enclosure.</p>
<div id="attachment_918" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/recessed-board.png"><img class="size-large wp-image-918" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/recessed-board-1024x682.png" alt="PCB fits recessed into the bottom of the top half of the enclosure." width="640" height="426" /></a><p class="wp-caption-text">PCB fits recessed into the bottom of the top half of the enclosure.</p></div>
<h3>Manufacturing the Enclosure</h3>
<p>I still don&#8217;t own a 3D printer. Instead, I opted to have my enclosures 3D printed at a service bureau on a selective laser sintering (SLS) 3D printer in black PA12 nylon. They turned out great. 3D prints on these machines are accurate and consistent from print to print.</p>
<h2>Three Key Stretch</h2>
<p>The three key version of the keyboard is a stretch of the one key version of the keyboard.</p>
<h3>PCB</h3>
<div id="attachment_928" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/3keypcb.png"><img class="size-large wp-image-928" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/3keypcb-1024x824.png" alt="Three key USB keyboard PCB top and bottom views." width="640" height="515" /></a><p class="wp-caption-text">Three key USB keyboard PCB top and bottom views.</p></div>
<h3>Enclosure</h3>
<div id="attachment_920" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/three-key-enclosure-rear.png"><img class="size-large wp-image-920" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/three-key-enclosure-rear-1024x683.png" alt="Rear view of the three key enclosure." width="640" height="427" /></a><p class="wp-caption-text">Rear view of the three key enclosure.</p></div>
<h2>Building the Keyboard</h2>
<div id="attachment_951" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00674_crop.jpg"><img class="wp-image-951 size-large" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00674_crop-1024x682.jpg" alt="DSC00674_crop" width="640" height="426" /></a><p class="wp-caption-text">Three variations of the small USB keyboards: single key with USB top, single key with USB right and optional LED and light pipe, and finally the three key version.</p></div>
<p>The keyboard has three variations:</p>
<ol>
<li>Single key with USB top. There&#8217;s a hidden red LED on the right hand side of the key.</li>
<li>Single key with USB right. There&#8217;s an LED on the top side of the key. Whether to expose the LED, keep the LED hidden, or use a light pipe to direct the LED light is up to you.</li>
<li>Three key with USB top. This board has a provision for a 3MM through-hole LED under each key. These three LEDs really don&#8217;t add much to the project but having them to indicate the USB status is helpful when bringing up the board.</li>
</ol>
<p>To build the keyboard, pick one of three basic variations then select the the PCB, enclosure, parts, and software for your board from the downloads section below. The one key USB right and one key USB top keyboards use the same 3D printed enclosure. To program the microcontroller, you need a PIC programmer such as a PICkit, ICD, or Real ICE.</p>
<div id="attachment_943" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00650.jpg"><img class="size-large wp-image-943" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00650-1024x683.jpg" alt="The parts and pieces required to build the single-key keyboard." width="640" height="427" /></a><p class="wp-caption-text">The parts and pieces required to build the single-key keyboard.</p></div>
<p>When assembling the PCB, I recommend soldering the USB connector first then soldering the PIC16F1459 next. After those two parts are soldered to the board, check the pins and traces for solder bridges very carefully then move on to soldering the rest of the surface mount components. Lastly, solder the Cherry MX key switch to the board. Do not solder a connector to the programming header on the PCB.</p>
<p>To program the micro, open the project in MPLAB X. Build the project. Connect the keyboard and programmer to USB ports on the PC. Finally program the micro while holding the programmer&#8217;s connector and a header in the holes of the programming of the header on the PCB.</p>
<p>When programming is complete, the red LED should flash quickly and the keyboard should begin working immediately. If it doesn&#8217;t, the most likely issue is solder bridges between the pins of the USB connector or PIC. To change what the key does, modify the key codes sent by the software on lines 359 to 372 of the function <span class="pl-en">APP_KeyboardTasks</span> in the file app_device_keyboard.c.</p>
<p>Once you&#8217;re happy with the operation of the keyboard, unplug it and assemble the case around the PCB. Finally, select a key cap and place the key cap on the key switch.</p>
<h2>More Photos</h2>
<p>Here are a few more photos.</p>
<div id="attachment_954" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00678_crop.jpg"><img class="size-large wp-image-954" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00678_crop-1024x683.jpg" alt="One key with USB top." width="640" height="427" /></a><p class="wp-caption-text">One key with USB top.</p></div>
<div id="attachment_953" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00680_crop.jpg"><img class="size-large wp-image-953" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00680_crop-1024x683.jpg" alt="Three key." width="640" height="427" /></a><p class="wp-caption-text">Three key.</p></div>
<div id="attachment_955" style="width: 650px" class="wp-caption alignnone"><a href="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00679_crop.jpg"><img class="size-large wp-image-955" src="http://bikerglen.com/wp/wp-content/uploads/2018/05/DSC00679_crop-1024x683.jpg" alt="One key USB right with optional LED and light pipe." width="640" height="427" /></a><p class="wp-caption-text">One key USB right with optional LED and light pipe.</p></div>
<p>Have fun! I hope you enjoyed this project!</p>
<h2>Downloads</h2>
<h3>PCB</h3>
<p>Pick one of the following PCB designs depending on which version of the keyboard you’d like to make. These link to directories on github containing both Eagle PCB files for modifying and Gerbers for manufacturing:</p>
<ul>
<li><a href="https://github.com/bikerglen/small-keyboards/tree/master/boards/one%20key%20usb%20right">Single key version with USB port on the right side</a></li>
<li><a href="https://github.com/bikerglen/small-keyboards/tree/master/boards/one%20key%20usb%20top">Single key version with USB port on the top</a></li>
<li><a href="https://github.com/bikerglen/small-keyboards/tree/master/boards/three%20key%20usb%20top">Three key version with USB port on the top</a></li>
</ul>
<h3>Enclosure</h3>
<p>Pick an enclosure to match the selected PCB. The single-key USB right and single-key USB top keyboards both use the same single-key enclosure. These link to directories on github containing both STEP files for modifying and STL files for printing:</p>
<ul>
<li><a href="https://github.com/bikerglen/small-keyboards/tree/master/enclosures/one%20key%20by%20half%20inch">Single key version for use with 2-56 x 1/2” screws</a></li>
<li><a href="https://github.com/bikerglen/small-keyboards/tree/master/enclosures/one%20key%20by%20short">Single key version for use with 2-56 x 7/16” screws</a> (not recommended, see note below)</li>
<li><a href="https://github.com/bikerglen/small-keyboards/tree/master/enclosures/three%20key%20by%20half%20inch">Three key version for use with 2-56 x 1/2” screws</a></li>
</ul>
<p>Note: the 7/16&#8243; screws I ordered from McMaster-Carr were approximately 0.020” short of 7/16”. They worked but it took some finagling to get the screw threads to catch the nuts. For this reason, I’d recommend the 1/2” version of the enclosure. Also 2-56 x 1/2” screws are much more common, easier to find, and less expensive than 2-56 x 7/16” screws.</p>
<h3>Software</h3>
<p>Pick a software version. All software versions support from one to three keys. The default configuration is for key 1 to type an <em>a</em>, key 2 to type a <em>b</em>, and key 3 to type a <em>c</em>. The Non-USB bootloader version is the easiest to work with but it gets old disassembling and re-assembling the keyboard to update the firmware. If you select the USB bootloader version, you will also need the USB bootloader and the Microchip USB hex bootloader app.</p>
<p>These link to directories on github containing both the MPLAB X projects and pre-built .hex files that may be directly programmed into the part without opening or building the projects:</p>
<ul>
<li><a href="https://github.com/bikerglen/small-keyboards/tree/master/software/tkk-pic16f1459.X">Non-USB bootloader version</a>. Requires disassembling keyboard to update firmware.</li>
<li>USB bootloader version. After bootloader is programmed, firmware may be updated over USB without disassembling keyboard.</li>
<li>USB bootloader. Bootloader for the USB bootloader version of the keyboard software.</li>
</ul>
<p>If you selected the USB bootloader version, you’ll also need the Microchip USB hex bootloader app. This app is distributed as part of the Microchip Library for Applications (MLA) and may be downloaded <a href="http://www.microchip.com/mplab/microchip-libraries-for-applications">here.</a></p>
<h2>Bill of Materials</h2>
<h3>Electrical Parts</h3>
<p>Part numbers in parenthesis are <a href="https://www.digikey.com/">Digi-Key</a> part numbers. Part numbers in brackets are <a href="https://www.mouser.com/">Mouser</a> part numbers.</p>
<ul>
<li>N=1 PIC16F1459-I/SS USB microcontroller. Microchip part # PIC16F1459-I/SS (PIC16F1459-I/SS-ND)</li>
<li>N=1 USB Micro-B PCB mount jack. Wurth part # 629105136821 (732-3155-1-ND)</li>
<li>N=1 0.47µF 50V 1206 capacitor. Similar capacitors with voltage ratings down to 16V may be substituted. Kemet # C1206C474K5RACTU (399-3498-1-ND)</li>
<li>N=1 0.1µF 50V 1206 capacitor. Similar capacitors with voltage ratings down to 16V may be substituted. Kemet # C1206C104K5RAC7867 (399-1249-1-ND)</li>
<li>N=1 1µF 16V 1206 capacitor. Similar capacitors may be substituted. Kemet # C1210C105K4PACTU [80-C1210C105K4P]</li>
<li>N=1  or N=3 Cherry MX blue key switch or similar. Cherry # MX1A-E1NW (CH197-ND)</li>
<li>N=1 or N=3 1kΩ 1206 resistors depending on if you selected the single key or three version of the keyboard. (optional, only needed if you add LEDs to your keyboard) Bourns # CR1206-JW-102ELF (CR1206-JW-102ELFCT-ND)</li>
<li>N=1 Red 3528 surface mount LED (optional, for the single key version of the keyboard). Kingbright # AA3528ES (754-1531-1-ND)</li>
<li>N=3 Red 3mm through hole LED (optional, for the three key version of the keyboard). Kingbright # WP710A10ID (754-1606-ND)</li>
</ul>
<h3>Mechanical Parts</h3>
<ul>
<li>N=4 2-56 x 1/2” or 7/16” black oxide socket cap flat head screws. McMaster-Carr part # 91253A081 (1/2”) or 91253A080 (7/16”) depending on the version of the enclosure selected above.</li>
<li>N=4 2-56 black oxide hex nuts. McMaster-Carr part #96537A110.</li>
<li>An assortment of Cherry MX compatible key caps. I ordered mine from <a href="http://www.maxkeyboard.com/products/cherry-mx-keycap/backlight-novelty-keycap/">Max Keyboard</a>.</li>
</ul>
<h3>Challenge Parts</h3>
<p>The single key version with USB port on the right side contains a single red LED above the key switch. A suggested challenge would be to open a hole in the enclosure and use a light pipe to pipe the LED’s light to the top of the enclosure. If you want to attempt this challenge, I recommend Visual Communications Company’s round 3mm x .125” diffuse light pipe, part # LFB012CTP (LFB012CTP-ND at Digi-Key). A possible solution to this challenge is located <a href="https://github.com/bikerglen/small-keyboards/tree/master/enclosures/top%20with%20light%20pipe%20opening">here</a>.</p>
<h2>Useful Resources</h2>
<p>Here is a list of resources I found useful during the construction of this project:</p>
<ul>
<li>SparkFun Cherry MX Eagle PCB <a href="https://github.com/sparkfun/SparkFun-Eagle-Libraries/blob/master/SparkFun-Switches.lbr">footprint</a>.</li>
<li>PIC16F1459-I/SS Eagle PCB <a href="http://digikey.ultralibrarian.com/?customers=RycPF1rrFAfHhx1FKbDMvyIhfAaVpfojYtrMkEWUzmMQdSfcVO7y%2blSpZPdVwobWTDvUSYygHvldEcommnlKY74M1oqx1amo9RHpyTg76aUim0tW8Ixasn2vKKgF2HxKUqAC9sXJVfIVyvnE2QxaAMefuQ97QukV0%2bx2GaAAxXHaw2RROBbtuzW8EoEJ8BRB6maVzCgLHexQO7mi4z8iPKxQyioAUo3ABSeiKMMsjE4DYwGW8SRk4qw2NtZx8cG%2fo1HtREBRFClZPrpxKvuPhMjIDjuW%2bDQrnAnzjzaiol2T3xYDM4m6c0PpWtamCw9D30myp3N%2brt%2bnBANG7Gkl3g%3d%3d&amp;parts=PIC16F1459-I%2fSS-ND&amp;submit">footprint</a>.</li>
<li>Wurth part 629105136821 <a href="http://katalog.we-online.de/en/em/COM_MICRO_SMT_TYPE_B_HORIZONTAL/629105136821?m=n&amp;sp=http%3A%2F%2Fwww.we-online.com%2Fweb%2Fen%2Fwuerth_elektronik%2Fsearchpage.php%3Fsearch%3D629105136821">Eagle PCB footprint and STEP 3D model</a>.</li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>https://bikerglen.com/blog/presenting-the-single-esc-key-usb-keyboard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
