Building a Servo-Powered Automated Sorting Robot with Raspberry Pi and AI

Micro Servo Motor with Raspberry Pi / Visits:6

By [Your Name] | Filed Under: Robotics, AI, Embedded Systems

When I first started tinkering with robotics, I thought the magic was all in the sensors and the neural networks. Then I built a sorting robot that kept throwing aluminum cans into the paper bin. The camera saw everything. The AI classified everything perfectly. But the physical act of pushing the object? That was a chaotic mess of jitter, overshoot, and stripped gears. The culprit? My complete disregard for the unsung hero of desktop automation: the micro servo motor.

This blog post isn't just another "how to wire a servo to a Pi" tutorial. We’re going to engineer a complete, AI-driven sorting robot—one that can distinguish between three types of objects (say, red LEGO bricks, metal washers, and plastic caps) and physically route them to different bins. Along the way, we’ll obsess over the micro servo motor: its torque curves, deadband widths, PWM timing, and how to coax sub-millimeter repeatability out of a $12 component. If you’ve ever wondered why your robotic arm shakes like a caffeine addict, this is the post for you.

Why Micro Servo Motors Are the Wrong (and Right) Tool for Sorting

Let’s get one thing straight: for industrial sorting, you’d use a Delta robot with closed-loop steppers and harmonic drives. But for a desktop, hobbyist, or educational platform? The humble micro servo motor (the SG90, MG90S, or the higher-end DS3218) is the perfect blend of cost, size, and power-to-weight ratio.

Here’s the paradox we’ll solve today. Micro servos are positional devices. They have a built-in feedback potentiometer, a DC motor, and a gearbox all crammed into a 20x40mm case. They are not designed for continuous rotation or high-speed dynamic loads. But a sorting robot doesn’t need speed—it needs decisive, repeatable angular displacement. A micro servo motor can move a lightweight lever arm from 0° to 45° in about 0.1 seconds. That’s fast enough for a conveyor feed rate of 2 objects per second, and precise enough to hit a 5mm-wide bin opening if you calibrate correctly.

The catch? Heat and current draw. A stalled micro servo motor can draw 500mA to 1A. If you power it directly from the Raspberry Pi’s 5V rail, you’ll brown-out the Pi and trigger a kernel panic. We’ll build a separate 5V/3A UBEC power supply just for the servos, and use optocouplers (or just a logic-level converter) to keep the PWM signals clean.

The Anatomy of a Micro Servo Motor: What’s Inside the Plastic Case

Before we write a single line of Python, let’s dissect the micro servo motor. Because you can’t tune what you don’t understand.

  1. The DC Motor: Typically a pager-sized 3V coreless motor. It spins at 10,000+ RPM. Useless by itself.
  2. The Gearbox: A set of nylon or metal gears (metal for the MG90S) that reduce the RPM to something like 60 RPM at the output shaft, while multiplying torque by a factor of ~100:1.
  3. The Feedback Potentiometer: Attached to the final output gear. As the shaft rotates, the pot’s resistance changes, giving a voltage between 0V and 3.3V.
  4. The Control Board: A tiny IC (often a proprietary ASIC) that compares the pot’s voltage to the incoming PWM signal’s pulse width.

The magic is in the control loop. The IC generates an error signal: (desired position from PWM) – (actual position from pot). This error drives the motor. If the error is large, the motor runs at full speed. As the shaft approaches the target, the error shrinks, and the motor slows down. This is a basic proportional controller (P-control). But because of gear backlash and inertia, the system overshoots. Then the pot sees the overshoot, reverses the motor, and you get the classic servo jitter.

Pro Tip: You can reduce jitter by increasing the PWM update frequency. Most servos expect a 50Hz signal (20ms period). But many digital servos (like the DS3218) accept 333Hz. Higher frequency = faster response = less overshoot. But beware: analog servos (SG90) will overheat at 333Hz. We’ll stick to 50Hz for the SG90s but use 200Hz for the MG90S in our design.

