Sistem Robot Pendeteksi Warna dengan Sensor Ultrasonik Berbasis Raspberry Pi dan OpenCV
Sistem Robot Pendeteksi Warna dengan Sensor Ultrasonik Berbasis Raspberry Pi dan OpenCV
Kelompok RE-3D/6 — Dhesta Athaya S., Khoirudin, Rachmadhani Aji K., Theofilus Ogawa G.
Abstrak
Praktikum ini menghasilkan robot beroda dua motor yang bergerak berdasarkan warna yang ditangkap kamera PiCam dan diproses dengan OpenCV pada ruang warna HSV. Tiga warna dikenali: hijau, kuning, dan merah, masing-masing dipetakan ke perintah maju penuh, maju pelan, dan berhenti. Perintah warna terakhir disimpan dalam variabel global sehingga robot tetap menjalankan perintah tersebut walau objek berwarna sudah keluar dari bidang pandang kamera. Sensor ultrasonik HC-SR04 berjalan pada thread terpisah untuk memantau jarak ke penghalang secara terus-menerus; pada jarak di bawah 5 cm robot dihentikan paksa dan buzzer dimatikan, sedangkan pada rentang 5-15 cm robot diperlambat menjadi 30% dan buzzer berbunyi berselang 0,3 detik.
Kata kunci: OpenCV, HSV, Raspberry Pi, sensor ultrasonik, robot pendeteksi warna.
I. Pendahuluan
A. Latar Belakang
Robot pengikut warna umum digunakan sebagai media praktikum untuk memperkenalkan pengolahan citra digital pada sistem tertanam. Pada praktikum kelompok RE-3D/6, robot dirancang untuk membaca warna melalui kamera PiCam yang terpasang pada Raspberry Pi, lalu mengubah warna tersebut menjadi perintah gerak. Tiga warna dipilih karena kemiripannya dengan lampu lalu lintas: hijau untuk maju, kuning untuk melambat, dan merah untuk berhenti.
Masalah yang sering muncul pada robot semacam ini adalah hilangnya objek warna dari bidang pandang kamera saat robot bergerak, sehingga robot berhenti mendadak atau kehilangan arah. Selain itu, robot yang hanya mengandalkan kamera berisiko menabrak dinding atau benda di depannya karena kamera tidak mengukur jarak secara langsung. Kedua masalah ini menjadi dasar penambahan mekanisme penyimpanan perintah terakhir dan sensor ultrasonik pada rancangan robot.
B. Rumusan Masalah
1) Bagaimana merancang program yang dapat mendeteksi warna hijau, kuning, dan merah secara langsung dari kamera dan mengubahnya menjadi perintah gerak robot?
2) Bagaimana agar robot tetap menjalankan perintah warna yang sedang aktif meski objek warna sudah tidak terlihat oleh kamera?
3) Bagaimana mencegah robot menabrak penghalang di depannya tanpa mengganggu proses pembacaan warna yang berjalan bersamaan?
C. Tujuan
Praktikum ini bertujuan membangun robot yang dapat mengubah warna hijau, kuning, dan merah menjadi perintah maju penuh, maju pelan, dan berhenti; mempertahankan perintah warna terakhir selama belum ada warna baru yang terdeteksi; serta menambahkan sensor ultrasonik sebagai pengaman independen yang bekerja pada thread terpisah agar pembacaan jarak tidak terhambat oleh proses pengolahan citra.
II. Metodologi
Robot dikembangkan melalui empat tahap. Tahap pertama adalah pemilihan komponen dan pengecekan kompatibilitas antara Raspberry Pi, kamera PiCam, motor DC, sensor HC-SR04, dan buzzer. Tahap kedua adalah perancangan diagram blok, diagram alir, rangkaian skematik, dan diagram pengawatan sebagai acuan sebelum pemrograman, sebagaimana disajikan pada bagian Kajian Pustaka. Tahap ketiga adalah penulisan program dengan Python, mencakup fungsi deteksi warna, fungsi kendali robot, dan thread pembacaan sensor. Tahap keempat adalah pengujian langsung: kartu warna digerakkan di depan kamera untuk menguji logika perintah warna, dan tangan didekatkan secara bertahap ke sensor untuk menguji ketiga level jarak (aman, hati-hati, bahaya).
III. Kajian Pustaka
A. Komponen
Raspberry Pi berperan sebagai unit pemroses utama yang menjalankan program Python, mengolah citra dari kamera, dan mengirim sinyal ke motor melalui pin GPIO. Kamera PiCam terhubung ke slot CSI dan diakses lewat pustaka picamera2 untuk mengambil citra secara langsung. Dua motor DC digerakkan lewat kelas Robot pada pustaka gpiozero, dengan pin GPIO 6 dan 5 untuk motor kiri, serta 12 dan 13 untuk motor kanan. Sensor ultrasonik HC-SR04 mengukur jarak lewat pantulan gelombang suara, dengan pin echo di GPIO 23 dan trigger di GPIO 18. Buzzer terhubung ke GPIO 4 sebagai indikator suara. Pada sisi perangkat lunak, OpenCV (cv2) digunakan untuk mengubah setiap frame ke ruang warna HSV dan mencari kontur warna, sedangkan modul threading menjalankan pembacaan sensor secara bersamaan dengan pengolahan citra tanpa saling menunggu.
B. Diagram Blok
Diagram blok berikut menggambarkan hubungan antara perangkat masukan (kamera dan sensor ultrasonik), unit pemroses (Raspberry Pi dengan dua thread), dan perangkat keluaran (motor kiri, motor kanan, buzzer).
Gambar 1. Diagram blok sistem robot pendeteksi warna.
C. Diagram Alir
Diagram alir berikut menjelaskan urutan proses dalam satu putaran program, mulai dari pengambilan frame kamera, pengecekan tiga level jarak sensor secara berurutan (bahaya, hati-hati, lalu perintah warna), hingga kondisi keluar program.
Gambar 2. Diagram alir logika program utama.
D. Rangkaian Skematik
Rangkaian skematik berikut menunjukkan hubungan tiap komponen ke Raspberry Pi secara garis besar: kamera ke port CSI, motor DC ke modul driver motor, sensor ultrasonik dan buzzer langsung ke pin GPIO, serta baterai sebagai sumber daya bersama.
Gambar 3. Rangkaian skematik komponen robot.
E. Diagram Pengawatan
Diagram pengawatan berikut memetakan pin fisik pada header GPIO 40-pin Raspberry Pi ke masing-masing komponen. Pin bertanda merah adalah pin yang benar-benar dipakai pada robot ini, sedangkan pin lain mengikuti fungsi bawaan Raspberry Pi dan tidak digunakan pada rangkaian.
Gambar 4. Diagram pengawatan pin GPIO Raspberry Pi.
IV. Hasil dan Pembahasan
Pada pengujian dengan tiga kartu warna (hijau, kuning, merah) yang digerakkan bergantian di depan kamera, robot
berpindah perintah sesuai warna yang ditunjukkan dan tetap menjalankan perintah tersebut walau kartu dijauhkan
dari bidang pandang kamera. Perilaku ini sesuai rancangan pada diagram alir, karena perintahTerakhir
tidak direset ke None kecuali digantikan oleh warna baru.
Pengujian sensor ultrasonik dilakukan dengan mendekatkan tangan ke sensor secara bertahap. Pada jarak di atas 15 cm buzzer diam dan robot mengikuti perintah warna aktif. Begitu jarak masuk rentang 5-15 cm, robot langsung melambat ke 30% terlepas dari warna yang sedang aktif, dan buzzer berbunyi berselang. Pada jarak di bawah 5 cm, robot berhenti total dan buzzer ikut mati; perilaku mati saat bahaya ini disengaja agar buzzer tidak berbunyi terus-menerus saat robot sudah diam menempel pada penghalang.
Satu keterbatasan yang ditemukan selama pengujian adalah rentang HSV untuk kuning yang cukup berdekatan dengan hijau pada pencahayaan redup, sehingga kadang kartu kuning sempat terbaca sebagai hijau selama satu-dua frame sebelum stabil kembali ke kuning. Masalah ini belum diuji pada kondisi pencahayaan di bawah 100 lux.
V. Program
"""============================================================================
Pemrogram : Kelompok RE-3D/6
1. 06-Dhesta Athaya S NIM:4.34.23.3.06
2. 12-Khoirudin NIM:4.34.23.3.12
3. 18-Rachmadhani Aji K NIM:4.34.23.3.18
4. 24-Theofilus Ogawa G NIM:4.34.23.3.24
Tgl.Praktikum : Rabu, 24 Juni 2026
===============================================================================
Proyek
ProyekOpenCV_RobotWarna.py
Program untuk mendeteksi warna (Merah/Kuning/Hijau) secara langsung (live)
menggunakan OpenCV(cv2) dan picamera2, lalu mengontrol gerak robot
berdasarkan warna yang terdeteksi (Merah, Kuning, Hijau).
Sensor ultrasonik HC-SR04 digunakan sebagai pengaman agar robot tidak
menabrak objek/tembok di depannya. Buzzer memberikan peringatan jarak.
Robot mengingat perintah warna terakhir dan terus menjalankannya
meski warna hilang dari kamera, sampai warna lain terdeteksi.
Saat jarak bahaya (<=5 cm): robot berhenti PAKSA dan buzzer ikut diam.
-------------------------------------------------------------------------------
Materi:
- Kamera PiCam
- Kelas Picamera2 pada pustaka picamera2
- Pustaka OpenCV (cv2) untuk mendeteksi warna pada ruang warna HSV
- Pustaka gpiozero untuk mengontrol Robot, DistanceSensor, dan Buzzer
-------------------------------------------------------------------------------
Komponen:
- 1x PiCam
- 2x Motor DC
- 1x Sensor Ultrasonik HC-SR04
- 1x Buzzer
-------------------------------------------------------------------------------
Tabel Perintah Warna:
Hijau -> Robot MAJU penuh (100%) -- terus sampai warna lain terdeteksi
Kuning -> Robot MAJU pelan (40%) -- terus sampai warna lain terdeteksi
Merah -> Robot BERHENTI -- terus sampai warna lain terdeteksi
<= 5 cm -> Robot BERHENTI PAKSA + Buzzer DIAM
<=15 cm -> Robot DIPERLAMBAT (30%) + Buzzer sedang
=========================================================================== """
#=== Pustaka ===
import time # pustaka untuk fungsi jeda waktu (sleep)
import threading # pustaka untuk menjalankan beberapa proses secara bersamaan (thread)
import numpy as np # pustaka numpy untuk membuat array nilai HSV (batas warna)
from gpiozero import Robot, DistanceSensor, Buzzer # mengimpor kelas Robot, sensor jarak, dan buzzer dari gpiozero
from picamera2 import Picamera2 # mengimpor kelas Picamera2 untuk mengakses kamera Raspberry Pi
import cv2 # mengimpor pustaka OpenCV untuk pengolahan gambar dan deteksi warna
#=== Deklarasi Variabel ===
robot = Robot(left=(6, 5), right=(12, 13)) # membuat objek robot dengan pin GPIO motor kiri (6,5) dan kanan (12,13)
sensor = DistanceSensor(echo=23, trigger=18) # membuat objek sensor ultrasonik dengan pin Echo=23 dan Trigger=18
bel = Buzzer(4) # membuat objek buzzer yang terhubung ke pin GPIO 4
kamera = Picamera2() # membuat objek kamera PiCam yang terhubung ke slot CSI
LUAS_MINIMUM = 800 # batas luas kontur minimum (piksel) agar warna dianggap terdeteksi (bukan noise)
JARAK_BAHAYA = 5 # batas jarak (cm) kondisi bahaya: robot berhenti PAKSA & buzzer diam
JARAK_HATI = 15 # batas jarak (cm) kondisi hati-hati: robot diperlambat & buzzer berbunyi sedang
rentangWarna = { # kamus berisi rentang nilai HSV untuk setiap warna yang ingin dideteksi
"Hijau" : [(np.array([40, 70, 70]), # batas bawah HSV warna Hijau
np.array([85, 255, 255]))], # batas atas HSV warna Hijau
"Kuning": [(np.array([20, 100, 100]), # batas bawah HSV warna Kuning
np.array([35, 255, 255]))], # batas atas HSV warna Kuning
"Merah" : [(np.array([0, 120, 70]), # batas bawah HSV warna Merah (rentang bawah, H=0-10)
np.array([10, 255, 255])), # batas atas HSV warna Merah (rentang bawah)
(np.array([170, 120, 70]), # batas bawah HSV warna Merah (rentang atas, H=170-180)
np.array([180, 255, 255]))], # batas atas HSV warna Merah (rentang atas) -- merah butuh 2 rentang karena melingkar di HSV
}
warnaKotak = { # kamus berisi warna garis kotak (BGR) untuk setiap label warna
"Hijau" : (0, 255, 0), # warna garis kotak untuk Hijau dalam format BGR
"Kuning": (0, 255, 255), # warna garis kotak untuk Kuning dalam format BGR
"Merah" : (0, 0, 255), # warna garis kotak untuk Merah dalam format BGR
}
#=== Variabel Bersama Antar-Thread ===
jarak_cm_global = 999.0 # variabel global penyimpan jarak terkini dalam cm (nilai awal 999 = aman)
lock_jarak = threading.Lock() # kunci (lock) agar variabel jarak tidak diakses dua thread sekaligus (race condition)
perintahTerakhir = None # variabel global untuk menyimpan warna/perintah terakhir yang terdeteksi; None = belum ada perintah sama sekali
statusBahaya = False # variabel global penanda kondisi bahaya aktif; True = jarak terlalu dekat, robot & buzzer dipaksa diam
#=== Fungsi Thread Sensor Ultrasonik & Buzzer ===
def thread_sensor(): # definisi fungsi yang akan dijalankan oleh thread sensor
global jarak_cm_global, statusBahaya # mendeklarasikan bahwa fungsi ini akan mengubah kedua variabel global ini
while True: # perulangan tanpa henti agar sensor terus membaca jarak
jarak = sensor.distance * 100 # membaca jarak dari sensor (satuan meter) lalu mengalikan 100 agar menjadi cm
with lock_jarak: # mengunci akses variabel global agar thread lain tidak membaca setengah-jalan
jarak_cm_global = jarak # memperbarui nilai jarak global dengan hasil bacaan terbaru
statusBahaya = jarak <= JARAK_BAHAYA # perbarui penanda bahaya: True jika jarak <= 5 cm, False jika tidak
if jarak <= JARAK_BAHAYA: # jika jarak kurang dari atau sama dengan 5 cm (kondisi bahaya)
bel.off() # matikan buzzer -- robot sudah berhenti paksa, tidak perlu bunyi peringatan
time.sleep(0.1) # jeda kecil agar CPU tidak bekerja terlalu keras saat menunggu robot menjauh
elif jarak <= JARAK_HATI: # jika jarak antara 5-15 cm (kondisi hati-hati)
bel.on() # nyalakan buzzer sebagai peringatan jarak dekat
time.sleep(0.3) # tahan buzzer selama 0.3 detik (bunyi sedang)
bel.off() # matikan buzzer
time.sleep(0.3) # jeda 0.3 detik sebelum siklus bunyi berikutnya (ritme sedang)
else: # jika jarak lebih dari 15 cm (kondisi aman)
bel.off() # pastikan buzzer mati (tidak berbunyi saat kondisi aman)
time.sleep(0.1) # jeda kecil agar CPU tidak bekerja terlalu keras (throttle loop)
#=== Fungsi Deteksi Warna Terbesar ===
def deteksiWarnaTerbesar(bingkaiHSV): # fungsi menerima bingkai gambar dalam format HSV
labelTerpilih = None # variabel untuk menyimpan nama warna yang terdeteksi (awal: belum ada)
luasTerbesar = 0 # variabel untuk menyimpan luas kontur terbesar yang ditemukan (awal: 0)
kotakTerpilih = None # variabel untuk menyimpan koordinat kotak pembatas warna terbesar (awal: belum ada)
for label, daftarRentang in rentangWarna.items(): # iterasi setiap warna (Hijau, Kuning, Merah) beserta rentang HSV-nya
maskGabungan = None # mask awal untuk warna ini dikosongkan dulu
for (bawah, atas) in daftarRentang: # iterasi setiap pasang batas bawah & atas HSV untuk warna ini
maskBagian = cv2.inRange(bingkaiHSV, bawah, atas) # buat mask: piksel putih jika warna cocok, hitam jika tidak
if maskGabungan is None: # jika ini adalah rentang pertama untuk warna ini
maskGabungan = maskBagian # langsung gunakan mask bagian ini sebagai mask gabungan
else: # jika sudah ada mask sebelumnya (warna Merah punya 2 rentang)
maskGabungan = cv2.bitwise_or(maskGabungan, maskBagian) # gabungkan kedua mask dengan operasi OR (piksel putih jika salah satu cocok)
maskGabungan = cv2.erode(maskGabungan, None, iterations=2) # erosi: mengecilkan area putih untuk menghilangkan noise kecil
maskGabungan = cv2.dilate(maskGabungan, None, iterations=2) # dilasi: memperluas kembali area putih agar bentuk warna tetap utuh
kontur, _ = cv2.findContours( # mencari semua kontur (tepi bentuk) pada mask
maskGabungan, # mask yang digunakan sebagai sumber
cv2.RETR_EXTERNAL, # hanya ambil kontur paling luar
cv2.CHAIN_APPROX_SIMPLE) # simpan hanya titik sudut kontur (hemat memori)
if not kontur: # jika tidak ada kontur ditemukan untuk warna ini
continue # lewati ke warna berikutnya
konturTerbesar = max(kontur, key=cv2.contourArea) # pilih kontur dengan luas terbesar dari semua kontur yang ditemukan
luas = cv2.contourArea(konturTerbesar) # hitung luas (piksel) dari kontur terbesar tersebut
if luas > LUAS_MINIMUM and luas > luasTerbesar: # jika luas melebihi batas minimum DAN lebih besar dari warna sebelumnya
luasTerbesar = luas # perbarui nilai luas terbesar
labelTerpilih = label # simpan nama warna ini sebagai warna yang terdeteksi
kotakTerpilih = cv2.boundingRect(konturTerbesar)# hitung kotak pembatas (x,y,lebar,tinggi) dari kontur terbesar
return labelTerpilih, kotakTerpilih # kembalikan nama warna dan koordinat kotak yang terdeteksi
#=== Fungsi Kendali Robot ===
def kendalikanRobot(labelWarna): # fungsi untuk menggerakkan robot berdasarkan warna dan jarak
global perintahTerakhir # mendeklarasikan bahwa fungsi ini akan mengubah variabel global perintahTerakhir
with lock_jarak: # kunci akses variabel global agar aman dibaca dari thread ini
jarak = jarak_cm_global # ambil nilai jarak terkini dari variabel global
bahaya = statusBahaya # ambil status bahaya terkini dari variabel global
# -- Prioritas 1 -- BAHAYA: jarak <= 5 cm -> robot berhenti PAKSA, buzzer diam --
if bahaya: # jika status bahaya aktif (jarak terlalu dekat ke objek/tembok)
print(f"[BAHAYA] Jarak {jarak:.1f} cm -- Robot BERHENTI PAKSA, Buzzer DIAM") # cetak status ke terminal
robot.stop() # hentikan PAKSA semua motor robot; perintah warna diabaikan sepenuhnya
bel.off() # matikan buzzer karena robot sudah berhenti (tidak perlu bunyi peringatan)
return # keluar dari fungsi, tidak proses warna sama sekali
# -- Prioritas 2 -- HATI-HATI: jarak 5-15 cm -> robot diperlambat paksa --
if jarak <= JARAK_HATI: # jika jarak cukup dekat tapi belum bahaya (5-15 cm)
print(f"[HATI] Jarak {jarak:.1f} cm -- Robot DIPERLAMBAT (override warna)") # cetak status ke terminal
robot.forward(speed=0.3) # jalankan robot maju paksa kecepatan 30%, mengabaikan perintah warna
return # keluar dari fungsi, tidak proses warna
# -- Perbarui perintah hanya jika ada warna BARU yang terdeteksi --
if labelWarna is not None: # jika kamera mendeteksi warna pada frame ini
if labelWarna != perintahTerakhir: # jika warna yang terdeteksi BERBEDA dari perintah yang sedang aktif
perintahTerakhir = labelWarna # simpan warna baru ini sebagai perintah aktif yang akan terus dijalankan
print(f"[GANTI] Warna baru: {labelWarna} -- perintah diperbarui") # cetak info pergantian perintah ke terminal
# -- Jalankan perintah terakhir (meski warna sudah hilang dari kamera) --
if perintahTerakhir == "Hijau": # jika perintah aktif adalah Hijau
print(f"[HIJAU] Jarak {jarak:.1f} cm -- Robot MAJU penuh (100%)") # cetak status ke terminal
robot.forward() # maju kecepatan penuh 100%; tetap berjalan meski Hijau hilang dari kamera
elif perintahTerakhir == "Kuning": # jika perintah aktif adalah Kuning
print(f"[KUNING] Jarak {jarak:.1f} cm -- Robot MAJU pelan (40%)") # cetak status ke terminal
robot.forward(speed=0.4) # maju kecepatan 40%; tetap berjalan meski Kuning hilang dari kamera
elif perintahTerakhir == "Merah": # jika perintah aktif adalah Merah
print(f"[MERAH] Jarak {jarak:.1f} cm -- Robot BERHENTI") # cetak status ke terminal
robot.stop() # hentikan robot; tetap berhenti meski Merah hilang dari kamera
else: # jika belum ada perintah sama sekali sejak program dimulai (perintahTerakhir = None)
print(f"[--] Jarak {jarak:.1f} cm -- Menunggu perintah warna pertama...") # cetak status ke terminal
robot.stop() # robot diam menunggu karena belum pernah menerima perintah warna apapun
#=== Program Utama ===
print("\t=== Demo Kamera + OpenCV + Ultrasonik + Robot ===") # tampilkan judul program di terminal
print("Program berjalan otomatis. Tekan 'q' pada jendela gambar untuk keluar.\n") # tampilkan petunjuk keluar
print("Logika perintah:") # tampilkan keterangan logika ke terminal
print(" Hijau -> Maju 100% (terus sampai warna lain terdeteksi)") # keterangan Hijau
print(" Kuning -> Maju 40% (terus sampai warna lain terdeteksi)") # keterangan Kuning
print(" Merah -> Berhenti (terus sampai warna lain terdeteksi)") # keterangan Merah: berhenti, bukan mundur
print(" <= 5 cm -> Robot BERHENTI PAKSA + Buzzer DIAM") # keterangan kondisi bahaya
print(" <=15 cm -> Robot DIPERLAMBAT (30%) + Buzzer sedang\n") # keterangan kondisi hati-hati
t_sensor = threading.Thread(target=thread_sensor, daemon=True) # buat thread baru yang menjalankan fungsi thread_sensor; daemon=True agar ikut berhenti saat program utama selesai
t_sensor.start() # mulai jalankan thread sensor secara bersamaan dengan program utama
kamera.configure(kamera.create_video_configuration()) # konfigurasikan kamera ke mode video (resolusi & format optimal untuk capture berkelanjutan)
kamera.start() # aktifkan kamera agar siap mengambil gambar
time.sleep(1) # jeda 1 detik untuk memberi waktu kamera menyesuaikan pencahayaan
try: # blok try untuk menangkap error atau penghentian paksa
while True: # perulangan utama: terus proses setiap frame kamera
bingkai = kamera.capture_array() # ambil satu frame gambar dari kamera dalam format array numpy (RGB)
bingkaiLtr = cv2.cvtColor(bingkai, cv2.COLOR_RGB2BGR) # ubah format warna dari RGB (format kamera) ke BGR (format OpenCV)
bingkaiHSV = cv2.cvtColor(bingkaiLtr, cv2.COLOR_BGR2HSV) # ubah format warna dari BGR ke HSV untuk mempermudah deteksi warna
labelWarna, kotak = deteksiWarnaTerbesar(bingkaiHSV) # panggil fungsi deteksi warna; kembalikan nama warna dan koordinat kotak
if labelWarna is not None: # jika ada warna yang berhasil terdeteksi pada frame ini
(x, y, w, h) = kotak # urai koordinat kotak menjadi: x=kiri, y=atas, w=lebar, h=tinggi
warna = warnaKotak[labelWarna] # ambil warna garis kotak sesuai warna yang terdeteksi dari kamus warnaKotak
cv2.rectangle(bingkaiLtr, (x, y), (x+w, y+h), warna, 2) # gambar kotak persegi di sekeliling area warna yang terdeteksi
cv2.putText(bingkaiLtr, labelWarna, (x, y - 10), # tulis nama warna di atas kotak
cv2.FONT_HERSHEY_SIMPLEX, 0.7, warna, 2) # dengan font Hershey, ukuran 0.7, tebal 2 piksel
# Tampilkan label perintah aktif di layar meski warna sudah tidak terdeteksi
if perintahTerakhir is not None: # jika sudah ada perintah aktif yang tersimpan
teks_perintah = f"Perintah: {perintahTerakhir}" # buat teks yang menampilkan perintah aktif saat ini
warna_perintah = warnaKotak[perintahTerakhir] # ambil warna teks sesuai perintah aktif dari kamus warnaKotak
cv2.putText(bingkaiLtr, teks_perintah, (10, 60), # tampilkan teks perintah aktif di layar posisi y=60
cv2.FONT_HERSHEY_SIMPLEX, 0.8, warna_perintah, 2) # dengan font Hershey, ukuran 0.8, tebal 2 piksel
with lock_jarak: # kunci akses variabel global agar aman dibaca
jarak_tampil = jarak_cm_global # ambil nilai jarak terkini untuk ditampilkan di layar
bahaya_tampil = statusBahaya # ambil status bahaya terkini untuk menentukan warna teks jarak
teks_jarak = f"Jarak: {jarak_tampil:.1f} cm" # format teks jarak dengan 1 angka desimal
warna_jarak = (0, 0, 255) if bahaya_tampil \
else (0, 255, 255) if jarak_tampil <= JARAK_HATI \
else (0, 255, 0) # pilih warna teks: merah=bahaya, kuning=hati-hati, hijau=aman
cv2.putText(bingkaiLtr, teks_jarak, (10, 30), # tampilkan teks jarak di pojok kiri atas layar (posisi x=10, y=30)
cv2.FONT_HERSHEY_SIMPLEX, 0.8, warna_jarak, 2) # dengan font Hershey, ukuran 0.8, tebal 2 piksel
# Tampilkan peringatan BAHAYA di layar saat robot berhenti paksa karena sensor
if bahaya_tampil: # jika kondisi bahaya aktif (jarak <= 5 cm)
cv2.putText(bingkaiLtr, "!! BAHAYA - ROBOT BERHENTI !!", (10, 90), # tulis teks peringatan di layar posisi y=90
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) # dengan warna merah, ukuran 0.7, tebal 2 piksel
kendalikanRobot(labelWarna) # panggil fungsi kendali robot dengan warna yang terdeteksi frame ini (bisa None jika tidak ada)
cv2.imshow("Deteksi Warna & Robot - Kelompok RE-3D/06", bingkaiLtr) # tampilkan bingkai gambar yang sudah diberi anotasi ke jendela OpenCV
if cv2.waitKey(1) & 0xFF == ord('q'): # tunggu input keyboard selama 1 ms; jika tombol 'q' ditekan
break # keluar dari perulangan utama dan hentikan program
except KeyboardInterrupt: # tangkap jika pengguna menekan Ctrl+C untuk menghentikan program paksa
print("\nDipaksa Berhenti Oleh Pengguna (CTRL+C)") # tampilkan pesan pemberitahuan penghentian paksa
finally: # blok ini selalu dijalankan, baik program selesai normal maupun dihentikan paksa
cv2.destroyAllWindows() # tutup semua jendela tampilan OpenCV
robot.stop() # pastikan semua motor robot berhenti (keamanan)
bel.off() # pastikan buzzer dimatikan (keamanan)
kamera.stop() # hentikan proses pengambilan gambar kamera
kamera.close() # lepaskan resource kamera agar tidak terkunci
print("\n\tKamera Dimatikan ... Demo Berakhir") # tampilkan pesan bahwa program telah berakhir
VI. Kesimpulan
Robot yang dibangun mampu menggabungkan deteksi warna berbasis OpenCV dengan pengaman jarak berbasis sensor
ultrasonik dalam satu sistem kendali yang berjalan pada dua thread terpisah. Penyimpanan perintah warna
terakhir membuat robot tetap bergerak konsisten meski objek warna sempat hilang dari kamera, sementara sensor
ultrasonik memastikan robot tidak menabrak penghalang terlepas dari perintah warna yang sedang berjalan.
Pengujian lanjutan pada kondisi pencahayaan rendah dan pada permukaan lantai yang tidak rata masih perlu
dilakukan untuk mengetahui batas kemampuan sistem ini secara lebih menyeluruh.
Komentar
Posting Komentar