contact us

Use the form on the right to contact us.

You can edit the text in this area, and change where the contact form on the right submits to, by entering edit mode using the modes on the bottom right.​

Projects

Various electronics, programming, welding, mods and other non-automotive projects.

iOS-Based Smart Mirror

Joe Angell

After my second Compute Stick died, I decided to just rewrite the whole thing in Swift and Swift UI and have it run on iOS. Also, it was an excuse to learn modern iOS development. I’ve found it much easier to maintain and that it just works better, but it is specifically tailored to my needs and not generally useful to others like some open-source projects are.

Read More

Simple AWS API Gateway Setup

Joe Angell

Ever wanted to set up a minimal HTTP proxy to protect your API keys so you don't have encode them in your app? So did I. It took me a while to figure out, having never done it before, but I finally got it working. I try to explain how to do it here.

Read More

AutoOfficeIR

Joe Angell

Update: December 2021

I replaced my Sony receiver with a Yamaha one and had to update the remote to support it. First, I had to fix a problem where one of the IR LED connections broke and wasn’t controlling the a TV anymore, which broke when I disassembled it so I could get to the ESP32’s buttons. I created a circuit diagram to help debug this, which I neglected to make the first time.

The volume control was updated to use raw codes I found on RemoteCentral.com. They didn’t have the Yamaha RX-V4A specifically, but the volume codes for another RX receiver worked fine. The input codes were trickier. The remote only has next/previous input buttons, not discrete buttons. However, it has a concept of “scenes”, which is an input some other settings like the listening mode. I simply assigned a different input to each scene, and used the individual scene buttons n the remote to switch inputs. I couldn’t find a raw code for those, so I had to capture those myself.

I also mapped the old Samsung TV input codes to fire when I held the button down for longer than a second, while the Yamaha input codes fire if you just press and release the button. I also have the Samsung HDMI 4 code fire whenever you do a Yamaha code so that it’s always on the right TV input.

Everything is working great now, although it did take longer than it should of.

Update: January 2021

As part of switching to HomeKit, I updated the software to report the current TV on/off state using the protocol defined by homebridge-http-webhooks. On the hardware side, I drilled out the screw holes and added brass heat-set inserts, which greatly improve the grip of the screws and only took a couple of minutes to install.

This update is part of my new Auto Office through HomeKit.


A while back I built my AutoOffice, which I still use. It consists of a few discrete parts:

  • ESP8266 with a glowing button mounted to my desk, and running a web server. This controlled the lights in my office, although that functionality is currently disabled until my new office is ready.

  • Vapor-based web server running on my iMac. This wakes or sleeps the Mac’s monitors when the ESP8266 button is pushed, and can also sleep or wake other devices when it sleeps or wakes.

  • Web server running on my Windows machine. This only listens for wake/sleep events and wakes/sleeps its monitors.

  • SmartThings-based switches and SmartApp for turning on/off monitors and TVs that couldn’t be controlled more directly (ie: lacking DPMS for computer wake/sleep control).

One hole in this system was the TVs that I use as monitors. Since TVs lack DPMS, I had to rely on cutting power to them and restoring it via SmartThings switches/appliance modules. Luckily, the displays remember their previous power states and come back on automatically. The problem is that the computers (mostly the Windows one) get confused about the monitor losing power, instead thinking it has been disconnected and moves all the windows to the other screen. This is very, very annoying.

For a while I used an EDID spoofer to kludge around this, but one day it simply stopped working, and I never found a way to fix it.

I recently got a new A/V receiver that supports 4K HDR. I only really need to switch inputs and change the volume with it, but the remote isn’t great and the volume button position is awkward. I decided to kill two birds with one stone and build a device to solve both problems.

The Goal

The new device would support a few key functions:

  • Use a rotary encoder to change the volume on my A/V receiver via IR remote control commands.

  • Run a web server that supports AutoOffice, which would send discrete power on/off codes to the Samsung TVs I use as monitors.

  • One or more buttons for other IR controls.

  • Multiple IR outputs that can be placed where they are needed most.

  • 3D printed, weighted base so it doesn’t shift around on my desk.

