Simple fitness timer / Arduino Uno R3

I’ve been working out religiously this year, and reading up on getting the most out of my workouts. I read something about optimizing the rest time between sets, and I started wondering how to best track that. The phone is a pain, because unlocking it, getting to an app, etc. is distracting and takes time. Laptop, same thing, plus I have to have a laptop in my workout area.

I started thinking, well, I have a whole bunch of unused Arduino Uno units and a 3D printer, maybe I could cobble something together. So what do I need? I want simplicity, so a box with buttons and a display.

I found this case shape on Thingiverse: https://www.thingiverse.com/thing:845415

It’s built for an Arduino Uno and the DFRobot LCD 1602 shield with buttons. The case even has 3D-printed button extenders that are used to press the buttons on the shield. Simple yet elegant. Ticks all the boxes.

I ordered the HiLetGo shield for $6.49 here: https://www.amazon.com/gp/product/B00OGYXN8C/ref=ppx_yo_dt_b_asin_image_o01_s00?ie=UTF8&psc=1

…and started printing the case. I decided to print in two colors for cool points. Black for the bottom case and buttons, silver silk for the top. Came out OK. I might sand & finish it later.

The shield arrived today. I quickly cobbled together some test code, attached the shield to one of my spare Unos and uploaded the sketch.

Nothing on the display. The backlit was lit, but nothing on the display.

Turned on serial in the code and added some debugging. Uploaded again. OK, good news, the Arduino is working, it’s moving around in the code, my button presses are recognized.

I tried adjusting the contrast via the onboard pot. Nothing.

Went to the amazon reviews/comments for the device. Finally found the relevant comment: “Adjust the ‘pot’ for contrast just realize this style pot takes ALOT of turn to get to the other end.”

So, with my tiny screwdriver, I turned and turned, for way longer than I would have expected, and eventually my sample text showed up.

Now I just have to write a quick sketch for button-initiated 60- and 90-second timers, and I’m good to go! Quick, no-fuss timer with customization capabilities and a simple interface and display. Might add a sound feedback in a future iteration.

UPDATE: Here’s my first stab at a script. Up gives a 60-second countdown, Down gives a 90-second countdown, and the screen shuts off when it’s done so you don’t even have to watch it closely. Screen shuts off after initial display, SELECT to see the very few instructions again.

https://github.com/dc540/arduino1602ShieldTimer

UPDATE 2: Here’s a link to a buzzer that will fit in this exact case. It’s not super loud when wired directly. Supposedly a transistor might kick it up a notch. https://www.adafruit.com/product/1740

As promised, Anet A8 vs Ender 5 comparison

And I realize this isn’t apples to apples. Other factors are involved. A lot of people have been able to get the Anet to print way better than this. But there’s a reason there’s a long list of “essential upgrades” for the Anet. It is a rock-bottom DIY machine. I’m not even going to call it entry-level. For entry-level, a primary requirement is ease-of-use. Lower quality can be excused, but entry-level should not frustrate users out of the hobby.

Left: Anet A8. Right: Same piece, Creality3D Ender 5

Here are two prints of the exact same part, side by side. Same Cura settings, good bed leveling. The piece is designed to hold glue sticks. The piece on the left, because of the inaccurate circle size printed, won’t even accept the glue stick. It’s just OFF. Can’t even jam it in there. No dice. The piece printed by the Ender, however, has well-rounded holes, and the glue stick just slips in with no friction as intended. The print is within spec.

Now for a closer look.

Anet A8 hole close-up
Ender 5 hole close-up

See how much neater and rounder the holes are on the Ender 5? I attribute this to the Anet having an acrylic frame and just being overall wobbly. And with an acrylic frame, you can’t really tighten it too much, else it will crack the acrylic. Accuracy is critical when printing parts that interact with other parts. Also note the uniformity in the fill lines. Still not perfect on this print, but way tighter. This is not because the nozzle is different in any way. It’s the same sized nozzle.

Next let’s look at the layer stacking.

Anet A8 layer stacking
Ender 5 layer stacking

Just so much cleaner.

