A Flagpole for the Hobbit House

Posted 09 April 2026

Last month I decided it was time to put up a real flagpole to display the American flag in all its glory. Being an engineer, I had to research the heck out of the subject to make sure we got something we would be proud to have in our front yard. A neighbor has a flagpole and he had gotten a flag pole kit from Admiral Flags, right here in Columbus Ohio. I also asked Grok, and he (It?) came up with the same company, so we ordered a 20′ kit from them.

Reading through the instructions on Admiral’s website, I was amazed at the amount of concrete needed for the flagpole foundation. They called for 6-8 80lb bags of quick setting concrete (480 – 640lbs!) for an 18″ diameter by 29″ deep hole – yikes! Being a septuagenarian, I wasn’t very eager to manage 80lb bags, so I decided to start with 10ea 50lb bags (500lbs) and add more if needed. The Admiral website also strongly recommended calling Ohio811 ‘call before you dig’ utility mapping service, so I did that right away. As it turned out that was one of my better moves, as my first intended location was right on top of a utility run to the house. Dodged the bullet on that one!

My planned location in our front yard is at least 150′ away from any electrical outlet and the nearest water faucet, so I had some logistics issues to work through. I needed an additional 100′ water hose, and I decided to use my backup electric generator for electric power. Here’s a short video showing the distances.

From watching some videos regarding quick setting concrete I decided to go with the 5-gallon bucket and electric drill mixing paddle route, so I loaded my brand-new Toyota Tundra pickup with 500lbs of QuickCrete, 2ea Lowes 5-gallon buckets, a cheap 100′ water hose and the mixing paddle.

I had conned a neighbor into helping, so we started digging mid-morning, and had a hole pretty much done in a couple of hours. I was amazed that the first 6-10″ was pretty rocky, but after that it was pretty easy going. Here are some photos of the hole:

Hole about 3/4 full, using 50lb QuickCrete bags and some rods to keep flagpole sleeve vertical

We had to stop at this point because my 20-year-old 1/2″ drill started smoking badly. I couldn’t really complain as I had gotten a LOT of use out of it, but it was apparently time for a new one. The next day I came back with a new 1/2″ hammer-drill and finished the foundation work. I poured concrete up to grade level so we could mow around it without having to come back and weed-whack the base.

The next step (literally) was to install the flag pole itself. My stepson was visiting from St. Louis, so helped me assemble the pole kit and set it into the sleeve.

And here is a short video of the completed flag pole with the U.S. flag proudly flying. Sure wish I had done this 20 years ago, but better late than never!

Proud to be an American!

Frank

Wall-E2’s many words for ‘obstacle’

In a manner analogous to the many words for ‘ice’ and ‘snow’ in the Inuit language, Wall-E2 has many words for ‘obstacle’, as follows:

  • Wall-E2 gets too close to an obstacle in front
  • Wall-E2 gets too close to the currently-tracked wall during tracking operations
  • Wall-E2 senses an upcoming wall while tracking the current wall
  • Wall-E2 hits something that causes it to get stuck and stop moving forward but the obstacle doesn’t register on the forward sensor
  • Wall-E2 gets too close to an obstacle to the rear

Wall-E2 gets too close to an obstacle in front

If Wall-E2 isn’t currently tracking a wall and senses an upcoming obstacle, it stops, backs up, and turns away from the nearest wall. If there is no ‘nearest wall’ it simply turns one way or the other and hopes for the best ;-).

Wall-E2 gets too close to the currently-tracked wall during tracking operations

This item in the above list was an unintended consequence of Wall-E2’s new parallel offset tracking ability. After finding the parallel orientation at a distance greater than the desired offset, Wall-E2 makes a cut toward the wall to capture the offset. Unfortunately this also means the forward LIDAR measures the slant distance to the near wall, NOT the distance to any upcoming walls. In some cases this leads Wall-E2 to believe it is running into an obstacle, and instead of continuing the offset capture maneuver, it instead executes an obstacle avoidance maneuver. The fix for this problem is to recognize that when Wall-E2 is deliberately angling toward the wall, and reduce the ‘obstacle avoidance distance’ OAD accordingly. So, for a desired wall offset distance Doff and for a maximum approach angle corresponding to a steering value of -Smax (negative steering values are ‘toward the wall’), the ‘effective obstacle avoidance distance’ OADeff should be less by some factor, (arbitrarily selected here to be 2). This gives OADeff = Doff/2 for a steering value of -Smax, linearly increasing to Doff when S = 0. This is a straight line with slope 1/(2*Smax) and y-intercept of Doff for all S values <= 0. For S > 0, OADeff = Doff. Here’s a graph of the equation for Stgt between 0 & -0.3

This image has an empty alt attribute; its file name is 201112-Calc-OAD-vs-SteerValTgt.jpg

Wall-E2 senses an upcoming wall while tracking the current wall

When tracking a wall, which by definition means in MODE_WALLTRACKING with a target steering value between -S and +S, Wall-E2’s desired response to an upcoming wall is to stop and make a 90º ‘spin turn’ away from the currently-being-tracked wall at the desired wall tracking offset value, on the theory that this will place Wall-E2 in the right place to start tracking the next wall.

Wall-E2 hits something that causes it to get stuck and stop moving forward but the obstacle doesn’t register on the forward sensor

This is the classic ‘I’m stuck!’ situation detected by monitoring the mathematical variance of front distance measurements over time, as described in this post. The recovery technique used up to now has been to back up for 1-2 seconds, and then turn 90º However, recovery from this condition can be problematic, as the robot will sometimes run backwards into another obstacle and execute the reverse ‘tractor scare maneuver’ of ‘Cars’ fame. With the addition of a 7th VL53L0X time-of-flight sensor, Wall-E2 can now detect a rear obstacle before it tries to climb it, leading to a better experience for the robot and it’s owner (that would be me). Now the ‘ExecuteStuckRecoveryManeuver()’ function first assesses whether or not there is enough room behind to successfully back up. If there is, it does the following:

  • Backs up a predetermined distance using the most suitable (forward or rear) distance sensor
  • Makes a 90º turn away from nearest wall
  • Moves forward a predetermined distance using either the forward or rear distance sensor
  • Makes another 90º turn to parallel the nearest wall again

The idea here is that if Wall-E2 is stuck on a shoe or a chair leg, it might be able to go around it and continue wall tracking. If not, it can repeat this procedure until it eventually works its way around the obstacle.

Wall-E2 gets too close to an obstacle to the rear

This condition rarely/never occurs in isolation; it happens during one of the other obstacle avoidance maneuvers, and only then when Wall-E2 fails to check it’s rear clearance before starting to back up.

Cheap Yellow Display – based Solfeggio Tone Generator

Posted 21 January 2026

My wife recently asked me if I could build a ‘Solfeggio’ tone generator that she could listen to as a sleep aid. A quick net search yielded the following:

Solfeggio frequencies are a set of specific tones believed to promote healing, relaxation, and balance. The primary nine frequencies range from 174 Hz to 963 Hz, each associated with different benefits, such as emotional healing, stress reduction, and chakra alignment.

963 Hz: Connection to the divine and awakening.
These frequencies can be used in sound therapy and meditation practices to enhance well-being.

174 Hz: Pain relief and grounding.

285 Hz: Healing tissue and organs.

396 Hz: Liberating guilt and fear.

417 Hz: Facilitating change and undoing situations.

528 Hz: Transformation and DNA repair.

639 Hz: Enhancing communication and relationships.

741 Hz: Awakening intuition and problem-solving.

852 Hz: Returning to spiritual order.

As a result of a previous project to create a GPS-enabled DashCam Power Switch, I thought this would be a perfect ‘Cheap Yellow Display project. The Cheap Yellow Display (CYD) is a ESP32-2432S028R development board integrated with a 240×320 pixel color touch-sensitive display. In the case of my DashCam project, this meant that I only needed a GPS module, a low-Rds MOSFET, and a bit of circuitry to make it all work – neat. For this tone generation project, it looked like I might be able to do the whole thing with just a CWD and a pair of BT earbuds, as the ESP32-2432S028R dev board incorporates BT capability. The wife already had a pair of BT earbuds, and I had acquired two more CYD modules after it worked so well for my DashCam, so I was all set.

As I did with the DashCam project, I started consulting with Grok right away. If you haven’t yet taken advantage of this – you should – Not only can Grok code in any language, it is also mind-bogglingly fast for internet searches on particular topics. So I started out with this conversation:

Me: I want to build a rechargeable battery-operated tone generator using the ESP32/CYD configuration. I would like the battery to be the same (or smaller) width/length as the CYD. The input to the charging circuit would be +5V from the Type-C connector on the CYD. What battery and charging circuit would you suggest?

Grok: For a rechargeable battery-operated tone generator using the ESP32-based Cheap Yellow Display (CYD), which measures approximately 50mm x 86mm, you’ll want a compact 3.7V LiPo battery that fits within those dimensions for easy integration (e.g., mounted behind the board). The tone generator can use the ESP32’s built-in DAC (8-bit resolution) or PWM for audio output, connected to a small speaker or amp. Power management involves charging the battery via the CYD’s USB-C (which supplies 5V) and boosting the battery voltage to 5V for the board when unplugged, as the CYD expects 5V input on its power pins.Suggested BatteryA 3.7V 1000mAh LiPo battery with JST connector, such as a 603450 cell or equivalent.

Why this? It provides 3-5 hours of runtime for a low-power tone generator (ESP32 + display draws ~200-300mA at 5V under load; enable deep sleep modes to extend life). It’s widely available, rechargeable, and includes built-in protection (PCM) against overcharge/discharge. Smaller options like 300-500mAh (e.g., 402030 at 40mm x 20mm x 3mm) work if runtime isn’t critical, but 1000mAh balances size and capacity for ESP32 projects. ezsbc.shop +3 Avoid larger capacities (e.g., 3000mAh) if they exceed ~65mm x 35mm, as they may not fit neatly.

