Motorized Furniture Dolly Feat. ESP32-S3 and Flipsky ESC Running VESC 6

by Penguingineer in Circuits > Arduino

67 Views, 2 Favorites, 0 Comments

Motorized Furniture Dolly Feat. ESP32-S3 and Flipsky ESC Running VESC 6

DSC00305.JPG
DSC00308.JPG
Building a motorized ride-along furniture dolly
DSC00328.JPG
DSC00307-1.JPG
DSC00317.JPG

In this project, I added wireless motor control to a humble wooden furniture dolly, transforming it from a mere furniture transportation tool into a ride-along, battery-powered electric vehicle! The dolly can still be used to transport furniture while unpowered, but the addition of motor control is helpful for particularly cumbersome moves. This project combines aspect of mechanical, electrical, and computer engineering, and is perfectly suited for anyone with an interest in mechatronics or robotics.

I made this video about the project!

https://youtu.be/Nf2UnYzyAdI?si=YcIrRnhJvHUKYie0

Warning: This project is undertaken at your own risk! There are multiple elements that can present danger if not treated with care, including electrical wiring, battery management and handling, multiple moving parts and pinch points, and use of the DIY electric assembly itself as a ride-along vehicle, which can provide a risk of injury to yourself and others. Here are some examples of safety equipment that can help to reduce the risk of injury:

  1. Safety goggles (these are a bare minimum when fabricating parts)
  2. Electrical grounding safety strap
  3. Helmet, hand pads, and knee pads when riding the motorized dolly

Note: Some of the links in this article are affiliate links. This means that, at zero cost to you, if you click through the link and make a purchase, I will receive a commission.

Supplies

  1. 2 x Single-axis joystick modules
  2. 1 x Custom ESP32-S3 based hand controller
  3. 1 x ESP32-S3 DevKitC board
  4. 1 x Flipsky 75100 dual ESC running VESC firmware
  5. 2 x Flipsky 7070 BLDC motors
  6. 1 x Hailong Li-Ion Battery Pack (36VDC Li-Ion battery pack, 10S3P configuration)
  7. 1 x Generic furniture dolly from Home Depot
  8. 1 x Step2 platic poolside chair (different colors available)
  9. 1 x Adhesive-backed solderless breadboard
  10. 1 x Set of JST-ZH cables + connectors to connect to the Flipsky 75100 dual ESC
  11. 1 x Assortment of multi-color heat shrink
  12. 1 x Assorted jumper wires
  13. 2 x Micro-USB to USB-A cables
  14. 2 x XT-90 to XT-60 adapter
  15. 2 x XT-60 extension cable
  16. 1 x Set of adhesive wire clips
  17. 1 x Set of 4 x rubber furniture dolly wheels (2 x rigid, 2 x swivel)
  18. 1 x Roll of black PLA+ 3D printing filament
  19. 1 x Wrench set
  20. 1 x Staple remover tool
  21. 1 x Stapler tool with staples
  22. 1 x Thread-checking tool set
  23. 1 x Automotive brake pad spreader tool (to force the dolly caster wheel brackets apart and make more room for the chain drive mount components)
  24. 2 x Tritan 55VX32 flat sprocket, one for each rear caster wheel
  25. 2 x Uxcell #25 chain roller sprocket with 10mm bore, 25-tooth (lower torque, higher RPM)
  26. 2 x Uxcell #25 chain roller sprocket with 10mm bore, 10-tooth (higher torque, slower RPM)
  27. 1 x Wen drill press to drill out the Tritan 55VX32 sprockets
  28. 1 x Set of metric drill bits for the Tritan 55VX32 sprockets (and useful in general)
  29. 1 x Set of 82-degree countersink drill bits for the flat head screws that mount the Tritan 55VX32 sprockets
  30. 1 x Chain breaker tool
  31. 2 x #25 chain master links
  32. 1 x Length of #25 chain
  33. 1 x Cordless drill
  34. 1 x Set of motor phase wire banana bullet connectors
  35. (Optional) 1 x Pair of 3-pin motor phase wire connectors to prevent accidental reversed wiring
  36. 1 x ZH-1.5mm connectors kit
  37. 1 x 3.2 foot length of LED strip lights (144 LEDs per meter, cut to equal lengths for each side of the dolly)
  38. 1 x Logic level converter breakout board (for sending commands from the ESP32-S3 dev module [3.3V logic] to the LED light strips [5V logic])
  39. (Optional) 1 x High-current battery on/off switch
  40. 1 x Soldering + hot air reflow station (for soldering cables)
  41. 1 x Spool of solder (for soldering cables)
  42. 4 x 1/4"-20 bolts (for mounting the folding seat on the dolly)
  43. 1 x Set of flat-head M3 machine screws (for the electronics enclosure top, and mounting the sprocket to its adapter on the wheel)
  44. 1 x Set of M3 heat set threaded inserts (for the electronics enclosure base)
  45. 1 x Set of #6 x 5/8" flat head Phillips wood screws (to mount the sprocket adapter to the caster wheel, and the 3D-printed electronics enclosure + battery mount to the underside of the dolly)
  46. 1 x Assortment of M4 flat head machine screws (to attach the Flipsky controller to the electronics enclosure base)
  47. 1 x Assortment of M3 pan head self-tapping wood screws (for the custom PCB controller + enclosure assembly)
  48. 8 x No. 6 x 5/8" pan-head wood screws (to attach the motor mounts to the dolly)
  49. 16 x 1/4"-20 Nylon lock nuts
  50. 16 x 1/4"-20 x 2 inch long carriage bolts (if spares are needed for mounting the new caster wheels)
  51. 2 x 3/8"-16 female threaded knobs (for the rear-wheel studded knobs)
  52. 2 x 3/8"-16 x 3 inch long threaded studs (for the rear-wheel studded knobs)
  53. 2 x 3/8"-16 Nylon lock nuts (for the rear-wheel studded knobs)
  54. 1 x Tube of thread locker
  55. (Optional - for racing flags) 1 x Pair of 1/2" to 3/4", and 3/4" to 1" EMT-conduit telescoping couplings
  56. (Optional - for racing flags) 1 x 6-foot piece of 1/2" EMT conduit
  57. (Optional - for racing flags) 1 x 6-foot piece of 3/4" EMT conduit
  58. (Optional - for racing flags) 1 x 6-foot piece of 1" EMT conduit
  59. (Optional - for racing flags) 2 x Flag clips
  60. (Optional - for racing flags)1 x Checkered flag
  61. (Optional - for racing flags) 1 x Orange safety flag
  62. (Optional - for racing flags) 2 x Flagpole ground stakes

