Building a Jarvis-inspired voice activated LLM powered virtual assistant

Just another day at the office
Just another day at the office

I’d like my computer to be smarter and more interactive and handle boring stuff for me and I’d also like to play around with some LLM / AI stuff… which brings me to this project.  I’ve got a ton of basic things I’d love for it to do – manage lists, reminders, some Outlook functions, some media functions, and then also be able to interact with me – all via voice commands.  Yes, you can do this with ChatGPT and probably others – but I am loathe to provide any outside resource with more of “me” (DNA, biometrics, voice, ambient noises, etc) than absolutely necessary.  Plus, I’ve been tinkering with these little LLM’s for a while now and see just what I can build out of them and with their assistance.

I’m not great at Python1 , so I admittedly enlisted the help of some very large LLM’s.  I started the main project in conjunction with ChatGPT, used Gemini to answer some basic questions about programming in Python syntax, etc, and Claude for random things.  The reason for keeping my general questions in Gemini versus ChatGPT was so that I could not “pollute” the ChatGPT flow of discussions with irrelevant sidetracks.  This was the same reason for separating out the Claude discussions too.  I find Claude reasonably helpful for coding tasks, but the use limits are too restrictive.

My kiddo asked me how much of the code was written by these models versus my own code.  I’d say the raw code was mostly written by LLM’s – but I’m able to tinker, debug, and… above all learn.  I’d rather be the one writing the code from scratch, but I’m treating these LLM’s like water wings.  I know I’m not keeping myself fully afloat – but I’m actually the one treading water, putting it all together, and learning how to do it myself.  Also… said kiddo was interested in building one too – so I’m helping teach someone else manually, and learning more that way.2

Ingredients

As with many of projects, I started by testing the individual pieces to see if I could get things working.  In order I started with validating individual pieces of the process:

  • Could I get Python to record audio?
  • Could I get Python to transcribe that audio?
  • Could I get Python to use an API to run queries in LM Studio?
    • Yep!  Using the openai API, I could use python to send queries to LM Studio after an LLM had been loaded into memory
  • Could I get Python to get my computer to respond to a “wakeword”?
    • Yep!  There’s another Python module for using  “wakewords” using PocketSphinx.  This was an interesting romp.  I found that I had to really tinker with the data being sent to the Wakeword to be properly recognized and then fiddle with the timing to make sure what came after the wakeword was properly captured before being sent to the LLM.  Otherwise, I ended up with “Jarvis, set a timer for 15 minutes” would become… “Jarvis, for 15 minutes” since the “Jarvis” would get picked up by the wakeword but the rest not caught in time to be processed by whisper.
  • Can I get Python to verbally recite statements out loud?
    • Yep!  I used text to speech using Piper.  However, this process took a while.  One thing I learned was that you needed not just the voice model’s *.ONNX file, but the *.JSON file associated with it.

Until this point, I had wanted to try running LLM’s with the training wheels from LM Studio’s API.  I really like the LM Studio program, but I don’t want to be dependent upon their service when I’m trying to roll my own LLM interface.  Python can run LLM’s directly using “llama-cpp-python” – except that it will throw errors on the version of Python I was running (3.14) and was known to work with a prior version (3.11).

This lead me to learning about running “virtual environments” within Python so that I can keep both versions of Python on my computer, but basically run my code within a specific container tied to the version I need.  Typing this command created the virtual environment within my project folder.  The second command will “activate” that virtual environment.

  • py -3.11 -m venv venv
    • This created the virtual environment, locked to Python 3.11
  • .venv\Scripts\activate
    • This activates the virtual environment, so I can start working inside it

Back to work!

The man's got a job to do
The man’s got a job to do

Building a Pipeline

This is where things really seemed to take off.  I was able to disconnect my script from LM Studio and use Python to directly call the LLM’s I’ve downloaded.  These were reasonably straightforward – and I was suddenly able to go from: Wakeword -> whisper transcribed LLM query -> LLM response -> Piper recited reply.  Then, it was reasonably easy to have the script listen for certain words, and perform certain actions (setting timers was the first such instance).

Optimizations, Problems, Solutions

Complicating factors
Complicating factors

Building something that kind worked brought me to a new and interesting  ideas, challenges, and problems:

  • The original cobbled together process was something like:  record audio, transcribe through Whisper, delete the recording, pass the transcribed statement to the LLM, give that statement to Piper, generate a new recording, play that recording.  However, this process has some obvious “slop” where I’m making and deleting two temporary audio files.  The solution was to find ways to feed the recording process directly into Whisper and feed Piper’s response directly to the speakers, cutting out the two audio files.
  • I realized that I wanted the script to do more than just shove everything I have to say / ask into an LLM – to be really useful, the script would have to do more than just be a verbal interface for a basic LLM.  This is where I started bolting on a few other things – like trying to call a very small LLM to try and parse the initial request to either:
    1. Something that can be easily accomplished by a Python script (such as setting a timer)
    2. Something that needed to be handled by a larger LLM (summarize, translate, explain)
    3. Something that maybe a small model could address easily (provide simple answer to a simple question)
  • I ran into some problems at this point.  I spent a lot of time trying to constrain a small LLM3 to figure out what the user wanted and assign labels/tasks accordingly.  After a lot of fiddling, it turns out that an LLM is generally a “generative” model and it wants to “make” something.  My trying to force it to make a choice among only a dozen “words”4 was really bumping into problems where it would have trouble choosing between two options, choose inconsistently, and sometimes just make up new keywords.  Now, I could come up with a simple Python script which just did basic word-matching to sort the incoming phrases – but it seemed entirely counterproductive to build a Python word-matching process to help a tiny AI.  I then tried building a small “decision tree” of multiple small LLM calls to properly sort between “easy Python script call” and “better call a bigger LLM to help understand what this guy is talking about” and quickly stopped.  Again, my building a gigantic decision tree out of little LLM calls was proving to be a bigger task, adding latency and error with each call.  I was hoping to use a small LLM to make the voice interaction with the computer simple and seamless and then pass bigger tasks to a larger LLM for handling, sprinkling in little verbal acknowledgements and pauses to help everything feel more natural.  Instead I was spending too much time building ways to make a small LLM stupider, doing this repeatedly, and then still ending up with too much slop.
  • And, frankly, it felt weird to try and lobotomize a small LLM into doing something as simple as “does the user’s request best fall into one of 12 categories?”  Yes, small LLM’s can easily start to hallucinate, they can lose track of a conversation, make mistakes, etc.  But, to constrain one so tightly that I’m telling it that it may only reply with one of 12 words feels… odd?
