Pada tutorial ini, kita akan membuat sistem pengendali lengan robot dengan 2 sumbu gerakan, dikendalikan menggunakan joystick analog. Proyek ini memakai Arduino UNO, satu analog joystick, dan dua motor servo — semuanya disimulasikan di Wokwi.
| Bagian | Komponen | Fungsi |
|---|---|---|
| Board | Arduino UNO | Pusat pembacaan input dan pengendali output |
| Input | Analog Joystick | Membaca gerakan sumbu vertikal dan horizontal |
| Output | Dua Motor Servo | Bergerak mengikuti posisi joystick |
| Library | Servo | Memudahkan Arduino mengirim sudut ke servo |
Alur kendali dua sumbu ini bekerja dengan cara: gerakan joystick diterjemahkan menjadi sudut motor 0 sampai 180 derajat.
Catatan dari panduan asli: tutorial ini disusun untuk praktik dasar kendali dua sumbu. Fokusnya adalah memahami hubungan input analog, fungsi map(), dan gerakan servo secara langsung di simulator. Untuk alat fisik sungguhan, rangkaian mekanik, sumber daya, dan keamanan tetap perlu diuji ulang sesuai beban yang sebenarnya.
Proyek ini membuat sistem kendali lengan robot sederhana dengan dua derajat kebebasan (artinya bisa bergerak ke dua arah berbeda). Joystick dipakai sebagai tuas kendali. Saat tuas digerakkan ke atas atau bawah, satu servo bergerak mengikuti sumbu vertikal. Saat tuas digerakkan ke kiri atau kanan, servo lain bergerak mengikuti sumbu horizontal. Jika tuas ditarik diagonal, kedua servo bergerak bersamaan, sehingga gerakannya terasa lebih luwes.
Dalam dunia robotika, derajat kebebasan adalah jumlah arah berbeda yang bisa digerakkan oleh sebuah sistem mekanik secara independen. Lengan robot dengan 2 derajat kebebasan bisa bergerak di 2 arah berbeda (misalnya atas-bawah dan kiri-kanan), sedangkan lengan robot yang lebih canggih (seperti lengan robot pabrik) bisa punya 6 derajat kebebasan atau lebih, sehingga bisa bergerak dan berputar ke hampir segala arah seperti lengan manusia.
Secara konsep, sistem ini mirip dasar dari pan-tilt kamera (kamera yang bisa digerakkan ke kiri-kanan dan atas-bawah), mainan capit sederhana, lengan robot edukasi, atau mekanisme pengarah sensor. Di tahap simulasi ini, yang kita pelajari bukan kekuatan mekanik, melainkan cara Arduino membaca data analog lalu mengubahnya menjadi sudut gerak servo.
map() untuk mengubah rentang angka.Simulasi ini tidak menghitung beban mekanik, torsi (gaya putar), arus puncak servo, gesekan, bracket (dudukan), dan kestabilan catu daya — semua ini adalah hal-hal yang baru akan terasa penting kalau proyek ini dibuat jadi alat fisik sungguhan.
Proyek ini bisa dijadikan dasar untuk pan-tilt kamera, lengan robot mini, alat pengarah sensor, atau kendali mekanik dua arah lainnya.
| Komponen | Fungsi |
|---|---|
| Arduino UNO | Membaca nilai analog joystick dari A0 dan A1, menjalankan program, lalu mengirim sinyal PWM ke servo. |
| Analog Joystick | Menghasilkan nilai analog berbeda saat tuas digeser. Pin VERT dipakai untuk sumbu Y, pin HORZ untuk sumbu X. |
| Servo 1 | Mewakili gerakan atas-bawah. Sinyal kontrolnya masuk ke pin 9 Arduino. |
| Servo 2 | Mewakili gerakan kiri-kanan. Sinyal kontrolnya masuk ke pin 10 Arduino. |
| Breadboard | Dipakai untuk membagi jalur 5V dan GND ke joystick serta servo, agar kabel lebih rapi. |
Analog joystick punya dua potensiometer (resistor yang nilainya bisa berubah) di dalamnya — satu untuk sumbu vertikal (VERT), satu untuk sumbu horizontal (HORZ). Saat tuas digeser, posisi potensiometer berubah, menghasilkan tegangan listrik yang berbeda-beda. Arduino UNO membaca tegangan ini lewat pin analog dan mengubahnya menjadi angka antara 0 sampai 1023 — ini disebut resolusi 10-bit (2 pangkat 10 = 1024 kemungkinan nilai, dari 0 sampai 1023). Semakin besar angkanya, semakin “penuh” tuas digeser ke satu arah.
Library yang perlu dipasang di Wokwi untuk proyek ini adalah Servo, yang memudahkan Arduino mengirim sudut servo dengan perintah sederhana write().
Buka tab Library Manager di Wokwi, lalu pastikan library Servo sudah muncul di daftar Installed Libraries.
Rangkaian terdiri dari Arduino UNO, breadboard, analog joystick, dan dua servo. Kabel daya dan ground dibagi melalui breadboard agar lebih rapi dan mudah diikuti.
5V Arduino masuk ke jalur positif breadboard. GND Arduino masuk ke jalur ground breadboard.
| Pin Joystick | Tersambung ke |
|---|---|
| VCC | Jalur 5V breadboard |
| GND | Jalur GND breadboard |
| VERT | Pin A0 Arduino (sumbu Y, atas-bawah) |
| HORZ | Pin A1 Arduino (sumbu X, kiri-kanan) |
| Pin Servo | Tersambung ke |
|---|---|
| V+ | Jalur daya breadboard |
| GND | Jalur ground breadboard |
| PWM | Pin digital 9 Arduino |
| Pin Servo | Tersambung ke |
|---|---|
| V+ | Jalur daya breadboard |
| GND | Jalur ground breadboard |
| PWM | Pin digital 10 Arduino |