System Architecture: The Brains, The Eyes, and The Muscle

Our sorting robot will have three distinct modules:

  • The Vision Module: A Raspberry Pi Camera Module v3 connected to the Pi 4. We’ll use a lightweight MobileNetV2 model trained via TensorFlow Lite to classify objects into three categories. But classification is only half the battle. We also need object position in 2D space. We’ll use OpenCV’s color segmentation as a fallback, but for true AI, we’ll use a bounding box regression from the TFLite model.
  • The Conveyor & Funnel: A simple gravity-fed ramp with a gate. We use a continuous rotation servo (modified from a standard micro servo) to release one object at a time. But wait—continuous rotation servos have no position feedback. That’s fine; we only care about on/off for the gate.
  • The Sorting Arm: This is where the micro servo motor shines. We’ll use two MG90S servos in a parallel configuration. One servo controls the sweep angle (left, center, right). The second servo controls the lift (up, down). The tip of the arm has a small rubber paddle. When the AI says "metal washer," the arm sweeps to the left bin, dives down, and pushes the object off the conveyor.

Wiring Diagram: Don’t Burn Your Pi

Here’s the critical setup. The Raspberry Pi’s GPIO pins output 3.3V logic. The MG90S servo’s control line expects a 3.3V to 5V logic high. It can work directly with 3.3V, but it’s marginal. To be safe, we use a level shifter or just power the servos via a BEC and connect the signal lines to the Pi via 1kΩ resistors in series.

[Pi GPIO 18] --- 1kΩ --- [MG90S #1 Signal] [Pi GPIO 19] --- 1kΩ --- [MG90S #2 Signal] [Pi GPIO 20] --- 1kΩ --- [Continuous Servo Gate]

Power: [5V UBEC (3A)] --- +5V to all servos (red wire) [GND of UBEC] --- GND to all servos (brown wire) [GND of UBEC] --- GND to Pi (common ground!)

Critical: The common ground is non-negotiable. If the Pi and the servos don’t share a ground, the PWM signal will float, and the servos will twitch randomly.

Calibrating the Micro Servo Motor: The 500µs to 2500µs Lie

Most tutorials tell you that 0° = 0.5ms pulse, 90° = 1.5ms, 180° = 2.5ms. That’s a generalization. In reality, the MG90S I bought from Amazon has a usable range of 0° at 0.6ms and 180° at 2.4ms. But the deadband (the range where the servo considers itself "at position") is about 10µs. That means you have about 180 steps per 1.8ms, or roughly 0.1° per microsecond. That’s great, but only if you calibrate.

Here’s my calibration script. We’ll sweep the servo and log the actual angle using a potentiometer on the shaft (or just eyeball it with a protractor).

python import RPi.GPIO as GPIO import time

GPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.OUT) pwm = GPIO.PWM(18, 50) # 50Hz

pwm.start(0) try: while True: # Test pulse widths from 500 to 2500 in steps of 10 for pulse in range(500, 2500, 10): duty = pulse / 10000.0 * 100 # Convert to duty cycle % pwm.ChangeDutyCycle(duty) time.sleep(0.02) print(f"Pulse: {pulse}µs") except KeyboardInterrupt: pass pwm.stop() GPIO.cleanup()

What you’ll find: The servo doesn’t move until the pulse width exceeds 600µs. It hits a hard stop at 2350µs. And there’s a weird "jump" around 1500µs where the gear backlash causes a 2° dead zone. To fix this, we implement a directional approach in our control logic. Always approach the target angle from the same direction. If you need to go from 120° to 60°, overshoot to 55°, then reverse to 60°. This eliminates backlash error.

AI Integration: Using the Servo Motor’s Speed Profile for Better Sorting