Tell me what I want to hear and this can all stop
Tell me what I want to hear and this can all stop

Over the last few days I’ve been tinkering with building an “intent classifier” or “intent encoder” to do the kind of automatic sorting I was trying to force an LLM to do.  As I understand this process, you feed the classifier a bunch of example statements that have been pre-sorted into different “intent slugs.”  The benefit of a classifier is that it can only reply with one of these “intent slugs” and will never produce anything else.  It’s also way faster.  Calling a small5 LLM with a sorting question could produce a sometimes reliable6 answer in about 0.2 ms, which is almost unnoticeable.  Calling a classifier to sort should enable a 97% reliable result within 0.05 ms.  This is so fast it is imperceptible.

I haven’t tried this yet.  I’ve built up a pile of “examples” from largely synthetic data to feed into a classifier, produce an ONNX file7 , and try out.  However, I wanted to pause at this juncture to write up what I’ve been working on.  I say synthetic data because I didn’t hand write more than 3,000 examples on some 50 different intent slugs.  I wrote a list of slugs, described what each one should be associated with, created a small set of examples, and then asked Gemini to produce reasonable sounding examples based on this information. 8 This list appeared pretty good – but needed to be manually edited and also tidied up.  I wanted to remove most of the punctuation and adjust the ways numbers and statements showed up, because I’m simply not confident that Whisper will be able to accurately match “Add bananas to shopping list” to “Add bananas to ‘shopping list'” to something that the classifier will correctly interpret.

As I tinker with this project… I’m also looking at how I might be able to extend it into further projects.  Not only might it be a great way to help me be more productive, but I might be able to create a really small version that could be put into a companion bot.  A little companion bot with limited space, power, inputs, and abilities to emote could be far more lifelike, independent, and non-deterministic in it’s responses and actions.

Project Jarvis
  1. Building a Jarvis-inspired voice activated LLM powered virtual assistant

 

 

  1. Yet!! []
  2. Thanks Mr. Fenyman! []
  3. Giving it limited context windows, limited tokens to use, highly restrictive system prompts []
  4. Make timer, list timers, make a reminder, add to a list, recite a list, media buttons, etc []
  5. ~1B parameter []
  6. Let’s say 65% reliable []
  7. Yes!  Just like the voice models!! []
  8. I know, more self-reflecting LLM garbage… []

Repairing My DIY Travel Uke

If you’re just catching up, check out the list of posts below for the full build log plus a short clip of me playing the ukulele.

I’ve gotten a lot of use out of my travel ukulele, but it’s need a little TLC now and then.  Most recently, I found myself in that classic DIY scenario…

But, what if more?

It started when I looked down at my uke months ago to discovery one of the frets I had superglued in place had come out!  Fortunately, I found it nearby and found I could temporarily push it back into the channel that was formed by the hardened glue.  Of course, it could still slip right back out – which is what happened in the first place.  I went to the age-old tactic of “just living with it” for the time being.  I’d slide the fret in, play for however long, slide it out and kept it somewhere safe.

As this was clearly not a long term fix, I finally removed the pin, loosened and removed the strings from the tuning pegs, wrapped them back behind the neck, cleared an area, superglued it back in place, and “clamped” it down using rubber bands and popsicle sticks.  Don’t laugh.  It worked the first time on all the frets and only failed on 1/15 of them after two years.

This, of course, is where the problems began.  I discovered the Graph Tech Ratio Tuners I had installed, which looked great, had developed cracks near where the screws held them in place on two tuners.  This crack essentially caused the insides of the gears to become misaligned to the point they wouldn’t turn.  A third tuner didn’t have any visible defects – but it would only had about 180 degrees of tuning range – nowhere near enough to wind strings, let alone fine tune the strings.  Now, seeing as how these plastic geared tuners failed after two years when all I did was unwind them once to fix the missing fret, I wasn’t going to get another set of the same thing.

These tuning pegs are a mess

Now, I still had the tuners I’d bought at the recommendation of my buddy and makerextraordinaire, Matt Stultz.  After all, the original holes I’d drilled in my uke were designed for these anyhow.  I had only gone with the Graph Tech’s due to the color and low-profile setup, so that the tuners wouldn’t rise above the strumming area.  After getting these out – I discovered the rubber grips for the tuners had taken on an almost… sticky / gooey quality.  I measured them up and 3D printed some slightly smaller ones that had a kinda cool “torpedo” look to them.

Finally, a good 3D printed knob

In case someone is reading this blog post WAY in the future, about six months ago a post went viral on the 3D printing sub-reddit due to some random woman’s white hot rage at seeing someone having repaired their stove knob with a 3D printed replacement.

ANYHOW, I printed a few test versions of these tuning knobs and replaced the wider sticker versions with sleek non-sticky 3D printed versions.  Once these were installed12 I started to restring the uke and discovered one of the 3D printed bridge holders was cracked.  The turn around was also cracked, but still working well enough.

Now the uke has these new / original tuners I’d purchased and the turning of their little metal gears brings me joy.  They don’t stick out to the side too much and, installed at an angle, they don’t rise very much above the playing area.

Ukulele after the repair

Now I just need to learn to play it!  I’m just kidding – I can play it, I just need to practice more often.  :)

DIY Travel Soprano Ukulele
  1. Learning Curves and Ukuleles
  2. Building a Travel Ukulele: Getting Started
  3. Building a Travel Ukulele: Cutting Stuff
  4. Building a Travel Ukulele: Cutting, Filing, Shaping
  5. Building a Travel Ukulele: Filing, sanding, filing, sanding, filing…
  6. Building a Travel Ukulele: Sanding.
  7. Building a Travel Ukulele: Test Fitting
  8. Building a Travel Ukulele: Preparation, Marking and Cutting Frets
  9. Building a Travel Ukulele: Shaping Frets, Sanding
  10. Building a Travel Ukulele: Building a Drill
  11. Building a Travel Ukulele: No Turning Back
  12. Building a Travel Ukulele: Sanding, sanding, and finishing
  13. Building a Travel Ukulele: Finishing, sanding, painting, etc
  14. Building a Travel Ukulele: So Much Experimentation, Bridges, Printing, and Sanding
  15. Building a Travel Ukulele: Plancratineering
  16. Building a Travel Ukulele: Swapping Hardware, Fret Experiments
  17. Building a Travel Ukulele: Bridge, Stringing It Up, and a Sound Test!
  18. Building a Travel Ukulele: Improvements
  19. Building a Travel Ukulele: Back to Basics
  20. DIY Soprano Scale Travel Ukulele
  21. Repairing My DIY Travel Uke
  1. Installed again?  Re-installed?  I test fit and installed them originally and then pulled them out in favor of the Graph Tech’s, so I perhaps they weren’t actually installed originally? []
  2. I digress. []

