Rancangan Kontrol Bluetooth Humanoid Robot BONJER
Kita buat sistem kontrol menggunakan 1 Arduino Uno + HC-05 + L298N + 3 servo. HP Android akan mengendalikan gerakan roda RC sekaligus kepala dan kedua tangan robot melalui satu koneksi Bluetooth.
1. Arsitektur sistem
HP Android
Aplikasi Bluetooth Terminal / Controller
HC-05 + Arduino Uno
Pusat pengendali seluruh gerakan
L298N
4 motor roda melalui 2 kanal
3 servo
Kepala, bahu kiri, bahu kanan
Asumsi desain: empat motor DC pada RC dibagi menjadi dua kelompok, yaitu motor sisi kiri dan motor sisi kanan. Setiap kelompok dikendalikan satu kanal L298N. Ini cocok untuk robot beroda dengan gerakan maju, mundur, dan belok.
2. Pemetaan pin Arduino Uno
Pin berikut dipilih agar tidak terjadi konflik antara PWM motor, komunikasi Bluetooth, dan library servo.
Komponen | Pin Arduino Uno | Fungsi |
|---|---|---|
HC-05 TXD → Arduino | D2 | Menerima data Bluetooth |
Arduino D12 → HC-05 RXD | D12 | Mengirim data Bluetooth |
L298N ENA | D5 | Kecepatan motor kiri |
L298N IN1 | D7 | Arah motor kiri |
L298N IN2 | D8 | Arah motor kiri |
L298N ENB | D6 | Kecepatan motor kanan |
L298N IN3 | D9 | Arah motor kanan |
L298N IN4 | D10 | Arah motor kanan |
Servo kepala | D3 | Menoleh kiri/kanan |
Servo bahu kiri | D4 | Mengangkat/menurunkan lengan |
Servo bahu kanan | A0 | Mengangkat/menurunkan lengan |
Catatan: pin D9 dan D10 dipakai sebagai pin digital biasa untuk arah motor. Ini tidak masalah karena library Servo pada Uno memengaruhi kemampuan PWM pada pin 9 dan 10, bukan fungsi digital biasa.
3. Skema pengkabelan
A. Modul Bluetooth HC-05
HC-05 berkomunikasi dengan Arduino melalui SoftwareSerial.
HC-05 | Arduino Uno |
|---|---|
TXD | D2 |
RXD | D12 melalui pembagi tegangan |
GND | GND |
VCC | 5V pada breakout HC-05 yang memang mendukung suplai 5V |
Untuk jalur Arduino D12 ke RXD HC-05, gunakan pembagi tegangan, misalnya resistor 1 kΩ dari D12 ke RXD dan resistor 2 kΩ dari RXD ke GND. Ini menurunkan sinyal 5 V menjadi sekitar 3,3 V. Periksa spesifikasi modul Anda karena level tegangan RX berbeda antarproduk.
B. Driver motor L298N
L298N | Sambungan |
|---|---|
ENA | Arduino D5 |
IN1, IN2 | Arduino D7, D8 |
ENB | Arduino D6 |
IN3, IN4 | Arduino D9, D10 |
OUT1–OUT2 | Dua motor sisi kiri, paralel |
OUT3–OUT4 | Dua motor sisi kanan, paralel |
GND | GND bersama |
Jika jumper ENA dan ENB terpasang, lepaskan keduanya agar kecepatan bisa dikontrol dengan PWM dari D5 dan D6. Jangan memasang atau melepas kabel motor saat rangkaian menyala.
C. Tiga servo
Servo | Kabel sinyal |
|---|---|
Kepala | D3 |
Bahu kiri | D4 |
Bahu kanan | A0 |
Kabel merah servo terhubung ke catu daya servo 5–6 V yang memadai, kabel GND ke negatif catu daya, dan kabel sinyal ke pin Arduino masing-masing. Jangan menyuplai ketiga servo langsung dari pin 5V Arduino. Satukan GND catu daya servo, Arduino, dan L298N.
Pembagian catu daya
Motor: gunakan baterai yang sesuai dengan tegangan motor dan kemampuan driver.
Arduino dan HC-05: suplai stabil sesuai spesifikasi modul.
Servo: catu daya 5–6 V terpisah yang sanggup menyediakan arus puncak ketiga servo.
Semua ground harus terhubung bersama.
Periksa arus macet (stall current) motor sebelum menghubungkan empat motor ke L298N. Dua motor paralel pada satu kanal menarik arus gabungan; jika melampaui kemampuan driver, gunakan driver yang lebih sesuai.
4. Format perintah dari HP Android
Aplikasi Bluetooth harus mengirim teks berikut. Untuk perintah posisi servo, akhiri dengan karakter baris baru (\n).
Perintah | Fungsi |
|---|---|
| Maju |
| Mundur |
| Belok kiri |
| Belok kanan |
| Berhenti |
| Atur kecepatan motor ke 180 dari 255 |
| Kepala ke posisi tengah, 90° |
| Kepala menoleh ke kiri, 45° |
| Kepala menoleh ke kanan, 135° |
| Bahu kiri ke 120° |
| Bahu kiri ke 60° |
| Bahu kanan ke 60° |
| Bahu kanan ke 120° |
Posisi sudut servo di atas adalah contoh. Arah gerakan nyata bergantung pada cara pemasangan servo. Jangan memaksa servo melewati batas mekanik lengan.
5. Kode Arduino lengkap
Salin kode ini ke Arduino IDE. Pastikan library Servo tersedia (biasanya sudah bawaan Arduino IDE). Library SoftwareSerial juga tersedia untuk Arduino Uno.
#include <SoftwareSerial.h>
#include <Servo.h>
// HC-05: RX Arduino = D2, TX Arduino = D12
SoftwareSerial BT(2, 12);
// Pin L298N
const int ENA = 5;
const int IN1 = 7;
const int IN2 = 8;
const int ENB = 6;
const int IN3 = 9;
const int IN4 = 10;
// Pin servo
const int PIN_HEAD = 3;
const int PIN_ARM_L = 4;
const int PIN_ARM_R = A0;
Servo headServo;
Servo armLeftServo;
Servo armRightServo;
int motorSpeed = 160; // Rentang 0-255
String command = "";
void setup() {
pinMode(ENA, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(ENB, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
headServo.attach(PIN_HEAD);
armLeftServo.attach(PIN_ARM_L);
armRightServo.attach(PIN_ARM_R);
// Posisi awal servo
headServo.write(90);
armLeftServo.write(90);
armRightServo.write(90);
stopRobot();
Serial.begin(9600);
BT.begin(9600);
Serial.println("BONJER Robot siap.");
BT.println("BONJER READY");
}
void loop() {
while (BT.available()) {
char ch = BT.read();
if (ch == '\n' || ch == '\r') {
if (command.length() > 0) {
command.trim();
processCommand(command);
command = "";
}
} else if (command.length() < 20) {
command += ch;
} else {
command = ""; // Batasi perintah terlalu panjang
}
}
}
void processCommand(String cmd) {
cmd.trim();
// Gerakan roda
if (cmd == "F") {
moveForward();
}
else if (cmd == "B") {
moveBackward();
}
else if (cmd == "L") {
turnLeft();
}
else if (cmd == "R") {
turnRight();
}
else if (cmd == "S") {
stopRobot();
}
// Kecepatan: V0 sampai V255
else if (cmd.startsWith("V")) {
int value = cmd.substring(1).toInt();
motorSpeed = constrain(value, 0, 255);
BT.println("SPEED OK");
}
// Kepala: K0 sampai K180
else if (cmd.startsWith("K")) {
int angle = cmd.substring(1).toInt();
headServo.write(constrain(angle, 20, 160));
BT.println("HEAD OK");
}
// Bahu kiri: A0 sampai A180
else if (cmd.startsWith("A")) {
int angle = cmd.substring(1).toInt();
armLeftServo.write(constrain(angle, 20, 160));
BT.println("LEFT ARM OK");
}
// Bahu kanan: C0 sampai C180
else if (cmd.startsWith("C")) {
int angle = cmd.substring(1).toInt();
armRightServo.write(constrain(angle, 20, 160));
BT.println("RIGHT ARM OK");
}
else {
BT.println("UNKNOWN COMMAND");
}
Serial.println(cmd);
}
void moveForward() {
// Sisi kiri maju
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
// Sisi kanan maju
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, motorSpeed);
analogWrite(ENB, motorSpeed);
}
void moveBackward() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENA, motorSpeed);
analogWrite(ENB, motorSpeed);
}
void turnLeft() {
// Belok di tempat: kiri mundur, kanan maju
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, motorSpeed);
analogWrite(ENB, motorSpeed);
}
void turnRight() {
// Belok di tempat: kiri maju, kanan mundur
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENA, motorSpeed);
analogWrite(ENB, motorSpeed);
}
void stopRobot() {
analogWrite(ENA, 0);
analogWrite(ENB, 0);
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
}
6. Cara menguji robot pertama kali
Lakukan pengujian bertahap, dengan roda terangkat dari lantai untuk pengujian motor awal.
- Unggah kode ke Arduino Uno dan pastikan proses upload berhasil.
- Pasangkan HP Android dengan HC-05 melalui pengaturan Bluetooth. PIN pasangan bergantung pada konfigurasi modul.
Buka aplikasi Bluetooth yang dapat mengirim teks, hubungkan ke HC-05, lalu kirim
Sdan pastikan robot berhenti.Kirim
F,B,L, danRsatu per satu. Jika arah salah, matikan daya lalu periksa polaritas motor atau logika arah.Kirim
K45,K90,K135, lalu ujiA60,A120,C60, danC120untuk memeriksa gerakan servo.- Setelah semua berfungsi, turunkan robot ke lantai dan uji gerakan pada kecepatan rendah dengan pengawasan.
7. Pengembangan berikutnya
Dengan 3 servo, gerakan robot saat ini adalah kepala menoleh, bahu kiri bergerak, dan bahu kanan bergerak. Untuk gerakan siku dan gripper, Anda dapat menambahkan servo berikutnya dan memperluas perintah Bluetooth.
Catatan penting: kode ini menggunakan perintah tombol, bukan kendali joystick proporsional. Perintah F akan terus menggerakkan roda sampai perintah lain diterima. Untuk keamanan, pastikan tersedia tombol berhenti yang mudah dijangkau dan jangan menguji robot di dekat tangga atau orang.
===================================================================
Untuk Humanoid Robot Bonjer tinggi 1 meter, saran saya tetap gunakan Bluetooth untuk menggerakkan RC 4 roda, lalu gunakan Arduino untuk mengendalikan servo pada tangan dan kepala. Jadi, satu robot bisa dikendalikan dari HP Android untuk bergerak sekaligus menggerakkan bagian tubuhnya.
1. Sistem kontrol yang saya sarankan
HP Android
Aplikasi Bluetooth Controller
Bluetooth HC-05 / HC-06
Arduino Uno
Menerima perintah dari HP
Motor RC
Driver motor
Tangan
Servo
Kepala
Servo
2. Komponen untuk tangan dan kepala
A. Servo MG996R — untuk bahu dan siku
Bahu kiri dan kanan: masing-masing 1 servo.
Siku kiri dan kanan: masing-masing 1 servo jika diperlukan.
Cocok untuk prototipe, tetapi kemampuan mengangkat beban harus dihitung berdasarkan panjang lengan dan beratnya.
B. Servo SG90 atau MG90S — untuk kepala
1 servo untuk kepala menoleh ke kiri dan kanan.
Untuk kepala yang lebih berat, gunakan servo dengan torsi lebih besar sesuai hasil perhitungan beban.
C. PCA9685 — opsional
Modul ini membantu mengendalikan banyak servo sekaligus. Untuk 3–5 servo, Arduino Uno juga dapat langsung memberikan sinyal kontrol servo tanpa modul tersebut.
3. Bagaimana cara mengontrolnya dari HP?
Anda dapat menggunakan aplikasi Bluetooth yang menyediakan tombol khusus. Contoh tata letaknya:
BONJER ROBOT CONTROLLER
Contoh susunan tombol aplikasi
MAJU
KIRI
STOP
KANAN
MUNDUR
TANGAN
Buka / tutup atau angkat
KEPALA
Kiri / kanan / tengah
Ini rancangan tampilan, bukan aplikasi yang sudah terhubung ke robot.
4. Pengkabelan yang perlu diperhatikan
Bluetooth HC-05/HC-06 terhubung ke Arduino melalui komunikasi serial.
Driver motor mengendalikan motor roda RC.
Kabel sinyal setiap servo terhubung ke pin digital Arduino yang ditentukan dalam program.
Servo sebaiknya menggunakan catu daya 5–6 V yang memadai sesuai spesifikasinya, bukan mengambil seluruh arus servo dari pin 5 V Arduino.
Satukan GND catu daya servo dan GND Arduino agar sinyal kontrol memiliki referensi yang sama.
Penting: jika RC Anda sekarang sudah mempunyai Arduino dan Bluetooth untuk mengontrol roda, kita dapat mengembangkan program yang sama. Anda tidak harus memasang Bluetooth kedua.
5. Saya perlu memastikan konfigurasi robot Anda
Arduino yang sekarang mengendalikan RC Anda menggunakan apa?
Arduino pada RC
Modul Bluetooth
Driver motor
Target jumlah servo
Bagus. Kita bisa mengembangkan Humanoid Robot BONJER menjadi robot Bluetooth semi-otonom: robot tetap dikendalikan lewat HP Android, tetapi sensor ultrasonik akan membantu mendeteksi dinding atau benda di depannya dan menghentikan atau menghindari halangan.
Saya sarankan memakai sensor HC-SR04 di bagian depan badan atau dada robot, diarahkan lurus ke depan.
1. Cara kerja robot setelah ditambahkan sensor
HC-SR04 mendeteksi jarak
Mengukur jarak ke dinding atau benda
Arduino Uno memutuskan
Jarak aman atau ada halangan?
Lebih dari 25 cm
Gerak sesuai perintah HP
25 cm atau kurang
Berhenti dan lakukan penghindaran
Untuk versi awal, robot bisa berhenti, mundur sebentar, lalu berbelok. Agar dapat memilih arah yang lebih aman, kita bisa menambahkan servo untuk mengarahkan sensor ke kiri dan kanan.
2. Pemasangan HC-SR04 ke Arduino Uno
Gunakan pin berikut agar tidak bertabrakan dengan rangkaian sebelumnya.
Pin HC-SR04 | Sambungan Arduino Uno |
|---|---|
VCC | 5V |
TRIG | A1 |
ECHO | A2 |
GND | GND |
Sensor dipasang di dada robot, menghadap ke depan. Usahakan tidak terhalang panel badan atau kabel.
3. Alur penghindaran otomatis
Contoh logika yang akan digunakan:
HP mengirim perintah
Funtuk maju.Arduino terus membaca jarak HC-SR04.
Jika jarak ke halangan kurang dari atau sama dengan 25 cm, motor berhenti.
Robot mundur sekitar 300 milidetik.
Robot berbelok ke kanan sekitar 450 milidetik.
Robot melanjutkan gerak maju dan kembali memantau jarak.
Perlu diperhatikan: karena hanya ada satu sensor depan, robot belum bisa memastikan apakah arah kanan benar-benar bebas. Untuk penghindaran yang lebih andal, nanti kita dapat menambahkan servo pemindai sensor atau sensor kiri dan kanan.
4. Kode Arduino lengkap dengan Bluetooth, 3 servo, dan ultrasonik
Kode berikut menggantikan program sebelumnya. Fitur perintah Bluetooth tetap tersedia, dan penghindaran dibuat bertahap agar perintah S masih bisa diproses selama manuver.
#include <SoftwareSerial.h>
#include <Servo.h>
// ===== BLUETOOTH HC-05 =====
SoftwareSerial BT(2, 12); // RX, TX
// ===== DRIVER MOTOR L298N =====
const int ENA = 5;
const int IN1 = 7;
const int IN2 = 8;
const int ENB = 6;
const int IN3 = 9;
const int IN4 = 10;
// ===== SERVO =====
const int PIN_HEAD = 3;
const int PIN_ARM_L = 4;
const int PIN_ARM_R = A0;
Servo headServo;
Servo armLeftServo;
Servo armRightServo;
// ===== SENSOR HC-SR04 =====
const int TRIG_PIN = A1;
const int ECHO_PIN = A2;
const int BATAS_JARAK = 25; // cm
int motorSpeed = 130;
// Perintah gerak aktif
char driveCommand = 'S';
// Status penghindaran
// 0 = normal, 1 = mundur, 2 = berbelok
byte avoidState = 0;
unsigned long avoidStart = 0;
unsigned long lastSensorRead = 0;
int distanceCM = 999;
String command = "";
void setup() {
pinMode(ENA, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(ENB, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
headServo.attach(PIN_HEAD);
armLeftServo.attach(PIN_ARM_L);
armRightServo.attach(PIN_ARM_R);
headServo.write(90);
armLeftServo.write(90);
armRightServo.write(90);
stopRobot();
Serial.begin(9600);
BT.begin(9600);
BT.println("BONJER READY");
}
void loop() {
// Selalu periksa perintah Bluetooth
readBluetooth();
// Perintah berhenti membatalkan manuver
if (driveCommand == 'S') {
avoidState = 0;
stopRobot();
}
// Baca sensor secara berkala
if (millis() - lastSensorRead >= 60) {
lastSensorRead = millis();
distanceCM = readDistance();
}
// Penghindaran aktif hanya ketika robot sedang maju
if (avoidState == 0 &&
driveCommand == 'F' &&
distanceCM > 0 &&
distanceCM <= BATAS_JARAK) {
avoidState = 1;
avoidStart = millis();
reverseRobot();
BT.println("HALANGAN: MUNDUR");
}
// Tahap 1: mundur sebentar
if (avoidState == 1 &&
millis() - avoidStart >= 300) {
avoidState = 2;
avoidStart = millis();
turnRight();
BT.println("MENGHINDAR: BELOK KANAN");
}
// Tahap 2: berbelok lalu lanjut maju
if (avoidState == 2 &&
millis() - avoidStart >= 450) {
avoidState = 0;
if (driveCommand == 'F') {
moveForward();
BT.println("LANJUT MAJU");
} else {
stopRobot();
}
}
// Kendali manual saat tidak sedang menghindar
if (avoidState == 0) {
if (driveCommand == 'F') {
if (distanceCM > 0 &&
distanceCM <= BATAS_JARAK) {
stopRobot();
} else {
moveForward();
}
}
else if (driveCommand == 'B') {
moveBackward();
}
else if (driveCommand == 'L') {
turnLeft();
}
else if (driveCommand == 'R') {
turnRight();
}
else {
stopRobot();
}
}
}
void readBluetooth() {
while (BT.available()) {
char ch = BT.read();
if (ch == '\n' || ch == '\r') {
if (command.length() > 0) {
command.trim();
processCommand(command);
command = "";
}
}
else if (command.length() < 20) {
command += ch;
}
else {
command = "";
}
}
}
void processCommand(String cmd) {
cmd.trim();
if (cmd == "F" || cmd == "B" ||
cmd == "L" || cmd == "R" ||
cmd == "S") {
driveCommand = cmd.charAt(0);
if (driveCommand == 'S') {
avoidState = 0;
stopRobot();
}
else if (driveCommand != 'F') {
// Perintah manual selain maju membatalkan
// manuver penghindaran yang sedang berlangsung
avoidState = 0;
}
}
else if (cmd.startsWith("V")) {
motorSpeed = constrain(
cmd.substring(1).toInt(), 0, 255
);
}
else if (cmd.startsWith("K")) {
headServo.write(constrain(
cmd.substring(1).toInt(), 20, 160
));
}
else if (cmd.startsWith("A")) {
armLeftServo.write(constrain(
cmd.substring(1).toInt(), 20, 160
));
}
else if (cmd.startsWith("C")) {
armRightServo.write(constrain(
cmd.substring(1).toInt(), 20, 160
));
}
Serial.println(cmd);
}
int readDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(3);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Timeout menghindari menunggu terlalu lama
unsigned long duration =
pulseIn(ECHO_PIN, HIGH, 25000UL);
if (duration == 0) {
return -1; // Jarak tidak terbaca
}
return duration / 58;
}
void moveForward() {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, motorSpeed);
analogWrite(ENB, motorSpeed);
}
void moveBackward() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENA, motorSpeed);
analogWrite(ENB, motorSpeed);
}
void reverseRobot() {
moveBackward();
}
void turnLeft() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, motorSpeed);
analogWrite(ENB, motorSpeed);
}
void turnRight() {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENA, motorSpeed);
analogWrite(ENB, motorSpeed);
}
void stopRobot() {
analogWrite(ENA, 0);
analogWrite(ENB, 0);
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
}
5. Pengujian dan catatan penting
Uji pertama dengan roda terangkat dan kecepatan rendah.
Letakkan benda atau kardus di depan sensor pada jarak 20–25 cm.
Kirim
Fdari HP dan periksa apakah robot mundur, berbelok, lalu maju kembali.Kirim
Suntuk menghentikan robot. Penghentian motor melalui perangkat lunak bukan pengganti sakelar pemutus daya fisik.Jika robot terus maju karena sensor tidak membaca jarak, kode di atas tidak menganggap pembacaan gagal sebagai jarak aman. Namun, untuk operasi yang lebih aman, pembacaan gagal sebaiknya juga memicu berhenti.
Catatan: penghindaran ini hanya bekerja saat perintah maju aktif. Ketika mundur atau berbelok manual, robot belum memiliki sensor belakang maupun samping. Waktu mundur dan belok juga perlu disesuaikan dengan kecepatan, berat, dan ukuran robot 1 meter Anda.
==================================================================
otomatis
Rancangan BONJER Humanoid Line Follower + Obstacle Avoidance
Kita rancang BONJER agar dapat berjalan mengikuti jalur isolasi hitam secara otomatis, sambil tetap bisa dikendalikan dari HP Android melalui Bluetooth HC-05. Jika sensor ultrasonik mendeteksi dinding atau benda, prioritas pertama adalah menghentikan robot dan menghindari halangan, bukan mengikuti garis.
Sistem menggunakan Arduino Uno, L298N, 3 servo, HC-SR04, dan sensor garis yang bisa dipilih kemudian.
1. Arsitektur sistem
HP Android + HC-05
START / STOP / kendali servo
Arduino Uno
Pengendali utama dan prioritas keselamatan
Line sensor
Mengikuti garis
HC-SR04
Mendeteksi halangan
L298N
Mengatur roda
Urutan prioritas kontrol:
STOP dari HP — menghentikan robot.
Halangan terdeteksi — berhenti dan menjalankan manuver penghindaran.
Mode otomatis aktif — mengikuti garis hitam.
Servo kepala dan tangan — tetap bisa menerima perintah Bluetooth.
2. Pilihan sensor garis
Rekomendasi: sensor garis IR 5 kanal
Cari modul line-tracking 5-channel yang memiliki keluaran digital S1–S5 atau OUT1–OUT5. Sensor dipasang di bawah bagian depan basis RC, menghadap ke lantai. Pastikan keluarannya kompatibel dengan logika 5 V Arduino Uno.
Sensor 5 kanal membantu mendeteksi posisi garis lebih baik dibandingkan satu sensor. Namun, kalibrasi tetap diperlukan karena hasil pembacaan dipengaruhi warna lantai, lebar isolasi, dan tinggi sensor.
3. Pemetaan pin Arduino Uno tanpa konflik
Komponen | Pin Arduino Uno |
|---|---|
HC-05 TXD → Arduino RX | D2 |
Arduino TX → HC-05 RXD | D12 melalui pembagi tegangan |
L298N ENA | D5 (PWM) |
L298N IN1, IN2 | D7, D8 |
L298N ENB | D6 (PWM) |
L298N IN3, IN4 | D9, D10 |
HC-SR04 TRIG | A1 |
HC-SR04 ECHO | A2 |
Servo kepala | D3 |
Servo bahu kiri | D4 |
Servo bahu kanan | A0 |
Sensor garis paling kiri (S1) | D13 |
Sensor garis kiri (S2) | A3 |
Sensor garis tengah (S3) | A4 |
Sensor garis kanan (S4) | A5 |
Sensor garis paling kanan (S5) | D11 |
Pin analog A0–A5 juga bisa berfungsi sebagai pin digital pada Uno. Dalam rancangan ini, A0 dipakai untuk sinyal servo dan A1–A2 untuk ultrasonik, sehingga sensor garis menggunakan D13, A3–A5, dan D11.
Pengkabelan sensor garis
VCC→ 5V Arduino, jika modul memang mendukung 5 V.GND→ GND bersama.S1sampaiS5→ pin sesuai tabel di atas.
Kode di bawah mengasumsikan keluaran sensor bernilai LOW ketika mendeteksi garis hitam. Jika modul Anda memberikan HIGH pada garis hitam, ubah satu konstanta dalam kode.
4. Format perintah Bluetooth
Perintah | Fungsi |
|---|---|
| Mulai mengikuti garis otomatis |
| Berhenti dan membatalkan mode otomatis |
| Kepala ke posisi tengah |
| Kepala ke sudut 45° |
| Bahu kiri ke sudut 120° |
| Bahu kanan ke sudut 60° |
Kirim perintah sebagai teks dengan akhiran baris baru (\n). Aplikasi Bluetooth terminal yang mendukung pengiriman newline bisa digunakan untuk pengujian.
5. Kode Arduino lengkap
Kode ini menggunakan lima sensor digital, tiga servo, HC-05, L298N, dan HC-SR04. Manuver menghindar menggunakan gerakan mundur dan belok kanan sebagai langkah awal; arah belok dan durasinya perlu disesuaikan dengan robot Anda.
#include <SoftwareSerial.h>
#include <Servo.h>
// ========== BLUETOOTH HC-05 ==========
SoftwareSerial BT(2, 12); // RX, TX
// ========== L298N ==========
const byte ENA = 5;
const byte IN1 = 7;
const byte IN2 = 8;
const byte ENB = 6;
const byte IN3 = 9;
const byte IN4 = 10;
// ========== SERVO ==========
const byte PIN_HEAD = 3;
const byte PIN_ARM_L = 4;
const byte PIN_ARM_R = A0;
Servo headServo;
Servo armLeftServo;
Servo armRightServo;
// ========== HC-SR04 ==========
const byte TRIG_PIN = A1;
const byte ECHO_PIN = A2;
// ========== 5 SENSOR GARIS ==========
// Urutan kiri ke kanan
const byte linePins[5] = {13, A3, A4, A5, 11};
// true jika sensor memberikan LOW pada garis hitam
const bool BLACK_IS_LOW = true;
// ========== PENGATURAN ==========
const int OBSTACLE_CM = 25;
const int MOTOR_SPEED = 115;
const int TURN_SPEED = 105;
// State manuver menghindar
const unsigned long REVERSE_MS = 300;
const unsigned long TURN_MS = 450;
bool autoMode = false;
bool lineLost = false;
byte avoidState = 0;
// 0 = normal, 1 = mundur, 2 = belok
unsigned long avoidStart = 0;
int lastError = 0;
String command = "";
unsigned long lastDistanceRead = 0;
int distanceCM = -1;
// ========== SETUP ==========
void setup() {
pinMode(ENA, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(ENB, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
for (byte i = 0; i < 5; i++) {
pinMode(linePins[i], INPUT_PULLUP);
}
headServo.attach(PIN_HEAD);
armLeftServo.attach(PIN_ARM_L);
armRightServo.attach(PIN_ARM_R);
headServo.write(90);
armLeftServo.write(90);
armRightServo.write(90);
stopMotors();
BT.begin(9600);
Serial.begin(9600);
BT.println("BONJER READY");
BT.println("Kirim START atau STOP");
}
// ========== LOOP UTAMA ==========
void loop() {
readBluetooth();
// STOP selalu mengalahkan mode lainnya
if (!autoMode) {
stopMotors();
avoidState = 0;
return;
}
// Baca jarak secara berkala
if (millis() - lastDistanceRead >= 60) {
lastDistanceRead = millis();
distanceCM = readDistance();
}
// Sensor gagal dibaca: pilih berhenti demi keamanan
if (distanceCM < 0) {
stopMotors();
BT.println("SENSOR JARAK ERROR - STOP");
autoMode = false;
avoidState = 0;
return;
}
// PRIORITAS 1: HALANGAN
if (avoidState == 0 && distanceCM <= OBSTACLE_CM) {
avoidState = 1;
avoidStart = millis();
reverseMotors();
BT.println("HALANGAN - MUNDUR");
}
// Tahap mundur
if (avoidState == 1) {
if (millis() - avoidStart >= REVERSE_MS) {
avoidState = 2;
avoidStart = millis();
turnRightMotors();
BT.println("MENGHINDAR - BELOK KANAN");
}
return;
}
// Tahap belok
if (avoidState == 2) {
if (millis() - avoidStart >= TURN_MS) {
stopMotors();
// Jangan lanjut jika jalur depan masih terhalang
distanceCM = readDistance();
if (distanceCM > OBSTACLE_CM) {
avoidState = 0;
BT.println("JARAK AMAN - LANJUT");
} else {
avoidState = 0;
autoMode = false;
BT.println("HALANGAN MASIH ADA - STOP");
}
}
return;
}
// PRIORITAS 2: IKUTI GARIS
followLine();
}
// ========== BLUETOOTH ==========
void readBluetooth() {
while (BT.available()) {
char ch = BT.read();
if (ch == '\n' || ch == '\r') {
command.trim();
if (command.length() > 0) {
processCommand(command);
}
command = "";
} else if (command.length() < 20) {
command += ch;
} else {
command = "";
}
}
}
void processCommand(String cmd) {
cmd.trim();
if (cmd == "START") {
autoMode = true;
avoidState = 0;
lastError = 0;
BT.println("AUTO ON");
}
else if (cmd == "STOP") {
autoMode = false;
avoidState = 0;
stopMotors();
BT.println("STOPPED");
}
else if (cmd.startsWith("K")) {
headServo.write(constrain(
cmd.substring(1).toInt(), 20, 160));
}
else if (cmd.startsWith("A")) {
armLeftServo.write(constrain(
cmd.substring(1).toInt(), 20, 160));
}
else if (cmd.startsWith("C")) {
armRightServo.write(constrain(
cmd.substring(1).toInt(), 20, 160));
}
}
// ========== SENSOR JARAK ==========
int readDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(3);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
unsigned long duration =
pulseIn(ECHO_PIN, HIGH, 20000UL);
if (duration == 0) return -1;
return duration / 58;
}
// ========== SENSOR GARIS ==========
bool seesBlack(byte index) {
int value = digitalRead(linePins[index]);
if (BLACK_IS_LOW) {
return value == LOW;
}
return value == HIGH;
}
void followLine() {
// Bobot kiri ke kanan:
// -2, -1, 0, +1, +2
const int weights[5] = {-2, -1, 0, 1, 2};
int total = 0;
int count = 0;
for (byte i = 0; i < 5; i++) {
if (seesBlack(i)) {
total += weights[i];
count++;
}
}
// Garis hilang: cari kembali dengan hati-hati
if (count == 0) {
lineLost = true;
stopMotors();
BT.println("GARIS HILANG - STOP");
autoMode = false;
return;
}
lineLost = false;
int error = total / count;
lastError = error;
// Koreksi arah sederhana
int correction = error * 28;
int leftSpeed = constrain(
MOTOR_SPEED + correction, 0, 200);
int rightSpeed = constrain(
MOTOR_SPEED - correction, 0, 200);
setForward(leftSpeed, rightSpeed);
}
// ========== KONTROL MOTOR ==========
void setForward(int leftSpeed, int rightSpeed) {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
analogWrite(ENA, leftSpeed);
analogWrite(ENB, rightSpeed);
}
void reverseMotors() {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENA, TURN_SPEED);
analogWrite(ENB, TURN_SPEED);
}
void turnRightMotors() {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
analogWrite(ENA, TURN_SPEED);
analogWrite(ENB, TURN_SPEED);
}
void stopMotors() {
analogWrite(ENA, 0);
analogWrite(ENB, 0);
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
}
6. Cara menguji
- Pasang sensor garis di bawah sasis RC, dengan roda terangkat saat tes awal.
- Buka Serial Monitor atau aplikasi Bluetooth dan pastikan HC-05 tersambung.
Kirim
START. Letakkan sensor di atas isolasi hitam dan amati pembacaan kelima sensor.- Letakkan kardus di depan HC-SR04. Robot seharusnya menghentikan proses mengikuti garis dan melakukan manuver menghindar.
Uji
STOPdari HP dan pastikan motor berhenti.
Perhatian: kode ini adalah dasar prototipe, bukan sistem keselamatan tersertifikasi. Penghindaran satu sensor hanya mencoba mundur dan belok kanan; robot tidak mengetahui apakah sisi kanan aman. Jika jalur hilang, mode otomatis berhenti. Untuk robot humanoid 1 meter, gunakan kecepatan rendah, sakelar pemutus daya fisik, serta pengujian dengan pengawasan.
0 Comments