This all seemed pretty feasible, so I decided to spend a weekend on it.

Variants

I built two of these. The first had just a clickable dial, while the second model had a larger case and four buttons to change inputs. I documented the original model first, and at the end I’ll cover the changes in the second model, which builds heavily off the first.

The Hardware

Microcontroller

I was going to use an ESP8266, but one of the IR libraries I found only supported the ESP32, so I used one of those instead. I wrote the code using the Arduino development system, although I mostly did so using Visual Studio Code with the Arduino plug-in.

Rotary Encoder

I bought a five pack of rotary encoders on Amazon, along with a 1.25” diameter knob, mostly because I couldn’t find anything larger. The encoders have detents and click into position as you turn it, but otherwise will turn continuously. I used the ESPRotary Arduino library to read the knob. This tutorial notes that a standard mechanical encoder sends four pulses per click, which I found to be true when I got exactly that for each rotation. ESPRotary lets you set the number of pulses per click, so that worked out well. The encoder wiring is simple and documented in the tutorial linked above.

The encoder can also be pushed like button by wiring the remaining two pins to the microcontroller, which also set up. Currently it’s being used to manually turn the TVs on and off.

IR LEDs

Years ago I had bought a five pack of IR LEDs and receivers from Amazon that I had never used. I hooked three of them up to their own 100 Ohm resistors, wired in parallel to a single P-channel MOSFET, a BS250KL, to avoid putting to much strain on the ESP32’s pin. While breadboarding my prototype I used an N-channel MOSFET, but that resulted in the LED being on all the time and flashing off when trying to send a code (I used a colored LED so I could see it flash for these tests). I swapped in a P-channel and everything worked fine.

The IR LEDs are at the end of 22 gauge two conductor cables in a black jacket. I used heat shrink tubing on both ends for strain relief and to keep things neat. I then simply taped them near the IR sensors on the TVs and A/V recovers.

Assembly

After breadboarding the basic setup, I mounted the ESP on the bottom of a small perfboard, and mounted the rotary encoder on the other side. This odd arrangement sought to minimize the mount of physical space that the assembly would require. I was then able to solder down the MOSFET and resistors, and attach a six-pin 90 degree header strip to the end of the board. Each pair of pins would drive one IR LED placed near the IR receiver of a device to control. Once soldered, I cut down the perfboard to keep the final footprint as small as possible.

The ESP3d mounted on the bottom of the board, connected to USB.

The top of the board with the knob attached. All three IR LEDs are connected to the 6 pi header. The MOSFET can be seen between the knob and the LED wires.

Circuit diagram. The “IR Control” transistor is what flashes the LEDs, rather than connecting the LEDs directly to the ESP32, and “Monitor Switch” is used to turn off the Windows TV’s LED when I only want to control the Mac mini TV. Note that the pin placements may be different on other manufacturer’s ESP32 carriers.

The Software

I found IR libraries to have less than great documentation. I could find examples, but they were a bit tough to parse as well. I finally went with an ESP32 variant of the IRremote library, Arduino-IRRemote. Due to naming conflicts, the built-in RobotIremote library has to be removed from the application bundle (on the Mac, which is the install dir on Windows) to get it to build properly. Getting IR to work took the most time of the development, from testing different libraries to figuring out what the codes actually work and how to get them into a format that the IR libraries would accept.

It’s very important to note that when I started this project, the official Arduino Library didn’t support the ESP32, but by the time I finished it did. The library I used is based on an older version of IRRemote. Somewhat annoyingly, if you click the “releases” link from the repository above, it goes to the official library that has had some significant changes and will not work with my existing code. It took me way too long to realize this when I had to update the remote for my new Yamaha receiver. I finally just downloaded the a zip of the repository so that I had the correct version. I’ll have to update the code for the new library someday…

Sony Codes