Prepping for Maker Faire Bay Area 2024

It’s always a whirlwind heading into Maker Faire.  This year is no exception.  This past weekend we got things mostly ready for the Rocklin Maker Faire.  All of our robots were functional, which was really great.  A quick update to document progress and also act like a to-do list of sorts:

  • MakerKnit’s companion robot
    • My wife has knit her octopus
    • I’ve installed the Adafruit QtPy, NeoPixels, and touch sensors connected via BrownDogGadgets conductive thread through the legs
    • It’s been programmed to “blink” the two LED eyes randomly plus a small number of light shows for the body
    • Designed/3D printed several eyes, settling on a nice design that should make the eye animations look good
  • Kim’dael LightningSlayer’s Pendant
    • The youngest’s project has morphed from an LED arm to a CircuitPlayground in a pendant that just plays some notes when she presses buttons.
    • A long extension for the battery pack, using thicker gauge wire wound through the back of stock CircuitPlayground enclosure, is now the “necklace” portion for this project.
  • Dexter Starfighter’s ED-E
  • MakerBlock
    • My robot wasn’t quite ready for Maker Faire last year, but “ready enough” to share.  Last year the little bot was just sitting in a jar I carried around and not really visible to anyone.
    • This year I’ve added feet (entirely cosmetic), changed the battery pack around so it is removeable, swapped out dome diffusers, and am working on new animations/behaviors.
    • I realized that my old LED goggles were… janky.  This was because I had soldered some buttons to one side and then wired them into the Trinket directly, without any resistors.  While it /worked/, it caused some problems whenever I pressed a button.  I pulled the Trinket out and swapped in my new favorite board, the QtPy.
      • I really prefer programming / updating via CircuitPython over Arduino since there’s no pre-compile time and fussy Arduino connections.
      • Besides the programming/uploading, I love the built in RGB, up to 6 capacitive touch sensor, and easy serial communication
      • As an added plus, I soldered on the 2MB flash chip so the project as a ton of space. 1
      • And at almost the same price as a Triket ($0.50 more than the original, $0.50 less than the M0 Trinkets), it’s just easier to swap them into any project I would have previously put a Trinket into
  •  Soldering
    • I’ve really upgraded my soldering experience and it’s made a world of difference.  We moved about a year ago and there’s a space in the house where I can keep a soldering station out and ready to use.  Just having it available is such an upgrade.  I’ve had several handheld / pen style soldering irons over the years and they’re usually pretty terrible.  In fairness, this is also because I’m kinda terrible at soldering.  I had a basic garbage soldering iron from the local hardware store, upgrade one that had a little temperature control from Adafruit, and then upon the recommendation of a friend upgraded a few weeks ago to an X-TRONIC soldering station.
    • I gave my old soldering iron to my neighbor so he could work on a project for his wife.  As I got to finishing up work on the above projects I realized I couldn’t find my pen soldering iron from Adafruit – and that I didn’t want to find it anyhow.  It was fine.  It worked.  But, my soldering iron holder was cheap and flimsy and easy to tip over and the helping hands I had from Adafruit were “okay” for very small projects, but the joints came loose easily and the helping hands kept falling off.  Rather than spend $20 on another soldering iron I would hate, I dropped $70 on the X-TRONIC station which has built in helping hands and soldering iron holder.  Setting aside that it heats up very quickly, has good temperature control, melts solder quickly, and has great helping hands… it has a way to hold the soldering iron in a way that isn’t constantly anxiety inducing. 2
    • Having the soldering station handy has meant I don’t really mind whipping out a quick battery pack extension cable for our projects.  I just need to strip some wires, fire it up, drop some solder, and turn it off again.
    • I may have ruined the first soldering iron tip kinda quickly.  Again, I have no idea what I’m doing.  I would add solder, dip the tip in flux, wipe on sponge, and then do it all again.  This is a terrible process since all it does it add extra contaminants and gunk to the tip, reducing the ability of it to transfer heat effectively.  Instead, after watching a video, I learned I should run it at the lowest temperature appropriate for the solder/joint, just dab the tip in the brass wool to clean it up a little, then maybe wipe on the slightly damp sponge, and absolutely coat the tip in solder before putting it down.

Things left to do!

  • Things to finish
    • I’d really like to finish up the Fallout themed shirt/vest to go with my project
    • A way to attach my wife’s octopus to a purse strap
    • A better way to wear my robot on my shoulder – may use a similar foam paldron
    • A big chunky seat belt looking thing for the strap wearing my robot
    • I’ve got designs for a new bag to wear/carry around Maker Faire, but haven’t sewn them up yet – maybe this week!?!!?
  • Make sure we have
    • Enough batteries, battery packs, etc for our projects
    • USB chargers for our LiPo batteries in goggles
    • Finish my goggles (install battery, update code, possibly change out diffusers
    • Bring a few Maker Coins to give out (I bought 100 of the 5,000 minted, probably never to be minted again…)
    • Ways to show people links to learn more about our projects – probably via QR codes – though I might also use an RFID tag :)

Okay, back to work on… work… so I can get back to making!

  1. Note to self:  It requires a different version of CircuitPython, Haxpress, to make use of the chip storage []
  2. I used to tape the cord of my soldering iron to the table and then place it on the flimsy stand []

Heat Transfer Vinyl T-Shirts Without a Craft Cutter (2023)

Saturday, October 21
Zone 2 – Make: Demo Stage
2:30 pm – 3:00 pm
Let’s goooooooooooooooooooo!

Heat Transfer Vinyl T-Shirts (Without a Craft Cutter)
  1. Heat Transfer Vinyl T-Shirts – Without A Vinyl Cutter
  2. Heat Transfer Vinyl T-Shirts – Without A Vinyl Cutter, Part II
  3. Heat Transfer Vinyl T-Shirts Without a Craft Cutter (2023)

Companion Robots and Maker Faire Season!

