// MECHATRONIC ARCHITECTURE & PINOUT TOPOLOGY

HARDWARE & WIRING SPECIFICATION

Complete electrical ratings, pin-level signal mapping, interactive wiring fault validator, and unified Common Ground bus topology for the KinetiX mobile pick-and-place platform.

INSPECT IN 3D X-RAY →
SUBSYSTEM SELECTOR [01–06]MECHATRONIC BOM
DATASHEET // Arduino UNO R3 (ATmega328P)16 MHz · 5V GPIO
[MOD_01] CONTROLLER // BRAIN

Arduino UNO R3 (ATmega328P)

Executes the 5-state control loop at 16 MHz: triggers the HC-SR04, times the Echo pulse via pulseIn(), computes distance d = t / 58, drives L298N direction/PWM pins, and generates the 50 Hz servo control signal.

[ENGINEERING CONSTRAINT]:Each ATmega328P GPIO pin sources at most ~20 mA safe continuous current at 5 V — far below the 100–500 mA required by DC gearmotors, necessitating the L298N power stage.
ELECTRICAL & MECHANICAL PARAMETERS
MCU Architecture
8-bit AVR ATmega328P
Clock Frequency
16 MHz Ceramic Resonator
Logic / Input Voltage
5 V Logic (7–12 V Vin)
Digital I/O Pins
14 Pins (6 Hardware PWM ~)
Analog Inputs
6 Channels (10-bit ADC)
Memory
32 KB Flash · 2 KB SRAM
Max GPIO Current
~20 mA per pin
ACTIVE SIGNAL & POWER TERMINALS
▸D10 (OUTPUT) → HC-SR04 Trig (10 µs pulse)
▸D11 (INPUT) → HC-SR04 Echo (Time-of-Flight)
▸D5 (PWM ~) → L298N ENA (Left Motor Speed)
▸D7 / D8 → L298N IN1 / IN2 (Left Dir)
▸D6 (PWM ~) → L298N ENB (Right Motor Speed)
▸D4 / D2 → L298N IN3 / IN4 (Right Dir)
▸D9 (PWM ~) → SG90 Servo Signal (50 Hz)
COMMON GROUND REFERENCE: MANDATORY (0V BUS)VIEW IN 3D EXPLODED MODE →
INTERACTIVE WIRING SCHEMATIC & FAULT SIMULATOR● PASS // BUS HEALTHY
INJECT ELECTRICAL FAULT CONDITION:
[NOMINAL // REFERENCE TOPOLOGY]:ALL WIRES NOMINAL

All modules share a unified 0V Common Ground reference. L298N receives 7.4V from the 2x18650 pack (delivering ~5.4V to motors after the 2V BJT drop), while Arduino GPIO pins source <5mA logic signals.

Vin = 7.4V | V_logic = 5.0V | I_gpio = 4.2mA (<20mA limit)
← SWIPE SCHEMATIC HORIZONTALLY TO VIEW ALL PINS →
UNIFIED COMMON GROUND BUS (0V REFERENCE) — Battery (–) · Arduino GND · L298N GND · HC-SR04 GND · SG90 BrownHC-SR04 SONAR40 kHz · 15° Cone · 2–400cmVCC → Arduino 5VTrig → Pin D10 (10µs)Echo → Pin D11 (t µs)GND → Common GNDSG90 SERVO GRIPPEROrange (Sig) → Pin D9~Red (+VCC) → 5V RailBrown (GND) → Common GNDARDUINO UNO R3ATmega328P · 16 MHz · 5V LogicD10 (OUT) : Sonar TrigD11 (IN) : Sonar EchoD9 (PWM) : Servo 50HzD5 (PWM) : L298N ENAD7 / D8 : L298N IN1/IN2D6 (PWM) : L298N ENBD4 / D2 : L298N IN3/IN4L298N DUAL H-BRIDGEENA(D5) IN1(D7) IN2(D8)ENB(D6) IN3(D4) IN4(D2)OUT1/OUT2 → Left MotorsOUT3/OUT4 → Right Motors12V In · 5V Reg Out · GND1:48 MOTORS + 7.4V PACK4x Geared DC Motors (65mm)2x18650 Li-Ion → L298N 12V
PRODUCTION FIRMWARE // KinetiX_Autonomous_Pick_Place.ino
// ============================================================================
// KINETIX // AUTONOMOUS ULTRASONIC PICK-AND-PLACE ROBOT FIRMWARE
// Hardware: Arduino UNO (ATmega328P) + HC-SR04 + L298N H-Bridge + SG90 Servo
// ============================================================================

#include <Servo.h>

// --- Hardware Pin Definitions ---
const int TRIG_PIN  = 10;  // HC-SR04 Trigger Input (10 us HIGH pulse)
const int ECHO_PIN  = 11;  // HC-SR04 Echo Output (Time-of-Flight pulse)

const int ENA_PIN   = 5;   // Left Motor Channel Speed (PWM 0-255)
const int IN1_PIN   = 7;   // Left H-Bridge Direction Input 1
const int IN2_PIN   = 8;   // Left H-Bridge Direction Input 2

const int ENB_PIN   = 6;   // Right Motor Channel Speed (PWM 0-255)
const int IN3_PIN   = 4;   // Right H-Bridge Direction Input 3
const int IN4_PIN   = 2;   // Right H-Bridge Direction Input 4

const int SERVO_PIN = 9;   // SG90 Gripper Servo PWM Signal (50 Hz / 20 ms)

// --- Tunable Control Thresholds ---
const int GRIP_OPEN_DEG     = 90;  // 1.50 ms pulse -> Jaws open wide
const int GRIP_CLOSED_DEG   = 30;  // 1.17 ms pulse -> Jaws clamp cylinder
const float PICK_DIST_CM    = 5.0; // Stop & grip distance threshold
const float AVOID_DIST_CM   = 20.0;// Obstacle avoidance distance threshold

const int CRUISE_PWM        = 170; // Normal forward duty cycle (0-255)
const int CREEP_PWM         = 115; // Slow precision approach duty cycle
const int SPIN_PWM          = 190; // Differential turn duty cycle

enum RobotState { SEARCH, PICK, CARRY, PLACE, DONE };
RobotState state = SEARCH;
Servo gripper;

unsigned long carryElapsedMs = 0;
unsigned long prevLoopMs     = 0;
const unsigned long TARGET_REACH_MS = 8000;

void setup() {
  Serial.begin(9600);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);

  pinMode(ENA_PIN, OUTPUT); pinMode(IN1_PIN, OUTPUT); pinMode(IN2_PIN, OUTPUT);
  pinMode(ENB_PIN, OUTPUT); pinMode(IN3_PIN, OUTPUT); pinMode(IN4_PIN, OUTPUT);

  gripper.attach(SERVO_PIN);
  gripper.write(GRIP_OPEN_DEG);
  stopMotors();
  delay(1000);
  prevLoopMs = millis();
}

float readDistanceCm() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  long durationUs = pulseIn(ECHO_PIN, HIGH, 30000);
  if (durationUs == 0) return 400.0;
  return (float)durationUs / 58.0; // Time-of-Flight: d = (t * 0.0343) / 2 = t / 58
}

void forward(int pwm) {
  digitalWrite(IN1_PIN, HIGH); digitalWrite(IN2_PIN, LOW); analogWrite(ENA_PIN, pwm);
  digitalWrite(IN3_PIN, HIGH); digitalWrite(IN4_PIN, LOW); analogWrite(ENB_PIN, pwm);
}

void spinRight(int pwm) {
  digitalWrite(IN1_PIN, HIGH); digitalWrite(IN2_PIN, LOW); analogWrite(ENA_PIN, pwm);
  digitalWrite(IN3_PIN, LOW);  digitalWrite(IN4_PIN, HIGH); analogWrite(ENB_PIN, pwm);
}

void reverseSlow(int pwm) {
  digitalWrite(IN1_PIN, LOW);  digitalWrite(IN2_PIN, HIGH); analogWrite(ENA_PIN, pwm);
  digitalWrite(IN3_PIN, LOW);  digitalWrite(IN4_PIN, HIGH); analogWrite(ENB_PIN, pwm);
}

void stopMotors() {
  digitalWrite(IN1_PIN, LOW); digitalWrite(IN2_PIN, LOW); analogWrite(ENA_PIN, 0);
  digitalWrite(IN3_PIN, LOW); digitalWrite(IN4_PIN, LOW); analogWrite(ENB_PIN, 0);
}

bool atTarget() {
  return carryElapsedMs >= TARGET_REACH_MS;
}

void loop() {
  unsigned long now = millis();
  unsigned long dt = now - prevLoopMs;
  prevLoopMs = now;

  float d = readDistanceCm();

  if (state == SEARCH) {
    if (d > PICK_DIST_CM) {
      forward(d < 22.0 ? CREEP_PWM : CRUISE_PWM);
    } else {
      stopMotors();
      state = PICK;
    }
  } else if (state == PICK) {
    gripper.write(GRIP_CLOSED_DEG);
    delay(1000);
    state = CARRY;
    carryElapsedMs = 0;
  } else if (state == CARRY) {
    if (d <= AVOID_DIST_CM) {
      stopMotors();
      delay(200);
      spinRight(SPIN_PWM);
      delay(450);
      stopMotors();
    } else if (!atTarget()) {
      forward(CRUISE_PWM);
      carryElapsedMs += dt;
    } else {
      stopMotors();
      state = PLACE;
    }
  } else if (state == PLACE) {
    gripper.write(GRIP_OPEN_DEG);
    delay(800);
    reverseSlow(CREEP_PWM);
    delay(450);
    stopMotors();
    state = DONE;
  } else {
    stopMotors();
  }
  delay(40);
}