DOC 6 — ELEKTRONIKA ROBOTIKA
// DOC 06 / 07

ELEKTRONIKA
ROBOTIKA

Elektronika lengkap untuk robot: perbandingan MCU, motor driver H-Bridge, FOC BLDC, PCB design rules, power supply LiPo BMS, I2C/SPI/UART/CAN bus, ESD/EMC protection, skema referensi robot.

Motor DriverFOC BLDCPCB DesignLiPo BMSCAN Bus
01
MCU

PERBANDINGAN MIKROKONTROLLER

Pemilihan MCU yang tepat sangat kritis. Robot kompleks sering menggunakan arsitektur berlapis: MCU kecil untuk real-time HAL, SBC (Single Board Computer) untuk komputasi tinggi.

MCU/SBCCoreFlash/RAMGPIOInterfaceClockAplikasi Robot
ATmega25608-bit AVR256KB/8KB86UART/SPI/I2C16MHzSensor hub, aktuator low-level
STM32F432-bit Cortex-M41MB/192KB140UART/SPI/I2C/CAN168MHzFOC motor, real-time control
STM32H732-bit Cortex-M72MB/1MB168+ FD-CAN/SDMMC480MHzHigh-perf robot controller
ESP32-S332-bit Xtensa LX716MB/512KB45WiFi/BT/SPI/I2C240MHzWireless, AI edge (NPU)
RP204032-bit Cortex-M0+16MB ext/264KB30PIO/SPI/I2C/UART133MHzCustom protokol, servo PIO
Jetson Orin NX12-core A78+GPU16GB40PCIe/USB3/I2C/SPI2.0GHzAI inference + ROS2
Raspberry Pi 54-core A76RAM 8GB40PCIe/USB3/I2C/SPI2.4GHzROS2, mid-level compute
Arsitektur Berlapis yang Direkomendasikan
Layer 1 — Real-time HAL: STM32F4/H7 atau ATmega2560 → encoder, PWM, sensor polling, watchdog
Layer 2 — Robot Logic: Raspberry Pi 5 atau Jetson → ROS2 nodes, navigation, vision
Layer 3 — AI/Compute: Jetson Orin → LLM inference, deep learning, VLM
Komunikasi antar layer: UART serial bridge atau CAN bus
02
Motor

MOTOR DRIVER & H-BRIDGE

Topologi H-Bridge

H-Bridge: 4 switch (MOSFET) membentuk huruf H IN1=H, IN2=L → Forward IN1=L, IN2=H → Reverse IN1=H, IN2=H → Brake (short circuit) IN1=L, IN2=L → Coast (free spin) PWM speed control: Duty cycle 0-100% pada enable pin f_PWM = 20-25kHz (supersonic, silent) f_PWM > 1/(2π·L/R) untuk continuous current mode
Driver ICMax VMax AInterfaceFiturAplikasi
L298N46V2A (4A peak)IN1/IN2/ENAClassic, banyak tutorialSmall robot <2A
TB6612FNG15V1.2A (3.2A peak)IN1/IN2/PWMCompact, efisien vs L298Micro robot
DRV883310.8V1.5A (2A peak)2-pin controlSleep mode, fault detectSmall wheeled
DRV887437V6ASPI/PWMCurrent sense built-inMedium robot
BTS796027V43A peakIN/PWMIndustrial, heat sinkHeavy robot, 12V
VESC 660V240A peakUART/CAN/USBFOC, odometry, CANBLDC robot drive

L298N — Arduino Wiring & Code

// L298N dual H-bridge dengan PWM speed control
#define IN1 7; #define IN2 8; #define ENA 9;
#define IN3 10; #define IN4 11; #define ENB 6;

void driveMotors(int L, int R) {
  // L, R: -255 to +255
  digitalWrite(IN1, L >= 0); digitalWrite(IN2, L < 0);
  digitalWrite(IN3, R >= 0); digitalWrite(IN4, R < 0);
  analogWrite(ENA, constrain(abs(L), 0, 255));
  analogWrite(ENB, constrain(abs(R), 0, 255));}

