// 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.
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/SBC | Core | Flash/RAM | GPIO | Interface | Clock | Aplikasi Robot |
|---|---|---|---|---|---|---|
| ATmega2560 | 8-bit AVR | 256KB/8KB | 86 | UART/SPI/I2C | 16MHz | Sensor hub, aktuator low-level |
| STM32F4 | 32-bit Cortex-M4 | 1MB/192KB | 140 | UART/SPI/I2C/CAN | 168MHz | FOC motor, real-time control |
| STM32H7 | 32-bit Cortex-M7 | 2MB/1MB | 168 | + FD-CAN/SDMMC | 480MHz | High-perf robot controller |
| ESP32-S3 | 32-bit Xtensa LX7 | 16MB/512KB | 45 | WiFi/BT/SPI/I2C | 240MHz | Wireless, AI edge (NPU) |
| RP2040 | 32-bit Cortex-M0+ | 16MB ext/264KB | 30 | PIO/SPI/I2C/UART | 133MHz | Custom protokol, servo PIO |
| Jetson Orin NX | 12-core A78+GPU | 16GB | 40 | PCIe/USB3/I2C/SPI | 2.0GHz | AI inference + ROS2 |
| Raspberry Pi 5 | 4-core A76 | RAM 8GB | 40 | PCIe/USB3/I2C/SPI | 2.4GHz | ROS2, mid-level compute |
Arsitektur Berlapis yang Direkomendasikan
Layer 1 — Real-time HAL: STM32F4/H7 atau ATmega2560 → encoder, PWM, sensor polling, watchdogLayer 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 IC | Max V | Max A | Interface | Fitur | Aplikasi |
|---|---|---|---|---|---|
| L298N | 46V | 2A (4A peak) | IN1/IN2/ENA | Classic, banyak tutorial | Small robot <2A |
| TB6612FNG | 15V | 1.2A (3.2A peak) | IN1/IN2/PWM | Compact, efisien vs L298 | Micro robot |
| DRV8833 | 10.8V | 1.5A (2A peak) | 2-pin control | Sleep mode, fault detect | Small wheeled |
| DRV8874 | 37V | 6A | SPI/PWM | Current sense built-in | Medium robot |
| BTS7960 | 27V | 43A peak | IN/PWM | Industrial, heat sink | Heavy robot, 12V |
| VESC 6 | 60V | 240A peak | UART/CAN/USB | FOC, odometry, CAN | BLDC 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
| Parameter | Signal | Power (≤3A) | Power (>3A) |
|---|---|---|---|
| Min trace width | 0.2mm | 0.8mm | 2mm+ |
| Min clearance | 0.2mm | 1.0mm | 2.0mm |
| Via drill | 0.3mm | 0.5mm | 0.8mm |
| Via annular ring | 0.15mm | 0.25mm | 0.3mm |
| Min silkscreen | 0.15mm width | — | — |
| Copper fill | GND plane wajib | Power plane | Thermal 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
| Parameter | LiPo 1S | LiPo 3S | LiPo 4S | LiPo 6S |
|---|---|---|---|---|
| Nominal V | 3.7V | 11.1V | 14.8V | 22.2V |
| Full charge | 4.2V | 12.6V | 16.8V | 25.2V |
| Cutoff V | 3.0V | 9.0V | 12.0V | 18.0V |
| C-rate 1C (2Ah) | 2A | 2A | 2A | 2A |
| Aplikasi Robot | Servo kecil | Small robot | Medium robot | Heavy 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
| Komponen | Vin | Vout | Imax | η | Kelebihan |
|---|---|---|---|---|---|
| LM7805 | 7–25V | 5V fixed | 1A | 45% | Mudah, linear, noise rendah |
| AMS1117-3.3 | 4.5–12V | 3.3V | 0.8A | ~60% | MCU supply, SMD mudah |
| LM2596 | 4–40V | 1.2–37V adj | 3A | ~75% | Buck switching, efisien |
| XL4016 | 8–40V | 1.2–36V adj | 8A | ~90% | Heavy buck, robot power |
| MP1584 | 4.5–28V | 0.8–20V | 3A | ~92% | Compact high-eff buck |
| TPS54360 | 4–60V | 0.8–58V | 3.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
| Problem | Sumber | Solusi |
|---|---|---|
| Motor noise | DC brush motor, chopper PWM | TVS diode + 100nF keramik dekat motor terminal, ferrite bead pada kabel |
| Ground bounce | High-current switching | Star grounding, ground plane terpisah antara analog & digital |
| Radiated EMI | Long wires, BLDC commutation | Twisted pair kabel power, shielded cable untuk sensor analog |
| Sensor noise | EMI coupling ke ADC line | RC low-pass filter di analog pin (1kΩ + 100nF), pisahkan dari power trace |
| USB disconnect | ESD pada USB port | ESD diode TVS (USBLC6-2SC6), common mode choke |
| Logic level mismatch | 3.3V MCU vs 5V sensor | Voltage 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
Antonius - bluedragonsec.com