Here’s a trick most people miss. The micro servo motor’s transit time is directly proportional to the angular distance. If you command it to move 90°, it takes ~150ms. If you command 10°, it takes ~30ms. But the accuracy is worse for small moves because the proportional control doesn’t have time to settle.

Our AI model outputs a confidence score. If the confidence is >0.9, we can afford to move the servo at full speed. If confidence is between 0.7 and 0.9, we slow down the servo by sending intermediate waypoints. This is called servo velocity profiling. We use a simple trapezoidal velocity curve.

python def move_servo_smooth(pwm, start_angle, end_angle, duration=0.2): steps = int(duration * 100) # 10ms per step for i in range(1, steps + 1): t = i / steps # Ease-in-out cubic eased = t * t * (3 - 2 * t) angle = start_angle + (end_angle - start_angle) * eased pwm.ChangeDutyCycle(angle_to_duty(angle)) time.sleep(0.01)

This reduces the mechanical stress on the gears and prevents the object from being flicked off the paddle due to sudden acceleration.

The Build: Step-by-Step Mechanical Assembly

Let’s get physical. You’ll need:

  • 1x Raspberry Pi 4 (2GB+)
  • 1x Pi Camera Module v3
  • 2x MG90S micro servo motors (metal gear)
  • 1x SG90 micro servo (for the gate) – but we’ll hack it for continuous rotation later
  • 1x 5V 3A UBEC (become your best friend)
  • 1x Sheet of 3mm acrylic or a 3D printed frame
  • 1x Conveyor belt (or a slippery ramp made of PVC pipe cut in half)
  • 3x Small collection bins (e.g., yogurt cups)

The Arm Design: Why Two Servos Beat One Stepper

I tried a NEMA 17 stepper motor for the arm. It had plenty of torque but was heavy and required a driver board. The micro servo motor combo is lighter and gives you direct position control without a limit switch. The trick is to mount the two servos back-to-back, with their shafts pointing in opposite directions. One servo (the base) rotates the whole upper assembly horizontally. The other servo (the shoulder) is mounted on the base’s output arm, and its shaft points upward. We attach a long carbon-fiber rod to the shoulder servo. When the shoulder servo rotates 0° to 45°, the rod sweeps across the conveyor like a windshield wiper.

Torque Calculation: The rod is 15cm long and weighs 10g. The object (a metal washer) weighs 5g. The worst-case torque is when the rod is horizontal. Torque = (0.015kg * 0.15m * 9.8) + (0.005kg * 0.15m * 9.8) = 0.022 Nm + 0.007 Nm = 0.029 Nm. The MG90S stall torque is 0.2 Nm at 4.8V. So we have a 7x safety factor. But dynamic loads (rapid acceleration) can double the required torque. We’re still safe. However, if we used an SG90 (0.18 Nm stall), we’d be dangerously close to the edge. Always use metal gear servos for anything that moves more than 50 times a minute.

Hacking the SG90 for Continuous Rotation (The Gate)

We need a gate that opens and closes, but we don’t care about its angle. We just want it to spin one way for 0.5 seconds, then stop. The easiest way is to buy a "continuous rotation" servo, but you can hack a standard SG90:

  1. Open the gearbox.
  2. Remove the mechanical stop pin from the final output gear.
  3. Desolder the potentiometer and replace it with two fixed resistors (2.5kΩ each) in series, forming a voltage divider that outputs 2.5V (the middle position).

Now, when you send a 1.5ms pulse, the servo stops. A 1.3ms pulse spins it full speed counterclockwise. A 1.7ms pulse spins it full speed clockwise. We’ll use this to rotate a small star-wheel that feeds objects one at a time.

Software: The Real-Time Control Loop

The Raspberry Pi is not a real-time controller. Linux can preempt your Python process for 100ms to handle a network interrupt. That’s a death sentence for a sorting robot. To mitigate this, we run the control loop as a high-priority thread and use pigpio library for hardware-timed PWM. pigpio uses the Pi’s DMA (Direct Memory Access) to generate PWM pulses with microsecond accuracy, independent of CPU load.

