-
1The Idea
The plan of execution for this project can be divided into two main categories:
- Electronics – How do we communicate with the drone to trigger the drop?
- 3D Design and Printing – What components can be used to facilitate the drop mechanism?
Now, to build the delivery drone, we need to follow a couple of steps, but the key question is what those steps actually are... But with all problem solving, we just need to ask ourselves a couple of questions that will guide us in the quest to turn our drone into a delivery drone⚡️.
Electronics
You: "How will the drone know when to drop the package?" 🤔💭
Me: "We’ll need to tell it when!☝️🤓"
You: "🧍♂️ Obviously, dude. But how do we actually do that?"
Me: "Okay, so most standard drone controllers have extra buttons that aren’t used during flight—they're just lying around, doing nothing right?💡"
You: "Yeah..."
Me: "Why not assign one of those buttons to trigger the package drop?"
You: "Hmm, that's kinda smart! But how do we actually do that? 🫡"
Me: (chuckling) "Alright, here’s the gist. The transmitter sends a signal to the receiver about the state of every channel, basically all the switches and buttons on the controller. The receiver then passes this signal to the flight controller, right?"
You: "Mm-hmm 🧐"
Me: "What if we tap into that signal and decode it? By using a powerful microcontroller, like an ESP32, we can read all the transmitter’s channel values. Then, we assign one of the unused channels to trigger the drop. When that button is pressed, the ESP32 sends the command to release the package."
You: "Bingo! I think we’re onto something!"
3D Design and Printing
You: "Okay, but what mechanism should we use to actually drop the package? 🤨"
Me: "🫡 Good question. We could use a simple string to hold the package, but then we’d have to deal with it swinging mid-air... not ideal."
You: "Yeah, it’s like we’d need a way to 'stick' the package to the drone until the moment it needs to drop."
Me: "Exactly. We’ll need a more stable design. I’ve got a few ideas… 🧙♂️🪄" (stares dramatically into the distance)
Let's continue🏃♂️💨
-
2Setting Up The ESP32
The ESP32 "listens in" on the communication between the receiver and the flight controller (FC) to extract the transmitter's channel values. By decoding the CRSF protocol used by the ELRS receiver, it translates this data into raw channel values. After several late nights of tinkering, I successfully implemented the decoding process.
Here’s how it works: The receiver sends data packets to the FC using its TX port. These packets include the transmitter's channel values. Once the ESP32 receives a packet, it gains access to the same data as the FC. Using this information, the ESP32 can be programmed to activate a motor and release the package when a specific, unused channel is triggered by a button press.
For more technical explanation and more code refer to my GitHub, it has the entire process explained in a lot more detail✨
Note: In the code below, the designated channel for triggering the package drop is channel 7, as on my controller, it was an auxiliary button that was latent. If you want to use a different channel value, modify it in the code.
// Code for the ESP32 Firebeetle #include <HardwareSerial.h> #include <ESP32Servo.h> #define speed_stop 90 // Stop position #define CRSF_SERIAL_PORT Serial2 // Using Serial2 on the ESP32 #define CRSF_BAUD_RATE 420000 // CRSF baud rate (400,000 bps) #define RX_PIN 17 // Receiver TX connected to ESP32 RX (GPIO17) #define CRSF_MAX_PACKET_SIZE 64 #define CRSF_FRAMETYPE_RC_CHANNELS_PACKED 0x16 Servo mymotor; // Servo motor object uint16_t rcChannels[16]; // Channel data // Servo control debouncing variables const int STABLE_THRESHOLD = 5; // Required consecutive stable readings int stableCount = 0; // Counter to track stable readings bool motorActive = false; // State of the motor void processCRSFPacket(uint8_t *packet, uint8_t length) { uint8_t packetType = packet[2]; if (packetType == CRSF_FRAMETYPE_RC_CHANNELS_PACKED) { // Extract 11-bit channel data rcChannels[0] = ((packet[3] | packet[4] << 8) & 0x07FF); rcChannels[1] = ((packet[4] >> 3 | packet[5] << 5) & 0x07FF); rcChannels[2] = ((packet[5] >> 6 | packet[6] << 2 | packet[7] << 10) & 0x07FF); rcChannels[3] = ((packet[7] >> 1 | packet[8] << 7) & 0x07FF); rcChannels[4] = ((packet[8] >> 4 | packet[9] << 4) & 0x07FF); rcChannels[5] = ((packet[9] >> 7 | packet[10] << 1 | packet[11] << 9) & 0x07FF); rcChannels[6] = ((packet[11] >> 2 | packet[12] << 6) & 0x07FF); rcChannels[7] = ((packet[12] >> 5 | packet[13] << 3) & 0x07FF); // Uncomment to print channel values for debugging // Serial.print("Channels: "); // for (int i = 0; i < 16; i++) { // Serial.printf("%2d: %4d ", i, rcChannels[i]); // } // Serial.println(); // Debounce logic for channel 7 (Anticlockwise only) if (rcChannels[7] >= 1000) { if (!motorActive) { stableCount++; if (stableCount >= STABLE_THRESHOLD) { mymotor.write(60); // Rotate motor anticlockwise (position 0) motorActive = true; stableCount = 0; // Reset counter } } } else { if (motorActive) { stableCount++; if (stableCount >= STABLE_THRESHOLD) { mymotor.write(90); // Stop motor motorActive = false; stableCount = 0; // Reset counter } } } } } void setup() { Serial.begin(115200); // Initialize serial communication CRSF_SERIAL_PORT.begin(CRSF_BAUD_RATE, SERIAL_8N1, RX_PIN); mymotor.attach(12); // Attach servo to GPIO12 Serial.println("CRSF Receiver Initialized."); } void loop() { static uint8_t packet[CRSF_MAX_PACKET_SIZE]; static uint8_t packetIndex = 0; while (CRSF_SERIAL_PORT.available()) { uint8_t incomingByte = CRSF_SERIAL_PORT.read(); if (packetIndex == 0 && incomingByte != 0xEE && incomingByte != 0xC8) { continue; // Skip invalid bytes } packet[packetIndex++] = incomingByte; if (packetIndex >= 2 && packetIndex == packet[1] + 2) { processCRSFPacket(packet, packetIndex); packetIndex = 0; // Reset for next packet } if (packetIndex >= CRSF_MAX_PACKET_SIZE) { packetIndex = 0; // Prevent buffer overflow } } }
-
3Designing the Drop Mechanism With AI
Now, let’s dive into the design of the package-dropping components 📦.
Now stick with me here, because this is where things get exciting 🧐. Designing these components turned out to be both a fun and challenging process, requiring multiple iterations to get just right. The main goal was to create a design that’s easy to assemble, compatible with a wide range of drones, and both robust and practical.
(a few early sketches ✍️)
After finalizing a design robust enough to handle multiple drops, we can now take things to the next level by leveraging, wait for it…
✨AI✨
With the help of AI, we can minimize the material required to produce the parts and optimize flight performance by reducing the component weight to an absolute minimum.
Using Fusion 360’s generative design feature 🤖, we can tackle the weight optimization challenge efficiently.
After considering all factors, I developed the final drop mechanism, which consists of two parts:
- Droke: The component that attaches to the drone.
- Flatch: The part that drops along with the package.
The Droke
The Flatch
-
4Optimising Using Generative AI
Now, I wouldn’t be surprised 😱 if you’re wondering how generative AI can create such "organic" 🌱 looking components, or even how to use it in the first place to optimize a design. While a crash course in generative design is beyond the scope of this project, skipping over the optimization process entirely wouldn’t do it justice 😔.
Below are some diagrams outlining the process:
Original: These are the initial, clunky designs that used significantly more material than necessary while still maintaining the structural integrity of the drone.
GD Study: This marks the beginning of the optimization process. Here, you define three main geometries (or bodies):
- Preserve: The regions that must remain unchanged.
- Obstacle: Areas the AI must avoid.
- Starting Shape: The initial structure that the AI will refine.
Additionally, you specify the forces the optimized structure must withstand to ensure it remains structurally sound.
Final: This is the best design the AI generated after evaluating thousands of variations. It satisfies the criteria while minimizing the material required to produce the component.
The Droke
The Flatch
-
5The Final Design
After all the prototyping and iterations, this is the final design that performed the best ✨.
For all the parts you can find them ---> here (Step 5)
-
6Let's Print
Fire up your 3D printer and get ready to print 🔥🖨️.
Pro Tip 🤫: If you're using a 3D slicer software (like Cura, which I used for this project), enable a setting called "adaptive layer height." This will minimise layer steps on the final print, resulting in a smoother finish.
Once the components are printed, you'll need to remove the supports. If they are too hard to remove by hand, you can use a crafting knife, and a small screwdriver for the supports stuck in tight places. Be patient and careful during this process!
After prototyping and making sure that the models actually worked, I got the part resin printed in a cool transparent colour scheme, UTR-8100 (Transparent) off of Justway, the build quality came out escellent so feel free to check them out.
To get the exact parts that have the cool transparent look it was a simple process:
- Head over to their website
- Add each of the STL files for the Droke, Latch, and Flatch and use this setup ⬇️:
The final parts looked really futuristic and cool, which I liked, a lot🤖. -
7Wiring the Electronics
Now that we understand how the drone operates, let’s dive into the exciting part—building it! Here’s the wiring diagram for the electronics 💡.
Disclaimer: Wiring diagrams for flight controllers (FCs) vary depending on the model. In the diagram below, I’ve highlighted the relevant pads specific to my FC. If you’re using a different FC, you can find its wiring diagram on the manufacturer’s website. The same pads should be present, though their locations may differ.
After establishing the connections between the ESP32 and the Buck Converter, you should get something similar to this:
-
8Stacking the Components
Before we start mounting the electronics onto the drone, here’s a key piece of advice: use more electrical tape than you think you’ll need. If your drone frame is made of carbon fiber, proper insulation is crucial. Carbon fiber is conductive, and uninsulated connections can cause short circuits—or worse, damage your components beyond repair.
Now, let’s get back to building 👷♂️. The next step depends on the space available on your drone. Many FPV drone frames have a relatively open section at the back, typically reserved for the receiver and the XT60 connector (battery plug).
First: Insulate the frame thoroughly using electrical tape, and then position the Buck Converter on the frame.
Next, secure the Buck Converter to the drone frame using electrical tape
Next, attach the receiver securely to the Buck Converter and the drone frame
-
9Component Placement
After soldering the wires to the flight controller according to the wiring diagram, your setup should resemble the image below.
Next when you flip the drone over, you can position the ESP32 in the same orientation as below, ready for the Droke to be attached.
-
10Connecting Motor and Latch to Droke
Now connect the motor and the latch together in the following orientation:
The connection to the Droke should be a simple process as below ⬇️
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.