Friday, January 5, 2024

Macro Keypad


Macro Keypad

As far as electronics projects go, a macro keypad is probably among the easiest. I was inspired by a friend of mine who built one, and since I'm always looking for a project I can actually complete, this seemed like the perfect one. It still took me over a year from start to finish, but in the end I did complete it. 

I have a real problem with starting projects, and never finishing them. Most of the time its because I over complicate it, and when I fail to realize my vision, I get discouraged and give up. I'm training myself to be more satisfied with "good enough". Because even good enough is better than incomplete.
 
Like I tell my engineers, "better is the enemy of done". And this project stands as a personification of that aphorism. 


So, why did it take so long to build something so simple? I built the case, soldered the switches, leds, and all the connecting wire. When it was time to program the thing, I could not find a HID library for the rp2040 pico that was written in C++, my language of choice. They had python libraries if you were using CircuitPython. But in my hubris, thought "No, Circuit python is for people that don't know how to program microcontrollers".

Hubris might be a virtue. But sometimes you're just wrong. And all the normal-person virtues are still worth something in the end. I switched to CircuitPython and within 30 minutes finished my macro keypad. It now sits on my desk, a symbol of my humility. 


Enclosure

I modeled the enclosure in Fusion360. It's very basic, with a hole for a USB cable, and a slot for access to the pico pin headers. I'm not sure I'll ever actually hook any thing to the gpio pins, but I have a slot if ever I change my mind. 

The holes in the top are designed to fit standard Cherry MX keys.


Electronics

The keypad is powered by an RPI2040 pico. One of the newer things to come out of the raspberry pi group. It's a microcontroller with quite a few peripherals, for a relatively low price. They even have a wireless version I own two of that are currently pending other projects. 

The keys themselves are soldered into these breakout boards from SparkFun: Link. I can't understate how cool these boards are. They really put a lot of time and attention into them.

The switches are soldered right onto it, it supports an LED and a diode, AND they can be soldered into a matrix for multiple keys. No only that, its fairly easy to offset the rows/columns of this matrix just like you would on a standard keyboard.  Each one costs around $2, which can definitely eat into the budget.

Firmware

As I mentioned in the intro, I resisted using CircuitPython for this. But when I could not find an alternative HID library, I finally broke down and installed it. I was very surprised at how cool it is.

It installs as firmware on the pico, and presents itself as removable media (Just like the bootloader does). But instead of expecting a compiled binary, it takes python files. It'll automatically restart the pico when a file save is detected, AND if you open up a serial connection to it, you'll get the python output/errors. It also comes with a substantial number of prebuilt libraries for various sensors, and other utilities.

It basically takes away all of the normal challenges faced with embedded development, and provides a really nice, polished, familiar development environment. While I feel a little guilty using something so slick, it's just too cool to repudiate.

The code for this was really simple: Github Gist

Next Steps

Right now  only three of the 6 buttons are programmed with a function. Volume Up/Down and Play/Pause. I'm struggling to come up with useful commands that I actually want to use.

My friend suggested a couple of cool ideas.... If you pair this keypad with some installed service (That is listening for key combinations) It actually opens a whole world of possibilities. Auto formatting JSON/HTML/XML/etc in the clipboard, running scripts, doing a git pull, opening a terminal with an established ssh connection. 

If you're reading this, and you happen to have some ideas for me, please send them along. The other three keys are longing for purpose in their current vestigial state.

Thursday, January 4, 2024

Wall Mounted Hydroponics (In Progress)

 Wall Mounted Hydroponics

 


 

For Christmas this year, my wife wanted me to build her an indoor hydroponics system. During the summer months we always plant a garden, even if it's small. We love the fresh vegetables and herbs, and it adds a really nice ambiance to our backyard. But when winter comes, and we have to give all that up, we struggle through without fresh mint. It's probably the hardest part of winter. Though, I do hear a lot of complaining about the cold...

When she mentioned the idea of building one of these, I was immediately interested. There is something special about combining digital control with fluid handling, to grow plants inside. And if there is one thing I can't pass up, it's the opportunity to significantly over complicate the process of obtaining tomatoes and basil. 

My hydroponics system is a combination of nutrient film technique, and ebb and flow. Using PVC for the main structure, and nylon tubing to pass the nutrient around.

Netcup Standoff

From the outset, I wanted to incorporate 3D printing somehow. I own three 3D printers after all, so I'm going to have to incorporate those into every project from now on I think... To that end, I came up with what I think is a fairly clever use.