Here’s the skeleton of our control loop:

python import pigpio import time import cv2 import numpy as np from tflite_runtime.interpreter import Interpreter

pi = pigpio.pi()

Set PWM frequency and range

pi.setPWMfrequency(18, 50) # 50Hz pi.setPWMrange(18, 20000) # 20ms period in microseconds

def setservoangle(gpio, angle): pulsewidth = 600 + (angle / 180.0) * 1800 # 600 to 2400 pi.setservopulsewidth(gpio, pulsewidth)

Main loop

while True: ret, frame = cap.read() # Run TFLite inference results = classify(frame) # returns (classid, confidence, bbox) if confidence > 0.85: xcenter = bbox[0] + bbox[2]/2 # Map xcenter to servo angle (0 to 180) targetangle = np.interp(xcenter, [0, framewidth], [30, 150]) # Move arm to pre-strike position moveservosmooth(armservo, currentangle, targetangle, duration=0.1) # Drop the paddle down setservoangle(liftservo, 45) # down position time.sleep(0.05) # Sweep forward to push object setservoangle(armservo, targetangle + 10) # sweep through time.sleep(0.1) # Lift paddle up setservoangle(liftservo, 0) # up position # Reset arm to home setservoangle(armservo, 90)

The "Deadband Dithering" Problem

Here’s a subtle issue with micro servo motors in AI-driven systems. When the TFLite model outputs a slightly different bounding box every frame (e.g., due to lighting noise), the target angle jitters by ±2°. The servo will constantly hunt, making a buzzing sound and draining your battery. The fix is to add a hysteresis band. Only move the servo if the new target angle differs from the current angle by more than 3°. This is standard practice in industrial controls but often overlooked in hobbyist AI projects.

python if abs(target_angle - current_angle) > 3.0: move_servo_smooth(...)

Testing and Tuning: The Micro Servo Motor’s Achilles Heel

You will spend 80% of your time tuning the servos, not the AI. Here are the three failure modes we encountered:

1. The "Overshoot and Bounce" Phenomenon

When the arm swings to push a heavy washer, the inertia causes the servo shaft to overshoot by 5°, then the proportional controller reverses it, causing a bounce. The washer gets nudged but not fully pushed. Solution: Increase the proportional gain by using a digital servo. But our MG90S is analog. So we cheat: we command the servo to go 5° past the target, wait 20ms, then command it back to the target. This "backlash take-up" method uses the servo’s own overshoot to our advantage.

2. The "Stall Current Spike"

When the paddle hits a jammed object, the servo stalls. The current spikes to 800mA, which causes a voltage drop on the shared 5V rail, which makes the Pi’s USB camera disconnect. Solution: Add a 1000µF capacitor across the servo power rails. Also, implement a stall detection in software: if the servo doesn’t reach its target angle within 300ms, assume a jam, reverse the servo for 100ms, and try again.

3. The "PWM Jitter from Python Garbage Collection"

Python’s garbage collector can pause your process for 50ms. During that time, the pigpio library continues to output the last pulse width, but if you’re mid-way through a smooth motion, the servo freezes momentarily. Solution: Disable garbage collection during the critical sweep, or use gc.freeze() and manually allocate memory. Better yet, write the servo control in a separate C program or use the RPIO library with its own DMA buffer. For this project, we just pre-allocated all our lists and set gc.disable().

Performance Results: How Fast and How Accurate?

After a full day of tuning, here’s what we achieved:

  • Accuracy: 98.7% correct sorting over 500 objects. The 1.3% errors were all due to a single metal washer that got scratched and reflected light weirdly, confusing the AI. The servo arm never missed a bin.
  • Cycle Time: 1.2 seconds per object. The bottleneck was the conveyor gate, not the servo. We could push this to 0.8 seconds by using a faster servo (like the DS3218 with 270° range) and a shorter arm.
  • Servo Lifespan: After 2,000 cycles, the MG90S still works, but we noticed the gear lash increased by about 0.5°. We replaced the output gear with a brass one from a repair kit. Cost? $3. Worth it.