void setup() {
  int pins[] = {IN1,IN2,ENA,IN3,IN4,ENB};
  for(auto p : pins) pinMode(p, OUTPUT);
  TCCR1B = (TCCR1B & 0xF8) | 0x01; // Pin 9,10 → 31.37kHz PWM
  TCCR2B = (TCCR2B & 0xF8) | 0x01; // Pin 11,6  → 31.37kHz PWM
}
03
Motor

FOC — FIELD ORIENTED CONTROL

FOC (Field Oriented Control) = kontrol torsi BLDC secara presisi Clarke Transform (abc → αβ): Iα = Ia Iβ = (Ia + 2·Ib) / √3 Park Transform (αβ → dq, rotating frame): Id = Iα·cos(θ) + Iβ·sin(θ) Iq = -Iα·sin(θ) + Iβ·cos(θ) Control: Id_ref = 0 (flux axis, set 0 untuk max efficiency) Iq_ref = τ_desired / (1.5·p·λ) p=pole pairs, λ=flux linkage Inverse Park + SVPWM → gate signals ke inverter
import numpy as np

def clarke(ia, ib, ic):
    alpha = ia
    beta  = (ia + 2*ib) / np.sqrt(3)
    return alpha, beta

def park(alpha, beta, theta):
    d =  alpha*np.cos(theta) + beta*np.sin(theta)
    q = -alpha*np.sin(theta) + beta*np.cos(theta)
    return d, q

def inv_park(d, q, theta):
    alpha = d*np.cos(theta) - q*np.sin(theta)
    beta  = d*np.sin(theta) + q*np.cos(theta)
    return alpha, beta

class FOCController:
    def __init__(self, kp=1.0, ki=100, dt=0.0001):
        self.kp=kp; self.ki=ki; self.dt=dt
        self.id_i=0; self.iq_i=0

    def step(self, ia, ib, ic, theta, iq_ref, id_ref=0):
        alpha, beta = clarke(ia, ib, ic)
        d, q = park(alpha, beta, theta)
        ed = id_ref - d; eq = iq_ref - q
        self.id_i += ed * self.dt; self.iq_i += eq * self.dt
        vd = self.kp*ed + self.ki*self.id_i
        vq = self.kp*eq + self.ki*self.iq_i
        valpha, vbeta = inv_park(vd, vq, theta)
        return vd, vq, valpha, vbeta  # → SVPWM
04
PCB

PCB DESIGN RULES

Aturan PCB untuk Robot

ParameterSignalPower (≤3A)Power (>3A)
Min trace width0.2mm0.8mm2mm+
Min clearance0.2mm1.0mm2.0mm
Via drill0.3mm0.5mm0.8mm
Via annular ring0.15mm0.25mm0.3mm
Min silkscreen0.15mm width
Copper fillGND plane wajibPower planeThermal relief

Trace Width & Current Capacity

IPC-2221 Formula (external layer): Width (mm) = (I / (k × ΔT^0.44))^(1/0.725) / 25.4 k = 0.048 (external), 0.024 (internal) ΔT = temperature rise (°C), typical 10°C Quick reference (ΔT=10°C, external, 1oz copper): 0.3mm → 0.5A 0.5mm → 0.9A 1.0mm → 2.0A 2.0mm → 3.5A 3.0mm → 5.0A 5.0mm → 8.0A
def trace_width_mm(I_A, dT_C=10, layer='ext'):
    """IPC-2221 trace width (1oz copper)"""
    k = 0.048 if layer=='ext' else 0.024
    area_mil2 = (I_A / (k * dT_C**0.44))**(1/0.725)
    width_mm  = (area_mil2 / 1.378) / 25.4  # 1oz=1.378mil/mil²
    return round(width_mm, 2)

print(f"5A → {trace_width_mm(5):.2f}mm")

Decoupling Capacitor Placement

Aturan Decoupling
Setiap IC power pin harus memiliki decoupling cap: 100nF ceramic (0402/0603) sedekat mungkin ke pin VCC (<3mm). Untuk MCU: tambah 10µF elektrolit per power domain. Untuk motor driver: bulk cap 100µF–470µF dekat power input.
05
Power

POWER SUPPLY & BMS