Again, some of this is definitely attributable to my own skill level. I’m still relatively new at this. A proven amateur. My point is that I got these results from the Ender 5 with a stock, straight out of the box machine, after only adjusting the extruder steps/mm. This is the way.

I still had a bit of an issue with edge curl-up on this print, you might notice that in the side-by-side. I printed the next piece, which is nearly identical, with a brim, and also brought the nozzle just a hair closer to the bed, and about four hours in to a 13 hour print, it looks like edge curl isn’t going to be an issue with this one. As I get more attuned to this machine, I should get better at predicting and preventing issues like that.

Update: Indeed, the brim held, and the next two pieces were virtually flawless, with no corner curl-up. It’s possible the problem was nozzle distance and it would print fine without a brim. Further testing will reveal that, when I’m not trying to complete pieces.

How I Became Less Discouraged About 3D-Printing

A few years back, I bought my first 3D Printer. I settled on the Anet A8. Mainly because it was cheap. Partly because it was a DIY challenge, and I tend to take on challenges, but mainly because it was cheap. I had it mostly assembled, but reached an obstacle which I can no longer remember, and set it aside. Then in 2018, I moved, having never printed anything, and packed it up.

When unpacking the “lab” boxes in the new home, I decided to refocus my efforts on getting it up and running. I was able to continue where I left off pretty easily, and printed several things successfully, and many more things unsuccessfully.

I will now rattle off all the things I hated about the Anet A8. I hated them so much that it actually gave me a feeling of dread when considering a 3D print job. My failure rate was so high that more than once I ordered things printed on the open market rather than attempt them myself.

  • I hated the bed. The bed on the A8 sits low and moves back and forth on one axis. If the belt is even slightly off, too loose or too tight, print problems will occur. The bed was also leveled by SCREWS set in the corners of the bed, so if you add an alternate build surface, you have to move that out of the way to adjust the bed leveling. I added larger knobs later, but they were still problematic due to that design. Also, because the bed was flat at the bottom of the build area, reaching underneath to level it was painful.
  • The Z axis was controlled by TWO SEPARATE MOTORS on two separate threaded rods. Yet another thing requiring manual synchronization, or print issues will occur.
  • I didn’t know any better, but I hated the acrylic frame, because it made the whole thing a bit rickety, and “wobbled” during prints.
  • The hot end was physically attached to the extruder. Maybe this was a good thing, because you don’t have a bunch of unused filament hidden away in a long bowden tube, but if anything goes wrong anywhere in the hot end on the Anet, it’s a real PITA to disassemble and reassemble. It almost requires four hands to hold the extruder, hot end and fan all together while tightening the screws. Once I didn’t tighten the heater block enough on reassembly, and it vibrated loose and came off during the print, and dragged all over the piece, melting plastic in its wake.

It got to the point where I was afraid to run bigger and more complex prints because all too often they resulted in just wasted PLA.

So after losing all faith in both my printer and my own abilities to manage it, I finally started researching better units. Several friends had reported that the printers they purchased were far less maintenance-heavy and far more reliable. I’m a smart, adaptable guy, but it was a new problem every time, and I was tired of it.

So I bought a new printer last week. I settled on the Creality3D Ender 5. Still very affordable ($300) but a step up from the Ender 3. Four corner thick extruded aluminum frame. The bed moves up and down on the Z axis, while the nozzle moves on the X and Y axis at the top of the unit. The extruder motor and hot end are separated by a long bowden tube, which is alternately annoying and a relief.

Assembled the Ender 5 in less than an hour. Before printing anything, I measured the extruder for accuracy, and corrected the E-steps/mm. My first test print came out better and sharper than anything on the Anet A8 ever did, with no further adjustments. My first large print failed, but that’s on me, because I didn’t properly route and secure the cables and bowden tube, and they snagged on a motor. Ever since fixing that with a zip-tie, I haven’t had a single failure. I can reliably print large items now, and I wish this had been my experience in the beginning.

Same tray as in the earlier photo. It isn’t just the dragging hot-end that disturbed that earlier piece, the actual resolution of the print suffered because of the instability and wobble of the machine.
SexyCyberg Maker Coin, about 5cm diameter. The “hairs” are prominent in this photo due to flash photography, they are mostly loose and will brush out easily.