Plants are grown in some sort of growing medium, held by a plastic net cup (black, in the below picture). It's very important for there to be some space between the top of the water, and the top of the roots, to allow them some room to breathe. Since they normally can extract oxygen from the moist dirt, it's very possible to drown a plant if the roots are constantly and fully submerged. 

So, to keep the net cup out of whatever water sits in the pipe, I designed these standoffs. They hold the netcups a few inches above the water, and the plants roots will eventually reach down to access the nutrient.

In this picture, you'll see two different sizes of standoffs. As I mentioned before, it's a combination NFT and ebb and flow - for very young plants that don't yet have long roots, you can place them in the short standoffs and when the pump runs to replenish the nutrients, it soaks the growing medium of the shorter ones. (At the moment I have the pump running once per day.... I don't honestly know what a proper cycle should be yet)


 

Hidden Nutrient Reservoir

It was made very clear to me, that the nutrient reservoir should not be in the dining area, but instead should be behind the wall in the pantry. That meant of course running the hoses through the wall. And, as you can imagine, this was the perfect time to use my 3D printer for a wall plate to make the holes in the drywall less drilled looking.

 


 

It does actually add a nice polished look to an otherwise industrial looking focal point of the room.

In the below picture  you can see the mess of wires and hoses that interact with the nutrient reservoir. I think putting all of this behind the wall was the right call in the end.

I have a basic submerged pump, an air pump to keep the water aerated, and a fish tank heater to keep the water at 78F, since it's winter and I'm hoping a little boost in temperature will help them grow more consistently. In this picture you'll see a couple of wifi plugs. These will get swapped out my a more complex system. At the time of writing this, I have no yet completed that, but we'll talk about the strategy in further sections.

 Worth noting, is that the system does not drain as fast as it pumps. I used the same size hose on the inlet and the outlet, which may be the contributing factor. So it is paramount that the pump does not run for more than a minute at a time, otherwise I will easily get overflowing. An attempt to remedy this was to add an air vent to the outlet. It seemed to help a little, but not nearly as much as I was hoping that it would.


Control System

Just like I can't avoid inserting 3D printing into every project, it's also hard to avoid adding some kind of digital/electronic/control systems as well. The WiFi switches weren't working very well for me any way, and I've wanted to build something like this for quite some time. 

The overall plan is to build a four switched outlets powered by a RaspberyPi Pico W. With four inputs for connecting temperature probes (or other sensors) if needed.

I started with the electrical work, routing power through a bank of relays. As well as a 5V power supply for powering the low voltage side.



And that's as far as I've gotten! As I progress I'll update this.


Bill of Materials

Nearly every thing I used was pretty easy to source. Here it is:

Main Structure

  1. 8ft of 3" PVC
  2. 4 x 3" end caps
  3. 4 x 3/4" reducers
  4. 4 x 3/4" x 1/2" push fit elbow
  5. 4 x 1/2" NPT to hose barb
  6. 20 ft of nylon tubing
  7. Shelving brackets

Nutrient Handling

  1. Water pump
  2. Air pump and stone
  3. Aquarium heater
  4. Food safe bucket
  5. Wifi switches (If not using the custom system) 

Control System 

TBD


Wednesday, January 3, 2024

When you really need access your two 3D printers outside your double NAT'd network you don't want to bother contacting the ISP about.

 I really like the idea of Octoprint(Link). There is something about a microservice, with a web front-end, that runs in a docker container, you can use to solve a very specific problem. It feels like putting in the last piece in a puzzle. I feel more complete after installing it.

In this case, I own Prusa MK3S+ 3D printer. An awesome printer I have extruded many miles of plastic  over many hours of run time. But it does not come with any WiFi capabilities at all. Loading it with models to print requires writing to an sd card and sneaker-netting it all the way across the room. Obviously, it's not ideal.

Octoprint solves this little challenge of mine. By plugging the printer into a raspberry pi, then configuring and launching Octoprint, I can upload my gcode files, and even start the printer without ever leaving my chair. I still have to get up when the print is finished, but that can be a project for another day. It also has the added functionality of managing the various uploads, camera feeds, stats, metrics, and a whole host of plugins. It's really great software.

 


Hosting multiple Printers


But I had a problem. I inherited a second Prusa, and Octoprint does not support multiple printers. Which I found odd, considering its mascot is an octopus.... But I digress.

Other than using a different software package that supported multiple printers, my only option was to host multiple instances of the Octoprint docker container. Each container would have to have it's own unique port number, and I would just have to remember which is which. I did this for a while, and it worked well enough. But eventually, I found the use of ports as the discriminator to be ugly. I have a domain name configured for services running on the raspberry pi, and it was a shame to have to remember to a fix a port number each time. 


