Panduan · 14 mnt baca

Robot Pengikut Garis dengan Arduino: Sensor TCRT5000 dan PID

Buat robot pengikut garis dengan Arduino: sensor TCRT5000, penempatan dan kalibrasi, kode if-else dan PID, penyetelan Kp/Kd, driver motor, baterai, dan aturan lomba.

Robot pengikut garis (line follower) adalah kendaraan otonom yang mendeteksi garis hitam (atau putih) di lantai dengan sensor inframerah dan terus mengatur kecepatan kedua rodanya agar tetap berada di garis itu. Ini salah satu proyek robot sungguhan pertama yang dibuat orang dengan Arduino, karena menggabungkan membaca sensor, mengambil keputusan, dan mengendalikan motor dalam satu proyek. Kereta otonom (AGV) yang memindahkan material di pabrik bekerja dengan ide yang sama, dan line follower adalah salah satu kategori paling ramai di lomba robotika sekolah.

Di panduan ini kamu akan mempelajari cara kerja sensor TCRT5000, perbedaan susunan 2, 3, dan 5 sensor, di ketinggian dan jarak berapa sensor dipasang, dan cara mengkalibrasi ambangnya. Pertama kamu akan membuat robot bergerak dengan sketch if-else sederhana, lalu pindah ke versi dengan kendali PID yang mengikuti garis tanpa zig-zag atau keluar lintasan di tikungan. Selain kode yang berfungsi untuk Arduino Uno, ESP32, dan Raspberry Pi Pico, kamu juga akan menemukan cara memilih driver motor dan baterai, aturan lomba yang umum, serta solusi untuk masalah yang paling sering muncul.

Sensor pantulan inframerah TCRT5000
TCRT5000: LED inframerah berwarna kebiruan dan fototransistor hitam berdampingan dalam satu wadah; modul sensor garis dibuat di sekitar komponen ini.

Bagaimana cara kerja robot pengikut garis?

Permukaan putih memantulkan kembali sebagian besar cahaya inframerah, sedangkan permukaan hitam doff menyerap sebagian besarnya. Sensor di bawah robot mengukur perbedaan ini untuk mengetahui di mana posisi garis relatif terhadap robot. Robot tidak punya setir; ia berbelok dengan yang disebut differential drive: jika roda kiri berputar lebih cepat dari roda kanan, robot berbelok ke kanan, dan jika lebih lambat, robot berbelok ke kiri. Program menjalankan loop yang sama ratusan kali per detik: baca sensor, hitung seberapa jauh garis bergeser, lalu koreksi kecepatan kedua motor sesuai itu. Makin cepat dan stabil loop tertutup ini berjalan, makin halus gerakan robot.

KomponenRekomendasiCatatan
Board pengendaliArduino Uno atau NanoNano lebih mudah muat di sasis kecil; ESP32 atau Pico juga bisa
Sensor garisSusunan TCRT5000 3 atau 5 kanal, QTR-8ASusunan dengan output analog memberi hasil lebih baik dengan PID
Driver motorL298N atau TB6612FNGTB6612FNG lebih kecil dan lebih efisien
Motor2 motor DC bergigi (TT 1:48 atau N20)Kedua motor sebaiknya model dan kecepatannya sama
Roda2 roda penggerak dan 1 roda casterRoda 65 mm paling umum
Daya2 × sel Li-ion 18650 (7,4 V) dan saklarBaterai 9 V PP3 terlalu lemah untuk motor
LainnyaSasis, push button, kabel jumperTombol memudahkan kalibrasi dan memulai
Board Arduino Nano
Board Arduino Nano
Driver motor L298N
Driver motor L298N
Motor gigi mikro N20
Motor gigi mikro N20
Baterai Li-ion 18650
Baterai Li-ion 18650

Sensor TCRT5000: susunan 2, 3, dan 5 sensor

TCRT5000 terdiri dari LED inframerah (950 nm) dan fototransistor yang berdampingan dalam wadah yang sama. Makin banyak cahaya LED yang memantul dari lantai dan sampai ke fototransistor, makin kuat transistor menghantar. Sensor bekerja paling baik pada jarak sekitar 2,5 mm; di atas 1 cm perbedaan hitam dan putih cepat mengecil. Modul siap pakai berisi komparator LM393: di kebanyakan modul pin DO mengeluarkan HIGH di atas hitam dan LOW di atas putih, tergantung ambang yang diatur dengan potensiometer, dan LED di board menyala di atas permukaan putih. Pin AO memberi nilai analog mentah: tinggi di atas hitam, rendah di atas putih. Kamu akan menemukan semua detail tentang sensor ini di Sensor Inframerah TCRT5000.

SensorPenempatanAlgoritmaKapan dipilih
2Di kedua sisi garis; keduanya biasanya melihat putihif-elsePercobaan pertama, lintasan lebar dengan tikungan landai
3Yang tengah di atas garis, yang luar di tepinyaif-else atau PID sederhanaProyek sekolah, lomba tingkat pemula
5Berjajar dengan jarak sama, yang tengah di atas garisPID (rata-rata berbobot)Mengikuti garis dengan cepat dan halus
8Barisan lebar (seperti QTR-8A)PID plus deteksi persimpanganLintasan lomba dengan belokan tajam dan persimpangan

Penempatan sensor: ketinggian, jarak antar sensor, dan jarak ke depan

Sebagus apa pun kodemu, robot tidak bisa berjalan dengan baik jika sensornya di tempat yang salah. Pasang batang sensor di depan as roda, sejajar dengan lantai dan simetris terhadap garis tengah robot. Ukuran-ukuran ini adalah titik awal yang bagus:

  • Ketinggian: Sisakan 3–5 mm antara bagian bawah sensor dan lantai. Pololu menyebut 3 mm sebagai jarak optimal dan 6 mm sebagai jarak maksimum yang dianjurkan untuk susunan QTR-8A-nya. Jika lebih tinggi, perbedaan hitam dan putih mengecil, sehingga robot kehilangan garis.
  • Jarak antar sensor: Pada susunan analog, buat jarak dua sensor antara setengah sampai dua pertiga lebar garis; 10–13 mm cocok untuk garis 20 mm. Dengan begitu garis biasanya berada di bawah dua sensor dan posisinya terhitung dengan halus.
  • Susunan digital 3 sensor: Pasang sensor tengah tepat di atas garis dan sensor samping tepat di luar tepinya; untuk garis 20 mm itu sekitar 18–22 mm dari pusat ke pusat.
  • Jarak ke depan: Pasang sensor 4–8 cm di depan as roda. Terlalu dekat dan robot terlambat menyadari tikungan; terlalu jauh dan belokan kecil saja membuat sensor berayun banyak, sehingga robot bergoyang.
  • Cahaya sekitar: Sinar matahari dan lampu halogen juga mengandung cahaya inframerah. Melindungi sensor dengan rok hitam atau selotip membuat pembacaan jauh lebih stabil.
