Great Ball Contraption (GBC) builders know the pain of burnt motors. A single jam can destroy an expensive motor in minutes. This guide shows you how to build a universal safety module that detects jams through sensor fusion and automatically cuts power—saving your motors and your sanity.

Table of Contents

The GBC Jam Problem

What Happens During a Jam

  1. Ball gets stuck in mechanism
  2. Motor stalls (can't rotate)
  3. Motor draws maximum current (stall current)
  4. Current converts to heat in motor windings
  5. Within 1-5 minutes: melted insulation, burnt windings, dead motor

Why It's Expensive

  • LEGO Power Functions XL Motor: ~$15
  • LEGO Technic Large Motor: ~$25
  • Large GBC modules may have 3-5 motors
  • A single event can cause $50-100+ in damage

Why Manual Monitoring Fails

  • GBC events run for hours
  • Builders can't watch every module constantly
  • Jams can happen in seconds
  • By the time you smell burning, it's too late

Jam Detection Strategy: Sensor Fusion

A single sensor isn't reliable enough. We use two sensors together:

Sensor What It Measures Jam Indicator
Hall Effect Shaft rotation (RPM) RPM = 0
INA219 Motor current draw Current > threshold

Detection Algorithm

IF (current > SAFE_LIMIT) AND (rotation_detected == FALSE)
THEN
    JAM_CONFIRMED = TRUE
    CUT_POWER()
    SOUND_ALARM()

Why Both Sensors?

  • Current alone: High current could mean heavy load (not jam)
  • Rotation alone: Motor could be stopped intentionally
  • Both together: High current + no rotation = definite jam

Hardware Components

Bill of Materials

Component Purpose ~Cost
Arduino Nano Main controller $5
INA219 Current Sensor Measure motor current $3
Hall Effect Sensor (A3144) Detect rotation $1
Small magnet Attach to shaft $0.50
Relay Module (5V) Cut motor power $2
Piezo Buzzer Audible alarm $1
LED (Red) Visual alarm $0.10

INA219 Current Sensor

The INA219 is an I2C current/voltage monitor. It measures current by sensing voltage drop across a small shunt resistor.

  • Current Range: ±3.2A (default), configurable to ±400mA for precision
  • Resolution: 0.8mA
  • Interface: I2C (address 0x40 default)

Hall Effect Sensor

The A3144 is a digital Hall effect sensor. It outputs LOW when a magnetic field is detected.

  • Attach a small magnet to the motor shaft or a gear
  • Each rotation triggers one pulse
  • Count pulses over time = RPM

Wiring Diagram


                                ┌─────────────────┐
                                │   Arduino Nano  │
                                │                 │
[Motor Power +] ──┬─────────────┤ VIN             │
                  │             │                 │
               [INA219]         │ A4 (SDA) ◄──────┤──── INA219 SDA
                  │             │ A5 (SCL) ◄──────┤──── INA219 SCL
                  │             │                 │
[Motor Power -] ──┴─────────────┤ GND             │
                                │                 │
                                │ D2 ◄────────────┤──── Hall Sensor OUT
                                │                 │
                                │ D7 ────────────►┤──── Relay IN
                                │                 │
                                │ D8 ────────────►┤──── Buzzer +
                                │                 │
                                │ D9 ────────────►┤──── LED +
                                │                 │
                                └─────────────────┘

[Power Supply +] ───► [INA219 VIN+] ───► [Relay COM] ───► [Motor +]
[Power Supply -] ───► [INA219 VIN-] ─────────────────────► [Motor -]
                                      [Relay NO] ◄─── (Normally Open)

Arduino Code

/*
 * GBC Watchdog Safety System
 * Detects motor jams and cuts power automatically
 */

#include <Wire.h>
#include <Adafruit_INA219.h>

// Pin definitions
#define HALL_PIN 2      // Hall sensor (interrupt capable)
#define RELAY_PIN 7     // Relay control
#define BUZZER_PIN 8    // Piezo buzzer
#define LED_PIN 9       // Status LED

// Thresholds (tune these for your motor)
#define CURRENT_LIMIT_MA 800    // mA - above this indicates stall
#define MIN_RPM 10              // Below this = not rotating
#define CHECK_INTERVAL_MS 500   // How often to check
#define ALARM_DURATION_MS 5000  // How long to sound alarm

Adafruit_INA219 ina219;

// Rotation tracking
volatile unsigned long pulseCount = 0;
unsigned long lastPulseCount = 0;
unsigned long lastCheckTime = 0;

// State
bool motorEnabled = true;
bool jamDetected = false;

void hallPulseISR() {
  pulseCount++;
}

void setup() {
  Serial.begin(115200);
  
  // Initialize pins
  pinMode(HALL_PIN, INPUT_PULLUP);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  
  // Start with motor enabled
  digitalWrite(RELAY_PIN, HIGH);
  digitalWrite(LED_PIN, LOW);
  
  // Initialize current sensor
  if (!ina219.begin()) {
    Serial.println("INA219 not found!");
    while (1);
  }
  
  // Attach interrupt for Hall sensor
  attachInterrupt(digitalPinToInterrupt(HALL_PIN), hallPulseISR, FALLING);
  
  Serial.println("GBC Watchdog Started");
  Serial.println("Monitoring for jams...");
}

void loop() {
  unsigned long now = millis();
  
  // Check every interval
  if (now - lastCheckTime >= CHECK_INTERVAL_MS) {
    lastCheckTime = now;
    
    // Calculate RPM
    unsigned long pulses = pulseCount - lastPulseCount;
    lastPulseCount = pulseCount;
    float rpm = (pulses * 60000.0) / CHECK_INTERVAL_MS;
    
    // Read current
    float current_mA = ina219.getCurrent_mA();
    
    // Debug output
    Serial.print("Current: ");
    Serial.print(current_mA);
    Serial.print(" mA, RPM: ");
    Serial.println(rpm);
    
    // JAM DETECTION
    if (motorEnabled && !jamDetected) {
      if (current_mA > CURRENT_LIMIT_MA && rpm < MIN_RPM) {
        // JAM CONFIRMED!
        jamDetected = true;
        triggerAlarm();
      }
    }
  }
  
  // Handle alarm state
  if (jamDetected) {
    // Blink LED
    digitalWrite(LED_PIN, (millis() / 250) % 2);
  }
}

void triggerAlarm() {
  Serial.println("!!! JAM DETECTED !!!");
  
  // Cut power immediately
  digitalWrite(RELAY_PIN, LOW);
  motorEnabled = false;
  
  // Sound alarm
  for (int i = 0; i < 10; i++) {
    tone(BUZZER_PIN, 2000, 200);
    delay(300);
  }
  
  Serial.println("Motor power cut. Reset to restart.");
}

void resetSystem() {
  // Call this to reset after clearing jam
  jamDetected = false;
  motorEnabled = true;
  digitalWrite(RELAY_PIN, HIGH);
  digitalWrite(LED_PIN, LOW);
  Serial.println("System reset. Monitoring resumed.");
}

Tuning Parameters

Finding Your Current Threshold

  1. Run motor under normal load
  2. Note the current reading (e.g., 300mA)
  3. Briefly stall the motor by hand
  4. Note the stall current (e.g., 1200mA)
  5. Set threshold between them (e.g., 800mA)

Typical Values

Motor Normal Load Stall Current Suggested Threshold
LEGO M Motor 100-200mA 500-700mA 400mA
LEGO L Motor 150-300mA 800-1000mA 600mA
LEGO XL Motor 200-400mA 1000-1400mA 800mA

RPM Threshold

  • Depends on your gear ratio and magnet placement
  • Start with MIN_RPM = 10
  • If false positives during slow operation, lower it
  • If it misses slow jams, raise it

Enhancements

Multiple Motors

// Use multiple INA219 sensors on different I2C addresses
Adafruit_INA219 ina219_motor1(0x40);
Adafruit_INA219 ina219_motor2(0x41);
Adafruit_INA219 ina219_motor3(0x44);

// Change address with solder jumpers on INA219 board

WiFi Notifications (ESP32)

// Send alert to your phone when jam detected
#include <WiFi.h>
#include <HTTPClient.h>

void sendAlert() {
  HTTPClient http;
  http.begin("https://maker.ifttt.com/trigger/gbc_jam/with/key/YOUR_KEY");
  http.POST("");
  http.end();
}

Automatic Reset After Timeout

// Try restarting after 30 seconds (might clear minor jams)
#define AUTO_RESET_MS 30000

if (jamDetected && (millis() - jamTime > AUTO_RESET_MS)) {
  resetSystem();
  // If jam persists, it will trigger again
}

Community Value

This project solves a real, expensive problem for GBC builders. Consider:

  • Sharing your build on GBC community forums
  • Open-sourcing the design on GitHub
  • Creating a modular PCB design others can order
  • Documenting threshold values for common motors

Resources