I’m super excited for Maker Faire Bay Area / Mare Island and Mini Maker Faire Rocklin.1  I’m not just excited to see everything, but to show all the things I’ve been working on for a while now.  It’s also time to pick up all the little dev boards I’ve somehow accumulated and see if I can make anything with them to show off.

  1. Project Boards
    1. Wemos D1 Mini.  A small insanely cheap (~$3?!) WiFi enabled dev board2 , which has 4MB onboard and can run Arduino.  I think it can also run MicroPython, but I haven’t tested this yet.
    2. Wemos 600 Pico.  An even smaller, even cheaper (~$2 when ordered from China) WiFi enabled dev board that runs… MicroPython?  I think??  I’m saying “I think” because I haven’t been able to get it to do anything yet.
      1. Since starting this blog post, I found a guide on installing MicroPython on Wemos boards that seems promising.
        1. Flashing MicroPython on an ESP8266
        2. https://github.com/espressif/esptool/tree/master
        3. Arguing with Python to let me use “esptool.py”
          1. esptool -p COM13 -c esp8266 flash_id
      2. As promising as that series of blog posts looked, I eventually scrapped the Wemos because it was just too much of a pain to get going with MicroPython.  I think I could have made it work, but for $7 I could also just use the Adafruit QtPy I already have.  The advantages of simply uploading code over a USB cable into a virtual drive just can’t be overstated.
    3. Other Boards
      1. I have a bad habit of picking up dev boards.  I’ve got several Adafruit QtPy’s, several Adafruit Trinkets, an Adafruit FX Sound Board, Raspberry Pi Pico (non-WiFi), various Digispark boards, a small handful of ATTiny85’s, and an even weirder assortment of VERY small programmable circuit boards (ISD1806B-COB) designed to go in greeting cards (just 6 seconds), etc.
  2. Companion Robot
    1. Background.
      1. I started this post at least a month ago when I only had a vague idea of what I wanted to make and even fewer skills.  After seeing my kid’s companion robot take shape, I wanted to get in on the action and make my own.  I decided to make a really small companion robot with just some LED’s, piezo, and small microcontroller unit.  I’d taken a stab at making a companion robot a few years ago, but set it aside for a variety of reasons and never went back.
      2. The idea for this new robot would be something a little less ambitious, make more use of NeoPixels than in prior projects3, with a little more interactivity, trying out some CircuitPython, and… let’s be real… more pizzazz!
    2. Idea:  Friendly Cloud/Vapor/Flame
      1. I still really like the copper-toned PLA I’ve been using since it has something of a steampunk flair to it.  I settled on repurposing a small plastic enclosure with a clear dome as the “body” for the robot.  I wanted it to look something like a small entrapped / captive / domesticated4 sentient cloud of vapor or perhaps flame held within a steampunk enclosure.
      2. As a very small, inexpensive board that could run either Arduino or CircuitPython, I decided on the Adafruit QtPy M0.  It could run NeoPixels, there were lots of cool guides on it, plenty of pinouts, and could definitely fit within the confines of my enclosure.
    3. Enclosure:
      1. I started the enclosure by trying to design and 3D print a part to mate with the clear plastic dome.  It took a few tries.

        This slideshow requires JavaScript.

      2. Once I had that, I extended the base so it could hold more electronics.  I could definitely have shoehorned everything into the dome, especially if I took up some of the space inside the dome, but even with an “elevated base” it was still plenty small and could use a battery pack rather than a rechargeable lipo.
      3. Once I had a good design for the enclosure, I tried to make it work with an existing 3xAAA battery pack.  In the process I yanked off the connector and ended up soldering the battery pack leads directly into the circuits.
    4. Internal Electronics
      1. I’m just not a great electrical engineer and am still copy/pasting from various guides, tinkering, changing bits of code, swapping out parts, and using “close enough” resistors.  Wiring up some LEDs or a piezo to a project isn’t very difficult – it’s some of the more fiddly bits.
      2. Piezo Element Speaker
        1. I wanted to use a piezo buzzer/speaker because they’re large and incredibly thin.  They’re not without their downsides.  The crystal wafer is also thin and a little fragile.  The piezo buzzer without additional electronics has the potential to act as a knock sensor and can generate a high voltage spike which can fry a board.  And, without additional electronics, the piezo just isn’t very loud.  There are some libraries for the Arduino that basically double the volume of a piezo by connecting it to two pins and then running each opposite of the other, doubling the voltage difference, but they only work for Arduino chips.5
        2. After searching for various ways to increase the sound of the piezo elements, I settled on trying to use the Adafruit piezo amp.  I bought two – and tried desoldering the terminal blocks.  This completely ruined one.  The other one worked great, but for the modest volume gain it was just too big in an already cramped enclosure.
        3. After searching around, I found some amplifier circuits using a small number of common parts.6
        4. Then I tried building an amplifier circuit using an NPN transistor.  After reviewing the datasheets for my NPN transistors (and PNP transistors), and breadboarding the circuit with resistors, I sketched it a few times, laid it down with copper tape, soldered it in place with SMD resistors, then pulled it off and placed it onto a piece of Kapton tape and put another piece on top – “laminating” it in place.
      3. Capacitive Touch
        1. Buttons are great and all, but with a capacitive touch pad, I could add metallic elements to my robot rather than a much bulkier button.  I bought a few brass upholstery tacks because they looked great – but they just would not accept molten solder.  I ended up cutting the prongs short with wire cutters, wrapping the stub with copper tape, then soldering the wires to the tape.  I’d also added a little piece of heat shrink tubing over the connection to help keep it together.  It’s been working well so far.
      4. LED Animations
        1. As we know from Phillip Burgess‘ incredible “power sipping NeoPixel” guide, we can conserve power and increase the impact of the LED’s by reducing the number of LED’s, keeping max brightness ~20% for a disproportionately large impact, running fewer LED’s at a time, and even running fewer colors at a time.  Between Phillip’s work, Todbot’s guide, and the specialized QtPy NeoPixel guide by Kattni Rembor, I was able to put together a few neat animations.
      5. Piezo Sounds
        1. I had a heck of time getting the piezo buzzer to do anything interesting.  Fortunately, with my kid helped convert the piano music for “Paint It Black” into tones for me.  I haven’t gotten all the note timings right, but I’m working on it!
  3. Future Modifications
    1. More Accessible Enclosure.  Right now the “lid” with a hole for the LED ring just sits on the enclosure with a light friction fit.  One idea is a hinged lid, either with a conventional hinge or perhaps a hidden swivel hinge.  The problem with that, of course, is it requires even more internal space.  Other ideas include a ring on top that screws down, holding the top down and in place.  I’m crap at designing screw threads, so I’ve avoided this.

      Hinged lid for enclosure
      Hinged lid for enclosure
    2. Piezo Knocks.  Perhaps the next version will include some kind of tap / double tap / knock sensors using one or more piezo elements.
    3. Knobs.  There’s not a ton of room inside the enclosure, but by including a gear within a gear, I might be able to rotate part of the case and have it manipulate a potentiometer.

      Offset gear within gear, manipulating an off-center internal potentiometer
      Offset gear within gear, manipulating an off-center internal potentiometer
    4. Motors.  A robot that just flashes lights and makes a few beeps can still be pretty interesting.  However, I have some neat potential features that could be added with just one or two motors.  There are some interesting limitations with the current incarnation of this robot and using a QtPy.  I’ve only got 10 pinouts7 , 1 for NeoPixels, 1 for the piezo, 6 in use for the capacitive touch sensors, leaving 2 for other potential tasks.8  However, space is already tight so one or two micro servos would be a big space commitment.  I’ve seen some really tiny micro servos that might work, but I have no idea where to source them.  One silly idea is a “weapons system” using a spring loaded projectile activated by a very small servo.

      A small spring loaded projectile launcher, actuated by a small servo
      A small spring loaded projectile launcher, actuated by a small servo
    5. Creating Tone Library.  The basic piezo tones are easy enough to play, but including the entire list of tones and the frequencies associated with them seems eat up the poor little QtPy’s memory.  I think compressing them into a library might be the way around this issue.
    6. Playing WAV files.  WAV files are bulky, but that’s the only sound file format a QtPy M0 can play.  However, with the extra 2MB from the SPI chip installed, this shouldn’t be a huge problem.  I used Audacity to mix the sound clip down to mono then to 22 KHz sample rate.  My preliminary tests worked – but it was incredibly quiet.  I haven’t run it through the audio amplifier yet, but I’m planning to.
    7. Sleep / Deep Sleep.  Ever since I swapped out the tiny LiPo for a 3xAAA battery pack, I’ve had a lot more battery life, so adding sleep / deep sleep functions haven’t been a priority.  However, this inclusion just couldn’t hurt.
  4. Other QtPy and CircuitPython Resources
    1. Adafruit’s QtPy CircuitPython PWM resource
    2. TodBot’s CircuitPython tricks