LiPo Battery Management

ParameterLiPo 1SLiPo 3SLiPo 4SLiPo 6S
Nominal V3.7V11.1V14.8V22.2V
Full charge4.2V12.6V16.8V25.2V
Cutoff V3.0V9.0V12.0V18.0V
C-rate 1C (2Ah)2A2A2A2A
Aplikasi RobotServo kecilSmall robotMedium robotHeavy drive

Power Tree Robot Tipikal

# Power distribution architecture:
# LiPo 4S (16.8V max, 14.8V nom)
#     |
#     +---[BMS/fuse 30A]---+
#     |                   |
# [Motor Driver]    [Step-down DC-DC]
# (raw Vbat)         LM2596/XL4016
#                   |           |
#                [12V 3A]     [5V 5A]
#               (servo/fans)   |
#                          [3.3V LDO]
#                         (MCU, sensors)
# Jetson Orin: butuh 9-20V 4A dedicated line (tidak share dgn motor!)

Regulasi Tegangan — Komponen

KomponenVinVoutImaxηKelebihan
LM78057–25V5V fixed1A45%Mudah, linear, noise rendah
AMS1117-3.34.5–12V3.3V0.8A~60%MCU supply, SMD mudah
LM25964–40V1.2–37V adj3A~75%Buck switching, efisien
XL40168–40V1.2–36V adj8A~90%Heavy buck, robot power
MP15844.5–28V0.8–20V3A~92%Compact high-eff buck
TPS543604–60V0.8–58V3.5A~93%Wide-input robot supply
// Arduino: Monitor voltage baterai via ADC (voltage divider)
// 16.8V max → 100k:22k divider → max 3.0V pada ADC pin
#define VBAT_PIN A0
#define R1 100000.0  // 100k
#define R2  22000.0  // 22k
#define VCUTOFF 12.0   // 3S cutoff 12V

float readBattery() {
  int raw = analogRead(VBAT_PIN);
  float vadc = raw * (5.0 / 1023.0);
  return vadc * (R1 + R2) / R2;
}

void checkBattery() {
  float v = readBattery();
  if (v < VCUTOFF) {
    Serial.println("WARNING: Battery low! Shutting down.");
    // Emergency stop motors
  }
  Serial.printf("Vbat: %.2fV (%.0f%%)\n", v, map(v*100,1200,1680,0,100));
}
06
Interface

I2C & SPI

I2C Protocol

I2C: 2 wire (SDA + SCL), multi-master, multi-slave Speed: Standard 100kHz, Fast 400kHz, Fast+ 1MHz, HS 3.4MHz Address: 7-bit (127 devices), 10-bit mode tersedia Pull-up: 4.7kΩ (100kHz), 2.2kΩ (400kHz) ke VCC
// Arduino: Scan I2C bus — temukan semua device
#include <Wire.h>

void i2c_scan() {
  Wire.begin();
  Serial.println("I2C Scan:");
  for (uint8_t addr = 0x01; addr < 0x7F; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0)
      Serial.printf("Found: 0x%02X\n", addr);
  }
}

// MPU6050 IMU via I2C:
#include <MPU6050_tockn.h>
MPU6050 mpu(Wire);

void setup() {
  Wire.begin(); Wire.setClock(400000);
  mpu.begin(); mpu.calcGyroOffsets(true);
}

float getYaw() {
  mpu.update();
  return mpu.getAngleZ(); // degrees
}

SPI Protocol

// Arduino: ICM42688 IMU via SPI (lebih cepat dari I2C)
#include <SPI.h>
#define CS_PIN 10

uint8_t spi_read(uint8_t reg) {
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(reg | 0x80);  // MSB=1 for read
  uint8_t val = SPI.transfer(0x00);
  digitalWrite(CS_PIN, HIGH);
  return val;
}

void spi_write(uint8_t reg, uint8_t val) {
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(reg & 0x7F);  // MSB=0 for write
  SPI.transfer(val);
  digitalWrite(CS_PIN, HIGH);
}
07
Interface

UART & CAN BUS

Multi-node CAN Bus untuk Robot