Kesalahan yang umum adalah memasang sensor miring atau terlalu tinggi. Jika robot kehilangan garis di tikungan pertama, cek ketinggian sensor sebelum kodenya: bahkan beberapa milimeter bisa membuat pembacaan turun setengah. Isolasi listrik yang mengilap juga memantulkan inframerah, jadi garis hitam kadang terlihat putih; pakai selotip doff atau garis cetak jika bisa.

Pengkabelan: Arduino Uno, ESP32, dan Pico

Tabel di bawah persis sesuai dengan sketch uji sensor dan PID; pengkabelan untuk contoh if-else 3 sensor dijelaskan di bagiannya sendiri. Beri nomor sensor dari kiri ke kanan dilihat dari belakang robot: sensor paling kiri adalah nomor 1. Kita memakai L298N sebagai driver motor; fungsi setiap pin dan cara kerja H-bridge dijelaskan rinci di Mengendalikan Motor DC dengan L298N. Pico hanya punya tiga input analog, jadi di sana kita memakai sensor 1, 3, dan 5.

SambunganArduino UnoESP32Raspberry Pi Pico
AO sensor 1 (paling kiri)A0GPIO 36GP26
AO sensor 2A1GPIO 39-
AO sensor 3 (tengah)A2GPIO 34GP27
AO sensor 4A3GPIO 35-
AO sensor 5 (paling kanan)A4GPIO 32GP28
VCC sensor5V3V33V3
ENA L298N (kecepatan motor kiri)D9GPIO 25GP15
IN1, IN2 L298ND8, D7GPIO 26, 27GP14, GP13
ENB L298N (kecepatan motor kanan)D10GPIO 33GP10
IN3, IN4 L298ND5, D4GPIO 18, 19GP11, GP12
Tombol start (kaki lainnya ke GND)D2GPIO 23GP16
GNDGNDGNDGND (bersama baterai dan driver)
Terminal negatif baterai, GND driver motor, dan GND board harus tersambung semuanya; tanpa ground bersama, motor berperilaku kacau. Jangan pernah memberi daya motor dari pin 5V board. Di ESP32 dan Pico, beri daya sensor dari 3V3: output AO modul yang diberi daya 5 V bisa naik sampai 5 V dan merusak input analog 3,3 V.

Memilih driver motor dan baterai

L298N murah dan tangguh, tapi transistor bipolarnya menelan 1,5–3 V: dari paket baterai 7,4 V hanya sekitar 5–5,5 V yang sampai ke motor. Pada robot kecil dan cepat, TB6612FNG atau DRV8833 berbasis MOSFET bekerja lebih baik. Dengan TB6612FNG kodenya tetap sama: kamu menyambungkan ENA, IN1, dan IN2 ke PWMA, AIN1, dan AIN2 (PWMB, BIN1, dan BIN2 di kanal B) dan menyambungkan pin STBY ke VCC. DRV8833 tidak punya pin kecepatan (enable) terpisah; sinyal PWM langsung masuk ke pin IN, jadi kamu perlu menyesuaikan fungsi drive(). Untuk daya, pilihan paling praktis adalah dua sel Li-ion 18650 seri: 8,4 V ketika penuh, 7,4 V nominal, dan mudah memberi arus tinggi. Baterai 9 V PP3 tidak sanggup menahan arus motor dan cepat habis. Kamu bisa menghitung berapa lama baterai akan bertahan dengan alat Umur baterai.

DriverTegangan motorArus per kanalTegangan jatuhPenilaian
L298N5–35 V2 A1,5–3 VTangguh, tapi besar dan tidak efisien
TB6612FNG4,5–13,5 V1,2 A (puncak 3,2 A)Sangat rendahPaling sepadan untuk line follower
DRV88332,7–10,8 V1,5 A (puncak 2 A)Sangat rendahRobot kecil dengan motor N20
L9110S2,5–12 V0,8 ARendahHanya robot ringan dan lambat
Motor DC bergigi TT kuning dan roda
Motor gigi TT kuning dengan roda 65 mm: gearbox menurunkan kecepatan dan menaikkan torsi; ini motor yang paling umum di proyek line follower dan mobil robot.

Contoh cepat soal kecepatan: motor TT kuning (1:48) berputar sekitar 200 rpm tanpa beban di 6 V. Roda 65 mm punya keliling π × 65 ≈ 204 mm, jadi robot paling jauh bisa menempuh 200 × 0,204 ≈ 41 m per menit, atau kira-kira 0,7 m per detik. Itu lebih dari cukup untuk kebanyakan lintasan sekolah; tantangan sebenarnya adalah tidak kehilangan garis pada kecepatan itu. Robot yang lebih cepat memakai motor gigi mikro N20 dan sasis ringan. Seiring tegangan baterai turun, motor melambat dan nilai PID yang sudah kamu setel bergeser; mengukur tegangan baterai dengan pembagi tegangan dan menskalakan kecepatan agar sesuai adalah peningkatan tingkat lanjut.

Langkah 1: Uji sensor dan cari ambangnya

Sebelum menyambungkan motor, cari tahu apa yang dilihat sensor. Sketch di bawah mencetak nilai analog mentah kelima sensor yang dipisahkan tab; buka Tools > Serial Plotter di Arduino IDE pada 115200 baud dan kamu akan melihat setiap sensor sebagai garisnya sendiri. Gerakkan robot perlahan melintasi garis dengan tangan dan perhatikan bagaimana nilainya berubah.

C++ (Arduino IDE)
1// 5 sensörün ham değerlerini okur / reads the raw values of 5 sensors
2const int N = 5;
3const int SENSOR[N] = {A0, A1, A2, A3, A4};   // A0 en solda / A0 is the leftmost
4
5void setup() {
6  Serial.begin(115200);
7}
8
9void loop() {
10  for (int i = 0; i < N; i++) {
11    Serial.print(analogRead(SENSOR[i]));
12    Serial.print(i < N - 1 ? '\t' : '\n');    // Serial Plotter için sekme / tabs for the Serial Plotter
13  }
14  delay(50);
15}