So if I have any advice at all to aspiring 3d-printer owners, it’s this. Get the right printer the first time. Don’t necessarily get the cheapest. Get something that someone you know recommends, or that gets great reviews. Learn calibration, learn bed-leveling. Consider a Pi 4 with a PiCam and Octoprint.

Would I recommend the Ender 5? Fuck yes. My friend has a CR-10S and he recommends that one as well, but I was trying to stick to a budget. I’m very pleased with this unit. I’ve got another piece being printed right now, and after only a few days, my confidence level has allowed me to forget about checking on it for a while. But it looks like it’s doing fine. But I have to focus that camera, LOL.

I’m waiting for a new spool of copper silk PLA to arrive in the next day or two. I have a large-ish complex piece I am going to reprint, because I’m unhappy about the results from the Anet. I will show a side-by-side comparison of the two pieces in my next post in the next few days.

Lock Bypass on a Zero Halliburton Centurion Elite Briefcase

I picked up this older briefcase at auction in 2018. It was a good deal. Listed as locked, no knowledge of the contents at the time, and sold for way less than a used case of this variety would normally sell for. I like these cases. Each half of the shell has small bracket tabs which can be used to install aluminum panels, making them ideal for portable radio or other instrumentation installs. I was confident I’d be able to get into it one way or another.

Indeed, I was able to get in by popping the hinge pin. From there I was able to remove the lock mechanism from the inside. It’s not a sophisticated protection mechanism, nor is it a particularly secure case. I’m going to venture to guess the new ones are even less secure, since they have TSA locks.

I spent quite a bit of time (before popping the hinge pin) brute-forcing the lock. You’d think that with only three 0-9 dials, just 1,000 possible combinations, that that would be sufficient, but I found that even with several tries, before and after removing the lock mechanism from the case, I was unable to make it happen. I think it’s a matter of imperfections in repetitive motions. After a certain amount of times, I guess your hands just “expect” the movement to continue to fail, and you fail to follow through with enough strength to clear the mechanism even when you get the right combo.

Last night I decided to give it another go.

When brute-forcing with the lock attached, the test is to attempt to open the case. When brute-forcing with the lock removed, the test is to attempt to slide the combination-reset switch on the back of the mechanism, which won’t budge without the right combo. Again, repetitive motion attention failure likely prevented this from working properly, so I went back to the drawing board and researched bypass techniques with wheel-based combination locks such as this one. I found one technique involving proving to the right of the wheel with a narrow probe while turning the wheel and feeling for a “notch.” I tried that, and lo and behold, I found that each wheel had a notch point, in my case corresponding to “7-5-8.” I engaged the reset switch, and it worked!

The reset switch is engaged by sliding it inwards, then upwards. It can only be engaged while the correct combo is set, and while engaged, any changes to the dials result in a change of the combination. I reset the combo to 666, just so it’s easy to remember for now, and reinstalled it in the case. Tests showed that the new combo works, and the case is both lockable and unlockable.

Here’s a photo of what the notches look like without the front cover. Interestingly, this mechanism, a Prestolock 2046 or 2546, is installed by screwing the lock mechanism directly to receiver tubes on the front cover from the inside. With the lock installed, you can’t see these notches. But knowing they’re there, on this and lots of other wheel-based combo locks, will help you to easily determine the current combination and disengage the lock. If your lockpicks are thin enough, they may work for feeling these notches even with the front cover engaged.

Hey, upgrading CentOS 7 to CentOS 8 in place still works!

So I had a remote VPS in the wild giving me issues, and while addressing the issues, I decided I should update the OS. No updates available, up to date… on CentOS 7. Well, I thought it was a good time to move up to CentOS 8. Yeah, I know the whole 7 vs 8 vs stream thing is a thing, I’m not too worried about that for the moment.

Because I didn’t want to rebuild it, I searched to see if there were upgrade instructions out there for 7->8. Found some, with the usual disclaimer. “This is unsupported,” “There is no upgrade path, you must reinstall,” blah blah blah.