Mechanical Assembly

Dolly Screenshot 3.png
Dolly Screenshot 2.png
Dolly Screenshot 1.png
IMG_20240812_094751849.jpg
IMG_20240812_094810514.jpg
IMG_20240812_094738930.jpg
IMG_20240820_104950802.jpg
IMG_20240820_110711049.jpg
IMG_20240820_122003125.jpg
IMG_20240820_111055096.jpg

I 3D-printed (PLA+ filament) the Flipsky BLDC motor mounts, and the enclosure for the Flipsky dual ESC motor controller and peripheral/receiving ESP32-S3 dev board. I added 4 x M3 heat-set threaded inserts to the base of the 3D-printed enclosure so that the lid could be attached with M3 screws. For all printed parts, it is best to print with 100% infill to help reduce the chance of breakage. Using a tougher printed material like Nylon over PLA would further strengthen the build.

The furniture dolly originally came with 4 x swivel caster wheels. I opted for rear wheel drive for this build, and first removed the swivel wheels on the rear of the dolly and replaced them with fixed (i.e. non-swivel) wheels. I used this set of 2 x rigid/fixed, and 2 x brake/swivel wheels which are made from a soft rubber, which makes for a much smoother and quieter ride than the stock plastic wheels that came with the original furniture dolly.

To install the new wheels, first remove the carpet/coverings on the front and rear of the dolly. The dolly was assembled by first bolting together its wooden planks using carriage bolts, and then covering them with carpeting material + staples. This staple remover tool can be used to tease out the staples. Then, the carriage bolts can be removed. Drill new holes to match the landing pattern for the wheels, re-attach them with the same bolts, and cover the newly-drilled area with carpet and fresh staples to re-hide the drill holes and bolts. Drill out the holes for mounting the plastic chair which is mounted on top of the dolly (the chair can be removed when you want to transport furniture instead of people.) This plastic chair turned out to be exactly the right size for this project, is foldable for dolly storage, has a carrying handle on its rear, and has multiple color options.

The new pair of fixed rear wheels may have slop/play in the inner bearing in the center of each wheel. To help reduce lateral slippage, use a hammer to repeatedly tap the flared head of the inner bearing of the wheel, to reduce the gap between it and the inner race of the bearings.

