bookmark_borderRemote control wheelbarrow with tracks

Here’s a new project I’m working on – a RC wheelbarrow on tracks. It’s exactly what you would expect.

I took some time to model all of the different parts in Solidworks – the motors, tracks, casters, wheelbarrow, actuators, etc. – then I arranged them in an assembly and designed the chassis that I would need to fabricate afterwards. In the image above the gray stuff was all existing parts I sourced and the green was what I would need to fabricate. This was time consuming, but it did make the build a lot more straightforward. I had the flat parts laser cut locally from 1/4″ steel plate and used tabs/slots for alignment, this worked out great and was not that much more expensive that the raw material in the first place.

The tracks

The basis for this are these rubber tracks. I noticed them on ebay/amazon and the usual overseas sites at least a year ago and have had this idea in my head since then. They seem like they’re intended for small ATVs, but the listings are all a bit sketchy – you can buy the tracks alone or with an axle, sprocket, and brake rotor. The drive sprocket uses splines, so I bought the set with the axle for ~300 dollars just so that I didn’t have to try machining my own like these guys did, in fact it was only after I watched that video that I decided to finally order them.

I sliced the axle in half and am driving it using off-the-shelf sprockets with a 1″ bore, but unfortunately the axle is metric and just a bit too small. I welded on a sleeve, turned it to size, and added a keyway. I could have used sprockets with a smaller hole and bored it to size, but cutting a slot on a shaft was easier than broaching one in a bore for me. Driving the chain is a wheelchair motor, the gear ratio is 12:18 which trades some top speed for increased torque. The motors have tapered shafts, there wasn’t an easy sprocket to buy for that end so I made my own (there’s a little more about that here).

Electronics

The magic happens inside of this plastic box. The robot uses two 12v lead-acid batteries in series and the motors are driven with the Cytron MDD20A board. I found this to be a decent and cheaper substitute for the Sabertooth 2×32 that I have used previously – it doesn’t have any smarts onboard so it takes a few more pins and a bit more code to interface with, but it seems to handle the job just fine. I use an ESP32 to run the show – it interfaces with the motor controller and the RC receiver and makes everything work together. The circuit board (yellow) above is of my own design, it has a 5v power supply and a set of relays for switching the various functions – like the brakes and dump actuators.

Remote control

The remote is a critical part of making this practical. It’s meant to be a little buddy that hauls stuff around for you, and for that reason it’s not reasonable to use a traditional RC transmitter – the kind with a big antenna, two joysticks, and lots of switches. My main requirement was to have something that fit in my pocket and that really limited the options. Initially I planned to hack a Wii nunchuck controller, but then I found the DS-600. It’s made for boats (I think?) and has some weird quirks and limitations, but crucially it has the form factor I needed.

If you want to use this… be warned that it is pretty funky. It does have the ability to trim each axis on the joystick, but you can’t adjust dead zones, maximums, etc. Very bare bones. I did all of this in code on the ESP32. Three of the face buttons are latching (toggle) and one is momentary, this is actually pretty limiting. For example, I want to use the joystick for driving the tracks, and separately I want to control the dump function: up and down. If there were two momentary buttons I could easily make one go up and the other go down, no problemo. Since there is only one, I used one of the latching buttons to change a “mode” in the ESP32, then I can remap a joystick channel to the dumper. This solves the problem but also means I can’t drive and move the dumper at the same time. I used the same approach for an even more important function: disabling the joystick entirely. The ESP has a mode that disables all movement of the machine unless one of the latching channels is “on” – enabling this lets you operate the machine, and disabling it makes it safe to put the controller in your pocket without sending bogus commands if you bump the joystick; without this the whole thing would be too inconvenient or dangerous to be practical.

bookmark_borderCutting a keyway in a tapered bore with an EDM

Slowmo shot of cutting a keyway on a CNC EDM. Definitely overkill, but easier than broaching the keyways on a taper for these sprockets:

These are for a remote control wheelbarrow project I’ll share later. For setup the sprocket was put in a v-block and tilted so the taper angle was vertical. The graphite electrode is just a long rectangle. This was done on a CNC EDM, not a sinker, so we went to full depth, burned in from the front, then burned into the corners to get to the final width.