Pada 5 V, modul TCRT5000 yang umum terbaca 30–200 di permukaan putih dan 600–1000 di garis hitam, tapi angka-angka ini berubah tergantung ketinggian sensor, bahan lantai, dan cahaya sekitar. Ambang paling sederhana adalah ambang = (nilai putih + nilai hitam) / 2. Misalnya, jika kamu membaca 80 di putih dan 820 di hitam, ambangnya 450. Karena setiap sensor terbaca sedikit berbeda, sketch PID melakukan ini secara otomatis: selama kalibrasi ia mencatat nilai terendah dan tertinggi setiap sensor, lalu menskalakan setiap pembacaan ke antara 0 (putih) dan 1000 (hitam) dengan (reading − min) × 1000 / (max − min). Dengan begitu ambangnya menjadi 500 untuk setiap sensor.

Pada modul dengan output digital (DO) kamu mengatur ambang dengan potensiometer di board. Putar trimmer-nya sampai LED modul tetap mati ketika sensor di atas garis hitam dan menyala ketika di atas permukaan putih; posisi tepat di tengah kedua titik itu paling stabil. Lakukan penyetelan di lintasan yang akan kamu pakai untuk lomba dan di bawah pencahayaan yang sama.

Langkah 2: Algoritma if-else sederhana (3 sensor)

Untuk robot pertama yang berfungsi, pendekatan paling jelas adalah memilih dari beberapa gerakan siap pakai berdasarkan keadaan tiga sensor. Sambungkan output DO modul 3 kanal ke A0 (kiri), A1 (tengah), dan A2 (kanan); pin analog Uno juga bisa bekerja sebagai input digital. Logikanya ditunjukkan di tabel ini (1 berarti sensor melihat garis):

KiriTengahKananArtiGerakan
010Garis di tengahJalan lurus
110Garis sedikit ke kiriRoda kiri melambat, belok kiri pelan
100Garis jauh ke kiriRoda kiri mundur, belok kiri tajam
011Garis sedikit ke kananRoda kanan melambat, belok kanan pelan
001Garis jauh ke kananRoda kanan mundur, belok kanan tajam
111Persimpangan atau garis finisJalan lurus menyeberang
000Garis hilangBerbelok ke sisi tempat garis terakhir terlihat
C++ (Arduino IDE)
1// 3 sensörlü basit çizgi izleyen / simple 3-sensor line follower
2const int ENA = 9, IN1 = 8, IN2 = 7;      // sol motor / left motor
3const int ENB = 10, IN3 = 5, IN4 = 4;     // sağ motor / right motor
4const int S_LEFT = A0, S_MID = A1, S_RIGHT = A2;   // sensörlerin DO çıkışları / sensor DO outputs
5const bool WHITE_LINE = false;            // siyah zemin + beyaz çizgi ise true / true for a white line on black
6
7const int SPEED = 150;                    // düz gidiş hızı / straight-line speed
8const int SOFT = 80;                      // hafif dönüşte iç teker / inner wheel on a soft turn
9const int BACK = -90;                     // sert dönüşte iç teker geri / inner wheel reverses on a sharp turn
10int lastSide = 0;                         // -1 sol, 1 sağ / -1 left, 1 right
11
12void drive(int left, int right) {         // her biri -255 … 255 / each -255 … 255
13  left = constrain(left, -255, 255);
14  right = constrain(right, -255, 255);
15  digitalWrite(IN1, left >= 0);  digitalWrite(IN2, left < 0);
16  digitalWrite(IN3, right >= 0); digitalWrite(IN4, right < 0);
17  analogWrite(ENA, abs(left));
18  analogWrite(ENB, abs(right));
19}
20
21void setup() {
22  int outputs[] = {ENA, IN1, IN2, ENB, IN3, IN4};
23  for (int p : outputs) pinMode(p, OUTPUT);
24  pinMode(S_LEFT, INPUT);
25  pinMode(S_MID, INPUT);
26  pinMode(S_RIGHT, INPUT);
27}
28
29void loop() {
30  bool l = digitalRead(S_LEFT) != WHITE_LINE;    // true = sensör çizgide / true = sensor on the line
31  bool m = digitalRead(S_MID) != WHITE_LINE;
32  bool r = digitalRead(S_RIGHT) != WHITE_LINE;
33
34  if (m && !l && !r) {                    // tam ortada: düz git / centered: go straight
35    drive(SPEED, SPEED);
36  } else if (l && r) {                    // kavşak ya da bitiş çizgisi: düz geç / junction or finish line: go straight
37    drive(SPEED, SPEED);
38  } else if (l && m) {                    // çizgi biraz solda / line slightly to the left
39    drive(SOFT, SPEED);  lastSide = -1;
40  } else if (r && m) {                    // çizgi biraz sağda / line slightly to the right
41    drive(SPEED, SOFT);  lastSide = 1;
42  } else if (l) {                         // çizgi çok solda / line far to the left
43    drive(BACK, SPEED);  lastSide = -1;
44  } else if (r) {                         // çizgi çok sağda / line far to the right
45    drive(SPEED, BACK);  lastSide = 1;
46  } else {                                // çizgi kayıp: son görülen tarafa dön / line lost: turn to the last seen side
47    if (lastSide < 0)      drive(BACK, SPEED);
48    else if (lastSide > 0) drive(SPEED, BACK);
49    else                   drive(SOFT, SOFT);
50  }
51}

Variabel lastSide mengingat di sisi mana robot terakhir melihat garis; jika ketiga sensor kehilangan garis di tikungan tajam, robot berbelok ke arah itu untuk menemukannya lagi alih-alih berjalan lurus tanpa arah. Dengan dua sensor, logika yang sama bahkan lebih sederhana: sensor berada di kedua sisi garis, robot jalan lurus selama keduanya melihat putih, berbelok ke kiri ketika sensor kiri melihat hitam, dan berbelok ke kanan ketika sensor kanan melihatnya. Kelemahan metode ini adalah gerakannya bertingkat: robot hanya berpindah di antara beberapa kecepatan tetap, jadi ia sedikit zig-zag bahkan di jalan lurus dan keluar lintasan di tikungan begitu kecepatannya kamu naikkan.

Langkah 3: Mengikuti garis dengan halus memakai PID