Dimensions: Approximately 60mm x 34mm x 5mm (fits well within 86mm x 50mm, leaving room for wiring).

Suggested Charging Circuit: Use a TP4056-based module with integrated battery protection (BMS).

  • Why this? It’s a simple, inexpensive ($1-2) 1A charger for single-cell LiPo batteries, accepting 5V input directly from the CYD’s USB-C (via wires to the module’s IN+ / IN- pads). It handles charging to 4.2V safely and includes overcharge/over-discharge protection. When USB-C is plugged in, it charges the battery; when unplugged, the module’s OUT+ / OUT- pads provide battery voltage (3.7V)
  • Additional component needed: Pair it with a small boost converter like the MT3608 (adjustable to 5V output) connected to the TP4056’s OUT pads. This boosts the 3.7V battery voltage to 5V for the CYD’s 5V pin (avoid direct 3.7V connection, as the board’s regulator expects 5V for stable operation). github.com +2 Add a switch on the boost output for power control.

There was some back-and-forth to nail down the actual modules I would need, but pretty soon I had the battery (li-ion 603450), charger (TP4056) and DC-DC converter (MT3608) on order from Amazon. The reason I went with separate charger and up-converter modules instead of the IP5306 all-in-one is due the IP5306 requiring a minimum load current to remain active, and this would conflict with my plan to put the ESP32 to sleep during idle times to extend battery life.

After getting the hardware issues resolved, the next step was the ESP32 software. I had Grok develop the software using Arduino code, with the following specs:

