Design a low-friction rotating gravity slide and kinematic distribution table to route classified candies into 5 sorted collection cups.
This week turns classification decisions from Week 8 into physical movement. A second stepper motor rotates a directional gravity chute to align with 5 destination buckets.
Slide Friction Mechanics: Candy sugar coatings sliding over 3D printed PLA layer lines have a static coefficient of friction μs ≈ 0.40–0.48. To guarantee that a Skittle always slides under gravity without stalling, the slide slope must exceed the critical angle θ where tan(θ) > μs (θ > 25.6°). We engineer our slide at 32° to 35° pitch, providing rapid acceleration and zero mid-chute hangs.
Minimizing Rotational Inertia ($I = m \cdot r^2$): When sorting at speed, the motor must accelerate, travel up to 180°, and decelerate to a dead stop in under 200 milliseconds. Any excess weight at the tip of the slide increases rotational inertia quadratically, causing the stepper to skip steps. The chute is designed with thin 1.6mm ribbed walls and a tapered radial profile (slide_v1.stl).
3D Files/slide_v1.stl, base_for_slide.stl, cup_plate.stlIn Fusion 360 (referencing 3D Files/slide_v1.stl):
The collection cups sit in a semi-circular arc beneath the discharge tip of the slide (cup_plate.stl):
Slice the slide with 4 perimeters and 20% infill. Orient the slide tilted on its spine to maintain smooth internal sliding surfaces. Install the M3 brass insert and clamp the chute to the second stepper motor shaft.
Connect the second stepper to Port M2 on the Adafruit Motor HAT. Wire the sorting limit switch signal to GPIO18 (pin 12) and ground to pin 14.
Map each colour name to its physical step offset from the home switch:
from adafruit_motorkit import MotorKit
from adafruit_motor import stepper
import RPi.GPIO as GPIO
import time
SORT_SWITCH = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(SORT_SWITCH, GPIO.IN, pull_up_down=GPIO.PUD_UP)
kit = MotorKit(0x60)
# Calibrated step offsets from Home (Bucket 1)
BUCKET_STEPS = {
"Red": 0, # Bucket 1 (Home)
"Orange": 18, # Bucket 2 (+32.4°)
"Yellow": 36, # Bucket 3 (+64.8°)
"Green": 54, # Bucket 4 (+97.2°)
"Purple": 72, # Bucket 5 (+129.6°)
"Unknown": 90 # Bucket 6 / Reject bin
}
current_bucket_pos = 0
def go_home_slide():
global current_bucket_pos
print("Homing sorting slide...")
while GPIO.input(SORT_SWITCH) == GPIO.HIGH:
kit.stepper2.onestep(direction=stepper.BACKWARD, style=stepper.SINGLE)
time.sleep(0.008)
for _ in range(8):
kit.stepper2.onestep(direction=stepper.FORWARD, style=stepper.SINGLE)
time.sleep(0.008)
kit.stepper2.release()
current_bucket_pos = 0
print("Slide homed at Bucket 1 (Red).")
def route_candy(color_name):
global current_bucket_pos
target_steps = BUCKET_STEPS.get(color_name, BUCKET_STEPS["Unknown"])
delta = target_steps - current_bucket_pos
direction = stepper.FORWARD if delta > 0 else stepper.BACKWARD
for _ in range(abs(delta)):
kit.stepper2.onestep(direction=direction, style=stepper.SINGLE)
time.sleep(0.006)
current_bucket_pos = target_steps
print(f"Slide routed to {color_name} (position {target_steps} steps).")
kit.stepper2.release()
0.006s to 0.010s.