PID menerapkan koreksi yang sebanding dengan seberapa jauh robot menyimpang dari garis. Pertama, posisi garis dihitung dari kelima sensor sebagai rata-rata berbobot: nilai 0–1000 setiap sensor dikalikan dengan posisinya sendiri (0, 1000, 2000, 3000, 4000), hasilnya dijumlahkan lalu dibagi dengan jumlah nilainya. Hasilnya angka antara 0 dan 4000, dan 2000 ketika garis tepat di tengah. Misalnya, jika sensor terbaca 0, 0, 300, 900, 0, posisinya (300 × 2000 + 900 × 3000) / 1200 = 2750. Error = posisi − 2000: nilai positif berarti garis di kanan, nilai negatif berarti di kiri.

Koreksinya adalah jumlah tiga suku: koreksi = Kp × error + Ki × jumlah error + Kd × (error − error sebelumnya). Suku P berbelok makin keras ketika penyimpangannya makin besar. Suku D melihat seberapa cepat error berubah dan mengerem ketika robot mendekati garis, sehingga meredam osilasi. Suku I memperbaiki error kecil yang lama bertahan di satu sisi, tapi pada line follower biasanya dibiarkan nol. Lalu motor kiri berjalan pada kecepatan dasar + koreksi dan motor kanan pada kecepatan dasar − koreksi. Misalnya, dengan error 800 dan Kp = 0.06 koreksinya 48; pada kecepatan dasar 140 motor kiri berjalan di 188 dan motor kanan di 92, dan robot berbelok halus ke kanan.

C++ (Arduino IDE)
1// PID çizgi izleyen: Arduino Uno + 5 analog sensör + L298N
2// PID line follower: Arduino Uno + 5 analog sensors + L298N
3const int ENA = 9, IN1 = 8, IN2 = 7;      // sol motor / left motor
4const int ENB = 10, IN3 = 5, IN4 = 4;     // sağ motor / right motor
5const int BUTTON = 2;                     // diğer bacağı GND'ye / other leg to GND
6const int N = 5;
7const int SENSOR[N] = {A0, A1, A2, A3, A4};   // A0 en solda / A0 is the leftmost
8const bool WHITE_LINE = false;            // siyah zemin + beyaz çizgi ise true / true for a white line on black
9const int CENTER = (N - 1) * 500;         // orta konum: 2000 / center position: 2000
10
11float Kp = 0.06, Ki = 0.0, Kd = 0.6;      // başlangıç değerleri / starting values
12int baseSpeed = 140;                      // düzlük hızı (0-255) / straight-line speed (0-255)
13const unsigned long PERIOD_MS = 5;        // sabit döngü süresi / fixed loop period
14
15int minVal[N], maxVal[N];
16int lastPosition = CENTER;
17float integral = 0, lastError = 0;
18unsigned long lastTime = 0;
19
20void drive(int left, int right) {         // her biri -255 … 255 / each -255 … 255
21  left = constrain(left, -255, 255);
22  right = constrain(right, -255, 255);
23  digitalWrite(IN1, left >= 0);  digitalWrite(IN2, left < 0);
24  digitalWrite(IN3, right >= 0); digitalWrite(IN4, right < 0);
25  analogWrite(ENA, abs(left));
26  analogWrite(ENB, abs(right));
27}
28
29void waitButton() {
30  while (digitalRead(BUTTON) == HIGH) {}  // basılmasını bekle / wait for a press
31  delay(30);
32  while (digitalRead(BUTTON) == LOW) {}   // bırakılmasını bekle / wait for the release
33  delay(30);
34}
35
36void calibrate() {                        // 5 sn: robotu çizginin üstünde sağa sola gezdir / 5 s: sweep the robot across the line
37  for (int i = 0; i < N; i++) { minVal[i] = 1023; maxVal[i] = 0; }
38  digitalWrite(LED_BUILTIN, HIGH);
39  unsigned long start = millis();
40  while (millis() - start < 5000) {
41    for (int i = 0; i < N; i++) {
42      int v = analogRead(SENSOR[i]);
43      if (v < minVal[i]) minVal[i] = v;
44      if (v > maxVal[i]) maxVal[i] = v;
45    }
46  }
47  digitalWrite(LED_BUILTIN, LOW);
48}
49
50int readPosition() {                      // 0 (en sol) … 4000 (en sağ) / 0 (leftmost) … 4000 (rightmost)
51  long sum = 0, weighted = 0;
52  bool onLine = false;
53  for (int i = 0; i < N; i++) {
54    int range = max(maxVal[i] - minVal[i], 1);
55    long v = (long)(analogRead(SENSOR[i]) - minVal[i]) * 1000 / range;
56    v = constrain(v, 0L, 1000L);          // 0 = beyaz, 1000 = siyah / 0 = white, 1000 = black
57    if (WHITE_LINE) v = 1000 - v;
58    if (v > 500) onLine = true;           // eşik: kalibrasyonun ortası / threshold: middle of the calibration
59    if (v > 50) {                         // küçük gürültüyü yok say / ignore small noise
60      weighted += v * (i * 1000L);
61      sum += v;
62    }
63  }
64  if (!onLine) {                          // çizgi kayıp: son görülen tarafa dön / line lost: turn to the last seen side
65    return (lastPosition < CENTER) ? 0 : (N - 1) * 1000;
66  }
67  lastPosition = weighted / sum;
68  return lastPosition;
69}
70
71void setup() {
72  int outputs[] = {ENA, IN1, IN2, ENB, IN3, IN4, LED_BUILTIN};
73  for (int p : outputs) pinMode(p, OUTPUT);
74  pinMode(BUTTON, INPUT_PULLUP);
75  drive(0, 0);
76  waitButton();                           // 1. basış: kalibrasyon / 1st press: calibration
77  calibrate();
78  waitButton();                           // 2. basış: yarış / 2nd press: race
79  lastTime = millis();
80}
81
82void loop() {
83  if (millis() - lastTime < PERIOD_MS) return;
84  lastTime += PERIOD_MS;
85
86  float error = readPosition() - CENTER;  // artı: çizgi sağda / positive: line is to the right
87  integral = constrain(integral + error, -20000.0f, 20000.0f);   // birikmeyi sınırla / anti-windup
88  float derivative = error - lastError;
89  lastError = error;
90
91  int correction = (int)(Kp * error + Ki * integral + Kd * derivative);
92  drive(baseSpeed + correction, baseSpeed - correction);
93}