bookmark_borderMixed berry cider: Brew Berrymore

This is a batch of cider made with just blackberries, raspberries, and blueberries. The image was generated by stable diffusion.

  • 9/10
    • Started with:
    • 3 lb blueberries
    • 6 lb blackberries
    • 5 lb raspberries
    • 6.5 lb sugar
    • Water to reach 5 gallons
    • Starting gravity: 1.060
  • 9/11
    • Added yeast: Safale S-04
  • 9/16
    • Fermentation was pretty slow, removed the fruit solids and racked to a carboy
    • Gravity: 1.050
  • 10/8
    • Racked and added sparkolloid
    • Final gravity 0.995 for ~7.2%
  • 10/14
    • Added 3 oz priming sugar, target is 2 volumes of Co2
    • Ended up with 4.2 gallons in the end
    • Bottled and labeled
Fermentation
Kept the fruit in a bag which made it much easier to separate the solids later

bookmark_borderCircuitpython + Pi Pico: saving settings at runtime without an EEPROM

Unlike some other microcontrollers, the RP2040 doesn’t have any EEPROM onboard. On something like the ATmega328P for example, it is easy to save the value of a variable to the EEPROM so that you can read it back on the next boot; this is handy for remembering a user setting or recalling the last state your project was in between power cycles. I have used this in the past with some of my word clocks so that when it is powered up it will “remember” the last color setting.

So, how to do this with something like the Raspberry Pi Pico? The solution I am putting forth uses the flash storage where the program files and libraries are stored. I didn’t invent this idea, but didn’t find everything I was looking for very easily so decided I would write it down here. The main idea comes from Adafruit: https://learn.adafruit.com/cpu-temperature-logging-with-circuit-python/writing-to-the-filesystem

A couple points on this solution:

  1. Limited write cycles: Flash memory has a limited number of write cycles before it wears out, so be conscious of this. A good strategy is to only write when something meaningful is changed, or if you are logging data to a file consider the interval and pick something reasonable. If you write on every loop of your program you could accelerate the failure
  2. Only one device can write files at a time: Files on the device are generally only available to be written by one device at a time. Normally the files are read-only for the microcontroller – it can read them but not change them during operation, and the files are read/write for a computer if it is mounted as a USB device.
  3. Write permissions are only changed on boot: switching the read/write permissions on the filesystem only happens when the microcontroller boots up. A reset doesn’t count, so resetting via software, the REPL, or writing a new file doesn’t do the trick – the setting is made when it powers up. This means this isn’t a good solution if you wanted to have both a PC and the microcontroller writing to the same (or two separate) files at the same time.
  4. When the microcontroller has write access, you cannot upload new code: This means that in order to update the device with new code, you need a way to switch the access – like a switch or jumper. If you accidentally end up locked out, check the Adafruit link above and there’s a note on how to fix this via the REPL.

How to do it:

First, create a JSON file that will contain the settings. Here is the example I’m using:

{"color": "Red", "brightness": 0.1, "mode": 1}

Second, the filesystem permission needs to be set at boot time, the code below needs to be in the “boot.py” file. In this example I’m using GPIO 17: when the pin is low at boot, the microcontroller has write access, and when it is high the PC will have write access. You could reverse this so the default behavior matches your requirement.

import board
import digitalio
import storage

switch = digitalio.DigitalInOut(board.GP17)
switch.direction = digitalio.Direction.INPUT
switch.pull = digitalio.Pull.UP

# If the GP17 is connected to ground with a wire
# CircuitPython can write to the drive
storage.remount("/", switch.value)
print(switch.value)

Third, in “code.py”, you can treat the filesystem like you might with python on any other system. I like to use a JSON file because it gives an easy structure to work with for things like settings, but once you are able to open and write files you can do whatever you want. In this example I’m reading the file, changing one value, then overwriting it.

#If the device boots up and has access to the filesystem, you should observe that the value for
#color in the settings.json file is "blue".  You will also be unable to modify or upload files