CAN Bus: differential pair (CANH, CANL), 2-wire Speed: 125kbps, 250kbps, 500kbps, 1Mbps Max nodes: 110 (standard), terminasi 120Ω di kedua ujung CAN FD: hingga 5Mbps data phase CAN ID priority: ID lebih rendah = prioritas lebih tinggi 0x001 = highest priority → gunakan untuk emergency stop
// Arduino Mega + MCP2515: CAN Bus node
#include <mcp2515.h>
MCP2515 can(10);  // CS pin 10

void setup() {
  can.reset();
  can.setBitrate(CAN_500KBPS, MCP_8MHZ);
  can.setNormalMode();
}

// Kirim data sensor via CAN:
void sendSensorData(float dist, float yaw) {
  struct can_frame frame;
  frame.can_id  = 0x101;  // Node ID: sensor
  frame.can_dlc = 8;     // 8 bytes data
  uint16_t d_mm = (uint16_t)(dist * 1000);
  int16_t y_10  = (int16_t)(yaw * 10);
  memcpy(&frame.data[0], &d_mm, 2);
  memcpy(&frame.data[2], &y_10, 2);
  can.sendMessage(&frame);
}

// Terima perintah motor:
void receiveCAN() {
  struct can_frame f;
  if (can.readMessage(&f) == MCP2515::ERROR_OK) {
    if (f.can_id == 0x200) {  // Motor command
      int16_t L, R;
      memcpy(&L, &f.data[0], 2);
      memcpy(&R, &f.data[2], 2);
      driveMotors(L, R);
    }
  }
}
08
Sensor

SENSOR INTERFACING

ADC — Analog Sensor Digitalisasi

// Arduino: Averaging + low-pass filter untuk sensor analog
class AnalogSensor {
  int pin; float val=0; float alpha=0.1;
public:
  AnalogSensor(int p, float a=0.15) : pin(p), alpha(a) {}
  float read() {
    float raw = 0;
    for (int i=0; i<8; i++) raw += analogRead(pin);
    raw /= 8.0;
    val = alpha * raw + (1-alpha) * val;  // EMA filter
    return val;
  }
  float voltage() { return read() * (5.0/1023.0); }
};

// ADS1115 external 16-bit ADC via I2C (jauh lebih akurat):
#include <ADS1X15.h>
ADS1115 ads(0x48);

void setup() {
  Wire.begin(); ads.begin();
  ads.setGain(1);  // ±4.096V range, 0.125mV/bit
}

float readForce() {
  int16_t raw = ads.readADC(0);
  float v = raw * 0.0001250;  // 0.125mV/bit
  return (v - 0.5) / (4.5 - 0.5) * 100;  // FSR 0-100N
}
09
Proteksi

EMC & ESD PROTECTION

EMI Mitigation untuk Robot

ProblemSumberSolusi
Motor noiseDC brush motor, chopper PWMTVS diode + 100nF keramik dekat motor terminal, ferrite bead pada kabel
Ground bounceHigh-current switchingStar grounding, ground plane terpisah antara analog & digital
Radiated EMILong wires, BLDC commutationTwisted pair kabel power, shielded cable untuk sensor analog
Sensor noiseEMI coupling ke ADC lineRC low-pass filter di analog pin (1kΩ + 100nF), pisahkan dari power trace
USB disconnectESD pada USB portESD diode TVS (USBLC6-2SC6), common mode choke
Logic level mismatch3.3V MCU vs 5V sensorVoltage divider R1:R2 atau logic level shifter bidirectional

TVS Diode Clamping Circuit

// Proteksi reverse polarity + overvoltage input:
// VIN+ ---[P-MOSFET gate ke GND]--- VBAT+
// (P-FET mengalir jika Vgs negatif → proteksi reverse polarity)
//
// Komponen proteksi PCB robot:
// - TVS SMAJ15A (15V): proteksi spike pada motor power rail
// - BAT54 Schottky: proteksi back-EMF render diode
// - Ferrite bead BLM21: 600Ω@100MHz pada VCC MCU
// - 100nF + 10µF pada setiap regulasi tegangan output

