Welcome to the EWNA Team 1 Hackaday project page! We built this project for the Robotics Challenge (sponsored by Quilter) at the Embedded World North America Hackathon, held at the Anaheim Convention Center. Our goal was a robotic arm that uses on-device AI to pick up a marker, trace a hand-drawn line, avoid obstacles in its path and return the marker to where it started, with all the computing on the Arduino UNO Q.
Every part used in this build, including those provided by the hackathon, is listed in the "Components" section, and a full Bill of Materials with estimated prices is available in the "Files" section. The project is designed to be reproducible and beginner-friendly: if you follow the "Instructions" section step by step, you should be able to build one yourself, from assembling the arm and wiring the servos to setting up the Arduino UNO Q and training the detection model. The "Files" section also contains our code and other useful resources.
We've documented our whole journey in the "Logs" section. That includes the hardware hurdles we worked through, how we hand-labelled more than 750 images to train our marker detection model, and the tips we picked up along the way. We hope it helps you learn from both our wins and our roadblocks.
The Problem
Warehouse robots, delivery bots and drones all share one challenge: they have to carry out precise tasks in spaces that are always changing. People walk past, boxes get moved, and new obstacles show up without warning. These robots can't afford to wait on a cloud server for instructions, and a pre-recorded script breaks the moment the world stops matching it. They need to sense what's around them and decide what to do on their own, in real time. Our project is a desk-sized version of that problem, using a small robotic arm, a marker and a sheet of paper.
Why it's different
Everything happens on the robot itself. We split the work between two boards and gave each one the job it's best at. The Arduino UNO Q is the brain: its Linux processor takes on the heavier work of vision and path planning, turning what the camera sees into a sequence of joint positions. The ESP32 controller that comes with the ACEBOTT kit is the muscle: it receives those positions from the UNO Q [over a serial/UART link] and drives the servos smoothly and precisely. Nothing in the run is pre-programmed either. The arm works out every path fresh from what the camera sees at that moment, so it can handle any line and any obstacle it's given.
Bill of Materials
Prices are in USD and don't include shipping, customs or import fees, which vary by location.
The hackathon organisers provided all of the components except the USB-C to USB-C cable, which we brought ourselves.
The ACEBOTT kit is priced as a single item. The individual prices for its parts are rough estimates for reference and aren't added to the total.
Components
1×
ESP32 Max V1.0 Controller Board
Comes as part of the ACEBOTT 4 DOF Robot Arm Kit (Inventor Series QD022)
1×
Acrylic Board Set
Comes as part of the ACEBOTT 4 DOF Robot Arm Kit (Inventor Series QD022)
4×
Servo MG90 9G
Comes as part of the ACEBOTT 4 DOF Robot Arm Kit (Inventor Series QD022)
2×
F-F 5P Dupont Wire
Comes as part of the ACEBOTT 4 DOF Robot Arm Kit (Inventor Series QD022)
2×
Joystick Module
Comes as part of the ACEBOTT 4 DOF Robot Arm Kit (Inventor Series QD022)
Detecting the marker is only half the job: the arm also needs to know exactly where it is on the table. Our script
marker_position.py
handles this step. It loads our trained detection model, watches the live camera feed and converts each detection into a real-world position in millimetres that the arm can reach for. For every frame, it reports the marker's coordinates, the spread (how much the position varies across recent readings, so lower means steadier) and the model's confidence that it's looking at a marker.
In this test, the readings settle quickly. As the detection locks on, the confidence rises and the spread drops from 2.4 mm to just 0.3 mm, so the marker's position holds steady at about (141.5, 87.4) mm. The occasional "no marker" lines are frames where the model wasn't sure enough to report a detection, and the script simply skips them. Once the reading is stable, pressing s saves it as the pickup position. That's the "remembered start location" the arm uses to put the marker back at the end of each run.
Caption: Live output from marker_position.py: as the model locks onto the marker, the confidence climbs from 0.71 to 0.94 and the position settles to within 0.3 mm.
Early this morning, on the second and final day of the hackathon, the organisers brought us the AC power adapter and USB-C hub, and it made a huge difference. The organisers have been helpful and resourceful the whole way through. Whenever we asked for something, they stepped in right away to help us find a solution.
We needed the AC adapter because the 18650 batteries couldn't hold their charge long enough for what our arm needs. Four servo motors moving together draw a lot of power, especially when the arm is lifting, reaching and gripping at the same time. Batteries work well for small tinkering tasks, but a project this demanding needs a steady, reliable supply. With the adapter plugged in, the arm now runs consistently, without the jitter and slowdowns we'd been seeing as the batteries drained.
Getting here took a lot of tinkering and troubleshooting, but that's what building something complex is like. Every small roadblock we cleared felt like a big win, and when the arm finally moved smoothly on steady power, the whole team felt the rush. It's the kind of moment that reminds you why you love building things!
AC Adapter (you need to select the round pin size depending on the ESP32 Port)
A detection model can only be as accurate as the data it learns from, so we labelled our training images ourselves. We hand-labelled more than 750 images, drawing a bounding box around each object in every frame. It took our team about 2–3 hours of careful, repetitive work, but hand-labelling meant every box sat tightly around its object. That precision is what the model needs to learn exactly where the marker is.
The model now detects the marker in real time and gives a confidence score for each detection, showing how sure it is that the object is a marker. It picks out the Crayola marker reliably from both a front and a side angle. It also recognises the robot arm itself, so the system can tell the marker apart from the arm reaching for it. We also compared these results with a marker-only model (the thin "m-only" boxes).
The marker is detected with 0.84 confidence and the arm with 0.51. The marker-only model finds the marker at 0.76.
The marker is detected with 0.83 confidence and the arm with 0.75. The marker-only model finds the marker at 0.75.
Day one came with a few hardware hurdles, most of them about power. The kit's battery holder takes 18650 cells, and the batteries in our box turned out to be a different size, so we couldn't power the arm at first. The organisers tracked down the right 18650s for us within a couple of hours. Chargers for them weren't available at first, though, so once the cells ran flat during testing, the arm had to sit idle. We tried connecting the board to our laptops for power but it was not enough to power all of our servo motors. This was truly a challenge for us!
The organisers have been quick and resourceful throughout. They've sourced replacement parts, checked in with teams regularly, and arranged USB hubs and extra power options to keep everyone moving. So we were relieved and grateful when they let teams take their builds home overnight. The extra time means we can charge the batteries, finish the wiring and keep working on the software, and be ready to test at full power in the morning.
With the arm assembled, our next job was giving it eyes. We set up the Logitech C270 webcam, taped to a cardboard box as a quick mount, and tested it on a laptop to check the view before moving everything onto the Arduino UNO Q. Our test scene was a white surface with our red Crayola marker standing upright and the webcam's own box as a stand-in obstacle.
Our quick camera mount: the C270 webcam taped to a cardboard box to hold it steady while we collect training images.Live feed from the C270 during testing: the red Crayola marker stands upright, with the webcam's box as a stand-in obstacle.
While the space was a little cramped up, we tried to lay out all of our components and assembled everything together while our other team members tried to figure out how to best make use of the Arduino Uno Q's AI capabilities for object detection and subsequent obstacle avoidance.
We meticulously peeled out the protective covering for all the parts of the arm.
Putting all the wires together! Making sure we connect the right colored wires to their designated pins both on the components as well as the ESP32.
We tested the servo motors one by one, as it was mentioned in the documentation, to check each one before assembling it onto the robotic arm structure, we made sure they were initialised at the proper position so that any further steps or any untoward movement wouldn't cause any wear or damage to the motors.
For initial prototyping, we attached the joysticks as well so that we could test how well the robotic arm was able to move around.
These were the wiring we followed for the joysticks accessories.
Before we could teach the arm to see, trace or dodge anything, we had to build it. The ACEBOTT QD022 kit arrives as a bag of laser-cut acrylic panels, four MG90 servos and a lot of small screws and nuts. A big chunk of our first day was spent on turning the components from that kit into a working arm.
What we followed
We used ACEBOTT's official assembly tutorial for the QD022.
It's beginner-friendly with each step showing exactly which panel and which screws to use. If you're building one yourself, we'd recommend following it step by step.
What we learned (tips for beginners)
Set the servos to their centre position before attaching the servo horns. If you skip it, a joint can end up at the edge of its range and won't be able to move fully one way.
Don't overtighten screws into the acrylic since it cracks easily. Tighten until snug, then stop.
Peel off the protective film on the acrylic panels before assembling. It's much harder to remove afterwards.
Check that every joint moves freely before moving on. A joint that's too tight makes the small servos strain, jitter and heat up.
Label the servo cables (base, shoulder, elbow, gripper) as you go. You'll need to know which is which when you wire them up and write code.
Result
By the end of this step we had a fully assembled arm that moved on all four joints when tested with the kit's joystick module.
Follow the instructions in the official video from the kit to assemble the arm
2
Understanding the Robot Arm and its Servos
The ACEBOTT QD022 arm moves with four MG90 servo motors, one at each joint. A servo is a small motor that turns to a precise angle (0°-180°) when it receives a control signal, which is what lets the arm move to exact positions. Together, the four joints let the arm reach, lower, trace and grip.
How to connect and test the servos
Plug each servo cable into its matching pin header on the ESP32 board, following the table above. The brown/black wire goes to GND, red to power, and orange/yellow to the signal pin.
Install the ESP32Servo library in the Arduino IDE (Library Manager → search "ESP32Servo").
3
Wiring and Pin Connections
It is important to note which pins to connect the wires coming out of the servos to.
Below is the ESP32 Max V1.0, the controller board that comes with the ACEBOTT kit and drives our arm's servos. The rows of pin headers along the top edge are where the servos plug in. Each column has a signal pin (blue), a 5V pin (red) and a GND pin (black), with its GPIO number printed above. The board can be powered through its USB-C port (5V) or the DC jack (7–15V), and the serial pins on the right (TX/RX) are how it can talk to other boards like the Arduino UNO Q.
Each servo has three wires: brown goes to GND, red to 5V, and orange to the signal pin. This example shows the chassis (base) servo plugged into GPIO5. Connect the other servos the same way: shoulder to GPIO16, elbow to GPIO17 and claw to GPIO18. Make sure the brown wire always faces the black GND row, because a servo plugged in backwards won't move.
This diagram shows all four MG90S servos connected to the ESP32 Max board at once. Each servo plugs into its own three-pin header in the first four columns of the top row (H1–H4), which match GPIO5, GPIO16, GPIO17 and GPIO18: the chassis, shoulder, elbow and claw. Every header supplies power (5V) and ground (GND) alongside the signal pin, so each servo needs just one plug and no extra wiring. Once all four are connected, the ESP32 can control every joint of the arm on its own, taking movement commands from the Arduino UNO Q.