Companion Robots: Building Robot Friends
  1. Cephalopod Robot Friend, the story so far
  2. Cephalopod Robot Friend Progress
  3. CuttleBot Body and OpenSCAD Design Tips
  4. An Assembled CuttleBot Body
  5. Building the Monocle Top Hat Cat for #MicrobitVirtualConcert
  6. Companion Robots and Maker Faire Season!
  1. I just got a notice they’re no longer a “Mini”! []
  2. pinouts for my future reference []
  3. LED goggles and a Marvel Universe inspired set of “Infinity Knuckles” []
  4. OMG dome-sticated?! []
  5. This is just my very basic understanding of how it works.  I’m entirely positive this is far too simplified. []
  6. And one very long article about using a lot of parts []
  7. 12 if you want to count the onboard NeoPixel []
  8. Or 4… []

Beep Boop: Emotions for ED-E

So I’m trying to program emotions for ED-E.

Better ed-e dialogue at Fallout New Vegas - mods and community

In Fallout New Vegas, ED-E doesn’t use regular dialogue, but communicates through beeps. Basically, he gets <(Emotion) + beeping> as his dialogue. Obviously the only way to research his beeping for this project is to replay Fallout New Vegas and talk to everyone’s favorite eyebot. I came up with a list of some of the emotional beeps he has in the game (and some that I just want) to start programming into him. I have ideas for what I want him to sound like, but I just need to find the right pitches and durations.

By this I mean I am sitting in my room and saying “beep beep” to myself at different pitches in sync with a program I wrote.

Yesterday my dad was checking in on me and how my programming was going and asked how I was doing. I replied, approximately, “bleurrrrghhhhh.”
I was having trouble programming the emotional beeps because I have very specific ideas for what ED-E should sound like and no way to get that into a computer. I’m a huge music nerd, but I unfortunately don’t have perfect pitch or some superhuman ability like that to use to get ED-E to sound exactly like I want him to.1 Dad suggested using a loop with an array going up every time, which made everything so. Much. Easier.
This plays frequencies starting at 100hz and going up by 10hz every time. I started with 100hz but going up by 50hz every time, but I liked the specificity of 10hz. Once I get in the ballpark of where I want to be, I can then just run the program and correct the pitches if need be.
If you read my last post, specifically the spoiler section, you will know why I started with a shy beep. If you didn’t read my last post, go do that! If you didn’t read the spoiler section, that’s fine. What you really need to know is that I want ED-E to make noises.
I’ll admit, this took a while to get right. Not playing the tones or even figuring out what pitches they were or how long they should play for. No, getting the tones to play was easy. Getting them to stop… was much harder.
ED-E was shyly screaming at me on repeat for at least 10 minutes while I was slowly losing my mind and trying to make him shut up.
I turned to ChatGPT to help me fix this, but it was utterly unhelpful and I ended up fixing the problem myself by deleting a bunch of the garbage it generated. Now the problem was that I had to continually upload the code to make the ShyBeep function run again. I was happy that it wasn’t looping anymore, but I wanted to fine tune the beeps and making it upload again and again was a pain. That’s why I decided to make it run when a button is pressed.2
It took a little while to make it run when a button was pressed, but then it would only run once and never again, even if the button was pressed. I finally realized that this was happening because runOnce was set to false, and fixed that.
Now that I have this framework, it has been much easier to program more beeps. Now I have a sad beep, and I’m going to start working on a happy beep because I have had just about enough of ED-E’s negativity.3
  1. I almost decided to use the definitions of pitch from my Rickroll code so I could just ask the computer to start at middle C and go down or say I want the pitch to be a half note in 3/4 time. I then realized I was making this WAY more complicated than it needed to be and just used seconds and hz like a normal-ish person []
  2. I seriously love Circuit Playgrounds. They have everything. []
  3. Just kidding ED-E, I love you []

ED-E Project: Origins