Me: Referencing our discussion of my ESP32 CYD Sinewave Tone Generator Project, I would like to see your take on Arduino code for the ESP32, with the following specs:

  1. Non-K&R bracket convention (beginning bracket on new line)
  2. Nine (9) touch-sensitive radio buttons for the ‘Solfeggio frequencies’ (https://www.bing.com/search?q=complete+list+of+solfeggio+frequencies&FORM=R5FD1).
  3. A volume slider (horizontal at the bottom or vertical on the side)
  4. Tone output directed to Bluetooth transmitter
  5. Sleep mode after 10 minutes from coming out of sleep mode
  6. Battery charge indicator based on A/D measurements of the LiPo battery voltage
  7. Whatever other obvious requirement that I have failed to mention

Within a few seconds, Grok produced the following code:

Not only did Grok produce initial code, but it helped me work through some subtle issues with the ‘AudioTools’ library as I had not used this library before. Grok would offer code, then I would run (or try to run) and report back on any errors encountered. Pretty soon I had code that compiled cleanly and ran, and then it was a case of exercising the code and reporting any debug output back to Grok. This went around for a while, but we eventually got to working code. I learned that while Grok is very fast, he’s not always all that accurate. For anything other than the most trivial programming task, the human at the other end of the conversation must have relevant experience. At one point in the debugging process, Grok was recommending some hardware changes on the CYD board, but I knew from prior experience with the DashCam project that no such mods were required for detecting user touches on the touch-screen. So I was able to provide Grok with a small working program to do this and Grok was happy to incorporate the new information into the complete program. This, however, brought up another ‘gotcha’. Grok takes input from the human, thinks for a few seconds, and then disgorges another complete program – without any accompanying explanation. So, I said “what was the problem with the previous code?” and got a pretty comprehensive answer- yay.

Grok really doesn’t do a very good job of troubleshooting or code debug at all – that’s where the human’s engineering experience comes in. At one point I tried to describe the ‘cut the world in two’ troubleshooting technique I have been using for decades, but I’m not sure if Grok has any ability to remember things like that, or any ability to apply them, so I suspect that was a waste of time. Grok will continue to produce code without explanation if you let it – kind of a ‘random walk’ shotgun approach AFAICT. At the end of this hours-long session, I got kind of frustrated with this behavior and terminated the session. I put up a DM to @xAI, but never got a response.

Eventually, over a 2-3 day period we got a working program that would connect via BT to my wife’s earbuds and play the tone (with some ‘reverb’ added, even!) selected by tapping a button on the CYD screen.

This program worked fine, but had a few problems:

  • The ESP32 ‘deep sleep’ mode was problematic. The mode itself worked fine (and dropped the current drain down to just a few mA, but when the system came back awake, it wouldn’t reconnect to the BT earbuds. We eventually wound up using the ‘light sleep’ mode, which would reliably reconnect to the earbuds, but drew significantly more current (less battery life).
  • The earbuds themselves were an issue. When/if the system failed to reconnect, then only way to do so was to put the earbuds back in their charging container and force them back into ‘pairing’ mode so the tone generator box could ‘see’ them again, and this was a PITA.

These issues led my wife to ask if I could change the project to use wired earbuds rather than wireless. This made the design both simpler and more complex. Simpler because now ‘sleep’ wouldn’t be an issue as the wired earbuds eliminated the need to connect via BT. More complex, because the CYD has no native stereo output, so an additional module to convert I2S protocol stereo audio data to human-audible stereo sound was required, and in turn this required finding a third output-enabled GPIO line (the CYD configuration uses most of the ESP32’s GPIO lines to run the display), and this required cutting a board trace and running a jumper to access GPIO26.

Here’s my statement to Grok:

Me: referencing our CYD Tone Generator project, I want to modify it to use plug-in wired earbuds rather than BT. I believe this will require outputting the audio on two GPIO lines (22 & 27)? and implementing an audio amplifier and a volume control. Can you recommend a good audio amplifier package for this?

Grok immediately identified a really nice module:

Grok: I recommend the PCM5102A I2S DAC module (often labeled as “PCM5102 DAC Decoder” or similar). It’s a compact, affordable breakout board widely used in ESP32 audio projects for its simplicity and good sound quality (32-bit, up to 384kHz sampling). Many versions include a built-in 3.5mm headphone jack, making it plug-and-play for wired earbuds without additional soldering for the connector.

Why this one?

Directly interfaces with ESP32 I2S output (no need for the internal DAC on GPIO 25/26).

Provides line-level analog output that can drive most earbuds (16–32Ω impedance) at reasonable volumes without distortion—users commonly report success with direct connection for low-power applications like tones.

Low noise, high SNR (112dB), and minimal external components needed.

Cheap and available: ~$5–10 on Amazon, AliExpress, or electronics sites like Adafruit/SparkFun (search for “PCM5102 I2S DAC module”).

If your earbuds are very sensitive or you need more headroom, some variants include an integrated headphone amplifier (e.g., based on LM4880M—look for “PCM5102 with headphone amp” on Tindie or AliExpress for ~$10–15).

Connections (assuming standard I2S remapping in code):

VCC: 3.3V from ESP32.

GND: Shared ground.

BCLK (bit clock): Connect to your GPIO 22 (or remap as needed).

LRCK/WS (word select/left-right clock): You’ll likely need a third GPIO (e.g., 25 or 26) for this—add it if not already in your setup.

DIN/SDIN (data in): Connect to your GPIO 27.

FMT, FLT, DMP, SCL: Ground these (or leave default for standard I2S format).

XMT/XSMT: 3.3V (unmutes the output).

Analog out: Directly to 3.5mm jack for earbuds.

So I got a couple of the PCM5102A I2S DAC modules from Amazon, and wired them up according to Grok’s instructions. 3.3V, Gnd, BCLK, DIN all came from CN1 on the CYD, but I had to cut a trace to free GPIO26 from it’s normal connection through an audio amp to the ‘speaker’ connector so I could use it for LRCK. See below for the details:

Here’s the program:

This all worked really well, except for one last major ‘gotcha’. We used GPIO35 (input only) to monitor the battery voltage, and implemented a small ‘slider’ style battery charge indicator at the very top of the display. A call to ‘analogRead()’ in loop() measured battery voltage, and this value was depicted by the length and color of the ‘slider’ display. Unfortunately it turned out that the ESP32 library required to run the PCM5102A DAC module conflicted with the Arduino library used for ‘analogRead()’ calls. As hard as this was to believe, it was real, and neither Grok nor I could figure any way around it. So, we wound up using ‘digitalRead()’ instead (which obviously will only return a ‘0’ or ‘1’) and displaying either a full-length green slider (battery good) or a full-length red slider (battery bad).

And the schematic:

GPS-enabled Dash Cam Power Switch

Posted 10 November 2025

A while ago I got a dash cam for my truck, thinking that would be a good thing to have if someone tries to cash in on my insurance by deliberately backing into me on the road. So, I got this dash cam, mounted it on the windshield of my truck, and life was good. Then my wife and I went out of town for a few days and when we came back (at 2am), the truck battery was dead and it took us a while (and a new car battery) to recover. This happened one more time, fortunately in my garage, and I decided I was going to have to come up with a way of killing the power to the dash cam when (or shortly thereafter) the truck stopped moving.

I researched the power outlets in my truck (a 2011 Ford F-150) and found that the power to the SYNC system was (at least theoretically) on only when the engine was running. Unfortunately, I had pulled the fuse for this circuit years before to keep SYNC from grabbing my phone’s Bluetooth signal even though I had long ago UNpartnered SYNC and my phone, so that was out.

My next idea was to construct a power switch around one of the recent GPS modules available cheaply, such as this one. I looked around a little bit, and found the nice ‘TinyGPS++’ library, and used a Sparkfun Pro Micro (the Arduino version) from my parts box to interface to the GPS module. Another search and I found an example sketch, and I was in business. After the usual number of errors I got the sketch working, with data displayed in the serial window of my Windows 11/Visual Studio/Visual Micro setup.

Unfortunately, all the data came back as ‘INVALID’, mostly because we live in an earth-sheltered house, and that pretty much snuffs out any GPS signals. The next day I took my laptop and the breadboard for a spin, and the GPS module started spitting out valid data about 30 seconds after I backed out of the garage. The data looks like this:

This isn’t particularly useful for my project, as I had planned to use speed < MPH_THRESHOLD for some time > ELAPSED_TIME_THRESHOLD, maybe something like 10-20 minutes. The above data has the time I need, but not the speed. Maybe the TinyGPS++ library has that capability?

Yes, the TinyGPS++ library does have the methods I want. Here’s the code I came up with:

Now to test the code. I found a free web-based app called NMEASimulator by panazzolo.com that allows me to set a course with heading and speed, and then output the corresponding NMEA sentences to a COM port. With a USB-to-Serial adapter I should be able to replace the data lines from the GPS module with the simulator output and test the code.

12 November 2025 Update:

My USB-to-Serial adapter arrived today, and I was able to connect it to my GPS switching board, bypassing the actual GPS. Then I was able to use the NMEA simulator to transmit NMEA messages to the Sparkfun Pro Micro and test the Dash Cam power switch algorithm.

This combination worked great! I started the action, NMEA sentences started flowing to the Pro Micro which output decoded speed values to the debug window. I could run the speed up and down and watch the program toggle power to the load (39-Ohm power resistor) in response to the speed changes. The only things left to do are to build an enclosure and change the time and speed threshold parameters. Here’s the ‘final’ code:

26 November 2025 Update:

Thinking about how to test my GPS-enabled power switch project, I decided to add a cheap LCD display so I could monitor GPS output and power switch status in real time. So, I reached into my parts box and what came out was a pair of ‘Cheap Yellow Display’ modules had been laying around for some time now. As I started working with the display, I realized it wasn’t just a display; the ESP32-2432S028R development board that runs the touch-sensitive display incorporates a ESP32-WROOM-32 module as its main microcontroller. This module features a dual-core Xtensa LX6 processor running at up to 240 MHz, 520 KB SRAM, 448 KB ROM, integrated Wi-Fi (802.11 b/g/n) and Bluetooth (v4.2 BR/EDR and BLE), and 4 MB flash memory. In addition, the board has a standard micro-USB port for power and programming, a USB-C port for power, three 4-pin micro-JST 1.25mm pitch connectors for UART and GPIO, and a 2-pin micro-JST connector for a speaker. Looking at the specs, I realized I could conceivably eliminate the Sparkfun Pro Micro module entirely, and have just the display/CYD connected to the GPS via CN1 (4-pin GPIO/power/GND) and a single GPIO output (plus GND) to run the power switch.

A not-so-insignificant hitch in the getalong for this project was the type of connector required to interface to the sockets on the CYD. It turns out these are ‘micro JST 1.25mm’ connectors, and it took me three tries with Amazon to get the right ones. These are the correct ones.

I was able to easily connect the GPS input to CN1 and use the NMEA simulator to test the code, ported over from the Pro Micro project. However, I hit a roadblock when I went looking for a GPIO port to use as a switch signal to the power switch board; it turns out the display occupies most of the GPIO lines, and the two ports needed for GPS Txd & Rxd took the only remaining output-capable lines (IO35 is available, but it is input-only). Some more research with the help of Grok led me to this project site that describes how to free up ports via hardware mods. There I found directions for freeing up IO21, the port that normally controls display backlight brightness by PWM-ing the backlight LED. This involved removing a surface-mount transistor and re-orienting a TINY! surface-mount 3.9 Ω current-limiting resistor, as shown in the screenshot below:

As you might guess, this took some doing, as these parts are TINY!

But after a couple of false starts, I got it done:

The photo below shows the CYD module with GPS data displayed, and with my newly-liberated IO21 line connected to the power switch board (the illuminated red LED shows that the power switch is ON)

So now we are pretty close to being done; all that is left is to mount the display/controller into its box, mount both the display & power switch boxes onto their custom-printed carrier, and test the whole thing in my truck. The ‘final’ (to the extent that anything I do is actually final) code is shown below:

Here is a short video of the CYD display and power switch during a driving test in my local development loop. At the start of the video, the GPS module has already detected 8 sats (hard to see), so as soon as the computed speed goes over 5mph, the power switch changes from OFF to ON (red LED on the power switch and ‘ON’ on the CYD.

Unfortunately it was at this point that I discovered that the BUZ76A MOSFET power switch had too high of an Rds (around 4Ω) to actually turn on the camera -bummer!

Some discussion with Grok netted me a low-Rds MOSFET – the AOD424G AOD424 TO252 with Rds in the milli-Ohms. This has a pretty low Vds(max) of around 20V, but this is fine for my needs as it will only be switching 5V. Here’s the new schematic:

01 December 2025 Update:

As things are coming together on the electronics side, I took some time to investigate mounting options in my truck. After fiddling around a bit, I came up with the following possibility:

This would actually work out great, as the PETG plastic boxes wouldn’t be directly exposed to sunlight, and, the display would still be very visible to the driver, and it wouldn’t block vision to my time and temperature display at the top of the radio stack. As a huge bonus, it turns out there is enough slack in the USB power cable to the dash camera that I could plug it directly into the switch box (green in the photo above, if I changed out one of the USB type-C chassis connectors for a USB2/3 type. $7 for 5 connectors from Amazon – delivery in less than a week – yay!

Of course this means I need to change the box design, but that won’t take long.

08 December 2025 Update:

I got my new USB2 connector, and redesigned the box & lid to accommodate it, creating a conundrum in the process.

See the problem?

When I started wiring everything in, I realized I had created a big problem. If I ever wanted to remove the proto-board from the enclosure, I would have to unsolder all the wires to the USB connectors first – UGH!! I thought I could solve this problem by adding connectors in the lines to the USB connectors, but I hated that idea as it just adds complexity (“a connector is a source of trouble between two other sources of trouble”), so I put the whole thing aside to await a better solution. This morning while exercising it came to me – redesign the enclosure so the parting line between box and lid is right at the top edge of the connector modules. Then the proto-board and connectors can be lifted right out after removing the two proto-board mounting screws – genius! Only one small ‘gotcha’ the USB-C connectors will have to be flipped 180𝆩 so the PCB slot is on top rather than on the bottom. Since USB-C connectors are orientation insensitive anyway, this shouldn’t be an issue. Here’s a screenshot of the ‘final’ (as final as anything gets in my world) enclosure, with the connector cutouts moved to the top so removing the lid will allow the PCB – with the connectors still attached – to be lifted out.

Here are some photos of the ‘finished’ product:

After installing it in my truck, I made a couple of test runs around my little development’s circle, and it seems to be working great. Here are some photos showing the installation in my truck:

Here is the ‘finished’ version of the firmware:

15 December 2025 Update:

Now that things seem to be working, I’m trying to clean up the installation a bit. Here are some photos showing some of the current temporary installation details:

I also took the opportunity to measure the current load with the display and switch box electronics powered, but with the dashcam OFF. This is important, as this load determines how long the battery will last in this configuration. I used my handy-dandy USB2 ‘Charger Doctor’ pass-through device that alternately displays output voltage and current. As shown in the following photo, the ‘OFF’ current draw is about 0.19A.

Showing current draw in the ‘dashcam OFF’ configuration. The meter shows 0.19A (190 mA).

The 12V car battery in this truck is a ‘DieHard’ AGM Technology battery as shown below:

So I asked Grok how long this battery would last with the dashcam OFF, but the display (and it’s imbedded MCU) still powered up with a 0.2A draw, and this is what I got back:

So almost a month – that sounds about right, and it means I wouldn’t have had a dead battery at 2 am when my wife and I got home from last summer after a week at the 2025 Senior Games in Des Moines, Iowa!

Just as a sidenote, I have a ‘premium’ subscription to X not because I think X posts are worthwhile, but because Grok *IS* worthwhile. As a long-time electrical engineer, I was familiar with the property of lead-acid batteries that extended the discharge time under very small loads compared to the normal A-Hr rating, but I had never heard of the ‘Peukert effect’, which allows for a much better estimate of discharge times for low loads. This took Grok about 30 seconds – what a *great* engineering assistant!

And, speaking of Grok, I also asked him (it?) for the name and purpose of the ‘cubbyhole’ I’m using as the mounting cavity for the dashcam switch project. Turns out this was probably originally intended for an ashtray, and then repurposed as the mounting cavity for a trailer brake module. And, he also came up with dimensions, which should allow me to design a cradle that will fit snugly in the hole and keep the dashcam electronics from sliding around. We’ll see!

17 December 2025 Update:

A couple of interesting things happened in the last two days. The first thing is I have been cursing at the maker of the SuperONE cigar-lighter automobile power adapter for providing a USB-C retractable cable that doesn’t deliver +5V to power my dashcam switch module.

Because of this, I gave the product a ‘1’ review and described my methodology in determining that the retractable USB-C cable just wasn’t providing +5V. This got the company’s attention, and they offered to send me a new one, free of charge. I said, ‘OK’ but if the new one doesn’t work either, then my review will be edited to say that. Well, the new one arrived, and the same thing happened – no +5V to my project box. However, this time I was smart enough to try plugging the cable into my BT headset, and voila – it started charging the headset! Hmm… After some back and forth with Grok I learned that a ‘Power Delivery’ (PD) device doesn’t deliver power to a connection until it is asked to do so. The BT headset did, my cheap USB-C chassis receptacle didn’t – oops! So, I wound up editing my review from a 1 to a 5 and explained why; I suspect that will make the SuperONE folks a lot happier ;). Also, I ordered a different USB-C receptacle – one that has the smarts to request power from the USB-C cable.

The second thing that happened is I’m trying to figure out how to mount my dashcam power switch project into the ashtray/trailer brake ‘cubbyhole’ (see the photos above). And because I have not only one – but two 3D printers it naturally involves 3D printed parts. I designed and printed a shape that fits nicely into the cavity, and then I’ll need to figure out exactly how the combined assembly can be fastened into the cavity in a way that can be removed easily, if necessary, but also won’t just fall out at the slightest provocation.

1;8 December 2025:

After getting the enclosure issues resolved, I turned my attention to the GPS module, which is kind of hanging around on the shelf above the central audio panel. I’d like to build a small enclosure just to hide it away, leaving only the small GPS antenna itself and the even smaller RF cable leading down to the GPS module visible.

22 December 2025 Update:

I received and installed the new PD-enabled USB-C module, and it went in OK, with the usual curse-words and adaptations:

I printed up a small right-angle adaptor to mate the holes on the USB-C module with the holes on the box, but I had to mount the module on the inside wall – I decided not to make a new box just for this issue. So now The PD-enabled retractable cable on the cigar-lighter adaptor delivers 5V to the module and life is good!

Here’s the ‘final’ installation (nothing is every really ‘final’ in the Paynter world)

23 January 2026 Update:

I’ve been using the DashCam power switch for about a month now, and it seems to be working great. A couple of weeks ago I modifed the ‘Too Slow’ and ‘No Data’ readouts to change the unit from ‘sec’ to ‘min’ and ‘hours’ as appropriate; trying to figure out what ‘83520 sec’ meant was too hard for my brain, so I changed the code so this number would read ‘23.2 hours’

I also noticed that when I drive into my earth-sheltered garage, I get some strange status display readings. The number of sats will go to zero, but the clock time will often stay running (and stay accurate). Also, since the clock is active, the speed value will actually start to climb (divide by-almost-zero?) and so the speed criteria for keeping the power ON will be met. I think the way to handle this is to have a separate block in the logic for sats < min_satellites to force everything but the ‘Too Slow’ and ‘No Data’ timers to show “n/a”

26 January 2026 Update:

The dashcam switch is working well, but I’m not happy with the physical installation. I thought I had a great idea by putting it into the space originally designed for an ashtray, but it turns out not to be such a hot idea. The gear selector lever blocks out a significant amount of the display in ‘D’, and looking down at the display (and peering around the gear shifter lever) isn’t great. So, I decided to ‘re-imagine’ the entire installation.

The original installation features separate boxes for the display and the switch, which wastes a LOT of space. Starting from a clean sheet, I laid out the the switch circuitry and GPS module on a plug board, as shown in the following photo.

Required hardware for complete GPS-to-CYD implementation.

As shown above, the power input (USB-C), power output (USB2), switch (AOD424 MOSFET) and GT-U7 GPS modules easily fit into the footprint of the CYD display. I should be able to put everything into one box with the footprint of the CYD and sufficient depth to accommodate the switch & GPS hardware

However, the display area where I want to install the new version of the dash cam features a deeply recessed display area, and a complex profile. So, I needed to somehow model the profile so the box design would work. As the following photos show I used a combination of ‘cut & try’ for the first rough estimate, and then a contour gauge to get an estimate of the rest of the profile.

Then I used my 3D printer magic to print out successive profile estimates until I got reasonably close to the actual profile. This then can be used for the actual box design. The following photo shows the progression from left to right.

After getting the profile reasonably close, I printed a prototype box by extruding out the profile a few tens of millimeters, and got this result:

After a few more iterations I printed a full-size box:

Here’s a photo showing the old and new installations:

The above photo shows the old and new installations. The new installation will actually move to the left a bit as shown below, as it will incorporate the GPS module internally.

This will still hide the truck’s clock display, but since the new unit will also display time, that’s not a loss of functionality.

The next step was to disassemble the old installation to reuse the parts:

As can be seen from the above photo, there is quite a bit of wasted space in the power switch box, and I also figured out that one of the two USB-C chassis-mount connectors can also be removed, as the power connection from the power-switch circuit to the display will be routed internally – no need for a separate USB-C cable. I breadboarded the power switch circuit again, this time with compactness in mind, and wound up with this:

and then transferred the parts to a small piece of DIY circuit board. Then the whole thing fits nicely into the new enclosure, as shown in the following photos:

After more than a few hours of frustration due to the lack of a reliable GPS signal in the house, I think I finally got everything running properly, and tested it on my subdivision loop:

Here’s the updated schematic, with a missing ground wire added and with signal/control GPIO numbers added:

Stay tuned,

Frank

ESP32-CAMs Distance Measurement Study

Recently I have returned to working with WallE my autonomous wall-following robot, and I started thinking again about the issue it has with reflective surfaces. At the same time I ran across a post about using two ESP32-CAM modules for distance measurements, and I started to wonder if I could do something like that with WallE. I already have a visible red laser on the front, so maybe the two ESP32-CAM’s could use the laser ‘dot’ for distance measurements? Would this technique have the same problem with reflective surfaces?

I just happened to have two ESP32-CAM modules in my parts bin, so I thought I would give this idea a try and see how it goes. I know next to nothing about image processing in general and about the ESP32-CAM in particular, so if nothing else it will be a learning experience!

After a bit of web research, I got my Visual Studio/Visual Micro development environment configured for ESP32-CAM program development and for the ‘AI Thinkier EP32-CAM(esp32_esp32cam)’ target, and found a couple of examples that came with the newly-installed library. The first one I tried was the ‘CameraWebServer’ example (C:\Users\Frank\Documents\Arduino\Libraries\arduino-esp32-master\libraries\ESP32\examples\Camera\CameraWebServer\camera_pins.h), which turns the ESP32-CAM module into a webserver that can be accessed over the local network using any browser. The example provides for still images and real-time streaming – nice! However, I wasn’t interested in this capability, so after looking around a bit more I found an example that just takes still images and writes them to the SD card. I modified the code to convert the captured JPEG into BMP888 format so I could look at the individual color channels in isolation. I set the capture size to 128×128 pixels and capture a JPEG frame. The JPEG frame is just 2352 bytes, but the BMP888 conversion expands to 49206 bytes (128 x 128 x 3 = 49152, plus 48-byte header + 6 bytes at end, I think). Here’s the code at present:

and here are the JPEG and BMP888 versions of the 128×128 pixel image captured by the camera:

Picture29.jpg
Picture29.bmp

Then I copied Picture29.bmp to another file byte by byte, zeroing out the Green & Blue bytes so that only the red channel was non-zero. However, when I viewed the resulting file, I got the following image:

Picture29_red.bmp

This doesn’t make any sense to me, unless the byte ordering in a BMP888 file is BGR or BRG instead of RGB. However, when I researched this on the web, all info I found indicated the byte order in an RGB888 file is indeed R, G, B. It’s a mystery!

Here’s the code that produced the above results:

I posted the ‘why is my red channel blue?’ question to StackOverflow, and got the following comment back from

I think your problem is with the reference that you found. ISTR the colour order for RGB888 24 bits per pixel BMP is actually Blue, Green, Red. So your all “red” image will indeed appear blue if you have it backwards. See Wiki BMP & DIB 24 bit per pixel. BTW you can get some funny effects converting all red or all blue images from JPEG to BMP since the effective resolution at source is compromised by the Bayer mask sampling.

Well, at least I’m not crazy – my ‘red’ channel WAS actually the ‘blue’ channel – yay! Per the wikipedia article, the actual byte order is “… blue, green and red (8 bits per each sample)”

17 February 2025 Update:

After figuring out the BGR sequence, I moved on to the idea of locating a red laser ‘dot’ on a black background; here’s the experimental setup:

Experimental setup for ‘red dot on black background’ test

And here is the 128×128 pixel image captured by the ESP32-CAM.

So now I needed to find the coordinates for the red dot in the black field. Rather than deal with the tedium of writing and debugging the search routine in Arduino, I decided to suck the image data into Excel, and write a VBA script to find the ‘dot’, as shown below:

This produced the following Excel spreadsheet (scale adjusted to show entire 128×128 pixel layout):

128×128 RGB pixel data with max value highlighted

For comparison purposes, I have repeated the ESP32-CAM image here:

So, it seems pretty clear that I can correctly extract pixel values from the ESP32-CAM image and find the laser dot – at least in this contrived experiment with a non-reflective black background. Also, it appears at first blush like the upper left-hand corner of the ESP32-CAM image corresponds to R1C1 in the Excel spreadsheet.

The next step is to move the ‘dot’ to a significantly different location on the target and see how that effects the location of the max value in the grid – we need this to determine the orientation of the Excel data relative to the image data; maybe I got lucky, and maybe not 😉

02 March 2025 Update:

After setting this project aside for a few weeks, I figured out how to get the ESP32-CAM system to repeatedly grab images, convert them to BMP, and find the maximum red pixel value in the scene. Here’s the code:

When I ran this code in the following experimental setup, I was able to roughly map the row/column layout of the image, as shown:

As shown, the (0,0) row/column location is the upper right-hand corner of the image, and (127,127) is located at the bottom left-hand corner. At the 20cm spacing shown, the image boundaries are about 85mm height x 100mm width.

The next step will be to mount two ESP32-CAM modules on some sort of a frame, with the laser mounted halfway between the two.

06 March 2025 Update:

As part of my evil plan to use two ESP32-CAM modules to optically measure the distance to a laser red dot, I needed the two modules to talk to each other. The ESP32-CAM modules don’t really have the same sorts of two-wire communications facilities as do the various Arduino and Teensy modules, but I discovered there is an ‘ESP-NOW’ feature that provides ‘packet’ communications between ESP32 modules using the wireless ethernet channel. I found this tutorial that explains the feature, along with demo code for determining the MAC for each unit and a separate program to demonstrate the technique. I modified the demo code to just repeatedly send a set of fake sensor values back and forth to demonstrate to my satisfaction that this technique would work for my intended application. Here’s the code:

And here’s some typical output from the two ESP32-CAM units:

From one device:

From the other device:

A couple of ‘user notes’ about this demo program and it’s application to two different devices:

  • The MAC address display program has to be run twice – once for each unit to get that all-important information.
  • The demo program also has to be run twice, but the MAC address used for each device is the address for the ‘other’ device.
  • As can be seen from the output, I simply used fake sensor data. However, I made sure to use different sets of values (10,20,30 on one and 20,40,60 on the other) so I could verify that the data was actually getting from one to the other.
  • The user must be careful to make sure the two devices are programmed correctly. I found it really easy to program the same device twice – once with the MAC & data for the other unit, and again with the MAC and data for the unit being programmed (which will not work). I wound up with clip-on labels on the two cables going to the two different devices, and then making sure the Visual Studio programming port was correct for the device I was programming. Doable, but not trivial.

21 March 2025 Update:

I broke a finger playing b-ball two days ago, so my typing speed and accuracy have suffered terribly; such is life I guess.

Since my last update I designed and printed a fixture to hold two ESP-CAM modules and a laser diode so I could run some distance experiments. Here’s a photo of the setup:

10 to 80cm distance setup. Note I’m using only one ESP-CAM module

I modified the firmware to simply print out the max value in the scene, along with the row/col coordinates for the max value. The firmware continues to save a red-only image as well. Here’s the hand-written results:

the numbers at the end of each measurement are the .bmp file suffixes (from picture_red58.bmp to picture_red87.bmp).

And here are the representative red-only photos (one per distance) for the selected measurement:

10cm: 114 @ (40,65) picture58_red.jpg
20cm: 241 @ (72,7) picture62_red.jpg
30cm: 215 @ (66,23) picture64_red.jpg
40cm: 215 @ (65,31) picture68_red.jpg
50cm: 225 @ (57,16) picture74_red.jpg
60cm: 199 @ (64,40) picture79_red.jpg
70cm: 255 @ (33,49) picture84_red.jpg
80cm: 255 @ (36,68) picture85_red.jpg

From the data and the photos, it is easy to see that the laser ‘dot’ doesn’t come into the view of the camera until the 20cm distance, and after 60cm the ‘dot’ is washed out by the normal overhead lighting. In between (20 – 60cm) the ‘dot’ can be seen to progress from the far left-hand edge of the scene toward the middle.

26 March 2025 Update:

I made another run, this time with two cameras, as shown in the following photos:

two ESP32-CAM modules mounted on the same frame, with red dot lase mounted on centerline

If my theory is correct, I should be able to see the location of the red dot move horizontally across the images, from left to right for the left cam, and right to left on the right cam. Unfortunately this wasn’t evident in the data. I loaded the above data into Excel and plotted it in various ways. The best I could come up with was to plot row & col locations from each camera vs distance, hoping to see a linear change in either the row or column values. The plots are shown below:

From the above plots, I could see no real progession in the row values, but if I used a lot of imagination I could sort of see a linear decrease in the column values for the left camera and a much less distinct linear increase in the column values for the right camera.

For completeness, I have included the actual camera images used to produce the above data:

Looking at all the above images, I can’t discern *any* real horizontal shift in the position of the red dot. In addition, at 70cm, the reflection of the laser dot off the table surface is just as bright as the reflection off the target, leading to frequent mis-identification of the maximum location.

Conclusion:

Well, this was a nice try and a fun project, but there’s no escaping the conclusion that this ain’t gonna work!

STM32 Firmware Debug Study

Posted 10 November 2024

Last month I tried ‘Klipperizing’ my Flashforge Creator Pro 2 (FFCP2) IDEX 3D printer, and it was an unmitigated disaster. After uploading the Klipper firmware, the printer refused to boot up, and I eventually I had to buy and install a new motherboard to regain functionality. Since then I have discovered that my original motherboard seems to be undamaged, but I can’t get it to boot into the FFCP2 firmware.

So, I have embarked on a quest to figure out how to restore FFCP2 functionality to my original STM32-based FFCP2 motherboard.

I started on this journey with one of the ‘blue pill’ devices I happened to have in my parts drawer. They are generally based on the STM32F1 series, so hopefully not different enough from the STM32F407 to matter.

To start with, I connected up my laptop to the ‘blue pill’ board using a ST-LINK clone and was able to program it via VS2022/VsMicro with the ST-LINK upload option selected, as shown in the following screenshot (note – this was done with the ‘blue pill’ jumpers set as shown in this photo):

And here is part of the ‘verbose’ build output:

I also tried some of the different upload modes advertised in the vMicro menu, as shown in the following conversation from the vMicro forum:

After receiving this input, I installed the JRE, confirmed it was actually there, and then tried the ‘STM32DuinoBootloader’ option again using the USB connector. It still failed, with the output shown below:

After passing this along, it was suggested I try this trick again, but after launching VS2022 in ‘Administrator’ mode. This made no difference – got the same error.

After some more thought and discussion, I came to the conclusion that the reason this was failing is because the ‘blue pill’ devices don’t have any (or at least, the proper) bootloader installed. This situation is discussed here, and also here

As an experiment, I changed the jumper back to the default location (same side for both jumpers) and tried again – same (bad) result.

After this, I also tried the ‘HID Bootloader 2.0’ upload method, also using the USB connector. It failed, with the following output:

This all led me to believe that my ‘blue pill’ devices either have no bootloader loaded, or have the wrong version.

Back to the books. From the original vMicro forum reply I went to their ‘STMicroelectronics STM32 Overview‘ page, and from there to the stm32duinio ‘Arduino_Core_STM32‘ and Serasidis ‘STM_32_HID_Bootloader‘ github sites.

Upload methods site:

I had real trouble understanding correlating the information on this site with my observations when working with my ‘blue pill’ devices. Apparently when I was able to program the device with the ST-LINK adaptor I was using the ‘SWD’ method, described on the Overview site as:

12 November 2024 Update:

Based on what I have learned so far, STM32* MCU’s aren’t naturally compatible with the Arduino ecosystem. However, there are several workarounds that allow Arduino programs to work on STM32 devices. There apparently are at least two hardware-facilitated methods for uploading Arduino programs to STM32 devices; one is by using a ST-LINK device (STM or ‘clone’) connected to a ‘SoftWare Debug’ (SWD) port if one is available, and another is by using a FTDI(Future Technology Devices International) USB-Serial adapter device connected to a MCU serial port.

In addition to the ‘hardware-facilitated’ workarounds, there are at least two different software implementations that allow Arduino programs to be uploaded via the USB port. Both of these require that a ‘bootloader’ be installed into the STM32* MCU. One implementation is the ‘Maple’ bootloader, which comes in two flavors – the ‘original Maple bootloader’ and a modification of the original Maple bootloader called ‘STM32duino-bootloader’, or ‘bootloader 2.0’.

Serial Adaptor Method

The FTDI (serial adaptor) method requires that the STM32* MCU be restarted in ‘native bootloader’ mode before attempting to program the device. This is accomplished (in the case of ‘blue pill’ devices) by moving the BOOT0 jumper from the ‘1’ setting to the ‘0’ setting, as shown below, and then pressing and releasing the RESET button:

Then the program can be uploaded via the Arduino IDE (in my case I’m using the Visual Studio 2022 Visual Micro extension for Arduino, so my ‘look and feel’ will be different).

I found a really good tutorial for this ‘serial’ mode here. It was created in 2018, so it is a bit out of date with respect to the state of development of arduino-compatible bootloaders allowing program upload via USB, but is by far the clearest, most readable treatment of FTDI-based serial adaptor program uploads. I copied the wiring diagram shown below from this tutorial, in case it goes away at some point:

The process for upload using Arduino and a serial adaptor for program upload described here assumes you have the Arduino IDE installed and have the STM32 family of boards installed in the Arduino IDE. The procedure for installing the board information varies depending on the Arduino IDE version (I’m using Arduino 2 with the Visual Micro extension to Visual Studion 2022).

  • Wire up the blue pill in accordance with the above diagram, and connect a USB cable from the adaptor to your PC. Note the port number associated with this connection
  • Select the ‘serial’ upload method and the port number from above, as shown in the screenshot below
  • Move the blue pill BOOT0 jumper from ‘0’ to ‘1’ and press/release the RESET button. This places the MCU in ‘Program’ mode using the built-in uploader.
  • Compile/Upload the desired Arduino program. I strongly suggest you start with a simple ‘blink’ program. You should see the upload progress from 0 to 100%. If you don’t see upload progress, you have something wrong.
  • Move the BOOT0 jumper from ‘1’ back to ‘0’ and press/release RESET. Moving the jumper places the MCU back in ‘user’ mode and pressing/releasing RESET will start your user program running. Note that in my experience, the user program will start right away, even with the BOOT0 jumper in the ‘1’ position, but you must actually move the jumper or the next time you cycle power or press/release the RESET button the MCU will come back up in ‘Program’ mode and your user program will not run.
‘Serial’ upload method and ‘COM15’ selected for program upload

The output from a successful compile/upload cycle is shown below:

13 November 2024 Update:

OK, now I have learned how to upload Arduino programs to my ‘blue pill’ STMF103C -based boards. I can program it using an ST-LINK adaptor, and I can program it using a FTDI serial adaptor. Both of these options rely on STMicro’s internal bootloader to transfer a program binary to flash memory.

After successfully programming both my ‘blue pill’ devices, I decided to try my luck with my 3D printer motherboard. This board has both serial (UART) and SWD (ST-LINK) connectors, and I chose the SWD connector option. My first try at this failed, at which point I used vMicro’s Visual Micro Explorer to check for a STM32F40xx board selection, found the ‘STM32F4xx’ selection, and installed it.

This then shows up as ‘STM32 Discovery F407’ in the board selection entry field.

With this configuration, I was able to program a variation on my blue pill ‘blink’ program to direct a square wave to the buzzer on the motherboard. Amazingly, this worked like a champ, proving that my motherboard has not been bricked at all – Yay!!

Here’s the compiler/uploader output:

Looking through the above output, I realized that this line:

which points to ‘stlink_upload.bat’ shown below:

Is where ‘all the magic’ happens. After the user program is compiled into a binary (in this case ‘BluePill.ino.bin’) this file is passed to an open-source version of STM32’s ST-LINK program, which then writes the binary file to STM32 flash memory starting at location 0x8000000.

I think this means that I could just as easily use ST-LINK on my PC to upload BluePill.ino.bin to 0x8000000.

YESSSSS! Using STM’s ST-LINK on my laptop (for some reason I can’t get STM32CubeProgrammer to work) I uploaded BluePill.ino.bin to the FFCP2 board, and it worked!

Next, I tried uploading the original FFCP2 firmware onto the device, hoping that I would then have *two* working FFCP2 motherboards. Unfortunately, although the upload succeeded, and I was able to verify that the contents of the MCU’s flash memory were identical to the binary file I got from FlashForge Tech support, I saw no indication that the program was actually running (even though no actual printer hardware was connected, I had expected that at least the display and the buzzer would be active).

Alas, now I can no longer connect to the board using ST-LINK 🙁 I fear my journey is over, and not in a good way 🙁🙁🙁🙁

Starting Over with Windows 11

posted 04 August 2024

I recently purchased a new Dell XPS15-9530 with Windows 11 installed, and I have spent the time since that purchase trying to get Windows 11 to work like I want it to, and Windows 11 has spent that same amount of time trying to get me to work like it wants me to – GRRR!

Here are some of the things I want to change from the basic Win 11 Home package I received.

  • Win 11 photo viewer sucks, and the photo viewer from Office 2010 rocks. In the old viewer, I can move from photo to photo with left and right arrows, and I can manipulate the photo multiple photos at the same time.
  • The right-click context menu in the file explorer view now has multiple pages of context menu items, most of which aren’t useful. The ‘preview’ option, which I use a lot, is buried at the bottom of the second page
  • Win 11 insists on storing my files in the ‘OneDrive’ (cloud) folder, and I hate that. Even if I ‘unlink’ my PC from ‘OneDrive’, it still tries to put stuff on the cloud – grr. See this link for information on how to adjust this
  • I now have multiple ‘Documents’ folders with multiple icons, and none of them point to my Documents folder.
  • Win 11 insists on using the first 5 characters of my email address as the name of the primary user folder (‘C:\users\[primary user name]’) and I want it use my first name for this. See this link for some information on this. Also, this link seems to imply that I might be able to ‘change my primary alias’ in my Microsoft account, (which might then change the default user account?). I was able to create a fake Outlook account (Frankabcede@outlook.com) and (although I didn’t do it this time) make it the primary alias. In theory, if I do this and then start over with Windows 11, I should wind up with ‘Frank’ as my default user account, and C:\users\Frank as my default user folder.
  • Win 11 insists on saving screenshots taken with Shift-Windows-S key combination to a screenshots folder in C:\Users\paynt\OneDrive\Pictures\Screenshots, even though I have unlinked my PC from OneDrive.
  • The private LAN connection between my old and new PC’s seems to come and go with the wind. At one point I got it working by setting it to ‘not use passwords’ or something like that.

So, for the nth time, I’m starting over, and this time I plan to document all the steps, so when I have to do this again (on the Nth+1 redo), I’ll have a little bit better roadmap. To prepare for the ‘redo’, I printed out the list of apps currently installed on the new PC, as shown in the screenshot below:

4 August 2024 list of apps on new Win 11 PC

When I look at the ‘Home’ file explorer display on my old PC, I see the following:

‘Home’ display on my old PC

Which shows that Downloads, Pictures, Videos, Desktop, Music and ‘Documents’ have ‘Stored Locally’ shown – so apparently, I got that done correctly on my old PC. When I do the same thing on my new PC, I get the following:

‘Home’ display on new PC

Resetting to factory defaults while keeping personal files:

I followed the steps shown in this link to restore to factory defaults while keeping personal files intact. Unfortunately when it came back up again, it still had ‘C:\users\paynt’ as the default folder, along with another one labelled Frank.Frank_9350, wherever the heck that came from.

Trying again, but this time I chose the option to download the OS from the web rather than restoring from a local copy.

This didn’t work either, so I elected to reset from web download, including ditching all my files and accounts (everything is backed up on my NAS, so shouldn’t be an issue).

On this run-through, I opted to not restore from my previous PC, instead opting to ‘set up as a new PC’. We’ll see how this goes. Also, I used my new ‘Frank_Paynter@outlook.com’ as my email address for my Microsoft account. Hopefully that will result in ‘C:\users\Frank’ (first 5 characters of email address) as my default user folder

Decided to skip ‘Let’s customize your experience’ and ‘Use your phone from your PC’. Accepted ‘Always have access to your recent browsing data’, skipped PC Game Pass, and then it went into updates.

Success! (with a small ‘S’). The default user folder is named ‘Frank’ instead of ‘paynt’, and there is only one of them. Also, Desktop, Downloads, Documents, Music, and Videos are ‘Stored Locally’. Unfortunately, ‘Pictures’ are still stored on OneDrive.

So, I found this:

How do I Unsync a picture folder from OneDrive?

Open OneDrive settings (select the OneDrive cloud icon in your notification area, and then select the OneDrive Help and Settings icon then Settings.) Go to the Account tab. Select Choose folders. In the Choose Folders dialog box, uncheck any folders you don’t want to sync to your computer and select OK.

And UNchecked all the folders. The first time I tried this, I couldn’t UNcheck the pictures folder, and there was a message “we are unable to stop synching some folders” After I searched on this, I found another page that said:

May 11, 2021 — Can’t stop syncing folder · Right-click OneDrive blue cloud icon in the system try, click Settings. · Go to Backup tab and click Manage Backup.

So, I did that and told Windows to stop backing up any folders to OneDrive. Then I was able to UNcheck the pictures folder (and all the other ones too), so hopefully I am almost fully weaned from OneDrive at this point. Curiously, when I went back to the ‘Choose Folders’ page to verify that everything was still UNchecked, it took a while (a minute or two) for the page to come up. When it did, however, everything was still UNchecked – Yay!

And, another success! When I took a screengrab of the ‘Choose Folders’ page, the storage location turned out to be “C:\Users\Frank\Pictures\Screenshots” – Yay Yay! I also confirmed it’s not actually necessary to bring the screengrab up to center screen and select ‘Save’, as screengrabs are automatically saved to the above folder – Yay Yay Yay!

Next, I unlinked this PC from OneDrive, using the procedure below:

To unlink your OneDrive account from a PC, you can do the following:

  1. Select the OneDrive cloud in your notification area to open the OneDrive pop-up
  2. Select the OneDrive Help and Settings icon
  3. Select Settings
  4. Go to the Account tab
  5. Select Unlink this PC

This actually worked, and now the OneDrive (cloud) icon has disappeared from the left side of File Explorer entirely – Yay Yay Yay Yay!

Windows 11 Pink Border on File Explorer

Apparently, Windows 11 has a weird sense of humor, as I have found that the border of the file explorer (and maybe others) dialog box is colored pink when it is selected, and gray when it isn’t. I hate the pink color, and naturally (because Windows 11) it can’t be changed! I found this page, where it says:

Windows 11 File Explorer uses Mica effect in the titlebar and toolbar and that’s why we can’t set any color in the titlebar using Personalization settings. In Windows 10, we could set any color in File Explorer’s titlebar by changing the accent color in Personalization settings. So, following the steps on this page, I downloaded ExplorerPatcher and tried to use it to get rid of the pink border around file explorer windows, but either windows 11 or ExplorerPatcher has changed, as this trick didn’t work -Rats!

Among other posts on the i-net, I found this one complaining about ‘pink everywhere’. The response by a ‘Microsoft expert’ contained a link to a ‘known problem in win 11’, bu the link is broken. Otherwise there was a long dissertation about display drivers (which I ignored because I haven’t changed the drivers on my laptop and they worked fine with the original win 11 install).

Finally, while just randomly changing things on the color settings dialog, I switched the ‘Transparency effects’ OFF, and voila! The pink border around file explorer windows was removed! Halleluiah! Here’s a screenshot of this particular dialog with the ‘Transparency effects’ switch highlighted:

File Sharing on Local Network:

Before I reset my new laptop, I had file sharing (somewhat) working between my new laptop, my old laptop, and my wife’s laptop, so I was hopeful that I could get it working again. In ‘Advanced Network settings’ I enabled ‘Network discovery’ and ‘File and printer sharing’ for private networks (and disabled them for public ones). I also disabled the ‘Password protected sharing’ option and enabled ‘Public folder sharing’. Here’s a screenshot of the setup:

New laptop sharing setup

Then I verified the above settings were the same for my old laptop (they were). In File Explorer I navigated to the C:\Users\Frank\Documents folder and in ‘Advanced Network Settings’ set it to share with full control by ‘Everyone’ as shown below:

Then I did the same thing with C:\Users\Public.

When I went back to my old laptop to verify sharing, I noticed that that the ‘Documents’ folder wasn’t shared, but the ‘Public’ folder was properly shared with full control for ‘Everyone’. That might explain why I was having problems with local network sharing before. In any case, I set up sharing for ‘Documents’ and ‘Public’ the same as the new laptop. Then I restarted both laptops.

When the laptops came back up, I double-clicked the network icon on both. On my old laptop I could see the NAS and Jo’s laptop, but not my new one. When I did the same on the new laptop, I couldn’t see any other devices, but there was a popup message at the top of the explorer window to the effect that network discovery had not been turned on, and to ‘click here’ to do so. I clicked, and after that I could see all the devices on my local network. I’m not sure why this happened, as I was sure I had already enabled network sharing, as shown in the ‘Advanced Network Settings – Advanced Sharing Settings’ screenshot above (maybe I didn’t click on OK?).

So, after rebooting both laptops, I can access folders on my new laptop from my old laptop, but not the other way around. I successfully copied a ~2MB folder from old to new Documents folders, but I can’t go the other way – strange. I worked through a ton of potential fixes for this, all without success. So, I’ve decided to bend to the inevitable and just go with the flow here.

Applications:

Windows Office – installed OK

Upgrade to Win 11 Pro – Per advice from CoPilot, navigated to Settings->System->Activation->Change Product Key -> Click on ‘Change’ -> enter generic Windows 11 Pro product key (VK7JG-NPHTM-C97JM-9MPGT-3V66T), and clicked OK. That was all there was to it. First time I’ve actually benefited from AI!

Activate Application Guard: Done

AJC Active Backup & AJCSync4: Done

Arduino & Teensyduino: According to this Teensy page, I Installed Arduino IDE 2.3.2, copied in the URL, and then installed teensy-specific software as described. Everything seemed to go well, with last line of log = ‘Platform teensy:avr@1.59.0 installed

Bridge Composer: Downloaded the 30-day trial, Installed and activated using emailed activation key

CopyTransControlCenter/CopyTransPhoto: For uploading videos from wife’s iphone – Done

DipTrace non-professional Standard License: Done

Movavi Video Editor 2024: Installed and activated using emailed activation key, but I don’t like the dark background – fix later

Notepad++: Done

P-touch Editor: Done

Prusa Slicer 2.8.0: Done

TeraTerm: Done

TrackIR5: Tried to install but was stopped by McAfee. Uninstalled McAfee – Done

Visual Studio 2022 Community Edition: Done

Wixel Configuration Utility: Done

Get Legacy Office Photo Viewer Back:

This site has the procedure for getting the old photo viewer back as a stand-alone app. Following the link to this site, I downloaded Microsoft SharePoint 2010 installer and launched it. Then I selected ‘Customize’. Then I set all options to ‘Not available’ except for ‘Microsoft Office Picture Manager’, which I set for ‘Run from My Computer’ (see screengrab below).

All options except ‘Microsoft Office Picture Manager’ set to ‘Not Available’

Then I clicked on ‘Install Now’ to install Picture Manager as a stand-alone app.

The next step is to restore the ‘Preview’ context menu option for photos. I found this site:

Procedure for restoring ‘Preview’ option to context menu for photos

However, I found that ‘Default Apps’ had been moved to Settings -> Apps -> Default apps. From there select ‘Photos’, and then set’ Microsoft Office 2010′ as the default app for each photo extension (.jpeg, .jpg, .png). This worked great – and as promised, the ‘Preview’ option appeared on the context menu (unfortunately it appeared on the ‘second page’ so you have to first select ‘Show more options’ to see it).

Restore Windows 10 context menu with ‘Preview’ item near top:

Now that I have the old Office Photo Manager back, the next trick is to move the ‘Preview’ context menu item to the ‘front’ page of the context menu. After some research, it appears that the easiest way to do this is to simply restore the Windows 10 context menu style. This involves adding a key to the registry. There are a number of ‘HowTo’ videos on this – pick one. After editing the registry, this is my new context menu for photos:

Windows 10 context menu, with ‘Preview’ 3rd from top

End Game:

At this point I think I have things pretty well recovered, without all the crap about multiple ‘Document’ folders and wrong-named user folders. I’ll let this play out for a while and make any other adjustments as necessary. Hopefully I can now settle into my new laptop without cringing every time it opens a File Explorer window

Stay Tuned,

Frank

Untangling gl_Left/Rightspeednum global/local variables

Posted 30 May 2024

While looking through the code for another reason, I discovered that I have committed the mortal sins of using the same name for a global variable, a local variable and a function definition parameter. Originally I defined global variables gl_Leftspeednum & gl_Rightspeednum thusly:

But then some years later in my code I see:

They’re everywhere! yikes!

So, what to do? The original (bad) idea was to have these variables ‘global’ so any part of the code could ‘see’ the current motor speeds. This was BAD because that also meant that any part of the code could change the motor speed (even if it shouldn’t) , and figuring out who did that would be a nightmare. This is where I should have started thinking about building a ‘motor’ class to hide all this – but I didn’t, so….

Also, using a global symbol name in a function definition is at least moronic if not suicidally stupid – does that overwrite the original declaration? To add insult to injury, the function definitions above use ‘int’ as the type rather than ‘uint_16’, so does that mean that motor speed can be negative, but just inside that function – ouch, my head hurts!

Alright – since I didn’t do the right thing and encapsulate this stuff in a motor class, and I don’t want to have to rewrite the entire 7K+ line program (at least not yet), I need to figure out a short-term non-idiotic fix (or maybe just close my eyes and have another beer?)

OK, so the functions involved in this debacle are:

  • void SetLeftMotorDirAndSpeed(bool bIsFwd, int speed)
  • void SetRightMotorDirAndSpeed(bool bIsFwd, int speed)
  • void RunBothMotors(bool bisFwd, int gl_Leftspeednum, int gl_Rightspeednum)
  • RunBothMotorsBidirectional(int leftspeed, int rightspeed)
  • void RunBothMotorsMsec(bool bisFwd, int timeMsec = 500, int gl_Leftspeednum = MOTOR_SPEED_HALF, int gl_Rightspeednum = MOTOR_SPEED_HALF)
  • void RunBothMotorsMsec(bool bisFwd, int timeMsec, int gl_Leftspeednum, int gl_Rightspeednum)
  • void MoveReverse(int gl_Leftspeednum, int gl_Rightspeednum)
  • void MoveAhead(int gl_Leftspeednum, int gl_Rightspeednum)

SetLeft/RightMotorDirAndSpeed(bool bIsFwd, int speed):

This declaration should probably be (bool, uint16_t) as negative speed values aren’t allowed. I changed the speed declaration from ‘int’ to ‘uint16_t’ and the program still compiles OK. The ‘speed’ argument gets passed to ‘AnalogWrite’ which is declared as AnalogWrite(int pin, int value).

RunBothMotors(bool bisFwd, int gl_Leftspeednum, int gl_Rightspeednum):

RunBothMotors() is called just once in the code, by RunBothMotorsMsec(). RunBothMotorsMsec() in turn is called just four times – three times by HandleExcessSteervalCase() and once by RunToDaylight(). In all four cases the speed arguments are positive constant integers <= 1000 (Teensy analog output resolution is set at 12 bits –>4096). It looks like RunBothMotors() and RunBothMotorsMsec() should declare their speed arguments to be uint16_t

RunBothMotorsBidirectional(int leftspeed, int rightspeed)

RunBothMotorsBidirectional(int leftspeed, int rightspeed) just calls SetLeftMotorDirAndSpeed() however, the speed arguments can be positive or negative, so the ‘int’ declaration is required in this case. The sign of the speed input argument is converted to the appropriate direction flag value and a negative input speed is converted to a positive value for the SetLeftMotorDirAndSpeed() call.

RunBothMotorsMsec(bool bisFwd, int timeMsec, int gl_Leftspeednum, int gl_Rightspeednum)

All this function does is call RunBothMotors(), then delay for the requested amount of time, then stop the motors. Note that RunBothMotors() does not check the speed arguments for range or sign.

MoveReverse(int gl_Leftspeednum, int gl_Rightspeednum):

MoveReverse() is used extensively in ‘CheckForUserInput()’, but only twice elsewhere ( both times in IRHomeToChgStn()).

MoveAhead(int gl_Leftspeednum, int gl_Rightspeednum):

Similar to MoveReverse(), but used more outside ‘CheckForUserInput()’. Once in ExecuteRearObstacleRecovery(), once in TrackLeftWallOffset(), once in TrackRightWallOffset(), once in IRHomeToChgStnNoPings(), once in IRHomeToChgStnNoPingsPID(), twice in IRHomeToChgStn().

int gl_Leftspeednum, int gl_Rightspeednum:

These symbols are everywhere in the code, in a global variable declaration, in the signature of many of the motor functions, and in the code itself as local variables in the functions that have those symbols in the signature.

As an experiment I commented the global uint16_t definitions out and re-compiled. I got a bunch of ‘was not declared in this scope’ errors, but they were all like the following snippit:

in the above code a local int16_t variable is declared because the result could be negative. Then the local variables are constrained into the range (0-255) and then loaded into the gl_Left/Rightspeednum global vars, and also passed to MoveAhead(). This only occurs in the two TrackLeft/RightWallOffset() functions.

gl_Left/Rightspeednum global vars are also used in the ‘OutputTelemetryLine()’ function

So it looks like the usage in the above snippet is actually OK. The global vars wind up being loaded with the latest left/right speed values just before those values are sent to the motor driver. The usage in the telemetry output functions are also OK, as they just print the current left/right speed value

gl_Left/Rightspeednum used in function declarations:

I re-educated myself on the fact that formal function declarations don’t actually need parameter names – just the type declarations, so:

could just as easily be written:

so maybe my use of the gl_Left/Rightspeednum names for these parameters wasn’t quite so scary bad as I thought. Still, defining the same symbol name in two different contexts as two different types (uint16_t and int) is demonstrably a bad idea, even if one of the symbol usages is ignored by the compiler (after all, this usage is what resulted in my current freakout). I changed these to ‘uint16_t leftspeednum’ and ‘uint16_t rightspeednum, in both the formal declaration at the top of the program (reqd for default parameter declaration) and the ‘inline’ declaration.

I wound up changing the following lines:

In addition, there are a number of places where the output from the PIDCalcs() function is added to or subtracted from the current speed to produce the next speed value, but the initial adjustment is to a ‘uint16_t’ variable. This is problematic because the initial adjustment can result in a negative value being loaded into a uint16_t variable, with unexpected (if still well-defined) behavior. The fix for this is to change the type of the ‘local’ variable to ‘int’ vs ‘uint16_t’ to accommodate the potential for negative values, and only load the result into the global ‘uint16_t’ variable when it is certain the result is positive. This resulted in the following changes:

After all these edits, the program still compiles cleanly. As to whether or not it behaves cleanly, that is still a very open questions. Only time will tell!

Stay tuned,

Frank

Python Script for Challenging Invalid Voter Registrations

Posted 31 May 2024

The folks at TrueTheVote.org (the organization that used cellphone geotracking to expose widespread voter fraud during the 2020 election) put together a database to expose huge numbers of invalid voter registrations across the country. Most of these invalid registrations are due to the voter having moved out of their original voting district/county, but not removed by the responsible election board. While this seems pretty innocuous (and was, in earlier, less troubled times), this now represents a huge opportunity for fraud in the upcoming 2024 election.

Although the TTV folks have the data, they can’t do much about it without the help of concerned citizens who actually vote in those regions because local laws require that any voter challenge be raised by a voting citizen in that particular region.

So, TTV generated a website called ‘IV3’ which allows concerned citizens from anywhere in the U.S. to create an account and query the IV3 database for problematic voter registration records for their voting district/county. For instance, I live and vote in Franklin county, Ohio and my page on the IV3 site looks like this:

If I click on ‘View Active’, I get a page displaying the first record that matches the criteria, i.e. a voter still registered in Franklin county but who has since moved to an address outside of the County, as shown below:

If I want to challenge this voter’s registration in Franklin county, I would click on ‘Challenge this record’, which would display ‘Cancel’ and ‘Submit’ buttons as shown below:

Clicking on the ‘Submit’ button would remove the record from the ‘Active’ list and place it on the ‘Challenged’ list, which could then be exported in .CSV format for submission to the Franklin county board of elections.

It sometimes takes more than 100 seconds for the site to display a new record after each challenge submission, so this gets old pretty fast. After several days of plugging along while working on other things, I had managed to challenge about 600 records from the more than 42,000, a mere ‘drop in the bucket’. So, I started to wonder if I might be able to automate this a bit with a Python script; a web-bot of sorts.

After some research, I discovered a web-page automation API called ‘Selenium’ that could be called from a Python script, so I started learning how to use Selenium to do what I wanted. After the usual number of mistakes and appeals to StackOverflow for guidance, I got a working Python script together, as shown below:

Note that in order to use this script, you must have Python3 and the Selenium extension installed on your computer.

Even though I used ‘FranklinCountyOhioChallenges’ as the name of the main function, this script should be usable for any other location (or you can simply change the name, as long as the two occurrences in the script have identical names).

After getting the script working, I can now run the script to challenge any number of voters with a very simple command, as shown below:

On my windows system (and I’m pretty sure this holds for **nux systems as well) all I have to do to run another batch of the same size is to click on the ‘up-arrow’ button once and then hit ‘Return’. If a different batch size is desired, it’s ‘up-arrow’, edit the batch size, then ‘Return’.

I have found that doing a batch size of 100 takes about 90 minutes, so I can do several of these during the day while working on other things, and then I generally do a batch of 500 overnight. This allows me to do at least 1000 or so each day, so it will still take me around 42 days to challenge all the 42K or so registered voters who have moved out of the county. Your mileage may vary, of course :).

Each time I get a thousand or so challenges done, I click on the ‘View My Challenges’ button on the main page, and then on the ‘Export’ button as shown below, to download the challenges into a .CSV file that is directly readable in Excel (or any other modern spreadsheet program). I then use Excel to print out the entire batch (using Portrait mode and scaling to ‘fit all columns on one page’). Then I fill out and sign the cover form required by the Franklin County Board of Elections, attach the printed out challenge records, and physically submit the form and data to the BOE. As courtesy I also email the .CSV file to the responsible officer there, and so far they seem to appreciate the effort.

22 June 2024 Update:

My script started failing on me a few days ago, and I couldn’t see why. After using the issue as my ‘going to sleep puzzle’, I realized I could go back to my old manual process and see if it worked. If it did, then something in my script was bad. If it failed, then something had changed on the iv3 website.

As it turned out, IV3 had added a new ‘View Moved and Registered’ button, and moved all the qualifying records (which, it turned out, was all of them) into the new database. So, when I clicked on my normal ‘View Active’ button, I got ‘No Records Found’, which of course also killed my script :(.

So, the fix was to direct my script to the new button instead, and then all was well. I have updated the above script to the new version.

Stay tuned,

Frank

Improved Pill/Caplet Dispenser

Almost three years ago I designed and fabricated some pill/caplet dispensers for the half-dozen or so prescription meds I have managed to accumulate over the last decade or so. A while ago, one of my prescriptions changed its tablet to a much smaller size, so I decided to update my design while fabricating a replacement dispenser.

Between the last project and this one I’ve been playing with OnShape, a web-based 3D CAD package, so I thought I would use it to see if I could do better than last time. I really like OnShape because it uses a 2D ‘sketch’ based design philosophy, which makes tweaks and/or modifications much easier – change a few 2D sketches, and the entire design changes along with it.

The previous design implemented a smooth collar that was a press-fit for the pill bottle cap which turned out to be kind of clunky. This time I thought I might try implementing internal threads on the collar so instead of a press fit it would simply screw on like the original cap, and I discovered that a ‘ThreadCreator’ extension existed for OnShape – neat!

So, I worked my way through the process, and came up with the following design, available to anyone with a free OnShape account

This design has internal threads for a 37mm cap with the standard 4.7mm thread pitch, so it will screw directly onto the pill bottle, ‘eliminating the middleman’. Here are some photos of the finished product:

And here is a short video showing the dispenser in action:

10 June 2024 Update:

Last night I attempted run two more prints of this model, as I have two additional pill bottles of the same diameter with older pill dispensers, but the prints failed catastrophically – bummer! I rounded up the usual suspects (bed temp, model arrangement, Z-axis tuning, etc, and finally managed to get another print going, at least through the raft and first few layers. After bitching and moaning about this for a while, it occurred to me that if I had documented the layout and settings more aggressively from the first print, I wouldn’t have wasted all those hours last night and today. So, once I’m sure I have a consistent print configuration, I will document it here.

I got a good print with the following settings:

  • Flashforge Creator PRO II ID
  • Left Extruder – Red PETG, 240C, 80C Bed
  • Right Extruder AquaSys120 240C, 80C Bed
  • 2-layer raft using support filament (AquaSys120)

See the following images for the full setup:

After a 3-hour side-trip into the guts of the Flashforge to clear an extruder jam, I was able to get the second print underway. As I write this it is about 6% finished, but all the way through all the support material parts (so it should finish OK).

17 June 2024 Update:

Not so fast! I realized that the threaded portion of the dispenser cap, while functional, was very poorly printed due to the lack of supports (and, as I found out later, also due to the resolution setting). In addition, the side walls of the V7 slide box were too thin and broke apart easily. After modifying the design, I attempted another print using the above settings, but the PVA dissolvable filament simply refused to stick to the print bed – arrrrrgggggghhhhh!

After going through the whole extruder & bed temperature search routine again yesterday, including replacing the heated bet PEI layer and even putting down blue painter’s tape with no success, I was perusing google-space for clues and kept running across reports where dehumidifying the PVA filament worked. I didn’t see how that would help me, as we control the relative humidity in our house to about 50% +/-, but hey, what did I have to lose at this point?

So, before going to bed I dug out my filament dehumidifier rig and left my filament in it overnight (and until about noon the next day for a little over 12 hours). Then I tried some prints and although not successful at first, the results were encouraging. I finally got two really good prints with the following setup:

  • Slicer resolution: ‘0.15m OPTIMAL’ setting in Prusa Slicer
  • Right (PVA) extruder: 220C
  • Left (PETG) extruder: 240C (this was constant throughout)
  • Bed: 40C
  • Layer of blue painter’s tape on top of the PEI substrate

So, I think the big takeaway from this episode is: PVA must be explicitly dehumidified BEFORE each print session. Otherwise the PVA will not stick to the print bed, no matter what you do.

Stay tuned,

Frank

07 July 2024 Update:

After getting the threaded pill bottle dispenser cap working, I decided to try my luck with my two 57mm twist-lock pill bottles. The twist-lock cap geometry was considerably harder to design. Rather than trying to design and print everything as one piece, I decided to separate the dispenser piece from the cap mating piece, as shown below:

Bottle Cap Mating Ring
Pill Dispenser body and slide
All three pieces together. Note that the cap mating ring fits into the dispenser body