Finding codes was its own challenge. After some searching, I finally just plugged an IR receiver into an Arduino Uno I had lying around and loaded IRremote’s IRrecvdemo onto it. I was able to read the volume up and volume down codes for my A/V receiver and pass those to the sendSony() method. This particular device uses 15 bit codes, as evidenced by the length of the hex codes: 0x240C for volume up and 0x640C for volume down.

Sony codes need to be transmitted three times for the device to accept them, with a short delay between. I originally used 40 ms, but this caused a lot of turns of the dial to miss, as sending the codes and the delay are done in a blocking section of code. I was able to get it down to a 5 ms delay with no ill effects, which made the knob much more responsive. It is still easy to miss steps, though, but in general use it’s fine, as I only tend to urn the dial small amounts anyway. However, you still need to turn it slowly to avoid missing steps too often.

Another detail I discovered is the first code sent to the receiver simply shows the current volume level on the VFD or TV overlay, rather than changing the volume level. This means that no matter what you need to go two steps for anything to happen.

Samsung Codes

The Samsung TV power codes were a bit trickier because of what I wanted to have it do.  The important thing here is to get discrete on and off codes, rather than the single toggle code that the remote control sends. This meant that I couldn’t just record the code from the remote, which is just an on/off toggle, and had to find another source. A particularly useful site for this is RemoteCentral.com, which has a slew of raw codes for various devices, including Samsung TVs. I converted those codes into a list of integers that could be copied into a C array using IrSscrutinizer (just paste them into the window and hit Scrutinize), which could then be transmitted with sendRaw().

Yamaha Codes

I later replaced the Sony receiver with a Yamaha RX-V4A receiver. This specific model isn’t listened on RemoteCentral.com, but I was able to use some of the raw codes fro another RX class receiver for volume control. I couldn’t find HDMI input codes, though, and the remote doesn’t have discrete input buttons, just next/previous buttons and four “scene” buttons. I would up mapping the scenes to different inputs, and using an ESP32 with an IR receiver and IRRecvDumpV2 from the IRRemote library to capture the NEC codes directly. I mapped these codes to the four input buttons, with the Samsung codes mapped to if the button is held for more than a second. I also have Samsung HDMI 4 fire when using any of the Yamaha codes to ensure that it’s on the correct TV input.

Repeat Codes

I also tried adding support for repeat codes via irsend.sendNEC( REPEAT, 15 ) if successive ticks from the encoder came in fast enough, but this seemed to do nothing at all. I tried different code lengths in place of 15, but nothing worked.  I was recording 0xFFFFFF (the repeat code) from the IRrecvdemo, so it definitely supports a repeat code, but I’m not sure how to transmit it. Luckily there are relatively few lost ticks unless you spin the knob quickly, so I decided to just let leave out repeats, at least for the time being. Apparently NEC repeat codes are sent every 110 ms, so even then I could spin the dial faster than it could transmit codes, assuming Sony uses the same repeat period. I didn’t try using the repeat codes with the Yamaha receiver.

Encoder Button

ESPRotary handled direction reporting from the rotary encoder. I read the encoder’s button with the InputDebounce library to easily deal with debouncing, and configured it to turn the TVs on and off.

HTTP Server

The web server was mostly copied from the AutoOffice-ESP8266 code. However, ArduinoJSON has since been updated fairly significantly and I need to make some code changes to get my sketch to build. I also had to make some tweaks to the web server startup sequence to keep it from crashing on boot, but nothing too major.

The final software (including the version 2 input switching functions) can be found on Github.

The Enclosure

I used MODO to design a simple case for the hardware, leaving holes for the USB port, LED headers and rotary encoder. I built in small vent holes in the side to help keep the ESP cool. The case was designed in two halves with screw holes to mate them. I printed this in ABS on my Ender 3 3D printer. I made a second version of the case that is more sloped, and a final third version that has space for the input switching buttons for the Version 2 design described further down.