Hi, I’m DexterStarfighter, offspring of MakerBlock.1 I am a maker and artist with possibly too many interests that include drawing, writing, cats, theatre, video games, horror podcasts, folklore, coding, Jenga, history, triangles, succulents, and reading literally anything. I have been going to MakerFaire for basically my entire life and it has always been something I look forward to for the whole year. As soon as Dad told me MakerFaire was coming back, I knew I had to make something super cool for the occasion. This brings me to my latest project, a companion robot.

First, some background. My favorite game is part of the Fallout series (New Vegas, if you were wondering). I started the Fallout series because my dad played them when the first Fallout came out and I wanted to be able to share a cool game with him. I started Fallout 1 and loved it, then played Fallout 2 and 3. Over the summer, Epic Games released Fallout New Vegas with all DLCs for free and of course, I played the crap out of that.23

In Fallout New Vegas, there are various companions you can take with you on your journey through the Wasteland. There are human companions of course (and ghoul and nightkin), but you can also take with you one nonhuman companion. At first I was super disappointed that I couldn’t find Dogmeat. I don’t actually like being around dogs in real life, but I got Dogmeat in Fallout 1 and somehow I have become very attached. (I do not even want to think about how many times I have reloaded a save to keep that little jerk alive.) I quickly got over my disappointment though, because there is a statue of a dinosaur and now I’m disappointed that you can’t have a dinosaur robot companion. Anyway, in my travels through the Mojave, I found two interesting nonhuman companions. The first one I found was this little eye bot named ED-E. I play as a charismatic nerd (high INT and CHA with good repair, speech, barter and science) so I was able to fix him up. ED-E was still only able to beep in ways I couldn’t understand and when I brought him to where I was supposed to for his quest, there was some sort of glitch and I couldn’t interact with the lady for the quest. ED-E seemed kind of lame to me then, so I took him back to the place I found him and left. I later ran into a dog named Rex who I had to take care of for an Elvis impersonator (no, really) and found he was a pretty good companion.

Flash forward to the endgame. I had met a cowboy robot, climbed a dinosaur statue, resurrected a B-29, fought a soldier for a dog’s brain, charmed a scientist, accidentally sided with the mafia, cleaned out an entire casino, assassinated a 261-year-old man, had my vital organs removed, stolen 27 bars of gold, befriended a man wrapped in toilet paper, and was well on my way to conquering New Vegas for myself. I had only one more thing to check off my list: walking the Courier’s Mile. Don’t worry, I won’t spoil the Lonesome Road quest for you- I’ll just tell you that I met ED-E again. Somehow, within the first few minutes of interacting with him, I had become so completely charmed by this little robot that I would do literally anything to protect him. I’m not sure what about ED-E made him so endearing to me, but he became my best friend. 

GameBanshee

In 2019, I met Odd_Jayy at MakerFaire. I remember seeing his spider bot and thinking how cool it was. I’ve always liked the idea of a companion bot, but I’ve never actually had a specific idea of what I want out of one. When dad told me that we would be going to MakerFaire again, I immediately thought of an ED-E companion bot.4 Dad loved the idea too and gave me lots of good tips on how to get started. I have a tendency to get lost in the details, so he helped me focus on the big picture and the first steps I could take to achieving my goals.

I have a lot of ideas about what I want ED-E to do eventually, but I’m a complete beginner at Arduino programming. Knowing this, Dad suggested starting small. First, turn on one light. Then multiple lights. Then make them flash. Then make them change colors. Then add beeps. Stuff like that. I was like “cool, cool” and immediately programmed ED-E to beep the entirety of Never Gonna Give You Up instead of doing literally anything sensible.

I regret nothing. It was frustrating at first because I was super out of my depth. I used Chlorondria’s arrangement of Never Gonna Give You Up and used ChatGPT to help me learn how the code works. ChatGPT was super helpful because I could get feedback on why my code wasn’t working. The sense of accomplishment when I finally recognized the tune made all the frustration so incredibly worth it.

After my self-indulgent first project for ED-E, I moved on to taking Dad’s suggestions. Sort of. I’m a teenager, and therefore I am legally obliged not to listen to any authority figures, real or perceived. I made ED-E flash some rainbow lights. I started with just red lights and it took a while to make the code work, but once I made it work, I just changed the color brightnesses. Fun fact: my ED-E bot now actually glows two shades of blue in his rainbow light show pattern. For some reason I decided RGB stood for Red Yellow Blue and messed up with the color values when I was trying to make green and accidentally made a light blue. The light blue actually looked pretty cool, so I decided to keep it.

Today, I worked more on5 ED-E’s… musical function. I’m going to warn you right now: there will be spoilers for MakerFaire below! I intend to take ED-E to MakerFaire with me, and if you meet him, there will be some fun surprises in store for you. Not if you read the spoilers, though. MakerFaire is a big place and I don’t expect everyone who visits this page to run into me at the Faire, so I’ll include some stuff about the surprises below. 

***SPOILERS START***

 

If you’re still here, I assume you want to read this. One of my favorite things about ED-E in Fallout are the little conversations you can have with him. I want to be able to have a few little “conversations” with my companion bot, kind of like in the game. I’m going to have a Pip-Boy with various buttons to run functions for ED-E, but one of the first conversations I thought of had to do with his musical function. This was my idea:

 

Me: Hey, ED-E. Do you wanna sing them your favorite song?

ED-E: [Shy beeping]

Me: Aw, are you shy?

ED-E: [Shy beeping]

Me: Come on, ED-E. We’d all really like to hear you sing!

ED-E: [Questioning beeping]

Me: Yes, of course! Listen, I’ll ask them. Do you want to hear ED-E sing his favorite song?

Other person: Yes!

Me: See, ED-E? 

ED-E: [Pleased beeps, wait, then Rickroll beeps]

 

Obviously, I’m not going to make ED-E understand my words and respond to them. ED-E will be a shoulder mounted bot, so I want to be able to have conversations that trigger based on movement. I’m using a Circuit Playground, so I intend to take full advantage of all the different sensors it has. I programmed ED-E to run his Rickroll function if he senses a significant change in acceleration. I’ll pop my shoulder like I’m giving him a nudge, triggering the function. He waits for 8 seconds to give me time to talk, then plays the Rickroll beeps.

I have to admit, this took a WHILE to get right. It was still incredibly satisfying to see it all come together and go right. I was so excited when it started working! I did a lot of testing to get the sensitivity right because I don’t want it to trigger if I’m just walking around. I’m still fine tuning that part because I bumped the cord earlier and he started Rickrolling me. Then again, maybe ED-E just has a funny sense of humor.

 