So I backed up what needed to be backed up in case I had to rebuild. and went for it.

I used this as the base:

https://www.howtoforge.com/how-to-upgrade-centos-7-core-to-8/

The first problem I ran into is that the version of the Centos-Release package was no longer being served. And the current release actually changed names, from CentOS-Release to CentOS-Linux-Release. “Interesting,” I thought, “I wonder if that’s going to bite me in the ass later.”

Then I ran into some issues with dependencies. gcc and annobin was the top line. A quick google revealed another user had encountered this and resolved by simply “uninstalling Perl and Python3, then reinstalling after the upgrade.”

So I tried that, and got past that little obstacle. A couple other minor dependency issues, I had to uninstall python-six and one or two obvious little interfering little noids. But it rolled through. The really scary part was the reboot, because part of the process is uninstalling ALL kernels and then reinstalling the new kernel, then making sure that grub is correct.

So I opened a serial console to it, so I could watch the boot process in case something went twisty. Double-checked that backups were thorough, and let her rip! Booted off my serial console, but opened it right back up again, and boom, everything came up. Not just the CentOS 8.3 base OS, but all my exotic internet apps. I was right back to being usable again. Why was Redis on this server again? Strange.

So that’s my story, and I’m sticking to it. Score one for the documented unsupported upgrade-in-place instruction set.

Baab out.

Schneier’s book giveaway

I picked up a few extra copies of Schneier’s book during a special offer a while back. They finally shipped yesterday. I’d like to make them a giveaway item at the next in-person event, or maybe figure out some easy way to give them out. Whaddya y’all think?

Network Scanner on a budget

I was about to pull the trigger on a network-enabled Fujitsu ScanSnap scanner, because I’ve been scanning on my Ricoh all-in-one that doesn’t do duplex, and I have a number of two-sided documents to scan. I was annoyed at the price tag on what seems to me to be not much more innovation than the older machines, which lack only networking.

Then I found this post by Chris Schuld:

https://chrisschuld.com/2020/01/network-scanner-with-scansnap-and-raspberry-pi/

Makes perfect sense. Set up a Pi to do the networking, then just get a SANE-enabled scanner and off to the races.

So I checked the SANE supported scanner list, and found that the ScanSnap S1500 or S1500M (pro-tip: they’re the same) was a good choice — a snappy duplex scanner with ADF, USB-connected, for a good price point, about $100. Picked one up in great condition on ebay, and it was absolutely up to the task. For testing, I used the Raspberry Pi 4 (4GB model) that had been commissioned for OctoPi for the 3D printer, and figured if it worked well I’d order another.

Well, following Chris’ blog post, I got all the scan functionality working, but even with other resources I haven’t yet figured out how to get the ADF button to trigger the scan. I’ve got the udev rules in place, everything should be running, but I still had to trigger the scan manually from the pi. Then I noticed that when I triggered the scan and nothing was in the scanner, it was a simple failure, no document detected or something like that. So I had a simple thought. I’ll just set up a cron job to run every minute and make an attempt to scan. If nothing’s in the feeder, no harm no foul, move right along. If so, scan that shit and send it to the Mayan EDMS share. Happy happy joy joy.

So now I just drop a doc into the feeder, and within a minute it’s on its way to the EDMS. Exactly what I was looking for. New RPi 4 is on the way.

UPDATE: It was migrated to an RPi 4, and I changed the single cron job to do the scans to a collection of cron jobs that run every five seconds.

Since triggering a scan does nothing if there’s nothing in the feeder, I added a simple lockfile test to the scan job: If the lockfile exists, bail. If not, create the lockfile, attempt to scan, then drop the lockfile. That way if a new scan is triggered during an existing scan run, it will abort.

