Pete's Log: ESPHome 74HC165 and other musings

Entry #1971, (Coding, Hacking, & CS stuff, Smokepacking, Work)
(posted when I was 43 years old.)

Yesterday I discovered that I own at least 16 74HC165s in DIP16 format. They can be seen in the two tubes below alongside the rest of my IC collection.

No alt text found for this picture. Please email to complain.

Jamie and JB were out and about with Jamie's Mom this evening, so I was able to finish up some project work I started yesterday, namely an absurd upgrade to my monitor stand control panel. This previously consisted solely of a switch to control my desk lights, but now also includes a light-up push button, a potentiometer, and a six-position rotary switch:

No alt text found for this picture. Please email to complain.

The push button I randomly added to an Adafruit order I placed a month or so ago. I already had this idea in mind then, but it turned out to be wider than any suitable drillbits I had. After dropping JB off on Saturday, I stopped by Microcenter and bought some step drill bits and a hot glue gun. Yesterday I started drilling. I also figured I'd see what else I might have laying around. I found the six-position rotary switch as well as a decent number of potentiometers.

No alt text found for this picture. Please email to complain.

It was easy to think of a potential use for the potentiometer - it could control the brightness of the desk lights. The button and rotary switch I need to ponder a little more. But ESPHome continues to be great and everything is already integrated into Home Assistant, so even though they're physically connected to the same ESP8266 as the desk lights, logically they can control anything that HA talks to. So that's fun.

No alt text found for this picture. Please email to complain.

The rotary switch is somewhat heavy duty and makes a pretty satisfying thunk when you switch it around. When and where did I get it? No idea. Maybe at the same time I bought all those 74HC165s. As it happens, I put them to use together. The rotary switch has six signal lines, one for each position. I think I have enough pins on the ESP8266 such that I could just hook each signal to one pin, but that seems silly. The 74HC165 is an 8-bit parallel-in serial-out shift register which lets me get a byte representation of my rotary switch using just three pins on the ESP8266. And theoretically I can daisy-chain more 74HC165s for even more inputs! Good thing I have so many!

No alt text found for this picture. Please email to complain.

Seriously, why do I have so many? I'm not entirely sure anymore. My Amazon history tells me I ordered them on June 20, 2018. I paid $12 for 15 of them. So I bought them shortly before getting married and finding out JB was on the way. That's why whatever this was for got put on hold. Pete's Log is sadly lacking any entries around that time, so I may have to reminisce a little. But first, let's finish up on the control panel.

The LED button and potentiometer were pretty easy to wire up (especially since the ESP8266 only has one analog pin, I knew exactly where the pot had to go). The rotary switch / 74HC165 was a bit trickier. But easier than anticipated, actually. ESPHome for the win again. I wired it up based on the diagram I found on this 74HC165-ESP8266 GitHub page. The only differences are that my D6 and D7 are connected only to GND since I only need six inputs and that I added a 100 uF decoupling capacitor between VCC and GND.

To get it working with ESPHome, I wrote up a simple custom component, which was surprisingly easy. ESPHome actually has a built-in component for the 74HC595, which is basically the inverse of the 74HC165 (it's an 8 bit serial-in, parallel out shift register). So I'm half tempted to clean up my component and submit a pull request and see if they want it. But without further ado, here it is. (Save this as SN74HC165.h in the esphome configuration directory)

#include "esphome.h" class SN74HC165Component : public PollingComponent, public Sensor { private: const byte LATCH = D0; const byte DATA = D6; const byte CLOCK = D5; public: SN74HC165Component () : PollingComponent(1000) {} float get_setup_priority() const { return setup_priority::IO; } void setup() override { pinMode(LATCH, OUTPUT); pinMode(CLOCK, OUTPUT); pinMode(DATA, INPUT); digitalWrite(CLOCK, HIGH); digitalWrite(LATCH, HIGH); } void update() override { digitalWrite(CLOCK, HIGH); digitalWrite(LATCH, LOW); digitalWrite(LATCH, HIGH); byte value = shiftIn(DATA, CLOCK, MSBFIRST); publish_state(value); } };

To use it, update the yaml file for the device and add an includes key to the esphome section:

includes: - SN74HC165.h

And then use it by defining a sensor that uses the custom platform:

- platform: custom lambda: |- auto my_sensor = new SN74HC165Component(); App.register_component(my_sensor); return {my_sensor}; sensors: name: "Desk Rotary Switch"

The sensor returns a byte value representing the parallel input. Since my rotary switch means only one bit can be on at a time, I get a 1, 2, 4, 8, 16 or 32 value representing the state. If I put a little time into it, this custom component could also support multiple 74HC165s daisy-chained together. Tempting. Since I have so many and all.

Anyway, that's what I did yesterday and today. Let's go back a few years.

My favorite project that I worked on at DMC was a weather-proof industrial sensoring device that used a cellular modem to report back. An IoT project if you will. We worked with this customer for some time and initially I had helped them with their cloud side of things. They were originally doing the monitoring with the PLCs that also actually did things, and they were happy with the cloud solution I designed for them. Then they came to us with the idea that they wanted to monitor devices for which they were not providing the control PLC, so sensing only, no controlling. But still outside. So we designed a solution for them. Our hardware people designed a custom PCB and we picked a microcontroller with cellular capabilities and I updated the cloud side of things. But I also got pulled into the hardware side a bit, helping with assembling the boxes (so much crimping!) and also writing the initial prototype code for the microcontroller as an Arduino sketch. And that got me hooked. I wanted to start doing more hardware stuff.

So I started buying Arduinos and electronic components for learning at home. And then life happened. In a very positive way. Marriage and JB and a new job that gave me back an hour of commute time every day. So it was probably two or more years between my first binge of hardware buying and my current obsession. So for the most part I remember why I was doing what I was doing. However, I still don't know why I bought so many 74HC165s. But I'm thrilled to have finally put one to use.

While going through things I put together this picture:

No alt text found for this picture. Please email to complain.

From top to bottom, left to right (ish), those are:

  • ESP32 (SparkFun Thing Plus)
  • ESP8266 (Wemos D1 Mini)
  • ESP 32 (Heltec LoRa 32)
  • Raspberry Pi Pico
  • Arduino Pro Micro
  • SAMD21 (Adafruit QT Py)
  • Bouffalo Labs BL602 RISC-V IoT SoC
  • Raspberry Pi 3B
  • Arduino UNO

So many things to play with.

A few other bullet points:

  • I want to make a webpage for the ESPHome 74HC165 component, but can't decide if it should go under Hardware or Software. I'm leaning towards Software. In other news, the top navigation now has a Hardware tab.
  • That customer I mentioned above told me to come work for them when I told them I was leaving DMC. And then reached out to me about six months later to ask me again. I think about that regularly and maybe when JB's a little older I'll reach out to them. The main reason I haven't is I'm pretty sure it would eat into my free time, which my current job is pretty good about not doing.
  • I configured the new LED desk button into a pulsing mode, and it's pretty neat looking. Might make for a decent notification system.
  • I just got an email that my XOR PCB is on its way to be fabricated. Yay!