LXO (all versions)
STL Original (V1) Base Top
STL Sloped (V2) Base Top
STL With Input Buttons (V3) Base Top

I left empty space below the ESP32 to fill with metal, which in this case was some bolts. Lead shot would have been better, but is surprisingly pricey. Tungsten would have been really cool, but even more expensive. Lead Pinewood Derby car would also be an option, but kits are only four ounces and kind of expensive for what they are. I stuck with the bolts, but something heavier would have been nice. A redesign of the enclosure would have made it easier to fit more in. I used some packing tape to ensure that they didn’t short the ESP32.

To keep it from sliding around my desk I bought some adhesive-backed rubber pads by 3M from Amazon, which were sold as “2-Piece Self-Stick Rubber Anti-Skid Pad Furniture and Floor Protectors (Black) by ROOS”. I (poorly) cut it down to the size of the base with cut-outs for the screw holes. It significantly improved how well it stayed in place on the desk, although more weight would have helped even more.

The electronics, bottom and top pieces of the case, with bolts as weights in the base.

The electronics mounted reseting in the base.

The bottom of the case, showing the screw holes.

The 3M rubberized sheet, after being cut and applied to the bottom of the enclosure to reduce slipping on my desk.

Power

Power can be provided from any USB port; I used some in-desk ones I’d previously installed purely for powering USB devices like this, which worked great. I can plug it into a computer if I need to debug it, but there’s no need for it to tie up a USB port most of the time.

Originally I had separate two-pin header connectors for each LED. The problem was the heat shrink I added, which caused them to not fit together very well. I popped out the pins and put them in a six-pin connector, which holds in place much better, although it does make it a bit harder to reposition the LED wires if I need to later.

Final setup with a separate LED connectors. The dot indicates which way is up when plugging them in, and was made with a silver Sharpie.

Final setup with a single LED connector.

Version Two: Input Switching and Aluminum

The second version of the remote adds four buttons on the face to change the inputs on one of the Samsung TVs. This required a few changes to the hardware.

The second switch design with an aluminum knob, aluminum-painted ABS case, and four buttons for changing inputs.

Adding Input Switching Buttons

The most obvious one is adding the four buttons. I bought an assortment of four-pin microswitches from Amazon with different length plungers, evenly spaced them on a strip of perf board, then designed a new case in MODO using procedural modeling that included the extra space needed for the board. I cut tabs into the model that can flex to push the microswitches so that it would look a bit prettier. After doing a test print, I positioned the microswitch board and swapped out switches until the case tabs rested on top of the buttons without pressing them, and confirmed that pressing the tab actually clicks the button.

I soldered the switches to short wires that ran to the ESP32 and updated the software to send IR codes when the buttons were pushed. I used RemoteCentral.com to get the discrete input codes for HDMI 1, 2, 3 and 4, ran them though IrSscrutinizer, and added them as a C array to my Arduino sketch, just liked I’d done for power and volume control.

Modifying the IR Wiring

I only wanted to apply input switching to one of my TVs, but they’re both Samsung and both respond to the same codes. To fix this, I rewired one of the LED connectors with an extra transistor. When I need to send input codes, I turn that transistor off so that the other TV won’t be sent any codes. When I need to send power codes, I turn that LED on again, and the codes go to both TVs.

Case Weights and Anti-Slip

As with the original design I used spare hardware as weights, and adhesive-backed anti-slip on the bottom to keep it from sliding around on my desk.

Bolts as weights in the base of the case.

The ESP32 and microswitch board installed in the case.

Anti-slip mat on the bottom. Poorly cut, but it works.

Aluminum Knob

The original black box would get lost on my desk, so I decided to go with an aluminum finish this time. I also wanted a larger knob, but without any kind of position marker on it. Finding large knobs is difficult, and finding ones without markings are nearly impossible.