My solution to this is a pretty simple NGINX reverse proxy that routes traffic to the correct octoprint instance based on the URL path instead of the port.

An example of the system architecture



can be seen here:



The config file is pretty straight forward also:



Nginx is super cool.

Accessing Externally

I really wanted to access these printers from outside my network. For no other reason than because a friend of mine got a Bambu and he could do it. But also if I'm running a long print, being able to checkup on the camera feed and and progress is pretty nifty.

Unfortunately, my ISP double NATs me, which means I don't have the option to host locally and setup port forwarding on my router(But who wants to deal with dynamic DNS any way?), so I had to come up with another way.

I've long been a proponent of over complicating things. And my solution is very much that. I built what I'm going to refer to as a "reverse jump server". Effectively it's an EC2 instance running in AWS, with an actively maintained SSH tunnel initiated from the raspberry pi. With remote port forwarding. This allows the EC2 instance to host the port externally, and traffic is then forwarded through the tunnel back to the internal network.

It works like a dream.

To manage these tunnels, I built an ASP.NET microservice (This is our THIRD microservice mentioned in this post). It acts as an SSH client, connecting to the ssh server, and actively maintains the tunnel. Reconnecting/logging errors as they come up. (The code for this service can be found here: https://github.com/jqt3of5/reverse-jump-server)


Sunday, February 27, 2022

James Web Space Telescope Wall Hanging

In honor of the successful launch of the James Web Space Telescope, my wife and I decided to make a commemorative wall hanging of the telescope's main reflector dish.

We cut the mirror acrylic, and the matte black acrylic on our Glowforge laser, and glued them to an MDF backing. Using materials from CraftCloset

It's roughly 30" x 30" big.

 
 
Learn more about the JWST and see some of the amazing pictures on the NASA website

Controlling remote control blinds with a RaspberryPi (Draft)

I recently installed electric blinds in my house because there were certain windows that were difficult to reach. The blinds came with a remote, but I wanted to take them a step further and make them wifi enabled. It would have been somewhat simple to attach an ESP32 to the circuitry inside the blinds. But I figured it would be less invasive, and more reasonable to create a wifi connected remote

The back of the remote says that it communicates at 433.92 MHz, which is a really common frequency for lowpower/bandwidth signals. I also happened to have a few serial transmitters that operate at this frequency, and figured I might be able to use one of these. 

TODO: Example of 433.92 transmitter

The first step in this project was to figure out the modulation, and protocol used by these blinds. For this, I bought myself a software defined radio USB device (amazon). With this device, I can specify a frequency, and sniff the exact signal being sent by the remote. Universal Radio Hacker is a simple to use, but useful tool that interfaced with the SDR. This is what I got:

TODO: Image of remote signal

I realized looking at this signal, that the remote uses OOK modulation. Which is exactly what the transmitters I had used. I knew then I could make this work with  what I had on hand.

Once I had this signal captured, I was able to measure the on/off time for high and low values.  It also appeared as though the remote would repeat the same pattern 6 times, and each repeat would start with a long high then low value. I wrote some code in C# that ran on a raspberry pi to duplicate this exact signal, using the SDR to debug any differences or inconsistencies. After a few adjustments, I ran my code and the blinds responded! I was so excited I had proven this will work.

The first iteration of the code would step the blinds down once per second. Oddly enough, the blinds only seemed to respond every couple seconds, but I was definitely transmitting. After further investigation, I discovered the problem. RaspberryPis do not use a real time operating system, meaning processes that are running will be preempted by the OS, and paused to allow other processes a slice of time. The code I wrote was very basically bit banging the GPIO pin connected to the transmitter. Which meant every few milliseconds the process doing the transmission would pause. This totally threw off the timing of the transmitted signal, causing the blinds not to recognize the command. Every so often the process would get lucky and transmit a full signal. But it was uncommon. There are a few ways I could have prevented the OS from preempting my process (configuring one core to only run my process, writing a kernel driver, installing an RTOS on the raspberrypi). But all of these were somewhat complicated to implement, and would negatively impact the usefulness of my raspberrypi. I ported my code to C++ running on an ESP32, and it started to work perfectly.

To reverse engineer the protocol, I captured multiple commands sent by the remote. The blinds have 5 channels, and 5 commands (up, down, open, close, stop). Comparing each of these signals, it was easy to determine which bits were the channel, and which were the command. The signal also included a CRC for each of these values. 

I was able to get each of these commands/channels working. I connected the ESP32 to homeassistant, and now I am able to open and close all the electric blinds from my phone!  C++ implenetation of the protocol

 

First 3D Printed Clock

Background

(Skip this section if you're really only interested in the clock)

For as long as I've been building things, I've felt very strongly that: "If you can't draw it, you can't build it". I have a whole collection of equipment to draw out my designs; from large sheets of graph paper, to  architectural rulers(Amazon), compasses, and a plethora of other drafting tools. Designing is ultimately a mental exercise, one that requires visualizing designs and imagining how each piece interacts with another. Keeping all these details in mind is an incredibly difficult  thing to do well (Unless you're Tesla himself, who was very proud of his ability to "perfectly" imagine mechanical designs). So I draw it out, and use it as a tool for design instead of the design itself.

Before I start any project, I make a few rough sketches to decide on exactly what I want - sometimes a project will warrant scale drawings, (for which my architectural ruler is invaluable). And sometimes it's a rough sketch illegible by any one but me. Which brings up an important point - none of these sketches are good. They're almost always drawn at right angles because I am not a proficient sketch artist. Drawing at oblique angles and with perspective would be pretty cool to help visualize it - but it is not necessary at all.

As an example, here is a sketch I used to design a drum sander some time ago:

 And my best attempt at drawing a workbench with perspective
 


As you can see, my preferred choice of graph paper is dotted as it doesn't distract as much as the lines on regular graph paper does. My first calculus professor taught me that blank sheets of paper are the best choice for taking notes - especially math notes. I followed her advice and never looked back. I still use blank sheets of paper when I need something more free-form - but most often I need a little structure, and dotted graph is the best compromise.

Over the past few months, I've been learning to use Fusion 360. A 3D modeling/CAD software. When 3D printing, or laser cutting materials, it's necessary to have a 3D model, or vector graphic to feed to the machine. So some sort of cad software is a requirement for building my own designs. This particular one has a fairly steep learning curve, and it requires certain level of rigor from designs (As in, it doesn't make it easy to rough sketch ideas, or quickly throw together models). But the level of detail and design it enables is incredible. I was able to design this whole clock before ever printing any thing. The physical parts only needed a little tweaking after they were printed. This is the largest project I've done yet with Fusion 360. So let's talk about the actual clock. 

Finished

Design

This clock is a weight-driven pendulum clock. Like the classic Grandfather clock. This is one of the simpler clock designs, as it's easier to build than a spring-driven, or flywheel type clock. Notice the escapement at the very top, and the drum for the weight on the far left. The gears are attached to steel arbors, and mounted between laser cut sheets of acrylic. The acrylic frame will be held together with 1/4" bolts passing through 3D printed spacers/sleeves. The pendulum will be full size at 1m long, and the gears for the hour hand are such that one revolution of the hand is 24 hours instead of the typical 12. I anticipate this clock will be able to run for 5 days, but I'll need to run some tests with the final build. 

 




 

Escapement

The escapement is the literal beating heart of a clock. It depends on oscillations (In this case a pendulum) to advance the gears of a clock at a specified interval of time (My clock is designed at once per second). In a mechanical clock, it is the source of the ticking. This device brought about a whole new way of keeping time, eventually leading to the modern quartz crystal oscillator used in most modern clocks. These crystals generate an electrical signal at a specific frequency, and all digital devices use these intermittent electrical pulses to to execute instructions.


There are a number of different types of escapements, each with their own advantages and disadvantages (You can read more about them here). I chose a deadbeat escapement, as it's a simpler design, but still very capable.

 


Escapements have two primary functions: To advance the gear train at a constant, known rate. And to power the oscillator (Pendulum, in this case). These two functions together is what makes an escapement such a marvel. As the pendulum swings, the pallet fork will rock back and forth. Each time allowing the wheel to advance one tooth. This is a 30 tooth wheel, and the pendulum will make a full swing once every 2 seconds. Meaning the escapement wheel will make a full rotation once per minute. I have attached a clock hand to the arbor of the escapement wheel - this is my second hand. 

You'll notice at the very ends of the pallet fork, there are angled faces that directly contact the teeth of the escapement wheel. The escapement wheel puts pressure on the fork, because it is being powered by the weights through the gear train. As the fork rocks, and the escapement wheel advances, the teeth will slide past these angled faces, causing them to push on the fork just a little bit. Which in turn will push on the pendulum. Left to it's own devices, a pendulum would eventually stop, due to friction from the air, and pivot. But these angled faces allow for the pendulum to be powered by the hanging weights.

With the understanding that the escapement wheel turns once per minute, the rest of the gear train was designed to convert once per minute, into once per hour; to give us the minute hand. 

Gear Train


The gear train is the back bone of the clock. It includes the drum from which the weights hang, as well as the gearing to convert from the per minute rotation of the escapement, to the per hour rotation of the minute hand. Some clocks will have multiple gear trains,  as large clocks with many complications might need multiple sources of power. These  complications might also need different gear ratios. An example might be a day of the week complication, a moon phase complication, or to display the orbits of the planets.


 
The wheel right in the center with the four circles is the center wheel. This wheel rotates once per hour. This means the gear ratio from the escapement to this gear is 1:60.  Starting from the escapement to the center wheel, my gear teeth ratios are 9:36, 11:39, 13:55.  You might wonder why I choose such awkward ratios, and why not just have one pair of gears with a teeth ratio of 8:480? It is very possible to create a clock like this - but I did not want to have to create a wheel with 480 teeth. It would have been huge, and likely beyond the capability of my 3d printer. Three pairs of gears brought the size of each gear down to something much more reasonable.

The seemingly random teeth ratios were chosen to improve the longevity, and reduce the wear on each wheel. If you choose a ratio that does not divide evenly (Eg. 36/9 is not an integer value, but 36/12 is) you'll end up with different teeth meshing each rotation. This allows the teeth to wear more evenly over the lifetime of the clock.

Also notice that the sum of each meshing pair of wheels increase monotonically - That is, 9 + 36 < 11 + 39 < 13:55. This was important for my clock, because the gears overlap with each other, and if the next pair of gears in the series were smaller than the previous - the arbor would hit the previous large gear.  


Hour Gear Train


The hour gear train were probably the most difficult feature to design. They are driven directly from the center wheel, and convert the once per hour rotation, into once per 24 hour rotation.
 



 
The reason these were so tricky, is because in a typical clock the hour and minute hands are concentric with each other on the clock face. That meant I had to pick gear ratios such that the diameters of the gears allowed the input, and the output gear to also be concentric. The ratios that worked best for me were: 14:56, 10:60. 

 

 

 


In the image to the left, you'll see the two concentric shafts for the hour and minute hands. The minute shaft comes from the center gear and connects to the input gear. And the hour shaft comes from the output gear.

 

 

 

 

 

 

The exact process I used to find these gear ratios involved jiggling around a lot of factors, to satisfy these two equations:

Find gear teeth ratios a:b, and c:d such that:

a + b = c + d
and
a / b * c / d = 1/24 (hours)

Instead of the painful process to find solutions to these equations, it's easiest to just run some code to find all solutions (gist)

 If you don't want to run the code, here are the first few results from the program:

1:24 ratio:

54:15   60:9
54:18   64:8
56:14   60:10
60:9     54:15
60:10   56:14
64:8     54:18
64:28   84:8

1:12 ratio:

30:10 32:8
32:8 30:10
32:12 36:8

Printing

For this iteration of the clock, I'm 3D printing all the gears, and laser cutting the acrylic frame. Here is the drum after printing:

Pile of printed gears:


 


Since the gears have steel arbors that need to fit tightly through the center, the gears need accurate holes. Printed plastic is well known to shrink 2% - 5% after cooling. This makes it difficult to get accurate holes. An easy solution is to print with the hole, and drill it out the rest of way.


It's important that you still print with the hole, even if you plant to drill it out. With default settings, holes are printed with walls. Theses walls provide some structure to the hole, and will guide the drill bit. Without these walls, the drill bit will tend to wander, especially so considering the infill might deflect the bit.


Assembly


The assembly was somewhat tricky. All the gears needed to be mounted on the arbors at specific points, so that they would mesh with the next gear in the train. I printed measured spacers so that I can easily, and quickly mount the gears at the right place before gluing to the arbor. Super glue worked really well for this. 

Some of the holes were really tight, and difficult to push the arbors through. Using a drill to spin the arbor into place worked really well, and made mounting the gears really easy. 

 

I test fit every thing, more than once. It's critically important to test fit before permanently gluing them. Here you can see I'm test fitting the gear train before attaching the hour train

The acrylic frame just had holes cut into it for the arbors to sit. To help retain them in the hole so they don't move around, I glued little acrylic dots on the outside of the frame, as seen in the following picture


Because my frame is clear acrylic, I wanted these glued dots to stay clear. I used this glue, and it worked really well, and kept the frame perfectly clear. It says it's for glass, but it worked fine with acrylic.



Double checking things fit nicely when it's set upright

More test fitting, but with the hour train and face place mounted.


 
 




Monday, January 17, 2022

Portable Dice Tower

 Portable Dice Tower

 I was inspired some time ago to build a dice tower. It was always something that sounded fun to build. And I really like the look of contrasting inlay'd wood.  Here are a few pictures of the final result. The main body is made of beetle kill maple, and the  inlay is paduke. The inlay was done using the double bevel technique.