***SPOILERS END***

So, what’s next for ED-E? I think the next thing I want to work on is getting his beeps right. I can make him beep music, and that’s great, but I also want to have him beep every so often and have “conversations” with him. I’m going to program some little beep clips for different emotions or situations that I can then mix and match into various conversations. I might also actually listen to Dad for once and work on a light show.

Thanks for reading about my ED-E project! I’ve enjoyed working on him and I’m so excited to share him with other makers. I’ll try to post updates regularly (they shouldn’t be as long as this one since you won’t need all the background next time). Thank you to Odd_Jayy for the inspiration, Chlorondria for the musical arrangement, ChatGPT for the troubleshooting help, Adafruit for making awesome boards, whoever made Fallout New Vegas, MakerBlock for being a great dad and helpful sounding board, and to you for reading this post.

ED-E Companion Bot Project

  1. ED-E Project: Origins
  2. Beep Boop: Emotions for ED-E

  1. I considered saying progeny and descendant of the House of MakerBlock, but offspring sounded the best. Progeny sounded weird and the descendant thing reminded me of Game of Thrones, which I have not read or watched, but I might someday and I don’t want to invite spoilers. []
  2. I love Epic Games. Free games every week? Yes please! Disclaimer: I am not being sponsored by Epic Games, but if I was, that would be awesome. []
  3. New Vegas is best Fallout, you can fight me on this. []
  4. I also considered a Muggy companion bot. I love Muggy and if ED-E turns out well, Muggy might be my next project. []
  5. Lol, moron []

EDC Bag Materials, Designs, Etc

I’ve been spending way too much time fiddling around thinking about a new every day carry bag, but not a lot of time actually doing anything about it.  I’ve got piles of notes, lots of links, sketches, and product photos.  Here’s a lot of them:

This slideshow requires JavaScript.

My notes and brainstorming are also rather extensive:

  1. Different Potential Uses
    1. Work (laptop, charger), day trips (water bottle), hiking (water bottle, clothing, snacks), running errands / tech / game nights / art
  2. EDC Items
    1. An EDC Bag should be able to accommodate things that I’d be likely to carry about 80% of the time.
    2. Mask, sanitizer, tissue, handkerchief, wipes, plastic baggie
    3. Cell phone, bluetooth pocket, charger pouch, sunglasses, pens, small pad of paper, ¼ A4, Kindle
    4. Keys on interior carabiner, ring whistle loop/loud whistle, lanyards
    5. Interior lining for wallet with RFID blocking, zip ties, carabiner (in pocket?) for keys
    6. On outside, hotel key, BART card
  3. Design Requirements / Goals
    1. When empty, it should be as flat as possible
    2. Wide straps for comfort if carrying something heavy, plus good for stowing a cell phone
    3. Pull rings, paracord top grip handle (also this guide), quick access pockets
    4. Bidirectional, so the main features can be worn over either shoulder
    5. Reduction of metal, heavy parts
    6. Outside straps which can be keep an umbrella, roll of material, or jacket
    7. Outside zippered pouch on the inside (against the body) to make it less likely to be pick pocketed, internal loops for clipping / hooking keys, rings, lanyards
    8. Reinforced corners, grommets
    9. Laptop pouch inside which is higher, area for charger to fall lower
    10. Pouches and pockets near the top
    11. How many pockets, pouches, zippered, velcro, etc?
  4. Materials
    1. Heavy nylon or similar
    2. Internal lining with fleece, ripstop nylon
    3. TPU (thermoplastic polyurethane) or PU (polyurethane) coatings
    4. Foam for padding
    5. Paracord for draw strings, grip wraps
    6. Zippers

Custom Every Day Carry Bag

  1. My Ultimate Bag
  2. Custom Every Day Carry (EDC) Bag
  3. Sewing Practice
  4. EDC Bag Materials, Designs, Etc
  5. Off the rack options for EDC bags
  6. A more practical EDC sling bag

Sewing Practice

About two years ago I purchased a few kits from RipstopByTheRoll.com – their Zipper Pouch Kit and their $10 kit.  They were partially for sewing practice and brush off long dormant sewing skills, but mostly for learning some new skills.  (You see, I have zipper cowardice.)

I did do a little bit of sewing at the beginning of the pandemic. 1

In learning how to get started sewing (again) I had to make sense of my sewing machine, settings, and sewing basics:

  • Brother XM3700 overview, settings
    • I had no idea what I was doing or what the dials were supposed to do.  Clockwise from left to right, they are the string tension (should stay between 3-5), left-right movement (irrelevant to straight stitches and seemingly best between 2-3 for zig zags), stitch length (between 1-3), and then the stitch selection dial (sticking with 2 for straight stitch and 3 for zig zags)
    • Using the automatic needle threader which way more helpful than I expected it to be
    • I created a “stitch sampler” where I noted the settings used for each stitch

      Annotated stitch sampler, with a stripe in one corner to orient the stitch setting guide
      Annotated stitch sampler, with a stripe in one corner to orient the stitch setting guide
    • I quickly discovered that the large Gutermann’s thread spool I’d purchased had way too large a core to work with the spool holder on my sewing machine.  Thus, I created a plastic insert that helped keep it from wobbling, which meant it would sometimes bounce right off the spool holder.  It was a little wobbly, so I printed a second one which worked beautifully.

      RBTR zippered pouch, and spool adapters pictured
      RBTR zippered pouch, and spool adapters pictured
  • Zipper sewing foot
  • RBTR $10 “Stuff Sack” Kit

    RBTR Stuff Sack
    RBTR Stuff Sack
  • RBTR Zipper Pouch Kit

    RBTR Zipper Pouch kit, all zipped up
    RBTR Zipper Pouch kit, all zipped up
  • When it comes to the guides by RBTR, I really have no notes.  Their video guides are helpful, detailed, and very accessible.  I got over my zipper cowardice very quickly by just watching the video a few times, letting it play while I went slowly, and pausing to go over each step.  I’m hopeful I’ll be able to use the skills I’ve developed here to build a new EDC bag.

Custom Every Day Carry Bag

  1. My Ultimate Bag
  2. Custom Every Day Carry (EDC) Bag
  3. Sewing Practice
  4. EDC Bag Materials, Designs, Etc
  5. Off the rack options for EDC bags
  6. A more practical EDC sling bag

  1. I sewed a mask for a friend of mine before realizing (re-realizing?) I’m not great at sewing and I could do more good helping people who were good at sewing make masks.  After learning about bias tape makers from @Raster and Hackaday, I printed and gave away perhaps 200 or so in the CA area []

Custom Every Day Carry (EDC) Bag

It’s been more than nine thirteen years since my last blog post regarding my every day carry bag.  Something must have happened between August of 2019 when I started this blog post and July of 2023, but for some reason, I just can’t seem to think of what could possibly happened to have derailed an idea.  Rather than putting this post off any longer, I’m just going to publish it largely as-is.

Perhaps it’s time for a progress report or update?

Back around about the summer of 1994 I wanted a bag to carry my stuff in. 12 I needed it to hold a binder, pens, pencils, and other assorted college student things.  Since this was my very first sewing project, I vastly over planned, prepared, and engineered everything.  I made a lot of mistakes, but nothing catastrophic.

LESSONS

  • Material.  It turns out that canvas was eventually scrapped in military uses because it doesn’t resist abrasion well and will rot and decompose if not stored carefully.  I also never treated mine to be waterproof with wax or some other substance.  A more modern and durable material is probably ballistic nylon or Cordura.  For a much more lightweight bag, a ripstop nylon, polyester, or polypropylene may work better.
  • Hardware.  I used 2-inch wide plastic buckles and clips on the bag as well as nylon webbing.3 These were the only sizes I could find back in 1994 at the local sewing / crafts store, so that’s what I bought.  In anticipation of making a new bag, I’ve already bought webbing made from seat belt material and plan to 3D print all new hardware.  I would probably add some loops of fabric or cord for attaching a small carabiner, lanyard, or keys.
  • Sewing.  I’m proud of this bag.  While there are a few rookie mistakes4 , it has held up incredibly well over the last 25 years.  I planned it out, drew everything out on large sheets of paper, transferred the designs to the canvas, cut everything leaving generous sewing allowances, and sewed it up with my mother’s already ancient sewing machine.  Next time, I’ll focus on x-box stitching on straps and better stitching practices.
  • Zippered Cowardice.  I admit my own cowardice as a beginner tailor in actively avoiding zippered pouches or pockets.  I’m not certain how important having zippered enclosures in a bag is, but it’s nice to have these.  Then again, I could probably just as easily have a velcro closed pouch that would serve just the same purposes and be less… clanky.
  • Flatness.  One of the things I appreciated most about the bag I made was that when it was empty/nearly empty, I could simply cinch up the strap and sling it across my back, where it would be basically hidden underneath a fleece vest I wear a lot.  This made it easy to take with me – or just ignore when not needed.  On a recent trip to an amusement park, I used one of those give-away schwag drawstring backpacks to similar effect.  When not in use, I just wore it underneath my vest.  When I needed it to care stuff for myself or family, I could tuck some small things inside it – or take it off and wear as intended.

BAG TYPES

  • Backpack.  A normal school-type backpack with two shoulder straps, large interior zippered area for books, binders, supplies, and a smaller outside zippered area for smaller supplies such as pencils, pens, etc.  There are usually a large number of interior pockets.
  • Laptop Backpack.  This type of backpack has an extra padded divider or compartment for protecting a laptop and a little extra space for carrying power cords and such.
  • Satchel.  A soft sided cross body single strap with a flap that folds over the front and can be buckled closed.
  • Courier/Messenger Bag.  A wide side slung bag with a wide strap suitable for carrying several stacks of large documents.   Usually has a large flap that folds over the front that buckles closed.
  • Laptop Bag.  Similar to a messenger back, but just wide enough to accommodate a laptop in a padded interior section, typically with a handle on top.
  • Tactical Backpack.  A backpack with a LOT of pockets, straps, buckles, harnesses, handles, etc.  Ranges from small to very large.
  • Fanny Pack.  I hate to admit the practicality of these bags because they’re so incredibly ugly.
  • Sling Messenger Bag.  “A bag with one strap that is designed to be carried on one shoulder.”  These tend to have a narrow and rounded triangular appearance, with a strap attaching to the left or right of the base.
  • Cortility Bag.  In episode #69 of the Cortex Podcast on 5/22/2018, CGP Grey talked about getting a small bag to carry a minimum amount of useful things since his everyday wear does not have enough storage.  Such things included his wallet, phone, headphones, earplugs, airpods case, a small camera, aspirin, etc.  This is my exact problem.  I want to be able to carry just a few more things with me.
  • Drawstring Backpack.  These are the kinds of bags that are basically drawstring bags where the loops of cinching cord are anchored at the bottom, so they can also serve as backpack straps.  They’re simple, easy to make, pack down super small, but they’re also… simple and don’t have a lot of room for many features.

STUFF

  • Stuff I Carry.  I’m not a survivalist, camping enthusiast, or have any special need for a bug-out bag.  Hopefully, I’ll never find myself in such a position that this bag will be what makes the difference.  With changes in life and lifestyle over the years, the things I need to carry has changed as well.
    • High School / College:  Books, notebooks, pens, pencils, playing cards
    • Grad School: Laptop plus books, notebooks, pens, pencils
    • Work Life: Sunglasses, bulky cell phone, laptop, small notebook/paper, pens, pencil, camera
    • Life Work:
      • Sunglasses, small cell phone, small notebook/paper, pens, pencil, small tools, sometimes a charger/portable battery and/or a laptop,
  • Bag Needs.  While pondering what I really need a bag for these days.  I’m no longer really very far from the things I need whether I’m at work, home, with the family, or just someplace near my car.  Now I’m of two minds on the topic.  Part of me wants something akin to a “tactical backpack” which is, depending upon your viewpoint, a glorified fanny pack worn across the back or a single strap side sling narrow backpack with lots of hooks, loops, straps, etc.  Part of me wants an unobtrusive and nearly invisible “drawstring backpack.”

I still use that old bag fairly regularly.

Annnnnd, that’s about where my blog post from 2019 left off…

Custom Every Day Carry Bag

  1. My Ultimate Bag
  2. Custom Every Day Carry (EDC) Bag
  3. Sewing Practice
  4. EDC Bag Materials, Designs, Etc
  5. Off the rack options for EDC bags
  6. A more practical EDC sling bag

  1. Mind you, this was back in the mid-90’s when it wasn’t uncommon for someone to have a fanny pack []
  2. Looking back, I was going for more of a manly Indiana Jones satchel / bugout bag []
  3. The technical term for these nylon straps []
  4. having way more than 10 stitches per inch basically perforated the canvas underneath the webbing []
Test