#If it boots up and the PC has write access to the filesystem, the serial monitor will show
#an error, and the contents of the file won't be modified

import json

#open the settings file, read the JSON into an object named "data", then close it
with open("settings.json") as infile:
    data = json.load(infile)
    print(data["color"])
infile.close()

#change one of the values in "data"
data["color"] = "Blue"

#finally, open the file again and overwrite it with the current contents of "data"
with open("settings.json", "w") as outfile:
    json.dump(data, outfile)
outfile.close()

Result

When this code all runs, the result should be that the JSON file now looks like this:

{"color": "Blue", "brightness": 0.1, "mode": 1}

And at the same time, if you try to edit or upload a file to the device, your PC should give an error like this:

And that’s all there is to it. I recommend adding a button to the pin that changes the mode at boot, at least while you’re developing, or reuse a pin that you already have a switch attached to. As a side-effect, this can reduce the risk of someone accidentally deleting or modifying the files for a device you’ve released into the wild. The three files are in a zip file below. Have fun!

bookmark_borderUltrasonic Direction and Range Finding Hack

In this post I’ll share my implementation (so far) of an approach to find the distance and direction of a beacon, with an end goal of building a human following robot. It’s not an original idea – here is an earlier project by Ben Heck and Jesse Robinson that does the same thing. Check the bottom of this post for a quick video demo of the thing.

The setup

The simple idea is to have a beacon that emits a 40kHz “ping” and a pair of receivers – by comparing the difference in arrival time at each receiver, the angle to the beacon can be calculated. For the distance measurement, a radio signal can be used to synchronize the beacon with the receiver, the difference between when the RF and sonic pulse corresponds to the distance.

What makes this a hack

The fun thing here is using common “HC-SR04” modules in a way they weren’t intended. Normally these devices send out a pulse when they are triggered, listen for the echo, and output a pulse with a varying width that corresponds to a distance measurement. The receiver is only active for a short period of time after it is triggered, making it nearly useless for passive listening unless you trigger repeatedly and rapidly – it also would be transmitting pings and filling the environment with noise and echoes.

The first “hack” part is easy – desolder the transmit transducer from the module – now it can’t transmit anything and gives a short window for receiving. The second part is to synchronize the trigger for the receivers with the transmission from the beacon, so that hopefully the incoming ultrasonic wave hits within the “listening” time window. A radio signal works great, relative to ultrasound we can pretend it is instantaneous and use it to align all of the events.

One important factor is the execution time for code on the microcontrollers that are running the show. It is best if interrupts can be used – ideally the amount of time between receiving the radio signal and triggering the modules is deterministic/repeatable – this way a consistent reading can be made for distance. In my test using a 433mhz radio I found the timing was very reliable; using the ESP-NOW protocol with the ESP-32 introduced about 200 microseconds of variability, which is not ideal, but only creates a couple of inches of distance error which is OK for the ranges I expect to use it at.

Rising edge of the blue channel shows the variability in the ESP-NOW packet interrupt

Wiring

Here is the first version I created with two Arduino Nanos:

And here is the second version with two ESP-32 modules

Program

This is the basic logic of the receiver – basically it starts a timer when a RF signal is received, then records the time when the ultrasonic ping is received at each receiver. Some math is done, then we have the distance and angle. The transmitter is even simpler, it just blindly fires off packets and pings repeatedly.

Code

Below is a zip file with four platformio projects in subfolders. There is a pair for the arduino and a pair for the ESP32. I didn’t do a great job on these, but I think they suffice to demonstrate the concept.

Result

The performance is pretty good in my opinion, but not without some limitations. The angle resolution is quite good from about 2 feet to 30 feet. I don’t have good data on the ranging accuracy at longer distances, but it seems to be reliable within to a few inches – more testing is needed. It is susceptible to obstructions and echoes, as well as line of sight – the receivers and transmitter only work within about an 80 degree cone, so they must be pointed at each other to work. Software filtering would be a good idea to smooth out the readings. Here’s a quick video of my preliminary results – I haven’t implemented any safety features or tried to handle loss of signal just yet: