ROBOTIK

 

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

F

Maju

B

Mundur

L

Belok kiri

R

Belok kanan

S

Berhenti

V180

Atur kecepatan motor ke 180 dari 255

K90

Kepala ke posisi tengah, 90°

K45

Kepala menoleh ke kiri, 45°

K135

Kepala menoleh ke kanan, 135°

A120

Bahu kiri ke 120°

A60

Bahu kiri ke 60°

C60

Bahu kanan ke 60°

C120

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.

  1. Unggah kode ke Arduino Uno dan pastikan proses upload berhasil.
  2. Pasangkan HP Android dengan HC-05 melalui pengaturan Bluetooth. PIN pasangan bergantung pada konfigurasi modul.
  3. Buka aplikasi Bluetooth yang dapat mengirim teks, hubungkan ke HC-05, lalu kirim S dan pastikan robot berhenti.

  4. Kirim F, B, L, dan R satu per satu. Jika arah salah, matikan daya lalu periksa polaritas motor atau logika arah.

  5. Kirim K45, K90, K135, lalu uji A60, A120, C60, dan C120 untuk memeriksa gerakan servo.

  6. 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

MG996R High-Torque Metal Gear Servo | RC & Robotics Parts

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.

Micro Servo Motor SG90 9g 180° - Eletrogate

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.

PCA9685 16-Channel I2C PWM Servo Controller Compatible with Arduino, ESP32 and Raspberry Pi

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

Buat rangkaian dan kode lengkap

=========================================================================
semi otonom

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:

  1. HP mengirim perintah F untuk maju.

  2. Arduino terus membaca jarak HC-SR04.

  3. Jika jarak ke halangan kurang dari atau sama dengan 25 cm, motor berhenti.

  4. Robot mundur sekitar 300 milidetik.

  5. Robot berbelok ke kanan sekitar 450 milidetik.

  6. 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 F dari HP dan periksa apakah robot mundur, berbelok, lalu maju kembali.

  • Kirim S untuk 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:

  1. STOP dari HP — menghentikan robot.

  2. Halangan terdeteksi — berhenti dan menjalankan manuver penghindaran.

  3. Mode otomatis aktif — mengikuti garis hitam.

  4. Servo kepala dan tangan — tetap bisa menerima perintah Bluetooth.

2. Pilihan sensor garis

5-way Tracking Sensor Module TCRT5000 เซนเซอร์ตรวจจับเส้นขาว-ดำ สต็อกไทยส่งไว - ขาย arduino เซนเซอร์ และโมดูลต่างๆ ส่งฟรี EMS Kerry : Inspired by LnwShop.com (v2)

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.

  • S1 sampai S5 → 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

START

Mulai mengikuti garis otomatis

STOP

Berhenti dan membatalkan mode otomatis

K90

Kepala ke posisi tengah

K45

Kepala ke sudut 45°

A120

Bahu kiri ke sudut 120°

C60

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

  1. Pasang sensor garis di bawah sasis RC, dengan roda terangkat saat tes awal.
  2. Buka Serial Monitor atau aplikasi Bluetooth dan pastikan HC-05 tersambung.
  3. Kirim START. Letakkan sensor di atas isolasi hitam dan amati pembacaan kelima sensor.

  4. Letakkan kardus di depan HC-SR04. Robot seharusnya menghentikan proses mengikuti garis dan melakukan manuver menghindar.
  5. Uji STOP dari 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.




Post a Comment

0 Comments