I used a wrench set to remove the lock nuts and carriage bolts from the original wheels on the dolly, and drilled mounting holes for the new wheels. Each wheel bracket has 4 x slots in its metal base which help with adjustability. I measured the thread size of the original carriage bolts (1/4"-20 x 2 inches long) using this tool set, and with the thread size determined, I used these nylon lock nuts to attach the new wheel brackets to the furniture dolly. After installing the new wheels, I re-added the carpet to the dolly using this stapler tool to maintain that "furniture dolly" look and feel.

I wanted to be able to fold the dolly when not in use, and I needed a cheap and lightweight seat for the assembly. I found this poolside plastic seat which has a folding backrest, and even has a lip on its front end to fill the gap between the rear and middle planks of the wood on the dolly. I bolted this seat to the dolly wood using these 1/4-20 screws and 1/4"-20 Nylon lock nuts.

To make installation, removal and replacement of the rear caster wheels easier, I built two studded hand knobs using female threaded knobs and 3/8"-16 x 3 inch long threaded studs, bonding the two together using thread locker.

Note: Keep in mind that for all parts which may be subject to vibration, it is best practice to use nylon luck nuts where possible, and thread locker where appropriate, so that the fasteners don't shake loose over time.

The Chain Drive and Motor Assembly section of this article provides details on how I modified the dolly to include the chain drive system.

3D-Printed Parts

IMG_20250409_151915575.jpg
CAD Screenshot Motor Bracket.jpg
CAD Screenshot Sprocket Mount Assembly.jpg
CAD Screenshot Enclosure Bottom.jpg
CAD Screenshot Enclosure Top.jpg
CAD Screenshot Battery Holder.jpg
CAD Screenshot Sprocket Wheel Adapter.jpg
CAD Screenshot Sprocket Drill Holder.jpg
Spacer_10mm.jpg
CAD Screenshot Joystick Cap 1.jpg
CAD Screenshot Joystick Cap 2.jpg

All 3D-printed parts were made using PLA+ black filament. These printable part files are all available at this Thingiverse link. I recommend printing with 100% infill to help reduce the risk of part breakage. The files include:

  1. Flipsky 7070 BLDC motor mount
  2. Flipsky 75100 dual ESC module enclosure bottom + cover
  3. Hailong Li-Ion battery bank mount (uses zip ties)
  4. Adapter to mount the sprocket to the rear caster wheels
  5. Sprocket holder to make modifying it easier
  6. 2 x Custom joystick caps (i.e. throttle/left, and steering/right)
  7. 10mm spacer and 5mm spacer for the 3/8"-16 studded knobs for the rear caster wheels

Chain Drive and Motor Assembly

IMG_20240829_141729579.jpg
IMG_20250115_172159899.jpg
IMG_20250115_172446580.jpg
IMG_20250115_201805409.jpg
IMG_20250115_201859799.jpg
IMG_20250115_201907728.jpg
IMG_20250115_202023755.jpg
IMG_20250115_202317706.jpg
IMG_20250204_153736760.jpg
Dolly Screenshot 4.png

There were multiple ways I considered adding motor control to the furniture dolly:

  1. Friction drive, i.e. simply relying on friction using a contact wheel
  2. Using hub motors such as those found in DIY electric skateboard kits (here's one example)
  3. Chain drive (as in a bicycle)
  4. Belt drive (as seen in automobiles)

I first attempted the friction drive concept using these bumpers, as it would require the least amount of part modification if it work. However, I found that maintaining contact pressure between the motor contact wheel and the rear caster wheels was very finicky, and if there was any weight on the dolly, the contacting rubber wheel would eat away at the softer caster wheel material.

After that, I tried installing a GT2 belt drive system with 3D-printed custom belt pulleys mounted on the caster wheels plus the following hardware, but even with an additional tensioner, I found that the belts slipped constantly. So, this attempt didn't work, but here are the parts I used for posterity:

  1. GT2 x 400mm long belt loop
  2. GT2 idler pulley (for adding tension to the belt)
  3. Low tooth count, and high tooth count GT2 pulleys (mounted on the motor shaft)

I finally settled on using a chain drive to drive the wheels using the motors, which has worked very nicely. To add the chain drive, I needed to source and then modify the right parts for a #25 chain. All the sprocket hardware needed to fit within the wheel mounting bracket. I found this flat Tritan 55VX32 flat sprocket, which I modified using 3 x countersunk mounting holes + a 12mm center hole. I selected this sprocket because it was largest diameter #25 sprocket which was smaller than the caster wheel diameter - by maximizing that diameter, the corresponding gear reduction from the motor sprocket to the wheel sprocket would maximize the motor torque.

Two sprocket sizes were readily available to install on the motor. The larger of the two will reduce torque but increase max RPM, and the smaller of the two will increase torque but decrease max RPM:

  1. Larger (25-tooth) sprocket with 10mm bore
  2. Smaller (10-tooth) sprocket with 10mm bore

To add the chain drive sprocket to the wheels so that they could be driven by the motors, I did the following:

  1. Modify the Tritan 55VX32 flat sprocket by drilling and then adding countersinks to 3 x mounting holes
  2. Increasing the diameter of the sprocket center hole by drilling it out to larger than 10mm
  3. 3D print the adapter for the sprocket gear
  4. Add 3 x M3 nuts to the rear/underside of the sprocket adapter
  5. Mount the sprocket adapter to the caster wheel using 3 x No. 6 x 5/8" length flat head self-tapping screws
  6. Mount the modified sprocket gear to its adapter using 3 x M3 x 10mm flat head machine screws (remember to include thread locker)

In order to accommodate the extra width of the sprocket mounting assembly on the wheel, I needed to pry open the wheel brackets. I found this automotive brake pad spreader tool, which I used to push the prongs on the rear caster wheel brackets apart, so that the sprocket hardware and chain would fit. To prevent the mounted sprocket from contacting the inner wall of the caster wheel mounting bracket, I added a 3D-printed 5mm spacer.

I additionally needed to build out two #25 chain loops. I purchased 5 feet of this #25 chain, broke it using this tool (the tool was a bit difficult to use), and then installed a master link at the broken location using needlenose pliers.

Electronics (Dolly)

Motorized Furniture Dolly Wiring Diagram.png
IMG_20250207_204759063.jpg
IMG_20250207_204849774.jpg
IMG_20250205_184836345.jpg
IMG_20250205_184851926.jpg
IMG_20240828_184406398.jpg
IMG_20250207_204810542.jpg
IMG_20250207_204819351.jpg
Flipsky Dual ESC Front Labeled.jpg
Enclosure Interior Wiring.jpg

The wiring diagram for the dolly-side electronics is shared above. The Flipsky 7070 motor designation stands for a motor diameter of 70mm, and a length of 70mm. The Flipsky 75100 dual ESC controller contains 2 x electronic speed controllers, and each is wired to its own 7070 motor. The Flipsky dual ESC module can be thought of as two of these single modules inside a shared enclosure.

The BLDC motors have 3 phases, corresponding to three thicker 12 gauge (AWG) wires. If any two of the wires are swapped, the motor direction will be reversed. The direction of the motors can be set using the VESC Tool programming software. The free version of that software sufficed for this project. Solder female bullet connectors to the 6 x 12 gauge wires leading out of the dual ESC unit, and solder male bullet connectors (same Amazon link) onto the ends of the BLDC motor phase wires. Add heat shrink to those connectors to help prevent electrical shorts.

The other cable leading out of each BLDC motor are low voltage and are used for the hall sensors corresponding to the three motor phases. Plug that cable into the Flipsky dual ESC controller as indicated in the wiring diagram. That cable connector type is ZH 1.5, so you can use this assorted connector kit if you need to create replacement wires extend the cables, etc.

The LED strip lights are wired in parallel. When installing the LED strip lights, make sure they are both cut to the same length (same number of addressable LEDs), and attach them to the dolly in the same direction (there is an arrow on the strip lights that indicates the direction of the LEDs, i.e. which data out (DOUT) pins feed into which data in (DIN) pins on the LEDs. To help further secure the strip lights, I added super glue and a strip of clear packing tape over top of them.

Mount the ESP32-S3 dev module into an adhesive-backed solderless breadboard and then connect it to the Flipsky Dual ESC module using jumper wires. The Flipsky Dual ESC module communicates over 3V3 logic, which is compatible for direct connection to the GPIO pins of the ESP32-S3 dev module. The logic level converter breakout board inside the electronics enclosure is for sending 5V logic level commands to the LED strip lights using the ESP32-S3's 3V3 signals.

Electronic Speed Controller (ESC) Setup Using VESC Tool

VESC Tool Home Page Marked.png
VESC Tool UART App Settings Screenshot.png
VESC Tool Disable Phase Filters Screenshot.png

The Flipsky 75100 Dual ESC controller has 2 x USB-C ports. It is possible to program one side of the controller using USB-C while specifying the other as a CANbus peripheral, but to prevent confusion it is simplest to program each side of the module one at a time via USB-C connection.

VESC 6 is the firmware that is run on the Flipsky Dual ESC module. To program the module, first download the software VESC tool (their free version will suffice for this project) at the bottom of the following web page. If you'd like to support their open source project, you can do so by purchasing one of their other tool options (Bronze, Silver, Gold, Platinum):

  1. https://vesc-project.com/vesc_tool

Connect the USB-C connector on one side of the dual ESC module to an open USB port on your PC or laptop and open VESC Tool. Flipsky's technical support team provided me with the following VESC Tool configuration settings for their VESC-compatible ESC product lines, referring me me to their blog post:

  1. https://flipsky.net/blogs/vesc-tool/tips-of-75-serise-esc

FOC in the context of motor control stands for Field Oriented Control - from the application perspective, it allows us to output the maximum torque of the motor at zero RPM, which is exactly what we want for this project, because we want the motors to strongly push the motorized dolly no matter the moving speed or motor position.

Motor theory dictates that motor torque is proportional to motor current draw, so increasing the motor current limit will increase the initial acceleration of the furniture dolly, but won't increase the maximum/top speed. Therefore, the idea is to set the battery current limit no higher than the continuous discharge rating of the battery, with some margin for safety. The motor calibration process will automatically set these values in the VESC Tool > Motor Settings > General > Current tab.

Flipsky provides an official YouTube tutorial video for updating the firmware on their dual ESC controller to VESC 6:

  1. Tips for New VESC Firmware 6.00

To calibrate each BLDC motor one by one using VESC Tool:

  1. Open VESC Tool. On the first page that opens, select AutoConnect, and select the COM port for the USB connection to the ESC.
  2. Flipsky makes a special point to note that you need to disable Phase Filters for this controller. Remember to do this so as to not damage the motors. They provide more instructions on this in their tutorial video.
  3. Under Motor Settings > FOC > General, set Sensor Mode to Hall Sensors.
  4. To enable each ESC inside the Flipsky dual ESC module to accept UART/Serial commands from the ESP32-S3 dev module, under App Settings > General, set APP to Use to be ADC and UART.
  5. When the USB connection is established, click Setup Motor FOC. Select Medium Outrunner motor (750g) and click Next.
  6. Refer to the Youtube video for the battery settings I selected for the particular battery pack for this project (36VDC Li-Ion, 10S3P configuration.)
  7. Set the motor direction/inversion for FWD or REV. You want the motor to spin such that the furniture dolly is pushed forward when the motor runs in the FWD direction.
  8. At this point, it's a good idea to click Save Motor Configuration, and Save App Configuration so that you can easily reload your settings if needed. Save one Motor Configuration file per motor. Finally, click Write Motor Configuration while the ESC is still connected to your computer. This will set the configuration/settingfs for the ESC side that is currently connected to your computer.
  9. When the motor is set up, repeat the above steps for the motor on the other side of the furniture dolly, taking care to set the FWD motor direction such that that direction pushes the dolly forward.

Here are some informative reference videos that discuss setting up VESC with Flipsky ESC controllers:

  1. https://www.youtube.com/watch?v=VsDWGix8Yhg
  2. https://www.youtube.com/watch?v=lDuV8cnPRmI
  3. https://www.youtube.com/watch?v=Vp_HvhrY388

PCB Design, KiCAD and JLCPCB

IMG_20250409_152304550.jpg
IMG_20250409_152312220.jpg
IMG_20250409_152726114.jpg
IMG_20250409_153057806.jpg
IMG_20250409_152929926.jpg
IMG_20250409_152233563.jpg
IMG_20250409_152603556.jpg
PCB Screenshot.jpg
Schematic Screenshot.jpg
Maithoga 2pt8 Display Schematic Snippet Screenshot.jpg

I designed a custom ESP32-S3 based hand controller with its own printed circuit board (PCB), which can connect to the on-board dolly ESP32-S3 dev module for wirelessly sending and receiving commands and data.

PCB vendor JLCPCB reached out to me to offer a sponsorship for the PCB manufacturing costs for this project, which I happily agreed to. I've been using JLCPCB's services for years, and I've found their work to be more more than sufficient for all my electronics projects.

I designed the custom controller PCB using my preferred design (EDA) software KiCAD, which is open-source, free for commercial use, and packs all the features that I've needed for my PCB designs. KiCAD can be downloaded for free here. Here is a modern KiCAD tutorial video that may serve as a good reference if you'd like to learn the software.

Here's my typical workflow for designing a PCB:

  1. Build a breadboard circuit to test the components.
  2. Create the circuit using KiCAD's Schematic module. Because I use JLCPCB to assemble the boards which I design, it is most convenient to source components that are already in stock at JLCPCB. You can check their in-stock parts using their search tool here.
  3. If the parts you need aren't in stock at JLCPCB, you can use their Global Sourcing Parts feature to instruct JLCPCB to order the custom parts that are needed for your PCB and keep that stock on hand for your projects. Alternatively, you can purchase the parts yourself, and ship them to JLCPCB for assembly using the Consignment feature on their website.
  4. If custom schematic symbols are needed, you can either (A) find the symbol of interest on a website such as SnapMagic, Digikey, Mouser, UltraLibrarian, etc and download it in KiCAD format, or (B) create the schematic symbol yourself, referring to the datasheet of that component to determine the pin order versus its footprint.
  5. Define the footprints for all the components in the schematic.
  6. KiCAD comes pre-packaged with a number of part libraries.
  7. If I need a custom footprint that isn't in KiCAD's libraries, first I check if I can find the needed footprints online, again on SnapMagic, Digikey, Mouser, UltraLibrarian, etc, and download and import them in KiCAD format.
  8. If the footprint isn't available online, I refer to the datasheet for that component and construct the footprint with pads, silkscreen, labels etc. If available, I use JLCPCB's component footprint preview in EasyEDA as a reference to help avoid mistakes.
  9. As part of creating the footprint, I also like to add a 3D model of the part.To obtain the 3D CAD model for a component, I again first check SnapMagic, Digikey, Mouser, UltraLibrarian, or occasionally GrabCAD. Download the component's 3D model in STEP format. In KiCAD's footprint editor, navigate to the Footprint Settings menu > 3D model, and select the CAD model, aligning it with the solder pads. The ability to export an accurate CAD model becomes crucial for projects (such as this one) where electronics need to be designed in tandem with mechanical hardware such as enclosures.
  10. Lay out all the footprints in the KiCAD layout module. As a spot check, at this stage I typically export the PCB as a STEP file to mate it with the mechanical part models in Autodesk Fusion 360.
  11. If the layout of the components works well, next, I connect the components using traces in the KiCAD layout module.
  12. Export the Gerber (manufacturing) files from KiCAD, along with the component placement/position file for automated (pick and place) assembly, and the bill of materials (BOM) specifying the component part numbers and JLCPCB/LCSC reference number which are needed in order to use JLCPCB's assembly service.
  13. Load the Gerber files, component placement file, and bill of materials (BOM) to JLCPCB's website, and click through their settings to specify your particular board's configuration (e.g. number of board layers, silk screen and solder mask colors, number of boards to order, etc.) Double check that the components you selected in the BOM are available and in stock at JLCPCB, and also check the positions of the components, using their online board preview window. JLCPCB has an auditing service where they'll look over the orientations of your components and traces, which is helpful for catching issues before production begins.
  14. Place your order and submit payment. 5 x assembled PCBs shipped by DHL typically take around 10-14 days to be manufactured and then arrive in Los Angeles after the order is placed.

I designed the custom PCB with the following features:

  1. Powered by one rechargeable 18650 Li-Ion battery
  2. Battery reverse polarity protection
  3. Uses ESP32-S3 module for BLE wireless communication (could alternatively use ESP-NOW)
  4. Reads 2 x single-axis joysticks
  5. Can be programmed and battery charged using USB-C
  6. Serial output port (RX/TX) for wired control of the dolly through the ESP32-S3 dev board's USB port, if desired
  7. On/off switch
  8. MicroSD card for extra storage (just in case)
  9. Color TFT display and capacitive touch panel (CTP) connected by FPC cable

A good reference for ESP32-S3 PCB designs is the open-source ESP32-S3 Dev Board schematic which is directly available from the ESP32 manufacturer Espressif. Their website provides datasheets and the schematic for their ESP32-S3 dev board, which I've found to be an extremely helpful resource for my projects.

I ordered this 2.8 inch TFT ILI9341 display and GT911-driven capacitive touch panel (CTP) from AliExpress. The TFT display cable and CTP cable each connect the PCB by way of 2 x 0.5mm pitch FFC connectors (pin order provided in the screenshot above.) Since the 2D drawing for this screen is provided in the purchase link, I recreated it in CAD as a 3D model so that I could check that it fits within my enclosure design, as shown in the next section of this article.

Hand Controller Enclosure Design and Assembly

Controller Unpowered Front.jpg
Controller Unpowered Rear.jpg
Controller Explode Animation.gif
Hand Controller Screenshot 2.png
Hand Controller Screenshot 1.png
Hand Controller Screenshot 3.png
Display Dimensions.jpg
Display CAD Model Front.jpg
Display CAD Model Rear.jpg
Display CAD Model Side.jpg

After designing the ESP32-based PCB for the hand controller, I designed a simple enclosure using Fusion 360 which could be 3D printed in two halves. Using the KiCAD-exported model of my PCB, and my recreated model of the TFT display + CTP from Aliexpress, I was able to verify that all pieces would fit together. I added 2 x single-axis joysticks on the underside of the PCB, with the left side oriented vertically (throttle), and hte right side oriented horizontally (steering.) I designed and 3D printed 2 x custom joystick caps and added those to the assembly as well. The PCB is mounted to the front half of the enclosure using 5 x M3 x 6mm long thread-forming screws. The two halves of the enclosure are held together using 6 x M3 x12mm long thread-forming screws.

Hand Controller UI Design

IMG_20250206_155045099.jpg
IMG_20250206_155049920.jpg
Main Screen Screenshot.jpg
Logo_Splash_Screen.bmp
Main_Screen.bmp
Settings_Screen.bmp

To create a basic layout for the graphical user interface (GUI) for the TFT display and capacitive touch panel (CTP) on the hand controller, I designed a simple static background image using Inkscape, which is free vector graphic design software. I use this software for a lot of my graphics design work, including custom diagrams and GUIs for displays controlled by ESP32-S3, Arduino, and Raspberry Pi. In Inkscape, set the size of the page to be the resolution of the TFT display, which in this case is 240x320 pixels as specified on the screen's purchase page.

The screens/pages are:

  1. Initial splash/landing screen showing my business logo (this screen wasn't necessary, but I like how it looks so I kept it)
  2. Main screen featuring:
  3. Bars showing the commanded duty cycles to the left and right BLDC motors (from 0%, to 100% for full forward motion, and -100% for full reverse motion)
  4. Top battery drain/voltage level as a fill bar
  5. Settings gear button to navigate to the Settings page
  6. Center readout of the motor speed in miles per hour/mph
  7. Debug messages section in case I want to send messages or data to be shown on the display.
  8. Settings screen featuring:
  9. LED strip lights on/off button
  10. Top speed value readout, editable using 2 x blue arrow buttons
  11. Acceleration value readout, editable using 2 x yellow arrow buttons
  12. Top battery drain/voltage level
  13. Send Values button to send the current max speed and acceleration values to the on-board ESP32-S3 dev module over BLE
  14. Connect button for re-establishing a lost BLE connection with the on-board ESP32-S3 dev module.
  15. Gear icon button to return to the main screen where the joysticks are active and sending their values to the dolly.

The idea is to create your static, unchanging graphics (screens/pages) in your user interface (UI) which will then be overlaid with elements that are programmable/changeable. For example, the speed value readout, battery level, debugging messages, etc aren't static and will change as the furniture dolly is operated. Export the screen/page Inkscape images in PNG format with 320x240 resolution. After that, the PNG files must be converted into C header format so that the Arduino TFT_eSPI library can be used to load them. There are image converters available online to do this conversion, but for my files I usually use the following Python script on my laptop. I specify the folder in which all the PNG files are located, and the script outputs BMP and C header versions of those files:

  1. Batch_Convert_PNG_to_BMP_Clean.py

The script is available at the project Github link here: https://github.com/TheESTest/Motorized_Furniture_Dolly

Phone App

App In Use.jpg
App In Use 2.jpg
iPad Photo.jpg
Phone App Screenshot.png
iPad Screenshot.PNG

As an alternative method for controlling the furniture dolly, I created a rudimentary phone app using Flutter + Dart, which I test on Android phone, but can later be extended to iOS. Cross-compatibility is a great benefit of using a Flutter + Dart framework for app development. I wrote the code using Android Studio, and built a .APK file which can be loaded directly onto an Android phone. I also demonstrate using the

The Github repository for the phone app Flutter project is below:

  1. https://github.com/TheESTest/motorized_furniture_dolly_app

The app features:

  1. Two simulated joysticks that "snap" back to their center position, emulating the tactile feel of the joysticks on the physical hand controller.
  2. Speed display in miles per hour
  3. On-board LED strip lights enable/disable button
  4. Bluetooth devices scanning and selection for connection
  5. Bluetooth connection status

The app works! And, it opens a lot of convenience and possibilities for data logging, different control schemes, pushing updates to the control interface more easily, etc. Compared to the simulated joysticks, I prefer the tactile feel of the physical joysticks on the hand controller. A fun and interesting next step could be to create a PCB with physical joysticks that plugs into the USB-C port on the phone, use the phone screen as the display and for data transmission. This way, the user could get the best of both worlds. Just an idea.

Programming

PlatformIO Code Screenshot 2.jpg
Arduino Code Screenshot.jpg
Motorized Furniture Dolly Code Snippet.jpg
Python Code Screenshot.jpg

For this project, I used the Arduino IDE to program the ESP32-S3 dev module on-board the furniture dolly, and PlatformIO to program the battery-powered hand controller with its custom ESP32-S3 PCB. The Github link for the codes is available here:

  1. https://github.com/TheESTest/Motorized_Furniture_Dolly

Files in that Github repository:

  1. Arduino code running on the ESP32-S3 dev module on the dolly: Motorized_Dolly_Motors_ESP32_6_Clean.ino
  2. PlatformIO project folder which can be opened directly in PlatformIO: Motorized_Furniture_Dolly_ESP32_Controller_Clean.zip
  3. Python code to batch convert PNG images to BMP and C header format so they can be loaded on the display: Batch_Convert_PNG_to_BMP_Clean.py

I created a separate Github repository for the phone app, which can be downloaded onto a Windows or MacOS computer with Android Studio + Flutter installed, to be loaded onto an iOS or Android device:

  1. https://github.com/TheESTest/motorized_furniture_dolly_app

Key libraries used by the codes:

  1. VescUart by SolidGeek (https://github.com/SolidGeek/VescUart)
  2. Used to receive UART data from from the left ESC over UART.
  3. FastLED (https://github.com/FastLED/FastLED)
  4. Used to control the LED strip lights. I originally used the Adafruit Neopixel library, but found an issue with this number of LEDs, so ended up switching to the FastLED library.
  5. TFT_eSPI (https://github.com/Bodmer/TFT_eSPI)
  6. Used for controlling the display on the hand controller.

ESP32-S3 dev module (on-board the dolly) program functions:

  1. Initially powers the on-board LED light strips to be cyan colored.
  2. Waits for a Bluetooth Low Energy (BLE) connection to be established from the hand controller. Upon successful connection, change the LED light strips to be green colored as indication to the user.
  3. When joystick data is received from the hand controller over BLE, update the LED light strip color from green, through yellow and then red depending on the position of the left throttle joystick.
  4. Receive and translate the received left + right joystick values over BLE, and translate them into appropriately-scaled UART commands (left + right motor power levels) that are sent via serial connection to the Flipsky Dual ESC module. You can think of this as sending UART commands to each of 2 x electronic speed controllers (ESCs.)
  5. This on-board ESP32-S3 dev module additionally reads the motor RPM back from the left-side Flipsky ESC, and sends it back over BLE to the hand controller. (The other ESC doesn't have its RPM read, but I would like to add reading both ESC RPM values and then averaging them to a future version of the code.)
  6. If the on-baord ESP32-S3 dev module can also receive on-board LED strips on/off command, as well as commands to set the max speed and acceleration of the dolly.

Custom ESP32-S3 hand controller program functions:

  1. Upon power on, attempt to connect to the furniture dolly ESP32 over BLE. Upon successful connection, enable joystick values to be sent which are used by the on-board ESP32-S3 module to send motor movement commands to the Flipsky ESCs.
  2. Continuously read the 2 x joysticks and send their values to the furniture dolly ESP32 via BLE while on the main screen, and update the 2 x power bars on the left and right sides of the display. Read the voltage of the Li-ion battery and update the fill bar at the top of the screen to indicate the remaining charge level (the battery can be charged via the USB-C port at the top of the hand controller.) If any RPM data is set from the dolly's ESP32-S3 module, update that value on the hand controller screen.
  3. If the user presses the top-left lightbulb icon, send a command to turn the LED strip lights on/off.
  4. If the user presses the top right gear icon, switch to the settings screen. On that screen, the max speed and acceleration of the dolly can be set and sent to the furniture dolly.

The ESCs can be controlled using CANbus or UART. I used UART for this project. I read the RPM data back from the ESC using the VescUart library. To send duty cycle commands to the motors (i.e. to command them to spin), I use the sendDutyCycle() command from my Arduino script. A number of commands can be used to communicate with the ESCs over UART (e.g. COMM_SET_DUTY, COMM_SET_RPM, COMM_SET_POS, etc), but I only sent duty cycle values for this project. A list of available UART commands is available from the following link, as a starting point if you want to customize the code by adding additional control, features, or feedback to and from the Flipsky ESCs to the ESP32-S3 dev module:

  1. https://github.com/LiamBindle/PyVESC/blob/master/pyvesc/VESC/messages/Vedder_BLDC_Commands.py

Optional - EMT-Conduit Mounted Racing Flags

IMG_20250409_153855500.jpg
IMG_20250409_154028975_HDR.jpg
IMG_20250216_152118531.jpg
IMG_20250216_151830685.jpg
IMG_20250216_152336048.jpg

For racing between checkpoints, I also built a simple flag marker. Using EMT conduit (found at most local hardware stores including Home Depot and Lowes) with some telescoping couplings, I built out 2 x types of markers. The first uses an orange triangular flag - I needed to unstitch and then re-sew the stitching so that it would fit over top of the 1/2" EMT conduit at the top of the pole. To do that, I used this seam/stich remover tool, and then re-stitched it using a Brother embroidary machine which I previously used for making patches, because it has a sewing machine mode. The second variant of racing flag uses this checkered flag, which I attached to the top 1/2" EMT conduit section using 2 x flag clips. I staked the flag pole into the ground using this ground stake, but this alternative stake may be a better choice depending on the type of soil.

Demonstration

DSC00314.JPG
DSC00312-1.JPG
IMG_20250409_155509742.jpg
DSC00309.JPG
IMG_20250409_155259648.jpg

I filmed a video with a full design review and testing at the link below! Check it out along with my other YouTube videos!

  1. https://youtu.be/Nf2UnYzyAdI?si=REo3pXitq6xtjjQa

Conclusion and Next Steps

Pull Bar Concept 2.jpg

This project successfully demonstrated using the following to motorize a humble furniture dolly, turning it into a ride-along electric vehicle! The dolly can still act as an un-motorized furntiture-transporting tool, too.

There are some improvements that I'd like to make for the next iteration of this project:

  1. Because Bluetooth Low Energy is running on the ESP32-S3 module on the dolly, this would lend itself well to a simple BLE phone app, e.g. written in Flutter + Dart for Android and iOS.
  2. Improved user safety, including a seat belt, and improved mechanical, electrical, and programming braking fail safes.
  3. Metal mounts for the motors and dual ESC module, which may get hot and warp/melt their plastic mounts, and which would also be more resistant to breakage or snapping off in the event of a crash.
  4. Locking/latching mechanism to keep the foldable seat closed for easier storage.
  5. On/off switch for the battery.
  6. Add dolly battery monitoring.
  7. More customized options for the LED strip lights on the dolly.
  8. Read the RPM from both ESCs and average their values to be reported back to the hand controller.
  9. Use the 3-pin bullet connectors to ensure the motor phase wiring is correct.
  10. Add labels to the cables.
  11. Improvements to the mechanical assembly of the hand controller.
  12. Improvements to the "feel" of the controls, with more responsive turning.
  13. Improvements to the reliability and handling of the BLE connection.

Next, I have an idea for adding an assist feature to the dolly, so that if the user is transporting a particularly heavy item, the motors will sense the load and kick in to help move the dolly along so that the load feels weightless. If you'd like to see that update when I share it, feel free to follow me on social media!

My business offers engineering consultations and design work in the realms of mechanical, electrical, and computer engineering. Feel free to reach out if you'd like to collaborate on a project, or if you you'd like to purchase any of the following:

  1. Assembled motorized dolly
  2. DIY kit of the dolly to build your own version
  3. The hand controller (ESP32-S3 based Bluetooth control)
  4. The single-axis joystick module: https://www.elationsportstechnologies.com/product-page/single-axis-joystick
  5. EMT conduit telescoping coupling: https://www.elationsportstechnologies.com/product-page/cinch-pair-of-couplings

Check out my other Instructables articles:

  1. ESP32 + BaseCam Bluetooth Gimbal Control
  2. Single-Axis Joystick Controller Module Using Arduino
  3. Accuracy-Sensing Smart Sports Rebounder With ESP32
  4. EMT Conduit-Mounted Weather Station Wind Sensors
  5. Telescoping EMT Conduit Pole Extension Sensing Methods + Photoresistor Implementation
  6. Force-Sensing Telescoping EMT Conduit Pole
  7. Jumbo-Sized Telescoping Light Painter Made from EMT (Electrical) Conduit
  8. Homemade/DIY Telescoping Pole From EMT (Electrical) Conduit


Thanks for reading!

Austin Allen

Founder and Owner

Elation Sports Technologies LLC