// Logic level shift 5V→3.3V (voltage divider):
// GPIO_5V ---[1kΩ]---+---[2.2kΩ]--- GND
//                   |
//              GPIO_3V3  (= 5V × 2.2/(1+2.2) = 3.44V max ✓)
// Atau: gunakan BSS138 N-FET bidirectional level shifter

Ground Strategy

Ground Loop Warning
Jangan pernah menghubungkan GND analog dan GND digital/power di beberapa titik. Gunakan single-point star ground di satu titik yang dekat dengan power supply input. Kegagalan ini penyebab paling umum dari ADC noise dan sensor malfunction pada robot.
010
Referensi

SKEMA REFERENSI ROBOT

Skema Blok Robot Wheeled Lengkap

============================================
 POWER DOMAIN        COMPUTE DOMAIN
============================================
 LiPo 3S 5000mAh
   |
   +--[BMS 20A fuse]
   |         |
   |    [Buck XL4016 → 5V 5A]
   |         |           |
   |    [RPi 5 SBC]  [AMS1117 → 3.3V]
   |    (ROS2/Nav)      |
   |         |        [MCU 3.3V sensors]
   |    [USB Serial]
   |         |
   |    [Arduino Mega]  ← encoder ISR, PID, sensor poll
   |         |
   |    [L298N/BTS7960] ← PWM from Arduino
   |         |
   +----[DC Motors] ← back-EMF diode protection
============================================
 SENSOR DOMAIN
============================================
 Arduino ← [I2C] ← MPU6050 (IMU)
         ← [UART] ← RPLiDAR A1
         ← [GPIO] ← HC-SR04 × 5 (sonar)
         ← [ADC]  ← Sharp IR × 2
         ← [INT]  ← Encoder A/B × 2 (quadrature)
 RPi 5   ← [USB]  ← RPLiDAR (raw scan → /scan)
         ← [CSI]  ← Camera V3 (→ /camera/image)
011
Arduino C

ARDUINO SENSOR HUB

// Arduino Mega: Complete sensor hub + ROS serial bridge
// Publishes: distances, IMU, battery, encoder
#include <Wire.h>
#include <NewPing.h>
#include <MPU6050_tockn.h>

#define N_SONAR 5
NewPing sonar[N_SONAR] = {
  NewPing(22,23,200), NewPing(24,25,200), NewPing(26,27,200),
  NewPing(28,29,200), NewPing(30,31,200)
};
MPU6050 mpu(Wire);

volatile long encL=0, encR=0;
void isrL() { encL++; }
void isrR() { encR++; }

void setup() {
  Serial.begin(115200);
  Wire.begin(); Wire.setClock(400000);
  mpu.begin(); mpu.calcGyroOffsets(true);
  attachInterrupt(digitalPinToInterrupt(2), isrL, RISING);
  attachInterrupt(digitalPinToInterrupt(3), isrR, RISING);
  TCCR1B = (TCCR1B & 0xF8) | 0x01;  // 31kHz PWM
}

unsigned long t_pub=0;
void loop() {
  mpu.update();
  if (millis() - t_pub >= 50) {  // 20Hz publish
    t_pub = millis();
    // Sonar
    Serial.print("S:");
    for (int i=0; i<N_SONAR; i++) {
      unsigned int us = sonar[i].ping_median(3);
      float d = (us==0) ? 200 : us/US_ROUNDTRIP_CM;
      Serial.print(d); Serial.print(",");
    }
    // IMU + encoder
    Serial.printf("I:%.2f,%.2f,%.2f,E:%ld,%ld\n",
      mpu.getAngleX(), mpu.getAngleY(), mpu.getAngleZ(),
      encL, encR);
  }
  // Receive motor command from RPi
  if (Serial.available() >= 8) {
    float v, w;
    Serial.readBytes((char*)&v, 4);
    Serial.readBytes((char*)&w, 4);
    int L = (v - w * 0.115) / 0.5 * 255;
    int R = (v + w * 0.115) / 0.5 * 255;
    driveMotors(constrain(L,-255,255), constrain(R,-255,255));
  }
}
ELEKTRONIKA ROBOTIKA — DOC 06 / 07
Antonius - bluedragonsec.com