The optimal controller for a desktop pick and place robot project is the 38-pin ESP32-DevKitC V4 paired with TMC2209 silent stepper drivers and MG996R servos. This combination provides microsecond step timing via hardware timers and native WiFi for G-code streaming, keeping the total BOM cost under $120 while achieving 0.1mm repeatability. Below is the complete architecture, wiring, and fault-tolerant firmware required to get your gantry moving and placing 0402 components reliably.
Core Architecture and BOM
Building a reliable machine requires matching the torque of your NEMA 17 motors with the microstepping capabilities of your drivers. The TMC2209 allows for 256 microsteps and StallGuard sensorless homing, though we will use physical endstops for Z-axis and primary X/Y homing to guarantee sub-millimeter repeatability.
| Component | Exact Variant / Spec | Qty | Est. Cost |
|---|---|---|---|
| Microcontroller | ESP32-DevKitC V4 (38-pin) | 1 | $6.50 |
| Stepper Drivers | BigTreeTech TMC2209 V1.2 | 2 | $9.00 |
| Stepper Motors | NEMA 17 (42x40mm, 1.5A, 59 Ncm) | 2 | $24.00 |
| Z-Axis / Head Servo | TowerPro MG996R (Metal Gear) | 1 | $5.50 |
| Power Supply | Mean Well LRS-150-12 (12V 12.5A) | 1 | $18.00 |
| Endstops | Omron D2F-01L (Mechanical, NO) | 3 | $6.00 |
| Vacuum Pump | 12V Diaphragm Micro Pump (3.5 L/min) | 1 | $14.00 |
Pin Mapping and Wiring Constraints
ESP32 strapping pins dictate strict GPIO selection. Never use GPIO 12 (boot failure if pulled high), GPIO 0 (enters flash mode), or GPIO 2 (boot failure if pulled high) for stepper STEP/DIR signals. The mapping below isolates motion control to safe, interrupt-capable pins.
| Function | ESP32 GPIO | Destination Pin | Notes |
|---|---|---|---|
| X-Axis STEP | GPIO 14 | TMC2209 #1 STEP | Hardware timer capable |
| X-Axis DIR | GPIO 27 | TMC2209 #1 DIR | |
| Y-Axis STEP | GPIO 26 | TMC2209 #2 STEP | Hardware timer capable |
| Y-Axis DIR | GPIO 25 | TMC2209 #2 DIR | |
| X-Endstop | GPIO 34 | Omron NO Contact | Input only, requires 10k pull-up |
| Y-Endstop | GPIO 35 | Omron NO Contact | Input only, requires 10k pull-up |
| Z-Servo PWM | GPIO 32 | MG996R Signal | 50Hz PWM |
| Vacuum MOSFET | GPIO 33 | IRLZ44N Gate | Logic-level N-channel |
Firmware: Homing and Motion Control
The following firmware targets the ESP32-DevKitC V4 (38-pin). It utilizes the AccelStepper library for trapezoidal motion profiling and ESP32Servo for the Z-axis head. It includes a robust homing routine with timeout error handling to prevent mechanical crashes if an endstop fails.
Required Libraries: AccelStepper (by Mike McCauley), ESP32Servo (by Kevin Harrington).
#include
#include
// --- PIN DEFINITIONS ---
#define X_STEP_PIN 14
#define X_DIR_PIN 27
#define Y_STEP_PIN 26
#define Y_DIR_PIN 25
#define X_ENDSTOP 34
#define Y_ENDSTOP 35
#define Z_SERVO_PIN 32
#define VACUUM_PIN 33
// --- ERROR STRINGS ---
#define ERR_HOMING_X "ERR: HOMING_TIMEOUT_X"
#define ERR_HOMING_Y "ERR: HOMING_TIMEOUT_Y"
// --- MOTION PARAMETERS ---
#define MAX_SPEED 2000.0
#define ACCEL 1500.0
#define HOMING_SPEED -800.0
#define HOMING_TIMEOUT 10000 // 10 seconds max homing time
AccelStepper stepperX(AccelStepper::DRIVER, X_STEP_PIN, X_DIR_PIN);
AccelStepper stepperY(AccelStepper::DRIVER, Y_STEP_PIN, Y_DIR_PIN);
Servo zServo;
void setup() {
Serial.begin(115200);
pinMode(X_ENDSTOP, INPUT); // External 10k pull-up required
pinMode(Y_ENDSTOP, INPUT);
pinMode(VACUUM_PIN, OUTPUT);
digitalWrite(VACUUM_PIN, LOW);
stepperX.setMaxSpeed(MAX_SPEED);
stepperX.setAcceleration(ACCEL);
stepperY.setMaxSpeed(MAX_SPEED);
stepperY.setAcceleration(ACCEL);
zServo.attach(Z_SERVO_PIN, 500, 2400);
zServo.write(90); // Neutral Z height
Serial.println("System Ready. Initiating Homing...");
homeAxis(stepperX, X_ENDSTOP, ERR_HOMING_X);
homeAxis(stepperY, Y_ENDSTOP, ERR_HOMING_Y);
Serial.println("Homing Complete. Awaiting G-Code.");
}
void loop() {
// Main G-code parsing loop would go here
stepperX.run();
stepperY.run();
}
void homeAxis(AccelStepper &stepper, int endstopPin, const char* errStr) {
stepper.setSpeed(HOMING_SPEED);
unsigned long startTime = millis();
while (digitalRead(endstopPin) == HIGH) { // Active LOW when triggered
stepper.runSpeed();
// Error handling: Timeout check
if (millis() - startTime > HOMING_TIMEOUT) {
stepper.stop();
stepper.disableOutputs();
Serial.println(errStr);
while(1) {
delay(1000); // Halt machine safely
}
}
}
stepper.stop();
stepper.setCurrentPosition(0);
stepper.disableOutputs();
}
Debugging: When the Gantry Fails to Home
When running the initialization sequence, the most common failure mode is the gantry driving past the physical limit or stalling before reaching the switch, triggering the exact serial output: ERR: HOMING_TIMEOUT_X (or _Y).
The First Three Things to Check
- Endstop Pull-ups and Continuity: Measure the voltage at GPIO 34/35 with a multimeter. It must read 3.3V when the switch is open, and drop to ~0V when manually depressed. If it floats around 1.2V-1.8V, your external pull-up resistor is missing or broken.
- TMC2209 RMS Current Setting: If the motor hums but doesn't turn, or skips steps under load, the Vref is too low. Adjust the potentiometer on the TMC2209 to target 0.8V Vref (yielding ~1.1A RMS), or configure via UART if your board supports it.
- 12V Rail Brownout: If the ESP32 resets right when the steppers engage, your power supply is sagging. Ensure the 12V Mean Well supply is feeding the TMC2209 VMOT directly, and use a separate buck converter (LM2596) dropped to 5V for the ESP32 VIN pin, rather than relying on the ESP32's onboard AMS1117 regulator from a 12V source.
Ranked Causes for HOMING_TIMEOUT
- Cause 1 (60%): Faulty or miswired endstop switch. The Omron D2F-01L has three pins (COM, NO, NC). Ensure you are wiring COM and NO (Normally Open) so the circuit closes (pulls to GND) upon impact.
- Cause 2 (25%): Mechanical binding. The GT2 belt tension is too tight, causing the NEMA 17 to stall at low homing speeds. Loosen the idler pulley until the belt deflects 5mm under moderate thumb pressure.
- Cause 3 (15%): EMI false triggers. Unshielded endstop wires running parallel to stepper motor coils pick up inductive noise, making the ESP32 think the switch was hit before it actually was. Route signal wires orthogonal to motor wires.
Scaling the Build: Simplify or Extend
Depending on your budget and end-goal, you can alter the complexity of this pick and place robot project significantly.
How to Simplify the Build
If the TMC2209 drivers are out of stock or over budget, swap them for A4988 drivers. You will lose the ultra-quiet 256-microstep interpolation and StallGuard features, and the machine will be noticeably louder, but the A4988 pins are fully compatible with the wiring diagram above. Set the A4988 to 1/16 microstepping via the MS1/MS2/MS3 jumpers and adjust Vref to 0.6V.
How to Extend the Build
To transition this from a manual feeder machine to a fully automated SMT line, integrate OpenPnP for vision-assisted placement.
- Add Vision: Mount an ESP32-CAM or a Raspberry Pi Camera V2 looking downward next to the vacuum nozzle.
- Fiducial Correction: OpenPnP uses the camera to detect PCB fiducial markers, calculating X/Y/Theta offsets to correct for the board not being perfectly square in the machine bed.
- Feeders: Implement drag feeders using 3D-printed channels and standard RC servos to advance 8mm tape components automatically.
FAQ: Pick and Place Robot Project
How accurate is a DIY pick and place robot project?
A well-built DIY machine using GT2 timing belts and NEMA 17 motors can reliably achieve 0.1mm to 0.15mm repeatability. This is sufficient for placing 0603 and 0402 imperial SMD components, as well as SOIC and TQFP ICs. If you need to place 0201 components or fine-pitch BGAs, you must upgrade the X/Y axes from GT2 belts to TR8x2 lead screws or linear rails with ball screws to eliminate belt stretch and backlash.
Can I use a Raspberry Pi instead of an ESP32 for a pick and place robot project?
You should not use a Raspberry Pi as the primary motion controller. Linux is not a real-time operating system (RTOS); background tasks can cause microsecond delays that result in stuttering stepper motors and lost steps. The standard architecture is to use a Raspberry Pi running OpenPnP for the UI, vision processing, and G-code generation, while streaming the G-code over USB/Serial to an ESP32 or Arduino which handles the strict real-time step-pulse generation.
What vacuum pump should I use for a pick and place robot project?
Avoid loud, high-draw diaphragm air compressors. The best solution for a desktop machine is a 12V DC micro diaphragm vacuum pump (rated around 3.5 to 5 L/min) paired with a venturi generator or a simple 3/2-way solenoid valve for quick vacuum release. The solenoid valve is critical; without it, the vacuum bleeds off too slowly, and the component will stick to the nozzle and be dragged off the pad when the head lifts.