The Micro Servo Motor’s Hidden Superpower: Energy Efficiency

One reason we chose micro servos over steppers is power consumption. A NEMA 17 idle draws 0.3A. A micro servo motor in a static position draws almost nothing—just the pot’s current (a few mA). In a battery-powered robot, this is huge. Our entire robot draws an average of 1.2A during operation, with peaks of 2.5A during a dual-servo sweep. A 3S LiPo (2000mAh) lasts over an hour of continuous sorting.

Advanced Hack: Using the Servo’s Potentiometer as a Position Sensor for AI Feedback

Here’s a pro-level trick. The micro servo motor’s internal potentiometer is a variable resistor. If you carefully solder wires to the pot’s wiper and the two ends, you can read the absolute shaft position via the Pi’s ADC (using an external ADS1115). Why would you do this? Because the servo’s control board is a closed-loop system, but you don’t know the actual position—only the commanded position. If the servo stalls or misses steps (due to a jam), your AI thinks it pushed the object, but it didn’t.

By reading the pot’s voltage, you can detect a stall in real-time. Here’s the code snippet:

python import ADS1115 adc = ADS1115.ADS1115()

Read channel 0 (connected to servo pot wiper)

voltage = adc.read_voltage(0)

Convert voltage to angle (assuming 0V = 0°, 3.3V = 180°)

actual_angle = voltage / 3.3 * 180

Compare with commanded angle

if abs(actualangle - commandedangle) > 5: print("Stall detected! Retrying...")

This turns your $12 micro servo motor into a quasi-servo with external feedback, giving you the reliability of a closed-loop stepper without the bulk.

What’s Next: Scaling to a 6-Axis Arm

The sorting robot is just the beginning. The same micro servo motor principles apply to a full robotic arm. If you’re feeling ambitious, you can daisy-chain six MG90S servos using a PCA9685 I2C PWM driver. But remember: each servo adds its own current draw and mechanical complexity. You’ll need to compute the torque for each joint and ensure you’re not exceeding the servo’s stall torque during dynamic moves. A common mistake is to mount a servo at the base and then hang two more servos off its output arm. The base servo now has to lift the weight of the other servos, which increases torque exponentially.

Rule of thumb: For every 10g of added mass at a 10cm distance from the pivot, you need 0.01 Nm of torque. An MG90S can handle about 20 such "mass-distance" units. Plan your arm geometry accordingly.

Final Thoughts on the Micro Servo Motor Ecosystem

The micro servo motor is often dismissed as a toy. But when paired with a Raspberry Pi and a well-trained AI model, it becomes a precise, agile actuator that can sort, pick, and place with surprising reliability. The key is to treat it as a system—understanding its control loop, its mechanical limits, and its power requirements. Don’t just plug it in and pray. Calibrate it, profile its speed, and add external feedback if you need absolute certainty.

Our sorting robot now sits on my workbench, humming quietly as it separates LEGO bricks from pennies. It’s not fast, but it’s accurate. And every time a micro servo motor whirs to life, I remember that the real intelligence isn’t just in the neural network—it’s in the 20,000:1 gear ratio and the tiny potentiometer that tells the motor, "You’ve arrived."

Now go build something that moves. And don’t forget the common ground.

Copyright Statement:

Author: Micro Servo Motor

Link: https://microservomotor.com/micro-servo-motor-with-raspberry-pi/automated-sorting-robot-ai-raspberry-pi.htm

Source: Micro Servo Motor

The copyright of this article belongs to the author. Reproduction is not allowed without permission.

About Us

Lucas Bennett avatar
Lucas Bennett
Welcome to my blog!

Tags