Setelah upload, tekan tombol sekali: LED di board menyala selama 5 detik. Selama waktu itu, geser robot ke kiri dan ke kanan melintasi garis dengan tangan beberapa kali agar setiap sensor melihat hitam dan putih. Ketika LED padam, letakkan robot di garis dan tekan tombol lagi. Loop berjalan setiap 5 ms memakai millis(); periode yang tetap menjaga suku D selalu pada skala yang sama. Jika garis hilang sama sekali, readPosition() mengembalikan 0 atau 4000 tergantung sisi tempat garis terakhir terlihat, dan robot mencarinya dengan belokan paling tajam. Untuk pengkabelan tombol lihat Cara Menghubungkan Push Button ke Arduino, dan untuk pengaturan waktu tanpa delay lihat Arduino millis() dan delay().

Cara menyetel Kp dan Kd

  1. Buat kecepatan dasar tetap rendah (misalnya 100) dan atur Ki serta Kd ke nol.
  2. Mulai Kp dari nilai kecil (0.02) dan naikkan bertahap sampai robot bisa melewati tikungan. Ketika robot mulai berosilasi cepat dan teratur di sekitar garis, kamu sudah mencapai batas atas Kp; tetaplah sedikit di bawah nilai itu.
  3. Mulai Kd dari sekitar 10 kali Kp dan naikkan sampai osilasinya hilang. Jika Kd terlalu besar, robot bergetar dan motornya berdecit.
  4. Begitu robot berjalan benar-benar lurus di jalan lurus dan halus di tikungan, naikkan kecepatan dasar sebesar 10–20 dan ulangi langkah 2 dan 3.
  5. Coba Ki hanya dengan nilai sangat kecil (seperti 0.0001) jika robot terus miring ke satu sisi di jalan lurus yang panjang.
  6. Catat nilai yang kamu temukan dan tegangan baterai pada waktu itu; seiring baterai melemah, nilai yang sama berperilaku berbeda.
Pada skala yang dipakai di artikel ini (posisi 0–4000, PWM 0–255, loop 5 ms), rentang awal yang bagus adalah 0.04–0.08 untuk Kp dan 0.4–1.2 untuk Kd. Jangan taruh Serial.print di dalam loop selama menyetel: setiap cetakan memperlambat loop dan mengacaukan suku D. Jika kamu perlu melihat nilainya, cetak paling sering sekali setiap 200 ms.

Line follower dengan ESP32: setel PID dari ponselmu

Kelebihan besar ESP32 adalah kamu bisa mengubah nilai PID dari ponsel tanpa meng-upload ulang kode setiap kali. Logikanya sama dengan versi Uno; bedanya: input analog ESP32 12 bit (0–4095), sensor harus di pin ADC1, GPIO 32–39 (pin ADC2 tidak bisa dibaca ketika Wi-Fi menyala), dan sensor diberi daya dari 3,3 V. analogWrite() bekerja di core Arduino ESP32 versi 2.x maupun 3.x. Instal aplikasi seperti Serial Bluetooth Terminal di ponsel Android-mu, sambungkan ke perangkat “CizgiRobot”, lalu kirim perintah seperti p0.07, d0.9, atau s160; robot langsung memakai nilai baru itu dan mengirimnya kembali. Bluetooth klasik hanya ada di ESP32 asli (tidak di S3 atau C3), dan iPhone tidak mendukung koneksi serial semacam ini. Jika kamu baru mengenal ESP32, baca dulu Apa Itu ESP32?.

C++ (Arduino IDE)
1// ESP32 PID çizgi izleyen + Bluetooth ile canlı ayar
2// ESP32 PID line follower + live tuning over Bluetooth
3#include "BluetoothSerial.h"
4
5BluetoothSerial SerialBT;
6
7const int ENA = 25, IN1 = 26, IN2 = 27;   // sol motor / left motor
8const int ENB = 33, IN3 = 18, IN4 = 19;   // sağ motor / right motor
9const int BUTTON = 23;                    // diğer bacağı GND'ye / other leg to GND
10const int LED_PIN = 2;                    // DevKit üzerindeki LED / onboard LED on the DevKit
11const int N = 5;
12const int SENSOR[N] = {36, 39, 34, 35, 32};   // yalnız ADC1 pinleri / ADC1 pins only
13const bool WHITE_LINE = false;            // siyah zemin + beyaz çizgi ise true / true for a white line on black
14const int CENTER = (N - 1) * 500;
15
16float Kp = 0.06, Ki = 0.0, Kd = 0.6;
17int baseSpeed = 140;
18const unsigned long PERIOD_MS = 5;
19
20int minVal[N], maxVal[N];
21int lastPosition = CENTER;
22float integral = 0, lastError = 0;
23unsigned long lastTime = 0;
24
25void drive(int left, int right) {         // her biri -255 … 255 / each -255 … 255
26  left = constrain(left, -255, 255);
27  right = constrain(right, -255, 255);
28  digitalWrite(IN1, left >= 0);  digitalWrite(IN2, left < 0);
29  digitalWrite(IN3, right >= 0); digitalWrite(IN4, right < 0);
30  analogWrite(ENA, abs(left));
31  analogWrite(ENB, abs(right));
32}
33
34void waitButton() {
35  while (digitalRead(BUTTON) == HIGH) {}
36  delay(30);
37  while (digitalRead(BUTTON) == LOW) {}
38  delay(30);
39}
40
41void calibrate() {                        // ESP32 ADC 12 bit: 0-4095 / ESP32 ADC is 12-bit: 0-4095
42  for (int i = 0; i < N; i++) { minVal[i] = 4095; maxVal[i] = 0; }
43  digitalWrite(LED_PIN, HIGH);
44  unsigned long start = millis();
45  while (millis() - start < 5000) {
46    for (int i = 0; i < N; i++) {
47      int v = analogRead(SENSOR[i]);
48      if (v < minVal[i]) minVal[i] = v;
49      if (v > maxVal[i]) maxVal[i] = v;
50    }
51  }
52  digitalWrite(LED_PIN, LOW);
53}
54
55int readPosition() {
56  long sum = 0, weighted = 0;
57  bool onLine = false;
58  for (int i = 0; i < N; i++) {
59    int range = max(maxVal[i] - minVal[i], 1);
60    long v = (long)(analogRead(SENSOR[i]) - minVal[i]) * 1000 / range;
61    v = constrain(v, 0L, 1000L);
62    if (WHITE_LINE) v = 1000 - v;
63    if (v > 500) onLine = true;
64    if (v > 50) {
65      weighted += v * (i * 1000L);
66      sum += v;
67    }
68  }
69  if (!onLine) {
70    return (lastPosition < CENTER) ? 0 : (N - 1) * 1000;
71  }
72  lastPosition = weighted / sum;
73  return lastPosition;
74}
75
76void readTuning() {                       // telefondan "p0.07", "d0.9", "s160" gibi komutlar / commands like "p0.07", "d0.9", "s160" from the phone
77  if (!SerialBT.available()) return;
78  char cmd = SerialBT.read();
79  if (cmd != 'p' && cmd != 'i' && cmd != 'd' && cmd != 's') return;   // satır sonlarını atla / skip line endings
80  float value = SerialBT.parseFloat();
81  if (cmd == 'p') Kp = value;
82  if (cmd == 'i') { Ki = value; integral = 0; }
83  if (cmd == 'd') Kd = value;
84  if (cmd == 's') baseSpeed = (int)value;
85  SerialBT.printf("Kp=%.3f Ki=%.4f Kd=%.3f speed=%d\n", Kp, Ki, Kd, baseSpeed);
86}
87
88void setup() {
89  int outputs[] = {ENA, IN1, IN2, ENB, IN3, IN4, LED_PIN};
90  for (int p : outputs) pinMode(p, OUTPUT);
91  pinMode(BUTTON, INPUT_PULLUP);
92  drive(0, 0);
93  SerialBT.begin("CizgiRobot");           // telefonda görünecek ad / name shown on the phone
94  SerialBT.setTimeout(20);                // parseFloat robotu bekletmesin / keep parseFloat from blocking
95  waitButton();
96  calibrate();
97  waitButton();
98  lastTime = millis();
99}
100
101void loop() {
102  readTuning();
103  if (millis() - lastTime < PERIOD_MS) return;
104  lastTime += PERIOD_MS;
105
106  float error = readPosition() - CENTER;
107  integral = constrain(integral + error, -20000.0f, 20000.0f);
108  float derivative = error - lastError;
109  lastError = error;
110
111  int correction = (int)(Kp * error + Ki * integral + Kd * derivative);
112  drive(baseSpeed + correction, baseSpeed - correction);
113}
Beberapa aturan lomba melarang modul Wi-Fi, Bluetooth, atau RF di robot, bahkan board yang punya Wi-Fi sama sekali. Cara paling aman adalah memakai ESP32 untuk penyetelan dan latihan, lalu bertanding dengan Arduino Uno, Nano, atau Pico tanpa Wi-Fi; jika ragu, tanyakan ke panitia.