* * * * * ( /usr/local/bin/scan.sh )
* * * * * ( sleep 5; /usr/local/bin/scan.sh )
* * * * * ( sleep 10; /usr/local/bin/scan.sh )
* * * * * ( sleep 15; /usr/local/bin/scan.sh )
* * * * * ( sleep 20; /usr/local/bin/scan.sh )
* * * * * ( sleep 25; /usr/local/bin/scan.sh )
* * * * * ( sleep 30; /usr/local/bin/scan.sh )
* * * * * ( sleep 35; /usr/local/bin/scan.sh )
* * * * * ( sleep 40; /usr/local/bin/scan.sh )
* * * * * ( sleep 45; /usr/local/bin/scan.sh )
* * * * * ( sleep 50; /usr/local/bin/scan.sh )
* * * * * ( sleep 55; /usr/local/bin/scan.sh )

Migrating YUUUGE photo galleries: exiftool FTW

Years back, I hosted several large photo galleries on a public website. Password-protected, but my family was the only consumer of the data anyway.

I decided to migrate that to my growing internal network, because I have disk space, backups, and faster networking. Plus that old gallery software was getting long in the tooth and I didn’t feel like continuing to maintain it.

Dilemma: The old gallery was one of those, like most of them, that import the files, give them a long filename and remove the uploaded copy. So there was no rhyme or reason to the 11G of photos on that server, just a single flat gigantic directory of JPG files, over 1500 of them in total.

It only took a few minutes to realize that there seemed to be three paths — (1) a fully manual path of uploading all of the files in a batch into the new photo management app (I’m using Lychee, by the way) and then sorting through them; (2) a less manual, but still involved, path of logging into the old gallery and exporting/downloading each set; or (3) finding a smarter way.

I chose (3) finding a smarter way. I realized that my photo sets were all event-based, and the date of those events are stored in the EXIF data of each individual photo file. So I wondered if there was an easy way to extract that in a useful way, and then possibly script it to segregated it by date. I quickly found something even better — the exiftool itself (installed on my macbook with Homebrew) will easily do exactly that:

exiftool '-Directory<DateTimeOriginal' -d %Y-%m-%d "$dir"

Will siphon through an entire directory, lickety-split, pull out the capture date from the EXIF data, and then file them in a directory named for the YYYY-MM-DD of the date. It will even create the directories if they don’t exist. I went in seconds from a flat directory of over 1500 files to, let’s see…. 12 individual date directories, each filled with a day of photos.

Lychee lets me import directories and will name them “[IMPORT] (directory name)” so all I have to do once they’re all imported is to log into Lychee, look into each newly-imported directory to figure out what the event was, and rename the album. Fun stuff.

Harrowing Tales of Networking FAILS.

With all the scary stuff you’re hearing about in the news this week, I thought I’d inject a little bit of light-hearted storytelling.

Long ago and far away, I inherited a network. Then I was tasked with relocating it to a new room. This was successful, and everyone lived happily ever after.

Until I checked in on it later and discovered that the backups were failing. Not only were they taking days to complete (or fail), but the restore points were becoming corrupted, which takes more time to repair, on top of an already excruciatingly slow (6mpbs) backup.

I looked at networking, I looked at server bottlenecks, I manually deleted restore points to eliminate that extra delay of rebuilding corrupted points. I was truly confused. So I looked deeper. Fearing a drive media failure, I looked at the device from which the backup drive was shared.

That’s when it hit me. The “backup” VM on which I was looking to determine the location of the network share — was NOT the same server as the backup server from which I was administering the backups via the web.

Looking closer, I discovered that the backups were running on TWO separate backup server. And yes, you guessed it. To the SAME Nakivo backup repository. Or even worse, to two identical configurations of “the same” repository. Disastrous. Backups were stepping on each other, corrupting each other, and slowing each other down. It seems the engineer who built the network was unhappy with performance on one server and just descheduled the jobs and built a newer, faster server to run the backups. After the move, I guess I came across this one instead of the correct one, and re-enabled the jobs, thinking they had been disabled for the move.

The moral of the story is this. When you migrate backups from one server to another because of speed, don’t just unschedule the jobs, because someone may reschedule them in the future. Take the extra step of deleting or disabling the jobs on the outgoing server, or do what I did after resolving this debacle — Since I couldn’t disable the old backup web interface (for reasons), I added a fake job with no targets, called “DONT-RUN-JOBS-HERE” to remind someone who happens upon it in the future, and updated the “where is everything” document to point to the newer location.