Lakukan dari jalur daya terlebih dahulu, baru sambungkan kabel data dan PWM:
Kesalahan satu pin saja bisa membuat servo tidak bergerak, nilai analog tidak berubah, atau komponen terlihat menyala tetapi tidak merespons. Karena itu, selalu cocokkan pemasangan kabel dengan tabel wiring di atas satu per satu, jangan buru-buru. Di simulator, warna kabel tidak menentukan fungsi secara teknis (semuanya cuma visual), tapi memakai warna yang konsisten sangat membantu saat mengecek ulang: biasanya merah untuk 5V, hitam untuk GND, dan hijau untuk sinyal data.
Program bekerja terus-menerus di dalam fungsi loop(), mengikuti alur berikut:
Karena servo dikendalikan dengan sudut (bukan angka analog mentah), nilai pembacaan joystick perlu diterjemahkan dulu dari rentang 0–1023 ke rentang 0–180 menggunakan fungsi map(). Setelah nilai berubah menjadi sudut, Arduino mengirim perintah ke masing-masing servo: servo pada pin 9 menerima sudut sumbu Y, servo pada pin 10 menerima sudut sumbu X. Perintah ini diulang cepat dengan jeda 15 milidetik, supaya perubahan posisi terasa lebih halus.
| Fungsi/Perintah | Kegunaan |
|---|---|
analogRead(A0) |
Membaca posisi VERT joystick. Nilainya berubah saat tuas digerakkan naik atau turun. |
analogRead(A1) |
Membaca posisi HORZ joystick. Nilainya berubah saat tuas digerakkan kiri atau kanan. |
map(nilai, 0, 1023, 0, 180) |
Mengubah skala pembacaan analog menjadi skala sudut servo. |
write(derajat) |
Mengirim target sudut ke servo agar porosnya bergerak ke posisi yang diminta. |
Nilai analog joystick 0 sampai 1023 diterjemahkan menjadi sudut servo 0 sampai 180 derajat, seperti berikut:
| Nilai Joystick | Sudut Servo | Keterangan |
|---|---|---|
| Mendekati 0 | Mendekati 0 derajat | Joystick berada dekat satu ujung. Servo bergerak menuju sudut rendah. |
| Sekitar 512 | Sekitar 90 derajat | Joystick diam di tengah. Servo berada di sekitar posisi tengah. |
| Mendekati 1023 | Mendekati 180 derajat | Joystick berada dekat ujung lain. Servo bergerak menuju sudut tinggi. |
Saat tuas joystick digerakkan secara diagonal, nilai A0 dan A1 berubah bersamaan, sehingga kedua servo ikut bergerak bersamaan juga.
map() adalah fungsi bawaan Arduino yang berguna untuk mengubah sebuah angka dari satu rentang skala ke rentang skala lain, secara proporsional. Rumusnya sederhana: map(nilai, dari_min, dari_max, ke_min, ke_max). Contoh: map(512, 0, 1023, 0, 180) akan menghasilkan sekitar 90, karena 512 berada persis di tengah rentang 0–1023, sehingga hasilnya juga di tengah rentang 0–180. Fungsi ini sangat berguna kapan pun kita perlu “menerjemahkan” satu jenis angka (seperti pembacaan sensor) menjadi jenis angka lain (seperti sudut servo).
Catatan dari panduan asli: dalam praktik nyata, servo bisa bergetar kecil jika sinyal joystick tidak stabil. Solusi realistisnya adalah menambahkan dead zone (area kecil di sekitar nilai tengah yang diabaikan perubahannya), meratakan pembacaan dengan rata-rata beberapa sampel, atau membatasi perubahan sudut per siklus agar gerakan lebih lembut.
Buka file sketch.ino di Wokwi, lalu salin kode berikut:
#include <Servo.h>
// Menyiapkan colokan Joystick
int pinJoystickY = A0; // Pin VERT (Atas-Bawah)
int pinJoystickX = A1; // Pin HORZ (Kiri-Kanan)
// Menyiapkan colokan Motor Servo
int pinServoY = 9; // Servo Atas-Bawah di pin 9
int pinServoX = 10; // Servo Kiri-Kanan di pin 10
Servo motorAtasBawah;
Servo motorKiriKanan;
void setup() {
Serial.begin(9600);
motorAtasBawah.attach(pinServoY);
motorKiriKanan.attach(pinServoX);
Serial.println("=== Sistem Lengan Robot 2 Sumbu AKTIF ===");
}
void loop() {
// 1. Membaca posisi tuas Joystick
int nilaiY = analogRead(pinJoystickY);
int nilaiX = analogRead(pinJoystickX);
// 2. Menerjemahkan nilai (0-1023) menjadi derajat (0-180)
int derajatY = map(nilaiY, 0, 1023, 0, 180);
int derajatX = map(nilaiX, 0, 1023, 0, 180);
// 3. Menggerakkan kedua motor secara bersamaan
motorAtasBawah.write(derajatY);
motorKiriKanan.write(derajatX);
// Menampilkan data di Serial Monitor
Serial.print("Sumbu Y: ");
Serial.print(derajatY);
Serial.print(" derajat | Sumbu X: ");
Serial.print(derajatX);
Serial.println(" derajat");
delay(15);
}
Klik masing-masing bagian di bawah ini untuk memahami fungsinya satu per satu:
#include <Servo.h> — memanggil library untuk mengontrol motor servo.int pinJoystickY = A0; — variabel yang menyimpan pin analog untuk sumbu Y (VERT), yaitu A0.int pinJoystickX = A1; — variabel yang menyimpan pin analog untuk sumbu X (HORZ), yaitu A1.int pinServoY = 9; dan int pinServoX = 10; — variabel yang menyimpan nomor pin PWM untuk masing-masing servo.Servo motorAtasBawah; dan Servo motorKiriKanan; — membuat dua objek (perwakilan) servo di dalam program, masing-masing diberi nama sesuai fungsi geraknya supaya mudah dipahami saat membaca kode.Serial.begin(9600); — mengaktifkan komunikasi Serial Monitor.motorAtasBawah.attach(pinServoY); — menghubungkan objek servo motorAtasBawah ke pin fisik yang tersimpan di pinServoY (yaitu pin 9).motorKiriKanan.attach(pinServoX); — sama seperti di atas, tapi untuk servo motorKiriKanan yang terhubung ke pin 10.Serial.println("=== Sistem Lengan Robot 2 Sumbu AKTIF ==="); — menampilkan pesan pembuka ke Serial Monitor.int nilaiY = analogRead(pinJoystickY); — membaca nilai analog dari pin VERT joystick (rentang 0–1023), disimpan ke variabel nilaiY.int nilaiX = analogRead(pinJoystickX); — sama seperti di atas, tapi untuk pin HORZ, disimpan ke nilaiX.int derajatY = map(nilaiY, 0, 1023, 0, 180); — mengubah nilaiY (yang rentangnya 0–1023) menjadi sudut servo dalam rentang 0–180 derajat, disimpan ke variabel derajatY.int derajatX = map(nilaiX, 0, 1023, 0, 180); — sama seperti di atas, tapi untuk sumbu X.motorAtasBawah.write(derajatY); — mengirim perintah ke servo Y supaya bergerak ke sudut yang sudah dihitung.motorKiriKanan.write(derajatX); — mengirim perintah ke servo X supaya bergerak ke sudut yang sudah dihitung.Serial.print(...) beberapa baris — menampilkan nilai sudut Y dan X ke Serial Monitor, supaya kita bisa memantau perubahan posisi joystick secara langsung sambil menggeser-geser tuasnya.delay(15); — menunda program sejenak selama 15 milidetik sebelum loop() mengulang membaca joystick lagi. Jeda kecil ini membuat pergerakan servo terasa lebih halus (tidak terlalu “kasar” atau patah-patah), tanpa membuat responsnya terasa lambat.sketch.ino.Ketika joystick digerakkan, Serial Monitor menampilkan perubahan derajat, dan kedua servo menyesuaikan posisinya. Jika joystick dilepas ke tengah, nilai kembali ke sekitar posisi tengah, dan servo bergerak mendekati 90 derajat.
Penting: jika hasilnya tidak sesuai perkiraan, cek dulu wiring dan pin terlebih dahulu. Jangan langsung mengubah kode, karena kesalahan paling umum pada project ini biasanya adalah: VERT/HORZ tertukar, kabel PWM masuk ke pin yang salah, atau jalur 5V/GND breadboard belum tersambung dengan benar.
Serial Monitor bukan sekadar tampilan tambahan — pada project ini, Serial Monitor membantu memastikan Arduino benar-benar membaca joystick dan mengirim sudut yang berubah.
| Kondisi | Artinya |
|---|---|
| Angka Y berubah, servo Y bergerak | Jalur VERT ke A0, fungsi map(), dan servo pin 9 bekerja dengan benar. |
| Angka X berubah, servo X bergerak | Jalur HORZ ke A1, fungsi map(), dan servo pin 10 bekerja dengan benar. |
| Angka berubah tapi servo diam | Kemungkinan ada masalah pada kabel PWM servo, jalur V+/GND, atau library Servo belum terpasang. |
| Servo bergerak tapi arah terasa terbalik | Ini bukan selalu salah — orientasi mekanik servo bisa berbeda-beda. Rentang map() bisa dibalik jika diperlukan. |
Untuk pengujian yang lebih teliti, gerakkan joystick perlahan dari ujung ke ujung, lalu perhatikan apakah angka berubah dengan mulus. Jika lompatannya terlalu besar, itu wajar terjadi pada simulasi tertentu, tetapi pada rangkaian fisik bisa dikurangi dengan menambahkan filter pembacaan.
| Masalah | Penyebab Umum dan Solusi |
|---|---|
| Servo tidak bergerak | Kabel PWM tidak masuk ke pin yang sesuai, library Servo belum aktif, atau jalur daya servo belum tersambung. Cek servo Y ke pin 9 dan servo X ke pin 10, lalu pastikan V+ dan GND masuk ke jalur breadboard yang benar. |
| Servo bergerak terbalik | Arah pemasangan horn (tuas) servo atau orientasi mekanik bisa berbeda. Secara program, bisa dibalik dengan mengubah menjadi map(nilai, 0, 1023, 180, 0) pada sumbu yang ingin dibalik. |
| Nilai di Serial Monitor tidak berubah | Kabel VERT/HORZ joystick tidak masuk ke A0/A1, kabel VCC/GND joystick tidak tersambung, atau tuas joystick belum digeser saat simulasi berjalan. |
| Gerakan patah-patah | Pembacaan analog berubah terlalu cepat, atau beban simulasi sedang berat. Delay 15 ms sudah cukup kecil; untuk hardware nyata bisa ditambah filter rata-rata dan catu daya servo yang lebih stabil. |
| Satu servo bergerak, satu lagi diam | Cek servo yang diam saja — pastikan kabel PWM-nya masuk ke pin yang dipakai sketch, dan pin V+/GND tidak tertukar. |
| Servo hanya bergetar (di rangkaian fisik) | Sering berhubungan dengan daya yang kurang kuat atau ground yang tidak sama. Gunakan catu daya servo sesuai kebutuhan dan satukan ground-nya dengan Arduino. |
| Arah sumbu tertukar | Jika gerakan atas-bawah malah menggerakkan servo kiri-kanan, kemungkinan pin VERT/HORZ tertukar, atau servo di pin 9/10 dipasang ke mekanik yang berbeda dari yang seharusnya. |
| Simulasi tidak bisa di-compile | Pastikan baris #include ada dan library Servo sudah terpasang. Cek juga tanda titik koma ;, kurung kurawal { }, serta nama variabel sudah sama persis di semua bagian kode. |
Untuk robot fisik, jangan menganggap sumber 5V dari Arduino selalu cukup untuk menyalakan dua servo sekaligus. Servo bisa menarik arus listrik yang jauh lebih besar saat mulai bergerak atau sedang menahan beban. Jika servo bergerak aneh di dunia nyata tetapi terlihat normal di Wokwi, penyebabnya sering ada pada catu daya, bukan pada kode program.
Servo di rangkaian nyata biasanya lebih stabil jika diberi catu daya terpisah yang sesuai, terutama jika servonya lebih dari satu atau sedang menahan beban. Meski begitu, ground catu daya servo dan ground Arduino tetap perlu disatukan, supaya sinyal PWM punya referensi listrik yang sama.
Proyek ini bisa menjadi dasar banyak perangkat, tapi perlu dikembangkan secara bertahap. Di simulator, servo hanya mengikuti angka sudut; pada alat nyata, motor akan menghadapi berat rangka, gesekan, posisi kabel, dan batas mekanik. Karena itu, pengembangan sebaiknya dimulai dari rangka kecil dan beban ringan.
| Ide Pengembangan | Penjelasan |
|---|---|
| Pan-tilt kamera | Dua servo dapat mengarahkan kamera kecil ke kiri-kanan dan atas-bawah. Tambahkan batas sudut agar kabel kamera tidak tertarik. |
| Lengan robot edukasi | Servo bisa dijadikan sendi sederhana. Gunakan bracket yang kuat dan batasi beban agar servo tidak panas. |
| Crane mini | Joystick dapat mengatur arah gerak. Untuk beban nyata, dibutuhkan motor dan driver yang lebih kuat daripada servo kecil. |
| Kontrol sensor | Servo dapat mengarahkan sensor ultrasonik, sensor cahaya, atau sensor kamera ke area tertentu. |
| Gerakan lebih halus | Tambahkan smoothing (penghalusan) atau pembatas perubahan sudut, supaya servo tidak langsung “melompat” saat joystick digerakkan cepat. |
| Mode aman | Tambahkan batas minimum dan maksimum sudut, untuk mencegah servo menabrak rangka mekanik saat digerakkan terlalu jauh. |
Urutan pengembangan yang disarankan: mulai dari simulasi, lalu uji satu servo fisik, kemudian dua servo tanpa beban, baru setelah itu dipasang ke mekanik sungguhan. Cara bertahap ini mengurangi risiko servo cepat panas atau rangka patah karena sudut gerak yang terlalu ekstrem.
analogRead() membaca nilai sensor analog dalam rentang 0–1023, sedangkan fungsi map() berguna untuk menerjemahkan rentang angka tersebut menjadi rentang lain, seperti sudut servo 0–180 derajat.loop(), memungkinkan gerakan diagonal yang luwes saat kedua sumbu digerakkan bersamaan.🔒 Simulasi ini dikunci. Minta passcode ke gurumu untuk membuka.