Line follower dengan Raspberry Pi Pico dan MicroPython

Pico hanya punya tiga input analog yang tersedia untuk pengguna (GP26, GP27, GP28), jadi kode di bawah bekerja dengan tiga sensor analog dan menghitung posisi antara 0 dan 2000. Jika kamu ingin lima sensor, kamu bisa menyambungkan modul 5 kanal dengan output digital ke lima GPIO mana saja dan menghitung setiap sensor sebagai 0 atau 1000; rata-rata berbobotnya jadi lebih kasar tapi tetap bekerja. read_u16() mengembalikan nilai dari 0 sampai 65535, dan kecepatan motor diberikan dalam persen (dari -100 sampai 100). Untuk instalasi dan langkah pertama, lihat Apa Itu Raspberry Pi Pico?.

MicroPython
1from machine import Pin, PWM, ADC
2import time
3
4ena = PWM(Pin(15)); ena.freq(1000)        # sol motor hızı / left motor speed
5in1 = Pin(14, Pin.OUT); in2 = Pin(13, Pin.OUT)
6enb = PWM(Pin(10)); enb.freq(1000)        # sağ motor hızı / right motor speed
7in3 = Pin(11, Pin.OUT); in4 = Pin(12, Pin.OUT)
8button = Pin(16, Pin.IN, Pin.PULL_UP)     # diğer bacağı GND'ye / other leg to GND
9led = Pin("LED", Pin.OUT)
10sensors = [ADC(26), ADC(27), ADC(28)]     # sol, orta, sağ / left, middle, right
11WHITE_LINE = False                        # siyah zemin + beyaz çizgi ise True / True for a white line on black
12
13N = len(sensors)
14CENTER = (N - 1) * 500                    # orta konum: 1000 / center position: 1000
15Kp, Ki, Kd = 0.05, 0.0, 0.4
16BASE = 45                                 # taban hız (%) / base speed (%)
17min_val = [65535] * N
18max_val = [0] * N
19last_pos = CENTER
20
21def drive(left, right):                   # her biri -100 … 100 / each -100 … 100
22    left = max(-100, min(100, left))
23    right = max(-100, min(100, right))
24    in1.value(left >= 0); in2.value(left < 0)
25    in3.value(right >= 0); in4.value(right < 0)
26    ena.duty_u16(int(abs(left) * 655.35))
27    enb.duty_u16(int(abs(right) * 655.35))
28
29def wait_button():
30    while button.value():                 # basılmasını bekle / wait for a press
31        time.sleep_ms(10)
32    time.sleep_ms(30)
33    while not button.value():             # bırakılmasını bekle / wait for the release
34        time.sleep_ms(10)
35    time.sleep_ms(30)
36
37def calibrate():                          # 5 sn sağa sola gezdir / sweep for 5 s
38    led.on()
39    start = time.ticks_ms()
40    while time.ticks_diff(time.ticks_ms(), start) < 5000:
41        for i, s in enumerate(sensors):
42            v = s.read_u16()
43            min_val[i] = min(min_val[i], v)
44            max_val[i] = max(max_val[i], v)
45    led.off()
46
47def read_position():                      # 0 (sol) … 2000 (sağ) / 0 (left) … 2000 (right)
48    global last_pos
49    total = weighted = 0
50    on_line = False
51    for i, s in enumerate(sensors):
52        rng = max(1, max_val[i] - min_val[i])
53        v = max(0, min(1000, (s.read_u16() - min_val[i]) * 1000 // rng))
54        if WHITE_LINE:
55            v = 1000 - v
56        if v > 500:
57            on_line = True
58        if v > 50:
59            weighted += v * i * 1000
60            total += v
61    if not on_line:                       # çizgi kayıp / line lost
62        return 0 if last_pos < CENTER else (N - 1) * 1000
63    last_pos = weighted // total
64    return last_pos
65
66drive(0, 0)
67wait_button()                             # 1. basış: kalibrasyon / 1st press: calibration
68calibrate()
69wait_button()                             # 2. basış: yarış / 2nd press: race
70integral = 0
71last_error = 0
72while True:
73    t0 = time.ticks_ms()
74    error = read_position() - CENTER
75    integral = max(-10000, min(10000, integral + error))
76    correction = Kp * error + Ki * integral + Kd * (error - last_error)
77    last_error = error
78    drive(BASE + correction, BASE - correction)
79    while time.ticks_diff(time.ticks_ms(), t0) < 5:   # 5 ms sabit döngü / fixed 5 ms loop
80        pass

Aturan lomba dan lintasan

Aturan lomba line follower berbeda menurut penyelenggara dan tahunnya, tapi ide dasarnya sama: robot harus menyelesaikan lintasan dalam waktu tersingkat tanpa keluar dari garis. Misalnya, di aturan line follower tingkat pemula 2024 dari Lomba Robot MEB nasional di Turki, lintasannya berupa garis putih 20 ± 2 mm di atas latar hitam. Robot boleh berukuran paling besar 280 × 180 mm termasuk roda dan berbobot paling berat 1 kg termasuk baterai; tegangan kerjanya tidak boleh melebihi 12 V, dan robot harus memakai dua motor gigi DC berbentuk L 6–12 V dengan gigi plastik, roda berdiameter tidak lebih dari 65 mm, dan susunan sensor sampai 8 sensor. Lintasannya punya jembatan dengan kemiringan 13 derajat dan bagian persegi di mana memotong lurus lewat tengah dikenai penalti 20 detik; robot yang badannya sepenuhnya berada di latar hitam dianggap keluar lintasan, dan robot yang diam di garis lebih dari 30 detik didiskualifikasi. Lomba sekolah dan regional lain memakai kebalikannya, garis hitam 20 ± 2 mm di atas latar putih, dan meminta robot yang lebih kecil dengan bobot tidak lebih dari 500 gram. Singkatnya, selalu baca aturan tahun itu sebelum merancang robotmu.

  • Lintasan terbalik: Untuk garis putih di atas latar hitam, atur variabel WHITE_LINE menjadi true di sketch. Jika warnanya bertukar di tengah lintasan, kamu bisa menambahkan pengecekan yang berganti mode ketika sensor luar mulai melihat hitam dan sensor tengah melihat putih.
  • Belokan 90 derajat: Turunkan kecepatan dasar sebelum belokan atau biarkan roda dalam berputar mundur; di sketch artikel ini roda dalam sudah berputar mundur ketika koreksi lebih besar dari kecepatan dasar.
  • Persimpangan: Ketika semua sensor melihat garis sekaligus, jalan lurus menyeberang; jika kamu perlu memilih arah, buat state machine yang menghitung persimpangan.
  • Garis putus-putus: Ketika garis hilang sebentar, coba terus jalan lurus selama 100–200 ms alih-alih langsung berbelok.
  • Tanjakan dan jembatan: Di bidang miring jarak antara sensor dan lantai berubah; buat batang sensor tetap rendah dan dekat dengan roda, dan pelankan sedikit di tanjakan.
  • Lintasan latihan: Tempel isolasi listrik hitam doff 19 mm di atas karton putih doff atau papan foam; di percobaan pertamamu, jangan buat tikungan yang lebih tajam dari radius 15 cm.

Masalah umum dan solusinya

MasalahKemungkinan penyebabSolusi
Robot zig-zag di jalan lurusKp terlalu tinggi, Kd terlalu rendah, atau kecepatan terlalu tinggiTurunkan Kp sekitar 20%, naikkan Kd; turunkan kecepatan dasar jika perlu
Keluar lintasan di tikunganKecepatan terlalu tinggi, susunan sensor terlalu sempit, atau reaksi yang salah ketika garis hilangTurunkan kecepatan dasar, biarkan roda dalam berputar mundur, berbelok ke sisi terakhir garis terlihat ketika garis hilang
Robot selalu tertarik ke satu sisiMotor berputar dengan kecepatan berbeda atau batang sensor tidak di tengahTengahkan sensor, kecilkan motor yang lebih cepat dengan faktor kecil (misalnya 0.95)
Sensor melihat hitam atau putih di mana-manaTidak dikalibrasi, sensor terlalu tinggi, atau trimmer belum diaturTurunkan ketinggian ke 3–5 mm, ulangi kalibrasi di lintasan
Arduino reset ketika motor mulai berputarTegangan baterai turun sesaat atau GND bersama burukBeri daya board secara terpisah atau tambahkan kapasitor 470 µF ke catu daya, pendekkan kabel
Robot berperilaku berbeda seiring baterai melemahKecepatan motor turun bersama teganganUkur tegangan baterai dan skalakan kecepatannya, atau pasang baterai penuh sebelum setiap putaran
Bekerja di rumah, gagal di lokasi lombaCahaya sekitar atau lantai mengilap mengganggu inframerahLindungi sensor dengan rok hitam, kalibrasi di bawah pencahayaan lomba
Cara tercepat mempersempit masalah adalah mengangkat roda dari lantai dan menggerakkan robot di atas garis dengan tangan: jika roda bertambah cepat ke arah yang benar, sensor dan kodenya baik-baik saja dan masalahnya ada di mekanik atau daya. Untuk diagnosis rinci masalah reset, lihat Arduino terus reset.

Langkah berikutnya dan ide proyek

  • Line follower penghindar rintangan: Tambahkan HC-SR04 di depan agar robot memutari rintangan di lintasan; logika keputusannya ada di Robot Penghindar Rintangan.
  • Mode Bluetooth: Beralih dari mengikuti garis ke kendali ponsel dengan tombol; mudah ditambahkan dengan Modul Bluetooth HC-05.
  • Pengukur waktu putaran: Robot yang mendeteksi garis start dan menampilkan waktu putaran di layar OLED.
  • Pemecah labirin: Robot yang menghitung dan mengingat persimpangan lalu mengikuti jalur terpendek di putaran keduanya.
  • Robot gudang: Maket AGV kecil yang berhenti di stasiun-stasiun sepanjang garis dan menjatuhkan muatan dengan servo.
  • Dasar yang kokoh: Jika kamu belum merakit sasis, motor, dan baterai, mulailah dari panduan Mobil Robot Arduino.

Robot pengikut garis mengajarkan sensor, algoritma, motor, dan daya sekaligus, dan menjadi sedikit lebih cepat di setiap putaran penyetelan. Buat robot bergerak dulu dengan versi if-else sederhana, lalu beralih ke PID dan setel nilainya dengan sabar. Jika kamu penasaran bagaimana PWM mengatur kecepatan motor, Apa Itu PWM? adalah bacaan lanjutan yang bagus. Di aplikasi BlueGrays kamu akan menemukan proyek Deteksi Permukaan Hitam dan Putih TCRT5000, Mobil Kendali Bluetooth dengan L298N, dan Robot Penghindar Rintangan langkah demi langkah, lengkap dengan skema rangkaian dan kode.

Pertanyaan umum

Berapa sensor yang dibutuhkan robot pengikut garis?

Dua sensor sudah cukup untuk robot yang berfungsi, tapi tiga memberi hasil yang jauh lebih stabil dengan sketch if-else sederhana. Untuk mengikuti garis dengan halus dan cepat, dianjurkan 5 atau 8 sensor analog dengan PID. Banyak lomba mengizinkan paling banyak 8 sensor.

Kenapa robot pengikut garisku zig-zag?

Penyebab paling umum adalah Kp yang terlalu tinggi dan Kd yang terlalu rendah: robot mengoreksi setiap penyimpangan secara berlebihan dan menyeberang ke sisi lain garis. Menurunkan Kp sedikit, menaikkan Kd, mengurangi kecepatan dasar, dan memindahkan sensor 4–8 cm di depan roda semuanya mengurangi osilasi. Dengan kode if-else sederhana sedikit zig-zag itu normal, karena robot berpindah di antara beberapa kecepatan tetap.

Bisakah membuat line follower tanpa PID?

Bisa. Dengan sketch if-else sederhana dan 2 atau 3 sensor robot mengikuti garis, dan itu sering sudah cukup untuk proyek sekolah. Namun seiring kecepatan naik, robot kehilangan garis di tikungan dan bergoyang di jalan lurus. Jika kamu mengincar peringkat bagus di lomba, kamu perlu beralih ke PID.

Baterai apa yang paling cocok untuk robot pengikut garis?

Pilihan paling praktis adalah dua sel Li-ion 18650 seri: keduanya memberi 7,4 V nominal dan mudah menyuplai arus tinggi yang ditarik motor. Robot ringan juga memakai paket LiPo 2S. Baterai 9 V PP3 tidak sanggup memberi arus motor dan cepat habis.

Bagaimana cara mengubah kode untuk garis putih di atas latar hitam?

Kamu cukup membalik nilai sensornya: di sketch artikel ini, mengatur WHITE_LINE menjadi true membuat nilai ternormalisasi menjadi 1000 − nilai, sehingga robot mengikuti garis putih. Pada modul digital, variabel yang sama membalik pembacaan DO. Kamu tetap perlu mengkalibrasi di lintasan yang akan dipakai lomba.

Seberapa tinggi sensor TCRT5000 sebaiknya dari lantai?

TCRT5000 bekerja paling baik di sekitar 2,5 mm; dalam praktiknya, menyisakan 3–5 mm antara sensor dan lantai memberi hasil yang bagus. Di atas 1 cm perbedaan hitam dan putih sangat mengecil dan robot kehilangan garis. Di lintasan dengan tanjakan, menjaga batang sensor dekat dengan roda mengurangi perubahan jaraknya.

Lihat semua proyek
Deteksi Permukaan Hitam dan Putih TCRT5000
#78Menengah
Premium

Deteksi Permukaan Hitam dan Putih TCRT5000

Dengan sensor kecil yang menjadi mata robot pengikut garis, kamu bisa tahu apakah lantainya hitam atau putih. TCRT5000 menyinari lantai dengan cahaya tak terlihat dan mengecek berapa banyak yang terpa

4.7(40)
49
Membaca Pantulan (Kedekatan) dengan TCRT5000
#77Menengah
Premium

Membaca Pantulan (Kedekatan) dengan TCRT5000

Dengan sensor kecil yang memancarkan cahaya tak terlihat dan mengukur berapa banyak yang terpantul kembali, kamu bisa mendeteksi permukaan di depannya. Makin dekat sebuah benda atau permukaan berwarna

4.6(33)
43
Mobil Kendali Bluetooth dengan L298N
#80Mahir
Premium

Mobil Kendali Bluetooth dengan L298N

Jadikan ponselmu remote dan kendarai mobil robotmu sendiri. Arduino menerima perintah dari aplikasi remote control di ponselmu lewat modul Bluetooth dan memutar roda dengan driver motor; mobil maju, m

5.0(38)
65
Robot Penghindar Rintangan
#81Mahir
Premium

Robot Penghindar Rintangan

Bagaimana kalau membuat kendaraan pintar yang mencari jalannya sendiri? Robot Penghindar Rintangan terus memindai sekelilingnya berkat sensor ultrasonik di depannya. Ketika menemui rintangan, robot be

5.0(38)
49
Pengukuran Jarak HC-SR04 (Tampilan Serial)
#27Pemula

Pengukuran Jarak HC-SR04 (Tampilan Serial)

Sensor HC-SR04 bekerja persis seperti kelelawar yang mencari jalan dalam gelap: ia mengirim suara yang tidak bisa kamu dengar, mendengarkan pantulannya, dan mengukur seberapa jauh benda di depannya. A

4.6(46)
71
Kendali LED dengan Tombol Tekan (Tekan)
#9Pemula

Kendali LED dengan Tombol Tekan (Tekan)

Persis seperti bel pintu: lampu tetap menyala selama kamu menekan, dan mati ketika kamu melepasnya. Arduino terus mendengarkan tombol; selama ditekan LED menyala, dan begitu jarimu terangkat LED mati.

4.8(113)
229
LED Fade dengan PWM ESP32
#110Pemula

LED Fade dengan PWM ESP32

Mengubah kecerahan LED secara halus dari 0 ke maksimum, dan dari maksimum ke 0. Kita mengendalikan PWM dengan analogWrite() seperti di Arduino; sintaks yang sama bekerja tanpa masalah di ESP32 Arduino Core 3.0+. Definisi pin + pinMode + analogWrite sudah cukup.

4.8(36)
54
LED Fade PWM Raspberry Pi Pico (Efek Bernapas)
#160Pemula

LED Fade PWM Raspberry Pi Pico (Efek Bernapas)

LED tidak lagi sekadar berkedip, ia bernapas! Dengan PWM (Pulse Width Modulation) Pico, kecerahan LED naik lalu turun perlahan, seperti lampu MacBook yang tidur. Pelajari kelas machine.PWM, duty_u16() (kecerahan 16-bit 0–65535), frekuensi PWM (freq(1000): 1000 siklus per detik, tanpa kedipan terlihat), loop range() bertahap, dan output mirip analog dari pin digital. PWM juga dipakai untuk warna RGB, motor, servo, dan buzzer.

0.0(0)
4