In the end I bought three knobs in different sizes, all aluminum. One was smaller, polished until shiny, with knurled edges at 36mm and 16mm tall, but didn’t have any markings on the top, which was nice. The second was similar, but 38mm and 22mm tall, and did have a small indent to mark the current position on one edge. The one I wound up using was a textured aluminum at 48mm and 22mm tall. It has a small embossed circle to mark the current position that I don’t need, but the design was the best of them.  The listing description was “1pcs 48mmx22mm SOLID Aluminum VOLUME CONTROL AMPLIFIER AUDIO CD PLAYER TEST KNOB”. Each cost about $10 from ebay, plus shipping.

Case Finish

For the case, I started with a prototype print with some aluminum PLA. The PLA seemed thinner than the black ABS I normally used, and didn’t quite print as tightly for some reason. It looked surprisingly similar to aluminum, but it was also five times more expensive than normal ABS or PLA.

I decided to try an experiment with paint instead. At Home Depot I bought a can of filler spray primer and aluminum spray paint. I printed a final version of the case, sanded it with progressively finer grades of sand paper, did two coats of primer, and then two coats of paint. The aluminum finish looked very good, so I decided to just go that route and skip the more specialized filaments.

Even better, the aluminum paint almost exactly matches the aluminum knob I bought. At a glance the entire thing looks like they’re made of the same material.

Final design, fully assembled. The aluminum knob and aluminum paint match perfectly.

Assembled and connected.

The wires now come out from the side so that the ESP32 doesn’t interfere with the switches.

Other random notes

  • Ultimaker Cura opens every serial port it can find, apparently, which made it difficult to program the ESP while Cura was running. Since I write my prints to an SD card, I disabled the USB support from the Marketplace window in Cura and no longer have problems with that.

  • The ESP32 WebServer can’t be started until a wifi connection is made. If you try, it will crash on boot. The ESP8266 didn’t have this limitation, oddly enough.

Smart Heating Registers

Joe Angell

Our new house has a total of fifteen floor-mounted forced air heating registers. The second floor tends to be colder, so I wanted to automatically redirect air to the rooms we’re in to say heating oil and keep us warm. After failing to find any suitable smart heating registers, I went about building my own.

Read More

Magic Mirror with Intel Compute Stick

Joe Angell

I got fed up the problems I was having with the Raspberry Pi 2/Linux combo that was running my Magic Mirror, so I replaced it with a second generation Intel Compute Stick running Windows 10.  This was fairly quick to do, and has given me fewer problems and is notably snappier to work with.

Read More

Clipped Drink Carrier

Joe Angell

I like having a drink with me, but I also like having my hands free and don't want to carry it around all the time.  The solution was to make my own drink carrier that would clip onto a belt loop.

Read More

Homebridge, SmartThings, Nest and Insteon

Joe Angell

With the forthcoming iOS 10 HomeKit updates, I decided to finally get Siri support for my SmartThings, Nest and Insteon hardware.  None of these directly support HomeKit (well, Insteon does, if you want to buy a new hub), but some industrious developers have put together their own intermediary solution to this problem, Homebridge.  I decided to take that route, and add my own support for Insteon FanLinc devices.

Read More

Bandwidth Monitoring

Joe Angell

With Comcast's expansion of data caps, I started looking into how to monitor both per-app usage on my Macs, as well as per-machine usage on my network.  I went with two solutions: Little Snitch and Gargoyle.

Read More

Magic Mirror

Joe Angell

One day I came across Michael Teeuw's Magic Mirror project -- a Raspberry Pi displaying daily information on a portrait mode HDTV behind a two way mirror.  This seemed like a great project, and I decided that I wanted to build my own (updated December 26th, 2015).

Read More

Washer/Dryer Finished Alert via SmartThings

Joe Angell

The laundry is in the basement, but we're usually on the second floor.  The variable length cycle of our washer and dyer make it hard to time when they will be done, and the variable running speed makes it difficult for a vibration sensor to accurately report when they're completed.  I decided to take advantage of my SmartThings ThingShield and build my own completion sensor that monitored the LEDs on both appliances to send push notifications to my phone.

Read More