Dasar Pemrograman Arduino: Variabel, Perulangan, dan Fungsi
Belajar pemrograman Arduino dari nol: setup dan loop, int, long, byte, overflow, const, #define, if-else, switch-case, perulangan, array, dan fungsi dengan contoh LED.
Pemrograman Arduino berarti memberi tahu board Arduino apa yang harus dikerjakan dengan bahasa C/C++: kamu menulis LED mana yang menyala dan kapan, apa yang terjadi ketika tombol ditekan, dan bagaimana angka dari sensor ditafsirkan, lalu board mengulang instruksi itu ribuan kali per detik. Kabar baiknya, hampir semua sketch yang akan kamu lihat, dari LED berkedip sampai mobil robot, tersusun dari sekitar sepuluh blok bangunan yang sama. Blok-blok itu adalah setup() dan loop(), variabel, konstanta, operator, if-else, switch-case, perulangan for dan while, array, dan fungsi.
Di panduan ini kamu akan mempelajari blok-blok bangunan itu satu per satu, masing-masing dengan contoh LED atau tombol sungguhan. Semua contoh berjalan di rangkaian sederhana yang sama dan sudah dikompilasi serta diuji untuk Arduino Uno. Bagian yang paling sering membuat pemula mentok, yaitu overflow variabel, tertukarnya = dan ==, break yang terlupa, dan penghitung yang ter-reset di setiap putaran, dijelaskan secara terpisah. Di bagian terakhir kamu juga akan melihat cara kerja logika yang sama di ESP32 dan bentuknya di MicroPython pada Raspberry Pi Pico.

Apa itu pemrograman Arduino dan bahasa apa yang dipakai?
Kode Arduino dibangun di atas C++; tidak ada “bahasa Arduino” yang terpisah. Arduino core menambahkan fungsi siap pakai seperti pinMode(), digitalWrite(), dan delay() ke C++. File yang kamu tulis disebut sketch dan berekstensi .ino. Ketika kamu mengklik Verify, Arduino IDE menambahkan header Arduino.h di bagian atas file dan membuatkan deklarasi fungsi untukmu, lalu compiler mengubah kode menjadi kode mesin yang dimengerti prosesor. Tombol Upload kemudian mengirim hasil itu lewat USB ke bootloader board. Kalau kamu belum menginstal IDE, mulai dulu dari panduan instalasi Arduino IDE.
Ada beberapa aturan dasar yang perlu diikuti ketika menulis kode. Mempelajarinya sejak awal menghilangkan separuh error kompilasi yang biasanya muncul di hari-hari pertamamu:
| Aturan | Benar | Kalau dilanggar |
|---|---|---|
| Setiap pernyataan diakhiri titik koma | digitalWrite(13, HIGH); | “expected ';' before '}' token” |
| Huruf besar dan kecil dibedakan | pinMode(13, OUTPUT); | “'pinmode' was not declared in this scope” |
| Blok kode ditulis di dalam kurung kurawal | void loop() { ... } | Setiap { butuh pasangan } |
| Komentar satu baris | // baris ini tidak dijalankan | Komentar tidak dikompilasi, gunanya untuk penjelasan |
| Komentar banyak baris | /* ... */ | Kalau tidak ditutup, semua yang ada di bawahnya menjadi komentar |
| Teks dalam tanda kutip ganda, satu karakter dalam tanda kutip tunggal | "Hello" dan 'A' | Tertukarnya jenis tanda kutip menghasilkan nilai yang salah atau error |
Rangkaian yang dipakai di contoh
Semua contoh berjalan di satu rangkaian. Hubungkan enam LED ke pin D8–D13, masing-masing lewat resistor 220 Ω; kaki pendek (katoda) setiap LED ke GND. Kamu bisa mengecek nilai resistor untuk LED-mu sendiri dengan kalkulator resistor LED. Hubungkan satu kaki tombol ke D2 dan kaki yang berseberangan secara diagonal ke GND. Karena kodenya memakai INPUT_PULLUP, resistor eksternal tidak diperlukan: pin membaca HIGH ketika tombol dilepas dan LOW ketika ditekan. Untuk detailnya, lihat Cara Menghubungkan Push Button ke Arduino dan Apa Itu LED?.
| Komponen | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| 6 LED (masing-masing dengan 220 Ω, katoda ke GND) | D8, D9, D10, D11, D12, D13 | GPIO 18, 19, 21, 22, 23, 25 | GP14, GP13, GP12, GP11, GP10, GP9 |
| Tombol (kaki lainnya ke GND) | D2 | GPIO 4 | GP2 |
| LED bawaan board | D13 (LED bertanda L) | GPIO 2 (sebagian besar DevKit) | GP25 (“LED” di Pico W) |
| Kecepatan serial | 9600 baud | 115200 baud | Shell Thonny |
setup() dan loop(): kerangka setiap sketch
Setiap sketch Arduino punya dua fungsi wajib. setup() hanya berjalan sekali, ketika board menyala atau tombol reset ditekan; persiapan seperti pengaturan pin dan Serial.begin() ditaruh di sini. loop() kemudian berulang terus-menerus setelah setup() selesai. Di balik layar, Arduino core punya fungsi main() tersembunyi: fungsi ini menyiapkan hardware dulu, lalu memanggil setup() sekali dan memanggil loop() berulang-ulang di dalam perulangan tanpa akhir. Area di bagian atas file, di luar kedua fungsi itu, adalah area global; konstanta dan variabel yang perlu bisa diakses dari mana saja didefinisikan di sana.
1// 1) Global alan: sabitler ve değişkenler / Global area: constants and variables
2const int LED_PIN = 13; // dahili LED / built-in LED
3unsigned long passCount = 0; // loop() kaç kez döndü / how many times loop() has run
4
5// 2) setup(): açılışta bir kez çalışır / runs once at power-up or reset
6void setup() {
7 pinMode(LED_PIN, OUTPUT);
8 Serial.begin(9600);
9 Serial.println("setup() bitti / setup() done");
10}
11
12// 3) loop(): sonsuza kadar tekrar eder / repeats forever
13void loop() {
14 passCount++; // her turda 1 artır / add 1 on every pass
15 Serial.print("Tur / Pass: ");
16 Serial.println(passCount);
17
18 digitalWrite(LED_PIN, HIGH); // LED'i yak / LED on
19 delay(500); // 500 ms bekle / wait 500 ms
20 digitalWrite(LED_PIN, LOW); // LED'i söndür / LED off
21 delay(500);
22}Upload kodenya dan buka Serial Monitor di 9600 baud: kamu akan melihat “setup() done” sekali, disusul nomor putaran yang naik setiap detik, sementara LED bawaan berkedip dengan ritme yang sama. Dua panggilan delay(500) di dalam loop() memanjangkan setiap putaran menjadi sekitar satu detik; loop() tanpa jeda dan tanpa cetak serial bisa berjalan ratusan ribu kali per detik di Uno. Supaya bisa memanfaatkan Serial Monitor sepenuhnya, lihat panduan Serial Monitor Arduino.
Variabel dan tipe data: int, long, float, bool, byte
Variabel adalah kotak bernama di memori yang menyimpan sebuah nilai. Ketika mendefinisikannya, kamu menulis tipe-nya dulu, lalu namanya, dan kalau perlu nilai awalnya, misalnya int counter = 0;. Tipe menentukan berapa byte yang dipakai kotak itu dan rentang angka yang bisa ditampungnya. Arduino Uno hanya punya RAM 2 KB, jadi memilih tipe yang tepat itu penting. Nama variabel diawali huruf atau garis bawah dan tidak boleh berisi spasi atau huruf beraksen seperti é, ü, atau ç.
| Tipe | Ukuran di Uno | Rentang | Penggunaan umum |
|---|---|---|---|
| bool | 1 byte | true atau false | Apakah LED menyala, apakah tombol ditekan |
| byte | 1 byte | 0 – 255 | Nomor pin, kecerahan PWM |
| char | 1 byte | -128 – 127 | Satu karakter: 'A' |
| int | 2 byte | -32.768 – 32.767 | Penghitung, hasil analogRead() |
| unsigned int | 2 byte | 0 – 65.535 | Hanya angka positif |
| long | 4 byte | -2.147.483.648 – 2.147.483.647 | Bilangan bulat besar |
| unsigned long | 4 byte | 0 – 4.294.967.295 | Mengukur waktu dengan millis() |
| float | 4 byte | Sekitar ±3,4 × 10^38, presisi 6–7 digit | Suhu, tegangan, rata-rata |
| double | 4 byte (sama dengan float di Uno) | Sama dengan float | 8 byte di ESP32 |
Beberapa aturan praktis akan menghindarkanmu dari banyak masalah. analogRead() mengembalikan angka 0 sampai 1023, jadi int sudah cukup. Sebaliknya, millis() mengembalikan unsigned long; kalau kamu menyimpan waktu di variabel int, nilainya overflow setelah 32,7 detik dan pengaturan waktumu rusak. Di Uno, perhitungan float dikerjakan oleh software, jadi lebih lambat daripada perhitungan bilangan bulat, dan apa pun di luar 6–7 digit tidak bisa diandalkan; karena itu kamu sebaiknya tidak membandingkan dua float dengan ==. Kalau kamu ingin tipe yang ukurannya sama di setiap board, pakai tipe yang mencantumkan ukurannya di nama, seperti uint8_t, int16_t, dan uint32_t.
Overflow: apa yang terjadi ketika variabel melewati batasnya?
Kalau kamu mencoba menyimpan angka yang lebih besar daripada kapasitas tipenya, Arduino tidak melaporkan error; angkanya berputar balik seperti odometer mobil. Di Uno, int menampung paling besar 32.767, dan menambahkan 1 mengubahnya menjadi -32.768. Byte berputar dari 255 ke 0. Jebakan yang lebih licik adalah perhitungan dengan konstanta: ekspresi seperti 60 * 1000 dihitung sebagai int dulu dan overflow, meskipun hasilnya disimpan di variabel long. Sketch di bawah mencetak semua kasus ini ke Serial Monitor, dan loop()-nya menunjukkan overflow byte di sebuah LED:
1const int LED_PIN = 9; // PWM destekli pin (~9) / PWM-capable pin (~9)
2byte brightness = 0; // byte: 0-255
3
4void setup() {
5 pinMode(LED_PIN, OUTPUT);
6 Serial.begin(9600);
7
8 int a = 32767; // Uno'da int'in en büyük değeri / largest int on an Uno
9 a = a + 1; // taşma: -32768 olur / overflow: becomes -32768
10 Serial.println(a);
11
12 long wrong = 60 * 1000; // int ile hesaplanır, taşar: -5536 / computed as int, overflows: -5536
13 long right = 60 * 1000L; // L eki hesabı long yapar: 60000 / the L suffix makes it long math: 60000
14 Serial.println(wrong);
15 Serial.println(right);
16
17 float half = 5 / 2; // tam sayı bölmesi: 2.00 / integer division: 2.00
18 float half2 = 5 / 2.0; // ondalıklı bölme: 2.50 / floating-point division: 2.50
19 Serial.println(half);
20 Serial.println(half2);
21}
22
23void loop() {
24 analogWrite(LED_PIN, brightness); // parlaklığı uygula / apply the brightness
25 brightness++; // 255'ten sonra 0'a döner / wraps to 0 after 255
26 delay(10);
27}| Baris kode | Output di Uno | Output di ESP32 dan Pico | Kenapa? |
|---|---|---|---|
| a = 32767 + 1 | -32768 | 32768 | int berukuran 2 byte di Uno, 4 byte di board lainnya |
| 60 * 1000 | -5536 | 60000 | Konstanta dihitung sebagai int dulu |
| 60 * 1000L | 60000 | 60000 | Akhiran L membuat perhitungannya menjadi long |
| 5 / 2 | 2.00 | 2.00 | Membagi dua bilangan bulat menghasilkan bilangan bulat |
| 5 / 2.0 | 2.50 | 2.50 | Kalau salah satu angka punya titik desimal, hasilnya juga begitu |
Perhatikan LED di D9: kecerahannya naik perlahan dari 0 ke 255, lalu baris brightness++ mengubah nilainya menjadi 0, bukan 256, dan LED tiba-tiba padam. Itulah cara paling mudah melihat overflow dengan mata sendiri. D9 adalah salah satu pin PWM Uno yang bertanda ~, jadi analogWrite() bekerja di sana; PWM dibahas secara detail di Apa Itu PWM?. millis() yang berputar balik setelah sekitar 49,7 hari juga merupakan overflow, dan itu tidak menimbulkan masalah di kode yang ditulis dengan benar; cara menulisnya bisa kamu lihat di panduan millis() vs delay().
const dan #define: nilai yang tidak pernah berubah
Ada dua cara memberi nama pada angka yang tidak akan berubah selama program berjalan, seperti nomor pin dan nilai ambang. Konstanta yang didefinisikan dengan const punya tipe, mengikuti aturan scope, dan kalau kamu tidak sengaja mencoba mengubahnya, compiler menghentikanmu dengan assignment of read-only variable 'LED_PIN'. Sebaliknya, #define adalah direktif preprocessor: sebelum kompilasi dimulai, direktif ini mengganti setiap BUTTON_PIN di kode dengan 2. Ia tidak punya tipe, dan barisnya tidak memakai titik koma maupun tanda sama dengan. Untuk angka sederhana, keduanya tidak memakai RAM, karena compiler langsung memasukkan nilainya ke dalam kode. Sekarang const lebih disukai, dan menulis nama konstanta dengan HURUF_BESAR adalah kebiasaan umum. Contoh di bawah memakai keduanya: LED tetap menyala selama tombol ditahan.
1#define BUTTON_PIN 2 // önişlemci: derlemeden önce metin değişimi / preprocessor: text swap before compiling
2const int LED_PIN = 13; // tipi olan, salt okunur sabit / typed, read-only constant
3
4void setup() {
5 pinMode(LED_PIN, OUTPUT);
6 pinMode(BUTTON_PIN, INPUT_PULLUP); // dahili pull-up: basılınca LOW / internal pull-up: LOW when pressed
7}
8
9void loop() {
10 if (digitalRead(BUTTON_PIN) == LOW) { // buton basılı mı? / is the button pressed?
11 digitalWrite(LED_PIN, HIGH); // evet: LED yanar / yes: LED on
12 } else {
13 digitalWrite(LED_PIN, LOW); // hayır: LED söner / no: LED off
14 }
15}Operator: aritmetika, perbandingan, dan logika
Operator memungkinkanmu menghitung dengan variabel, membandingkannya, dan menggabungkan kondisi. Hampir semua operator yang akan kamu pakai di proyek sehari-hari ada di tabel ini:
| Kelompok | Operator | Arti | Contoh |
|---|---|---|---|
| Aritmetika | + - * / | Empat operasi dasar | x = a * 2; |
| Sisa bagi | % | Sisa hasil pembagian (hanya bilangan bulat) | 7 % 3 menghasilkan 1 |
| Penugasan | = += -= *= /= | Atur, tambahkan, kurangi… | total += 5; |
| Increment, decrement | ++ -- | Tambah 1 atau kurangi 1 | i++; |
| Perbandingan | == != < > <= >= | Hasilnya true atau false | if (x >= 10) |
| Logika | && || ! | AND, OR, NOT | if (a && !b) |
| Kondisional | ? : | if-else singkat | x > 0 ? HIGH : LOW |
| Bitwise | & | ^ ~ << >> | Bekerja pada bit-bit sebuah angka | 1 << 3 menghasilkan 8 |
Dua pasangan yang paling sering tertukar adalah = dan == serta & dan &&. Satu tanda sama dengan memberi nilai, dua tanda sama dengan membandingkan. Satu & bekerja pada bit-bit angka, sedangkan && menanyakan apakah kedua kondisi bernilai benar. Kamu bisa mencoba tabel kebenaran AND, OR, dan NOT di alat gerbang logika, dan operator bitwise dijelaskan secara detail di panduan sistem bilangan dan operasi bitwise. Contoh di bawah menghitung berapa kali tombol sudah ditekan dan menyalakan LED setelah jumlah tekanan ganjil:
1const int LED_PIN = 13;
2const int BUTTON_PIN = 2;
3
4int presses = 0; // toplam basış sayısı / total number of presses
5bool lastPressed = false; // önceki turdaki durum / state on the previous pass
6
7void setup() {
8 pinMode(LED_PIN, OUTPUT);
9 pinMode(BUTTON_PIN, INPUT_PULLUP);
10 Serial.begin(9600);
11}
12
13void loop() {
14 bool pressed = (digitalRead(BUTTON_PIN) == LOW); // karşılaştırma: true ya da false / comparison: true or false
15
16 if (pressed && !lastPressed) { // şimdi basılı VE önceden değildi: yeni basış / pressed now AND not before: new press
17 presses++; // 1 artır / increment by 1
18 Serial.print("Basış / Presses: ");
19 Serial.println(presses);
20 delay(50); // basit debounce / simple debounce
21 }
22 lastPressed = pressed;
23
24 // Kalan (%) ile tek mi çift mi? / odd or even using the remainder (%)
25 digitalWrite(LED_PIN, (presses % 2 == 1) ? HIGH : LOW);
26}Kuncinya ada di kondisi pressed && !lastPressed: artinya “ditekan sekarang DAN tidak ditekan di putaran sebelumnya”. Dengan begitu angkanya tidak terus naik selama kamu menahan tombol, dan setiap tekanan hanya dihitung sekali. presses % 2 memberi sisa pembagian angka itu dengan 2: 1 untuk bilangan ganjil, 0 untuk bilangan genap. Operator ? : di baris terakhir lalu memilih HIGH atau LOW berdasarkan hasil itu.
if, else if, dan else: mengambil keputusan
if menjalankan kode di dalam kurung kurawal ketika kondisi di dalam kurung bernilai benar. Kalau kondisinya salah, blok else yang berjalan, kalau ada. Ketika kamu butuh lebih banyak pilihan, tambahkan else if di antaranya. Kondisi dicek dari atas ke bawah, dan begitu blok kondisi benar yang pertama selesai dijalankan, sisanya dilewati. Di C++, setiap nilai yang bukan nol dianggap benar, jadi if (counter) berarti “kalau penghitungnya bukan nol”. Kita sudah melihat contoh if-else sederhana di bagian const. Sekarang mari tulis contoh yang membedakan tekanan singkat dari tekanan panjang:
1const int LED_PIN = 13;
2const int BUTTON_PIN = 2;
3
4void setup() {
5 pinMode(LED_PIN, OUTPUT);
6 pinMode(BUTTON_PIN, INPUT_PULLUP);
7 Serial.begin(9600);
8}
9
10void loop() {
11 if (digitalRead(BUTTON_PIN) == LOW) { // basıldı / pressed
12 unsigned long start = millis();
13 while (digitalRead(BUTTON_PIN) == LOW) { // bırakılana kadar bekle / wait until released
14 }
15 unsigned long held = millis() - start; // basılı kalma süresi (ms) / hold time (ms)
16
17 if (held < 50) {
18 return; // 50 ms'den kısa: parazit, yok say / under 50 ms: bounce, ignore
19 } else if (held < 1000) {
20 digitalWrite(LED_PIN, HIGH); // kısa basış: LED yak / short press: LED on
21 Serial.println("Kısa basış / Short press");
22 } else {
23 digitalWrite(LED_PIN, LOW); // uzun basış: LED söndür / long press: LED off
24 Serial.println("Uzun basış / Long press");
25 }
26 }
27}Begitu tombol ditekan, kode mencatat waktunya dengan millis(), menunggu di dalam perulangan while sampai tombol dilepas, lalu menghitung selisih waktunya. Tekanan yang lebih singkat dari 50 ms dianggap noise dari pantulan mekanis tombol, dan return mengakhiri putaran loop() itu lebih awal. Tekanan yang lebih singkat dari 1 detik menyalakan LED, yang lebih lama mematikannya. Urutan kondisi itu penting: kalau kamu menaruh pengecekan held < 1000 lebih dulu, gangguan 30 ms juga akan terhitung sebagai “tekanan singkat”.
switch-case: memilih di antara banyak kasus
Kalau kamu perlu melakukan banyak hal berbeda tergantung nilai sebuah variabel, switch-case lebih mudah dibaca daripada rantai else if yang panjang. switch membandingkan nilai di dalam kurungnya dengan setiap label case dan mulai berjalan dari yang cocok. Setiap case sebaiknya kamu akhiri dengan break; kalau tidak, program terus masuk ke kode case berikutnya. Kalau tidak ada case yang cocok, blok default yang berjalan. switch hanya bekerja dengan tipe bilangan bulat seperti int, byte, char, dan enum; untuk String, float, atau rentang seperti “antara 10 dan 20” kamu butuh if. Di contoh di bawah, setiap tekanan memindahkan lampu ke mode berikutnya: mati, nyala, kedip lambat, kedip cepat.
1const int LED_PIN = 13;
2const int BUTTON_PIN = 2;
3
4byte mode = 0; // 0 kapalı, 1 açık, 2 yavaş, 3 hızlı / 0 off, 1 on, 2 slow, 3 fast
5bool lastPressed = false;
6
7void setup() {
8 pinMode(LED_PIN, OUTPUT);
9 pinMode(BUTTON_PIN, INPUT_PULLUP);
10}
11
12void loop() {
13 bool pressed = (digitalRead(BUTTON_PIN) == LOW);
14 if (pressed && !lastPressed) {
15 mode = (mode + 1) % 4; // 0 → 1 → 2 → 3 → 0
16 delay(50); // basit debounce / simple debounce
17 }
18 lastPressed = pressed;
19
20 switch (mode) {
21 case 0: // kapalı / off
22 digitalWrite(LED_PIN, LOW);
23 break;
24 case 1: // sürekli açık / always on
25 digitalWrite(LED_PIN, HIGH);
26 break;
27 case 2: // 500 ms'de bir değiş / toggle every 500 ms
28 digitalWrite(LED_PIN, (millis() / 500) % 2 ? HIGH : LOW);
29 break;
30 case 3: // 100 ms'de bir değiş / toggle every 100 ms
31 digitalWrite(LED_PIN, (millis() / 100) % 2 ? HIGH : LOW);
32 break;
33 default: // beklenmeyen değer: başa dön / unexpected value: reset
34 mode = 0;
35 break;
36 }
37}Baris mode = (mode + 1) % 4 menggeser mode melalui 0, 1, 2, 3 dan, berkat operator %, kembali ke 0 ketika mencapai 4. Perhatikan bahwa kita tidak memakai delay() untuk berkedip: ekspresi (millis() / 500) % 2 berganti antara 0 dan 1 setiap 500 ms, jadi tombol langsung merespons sementara LED berkedip. Versi dewasa dari pendekatan “mode” ini disebut state machine; cara memakainya di proyek seperti lampu lalu lintas dan menu bisa kamu lihat di panduan state machine Arduino.
Perulangan for, while, dan do-while
Perulangan menjalankan sebuah blok kode berulang-ulang. Tanda kurung perulangan for punya tiga bagian: awal (int i = 0), kondisi untuk terus berjalan (i < 6), dan langkah setelah setiap putaran (i++). for ideal ketika kamu tahu berapa kali harus mengulang. while terus berjalan selama kondisinya benar dan mengecek kondisi sebelum setiap putaran, jadi cocok untuk menunggu sesuatu yang lamanya tidak kamu ketahui sebelumnya. do-while mengecek kondisi di akhir, jadi selalu berjalan paling tidak sekali. Di dalam perulangan, break langsung keluar dari perulangan dan continue melewati sisa putaran yang sedang berjalan lalu lanjut ke putaran berikutnya. Karena loop() sudah merupakan perulangan tanpa akhir, biasanya kamu tidak perlu menulis while (true) di dalamnya.
| Perulangan | Kapan kondisinya dicek? | Kapan dipakai | Contoh |
|---|---|---|---|
| for | Sebelum setiap putaran | Ketika jumlah pengulangan sudah diketahui | for (int i = 0; i < 6; i++) |
| while | Sebelum setiap putaran | Selama menunggu sesuatu terjadi | while (digitalRead(2) == HIGH) |
| do-while | Setelah setiap putaran | Ketika harus berjalan paling tidak sekali | do { ... } while (x < 10); |
Contoh di bawah membuat efek Knight Rider dengan enam LED. Perulangan for di setup() menjadikan keenam pin sebagai output dalam satu baris, dan perulangan while di loop() menunggu sampai tombol ditekan. Selama kamu menahan tombol, cahayanya berjalan dari D8 ke D13 lalu kembali:
1const int FIRST_LED = 8; // ilk LED pini / first LED pin
2const int LAST_LED = 13; // son LED pini / last LED pin
3const int BUTTON_PIN = 2;
4
5void setup() {
6 for (int pin = FIRST_LED; pin <= LAST_LED; pin++) {
7 pinMode(pin, OUTPUT); // 6 pini tek döngüyle çıkış yap / make 6 pins outputs with one loop
8 }
9 pinMode(BUTTON_PIN, INPUT_PULLUP);
10}
11
12void loop() {
13 while (digitalRead(BUTTON_PIN) == HIGH) {
14 // butona basılana kadar burada bekle / wait here until the button is pressed
15 }
16
17 for (int pin = FIRST_LED; pin <= LAST_LED; pin++) { // ileri: 8 → 13 / forward: 8 → 13
18 digitalWrite(pin, HIGH);
19 delay(80);
20 digitalWrite(pin, LOW);
21 }
22 for (int pin = LAST_LED - 1; pin > FIRST_LED; pin--) { // geri: 12 → 9 / back: 12 → 9
23 digitalWrite(pin, HIGH);
24 delay(80);
25 digitalWrite(pin, LOW);
26 }
27}Memulai perulangan balik dari LAST_LED - 1 dan menjalankannya hanya selama pin lebih besar dari FIRST_LED adalah pilihan yang disengaja: LED di kedua ujung tidak menyala dua kali berturut-turut, jadi gerakannya terlihat mulus. Untuk kontrol kecepatan, efek mengisi, dan pola lainnya, lihat panduan LED berjalan Knight Rider.
Array: menyimpan banyak nilai dengan satu nama
Array menampung beberapa nilai bertipe sama secara berurutan dengan satu nama. Baris const byte LEDS[] = {8, 9, 10, 11, 12, 13}; membuat array dengan enam elemen. Elemen-elemennya diakses dengan kurung siku, dan hitungannya dimulai dari 0: LEDS[0] adalah 8 dan LEDS[5] adalah 13. Panjang array tidak bisa berubah setelah didefinisikan. Kalau kamu membiarkan sizeof(LEDS) / sizeof(LEDS[0]) menghitung jumlah elemen alih-alih mengetiknya sendiri, perulanganmu otomatis menyesuaikan diri ketika kamu menambahkan pin baru ke array. Indeks di luar array, seperti LEDS[6], tidak menimbulkan error; indeks itu membaca atau merusak variabel lain di memori. Karena itu kamu perlu memastikan indeksnya tetap di antara 0 dan jumlah elemen dikurangi satu. Contoh di bawah mengubah enam LED menjadi dadu elektronik:
1const byte LEDS[] = {8, 9, 10, 11, 12, 13}; // LED pinleri / LED pins
2const byte LED_COUNT = sizeof(LEDS) / sizeof(LEDS[0]); // eleman sayısı: 6 / number of elements: 6
3const byte BUTTON_PIN = 2;
4
5void setup() {
6 for (byte i = 0; i < LED_COUNT; i++) { // indeks 0'dan başlar / index starts at 0
7 pinMode(LEDS[i], OUTPUT);
8 }
9 pinMode(BUTTON_PIN, INPUT_PULLUP);
10 randomSeed(analogRead(A0)); // boştaki A0'ın gürültüsüyle tohumla / seed from noise on the unconnected A0
11}
12
13void loop() {
14 if (digitalRead(BUTTON_PIN) == LOW) {
15 byte dice = random(1, 7); // 1 ile 6 arası / between 1 and 6
16 for (byte i = 0; i < LED_COUNT; i++) {
17 digitalWrite(LEDS[i], (i < dice) ? HIGH : LOW); // ilk 'dice' kadar LED yanar / the first 'dice' LEDs light up
18 }
19 delay(300); // basılı tutarsan zar dönmeye devam eder / keeps rolling while held
20 }
21}random(1, 7) menghasilkan angka 1 sampai 6, karena batas atasnya tidak termasuk dalam hasil. Sebanyak itulah LED yang menyala: kalau dadunya menunjukkan 4, empat LED dari LEDS[0] sampai LEDS[3] menyala. Baris randomSeed(analogRead(A0)) memakai noise listrik di pin A0 yang tidak tersambung sebagai nilai awal; tanpa baris itu, board akan menghasilkan urutan angka yang sama setiap kali menyala. Keuntungan lain array: kalau kamu memindahkan LED ke pin lain, kamu cukup mengubah baris pertama.
Menulis fungsi: memecah kode menjadi bagian-bagian
Kalau kamu mengerjakan tugas yang sama di beberapa tempat dalam programmu, jadikan tugas itu sebuah fungsi. Fungsi terdiri dari tipe kembalian, nama, parameter di dalam kurung, dan isi di dalam kurung kurawal. Fungsi yang tidak mengembalikan nilai bertipe void; fungsi yang mengembalikan nilai menyerahkan hasilnya dengan return. Parameter diteruskan sebagai salinan, jadi mengubah parameter di dalam fungsi tidak mengubah variabel di tempat fungsi itu dipanggil. Arduino IDE membuat sendiri deklarasi untuk fungsi di file .ino, jadi kamu juga bisa menulis fungsi di bawah loop(). Namun di file .cpp atau di PlatformIO, kamu harus mendeklarasikan fungsi sebelum memakainya. Beri fungsimu nama yang menjelaskan tugasnya, seperti blinkLed atau isPressed.
1const byte LED_PIN = 13;
2const byte BUTTON_PIN = 2;
3
4// Değer döndürmeyen (void) fonksiyon / function that returns nothing (void)
5void blinkLed(byte pin, byte times, int ms) {
6 for (byte i = 0; i < times; i++) {
7 digitalWrite(pin, HIGH);
8 delay(ms);
9 digitalWrite(pin, LOW);
10 delay(ms);
11 }
12}
13
14// bool döndüren fonksiyon / function that returns a bool
15bool isPressed(byte pin) {
16 return digitalRead(pin) == LOW; // INPUT_PULLUP: basılı = LOW / pressed = LOW
17}
18
19void setup() {
20 pinMode(LED_PIN, OUTPUT);
21 pinMode(BUTTON_PIN, INPUT_PULLUP);
22 blinkLed(LED_PIN, 3, 100); // açılışta 3 hızlı yanıp sönme / 3 quick blinks at start-up
23}
24
25void loop() {
26 if (isPressed(BUTTON_PIN)) {
27 blinkLed(LED_PIN, 2, 250); // basınca 2 yavaş yanıp sönme / 2 slow blinks per press
28 }
29}blinkLed() menerima pin, jumlah kedipan, dan kecepatan sebagai parameter, jadi kamu bisa memakai ulang fungsi yang sama untuk LED lain dan kecepatan lain. isPressed() mengembalikan bool dan menyimpan logika “ditekan = LOW” dari INPUT_PULLUP di satu tempat; kalau suatu hari kamu memasang tombol dengan cara sebaliknya, kamu cukup mengubah baris ini. Meski begitu, delay() di dalam fungsi tetap menghentikan program. Untuk fungsi yang mengerjakan beberapa hal sekaligus, kamu butuh pengaturan waktu berbasis millis().
Variabel global, lokal, dan static
Tempat sebuah variabel bisa terlihat disebut scope-nya. Variabel global, yang didefinisikan di luar fungsi, hidup selama program berjalan dan bisa dibaca serta diubah dari mana saja. Variabel lokal, yang didefinisikan di dalam fungsi atau blok kurung kurawal, dibuat ulang setiap kali blok itu berjalan dan hilang ketika blok itu selesai. Dari sinilah keluhan pemula yang paling umum berasal: “penghitungku selalu berhenti di 1”. Kalau kamu menaruh static di depan variabel lokal, variabel itu hanya mendapat nilai awalnya pada kali pertama dan mempertahankan nilainya di antara putaran, tetapi tetap hanya terlihat di dalam fungsi itu.
1const byte LED_PIN = 13;
2const byte BUTTON_PIN = 2;
3
4int globalCount = 0; // global: her yerden görünür, değerini korur / global: visible everywhere, keeps its value
5
6void setup() {
7 pinMode(LED_PIN, OUTPUT);
8 pinMode(BUTTON_PIN, INPUT_PULLUP);
9 Serial.begin(9600);
10}
11
12void loop() {
13 int localCount = 0; // yerel: her turda yeniden 0 olur / local: back to 0 on every pass
14 static int staticCount = 0; // static yerel: değerini korur, yalnız burada görünür / static local: keeps its value, visible only here
15
16 if (digitalRead(BUTTON_PIN) == LOW) {
17 globalCount++;
18 localCount++;
19 staticCount++;
20 Serial.print(globalCount);
21 Serial.print(' ');
22 Serial.print(localCount);
23 Serial.print(' ');
24 Serial.println(staticCount); // 3. basışta: 3 1 3 / on the 3rd press: 3 1 3
25 digitalWrite(LED_PIN, (staticCount % 2) ? HIGH : LOW);
26 delay(300);
27 }
28}Ketika kamu menekan tombol tiga kali, Serial Monitor menampilkan baris 1 1 1, 2 1 2, dan 3 1 3: penghitung global dan static terus naik, sedangkan penghitung lokal selalu berhenti di 1 karena mulai lagi dari 0 di setiap putaran loop(). Kalau kamu mendefinisikan variabel lokal dengan nama yang sama seperti variabel global, variabel lokal menutupi yang global, dan di dalam fungsi itu kamu sama sekali tidak menyentuh variabel global. Variabel global yang diubah oleh fungsi interrupt (ISR) juga harus dideklarasikan sebagai volatile; detailnya ada di panduan interrupt Arduino.
Pemrograman Arduino di ESP32: bahasa sama, ukuran berbeda
Ketika kamu memprogram ESP32 dengan Arduino IDE, kamu memakai bahasa C++ dan perintah yang sama, tetapi ada beberapa perbedaan. Karena ESP32 adalah prosesor 32-bit, int berukuran 4 byte dan menampung nilai dari -2.147.483.648 sampai 2.147.483.647, jadi 32767 + 1 di contoh overflow menghasilkan 32768. double berukuran 8 byte, analogRead() mengembalikan nilai 0 sampai 4095, dan pin-pinnya bekerja di 3,3 V. Kamu bisa mencetak dengan format memakai Serial.printf(). random() secara default memakai generator angka acak hardware, jadi baris randomSeed() tidak diperlukan. Program di bawah menggabungkan semua yang sudah kamu pelajari di artikel ini: array, fungsi, switch-case, dan tombol pengganti mode. Untuk fitur umum board ini, lihat Apa Itu ESP32?.
1// ESP32: aynı dil, farklı pinler / ESP32: same language, different pins
2const byte LEDS[] = {18, 19, 21, 22, 23, 25}; // güvenli GPIO'lar / safe GPIOs
3const byte LED_COUNT = sizeof(LEDS) / sizeof(LEDS[0]);
4const byte BUTTON_PIN = 4; // diğer bacağı GND'ye / other leg to GND
5
6byte mode = 0; // 0 kapalı, 1 yürüyen ışık, 2 hepsi yanıp söner / 0 off, 1 chaser, 2 all blink
7bool lastPressed = false;
8
9void setAll(bool on) {
10 for (byte i = 0; i < LED_COUNT; i++) {
11 digitalWrite(LEDS[i], on ? HIGH : LOW);
12 }
13}
14
15void setup() {
16 Serial.begin(115200);
17 for (byte i = 0; i < LED_COUNT; i++) {
18 pinMode(LEDS[i], OUTPUT);
19 }
20 pinMode(BUTTON_PIN, INPUT_PULLUP);
21 Serial.printf("int = %d bayt / bytes\n", (int)sizeof(int)); // ESP32'de 4 / 4 on the ESP32
22
23 int a = 32767;
24 a = a + 1;
25 Serial.println(a); // ESP32'de 32768, taşma yok / 32768 on the ESP32, no overflow
26}
27
28void loop() {
29 bool pressed = (digitalRead(BUTTON_PIN) == LOW);
30 if (pressed && !lastPressed) {
31 mode = (mode + 1) % 3; // 0 → 1 → 2 → 0
32 delay(50);
33 }
34 lastPressed = pressed;
35
36 switch (mode) {
37 case 0:
38 setAll(false);
39 break;
40 case 1: { // case içinde değişken için süslü parantez / braces for a variable inside a case
41 byte step = (millis() / 120) % LED_COUNT; // sıradaki LED / LED whose turn it is
42 for (byte i = 0; i < LED_COUNT; i++) {
43 digitalWrite(LEDS[i], (i == step) ? HIGH : LOW);
44 }
45 break;
46 }
47 case 2:
48 setAll((millis() / 300) % 2); // 300 ms'de bir hepsi / all of them every 300 ms
49 break;
50 }
51}Untuk menjalankan program ini di Uno, kamu cukup mengubah array LEDS menjadi {8, 9, 10, 11, 12, 13}, mengatur BUTTON_PIN ke 2, dan mengganti baris Serial.printf(), yang tidak didukung Uno, dengan Serial.print(). Itulah manfaat mendefinisikan nomor pin sebagai konstanta dan array di bagian atas. Perhatikan juga bahwa blok case 1 berada di dalam kurung kurawal; karena variabel step didefinisikan di dalamnya, kurung kurawal itu wajib di ESP32.
Raspberry Pi Pico: logika yang sama di MicroPython
Kamu bisa memprogram Raspberry Pi Pico dengan C++ dengan menambahkan paket board RP2040 ke Arduino IDE; dalam hal ini kode di artikel ini bekerja setelah kamu mengganti nomor pinnya, dan int lagi-lagi berukuran 4 byte. Namun cara paling umum memakai Pico adalah MicroPython. Di Python kamu tidak menulis tipe variabel, blok ditentukan oleh indentasi alih-alih kurung kurawal, tidak ada titik koma di akhir baris, dan bilangan bulat tidak overflow, melainkan membesar sesuai kebutuhan. Kode di bawah adalah versi MicroPython dari contoh dadu elektronik. Untuk pengaturannya, lihat Apa Itu Raspberry Pi Pico?, dan untuk detail bahasanya, dasar-dasar MicroPython.
1from machine import Pin
2import time, random
3
4leds = [Pin(n, Pin.OUT) for n in (14, 13, 12, 11, 10, 9)] # liste = dizi / list = array
5button = Pin(2, Pin.IN, Pin.PULL_UP) # basılınca 0 / reads 0 when pressed
6
7def show(count): # fonksiyon / function
8 for i, led in enumerate(leds): # for döngüsü / for loop
9 led.value(1 if i < count else 0)
10
11show(0) # setup() karşılığı: bir kez çalışır / like setup(): runs once
12while True: # loop() karşılığı / like loop()
13 if button.value() == 0: # buton basılı mı? / is the button pressed?
14 show(random.randint(1, 6)) # 1-6 arası zar at / roll a number from 1 to 6
15 time.sleep_ms(300)| Konsep | Arduino (C++) | MicroPython |
|---|---|---|
| Bagian yang berjalan sekali | setup() | Kode sebelum baris while True: |
| Bagian yang berulang terus-menerus | loop() | while True: |
| Variabel | int x = 5; | x = 5 |
| Konstanta | const int PIN = 2; | PIN = const(2) (setelah from micropython import const) |
| Kondisi | if / else if / else | if / elif / else |
| Banyak pilihan | switch-case | Rantai if / elif |
| Perulangan hitung | for (int i = 0; i < 6; i++) | for i in range(6): |
| Array | byte a[] = {1, 2, 3}; | a = [1, 2, 3] |
| Fungsi | void blink(int pin) { ... } (fungsi tanpa nilai kembalian) | def blink(pin): (definisi fungsi) |
| Logika | && || ! | and or not |
| Komentar | // komentar | # komentar |
Ide proyek yang bisa kamu buat dengan dasar-dasar ini
- Lampu lalu lintas: buat penyeberangan dengan tombol pejalan kaki memakai nilai const, delay(), dan if; panduan langkah demi langkahnya ada di Lampu Lalu Lintas Arduino.
- Knight Rider dan LED berjalan: buat puluhan pola cahaya berbeda dengan perulangan for dan array.
- Dadu elektronik: pindahkan dadu 6 LED ke display 7-segmen dengan array, random(), dan fungsi; untuk itu lihat panduan display 7-segmen.
- Tes reaksi: nyalakan LED di momen acak dan ukur seberapa cepat kamu menekan tombol memakai unsigned long dan millis().
- Lampu multi-mode: mode mati, menyala tetap, bernapas, dan kilat dari satu tombol dengan switch-case; untuk versi berwarna, lihat Cara Memakai LED RGB.
- Kunci kode: kumpulkan tombol yang ditekan di sebuah array lalu bandingkan dengan kode yang tersimpan; detailnya ada di panduan keypad.
Kesalahan umum dan cara memperbaikinya
| Kesalahan | Gejala | Solusi |
|---|---|---|
| Memakai = dalam perbandingan | Blok if selalu berjalan | Pakai == untuk membandingkan |
| Ada ; atau = di baris #define | “expected ')' before ';' token” | Tulis sebagai #define LED_PIN 13 |
| Penulisan huruf besar perintah salah | “'pinmode' was not declared in this scope” | Perhatikan huruf besar dan kecil, seperti pada pinMode |
| Huruf beraksen di nama variabel | “stray '\303' in program” | Pakai hanya huruf Latin dasar, angka, dan _ di nama |
| Menghitung 60 * 1000 sebagai int | Hasilnya -5536 | Tulis 60 * 1000L atau 60000UL |
| Menyimpan millis() di int | Pengaturan waktu rusak setelah 32 detik | Pakai unsigned long |
| Pembagian bilangan bulat | 5 / 2 menghasilkan 2 | Tulis 5 / 2.0 atau ubah ke float |
| Lupa break di akhir case | Case berikutnya ikut berjalan | Akhiri setiap case dengan break |
| Menulis di luar array | Nilai acak, program macet | Jaga indeks di antara 0 dan jumlah elemen - 1 |
| Menjadikan penghitung sebagai variabel lokal | Penghitung selalu berhenti di 1 | Jadikan global atau static |
Setelah mempelajari blok-blok bangunan ini, langkah berikutnya adalah mengenal perintah yang paling sering dipakai: Daftar Perintah Arduino membahas semuanya dari pinMode() sampai attachInterrupt() lengkap dengan contoh. Di aplikasi BlueGrays kamu juga akan menemukan proyek seperti LED berkedip, mengendalikan LED dengan tombol, Knight Rider, lampu lalu lintas, dan dadu, langkah demi langkah dengan skema rangkaian dan kode siap pakai, jadi kamu bisa mencoba setiap struktur yang kamu pelajari di sini di rangkaian sungguhan.
Pertanyaan umum
Bahasa pemrograman apa yang dipakai Arduino?
Kode Arduino dibangun di atas C++. Arduino core menambahkan fungsi siap pakai seperti pinMode(), digitalWrite(), dan delay() ke bahasa itu, dan kodenya ditulis di file berekstensi .ino. Board seperti ESP32 dan Raspberry Pi Pico juga bisa diprogram dengan MicroPython kalau kamu lebih suka.
Dari mana sebaiknya aku mulai belajar pemrograman Arduino?
Pertama, instal Arduino IDE dan upload contoh Blink, yang membuat LED bawaan berkedip. Setelah itu coba setup() dan loop(), variabel, if-else, perulangan, array, dan fungsi sesuai urutan itu, masing-masing dengan rangkaian LED atau tombol. Memakai setiap topik baru di proyek kecil membuatnya jauh lebih melekat daripada sekadar membacanya.
Apa bedanya int dan long di Arduino?
Di Arduino Uno, int berukuran 2 byte dan menampung angka dari -32.768 sampai 32.767, sedangkan long berukuran 4 byte dan mencapai sekitar ±2,1 miliar. Angka yang melewati batas ini berputar balik tanpa error apa pun, jadi long atau unsigned long dipakai untuk nilai besar seperti millis(). Di ESP32 dan Pico, int juga berukuran 4 byte.
Apa bedanya const dan #define di Arduino?
Konstanta yang didefinisikan dengan const punya tipe, mengikuti aturan scope, dan compiler melaporkan error kalau kamu mencoba mengubahnya. #define adalah penggantian teks yang dilakukan sebelum kompilasi; ia tidak punya tipe dan menimbulkan error tak terduga kalau kamu mengakhirinya dengan titik koma. Keduanya tidak memakai RAM untuk angka sederhana, tetapi const biasanya lebih disukai karena lebih aman.
Apa bedanya perulangan for dan while di Arduino?
Perulangan for menaruh awal, kondisi, dan langkah di satu baris dan dipakai ketika kamu tahu berapa kali harus mengulang, misalnya untuk menyalakan enam LED satu per satu. Perulangan while hanya mengecek sebuah kondisi dan terus berjalan selama kondisi itu benar, jadi cocok untuk situasi yang lamanya tidak diketahui, seperti menunggu tombol ditekan.
Apakah Arduino bisa diprogram dengan Python?
Board 8-bit seperti Arduino Uno tidak bisa menjalankan Python, jadi diprogram dengan C++. Namun ESP32 dan Raspberry Pi Pico bisa diprogram dengan MicroPython. Program Python yang berjalan di komputermu juga bisa mengendalikan Uno secara tidak langsung dengan berkomunikasi lewat port serial.
Proyek untuk dibuat setelah membaca ini
Lihat semua proyek
LED Berkedip
"Halo" pertama di dunia elektronika: menyalakan dan mematikan satu LED. Arduino menyalakan dan mematikan LED dengan jeda singkat, sehingga cahayanya berkedip cepat. Kamu melihat dengan cara paling sed

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.

Nyala/Mati LED dengan Tombol (On/Off)
Tekan tombol sekali dan lampu menyala, tekan lagi dan lampu mati, persis seperti sakelar lampu di kamarmu. Arduino menyadari setiap tekanan dan membalik LED ke keadaan sebaliknya, sambil menunggu sebe

Efek LED Knight Rider
Lampu pemindai klasik: sebuah titik cahaya meluncur dari satu ujung enam LED ke ujung lainnya lalu kembali. Arduino menyalakan setiap LED selama sepersepuluh detik sebelum pindah, berbalik di setiap u

Lampu Lalu Lintas
Tiruan mini lampu lalu lintas yang kamu lihat di jalan setiap hari. Merah menyala dua detik, kuning menyala sebentar, hijau menyala dua detik, lalu kembali ke merah lewat kuning lagi, terus berulang.

Kendali LED dengan Tombol Tekan ESP32 (Tekan)
LED menyala ketika tombol ditekan dan mati ketika dilepas. Menunjukkan cara memakai pin input digital ESP32 dan resistor pull-up internalnya. Mode INPUT_PULLUP membuat resistor eksternal tidak diperlukan.

LED Toggle dengan Tombol Raspberry Pi Pico
Tombol + LED, level berikutnya! Berbeda dengan proyek tombol dasar, tombol tidak perlu ditahan. Tekan dan lepas → LED menyala. Tekan dan lepas lagi → LED mati (toggle). Rangkaiannya sama (LED GP14, Tombol GP2), tetapi kodenya sangat berbeda. Pelajari deteksi tepi (menangkap momen turun 1→0), pelacakan status, dan debounce (penyaring pantulan mekanis). led.toggle() MicroPython menukar status dalam satu baris. Dasar semua proyek tombol interaktif (pengganti mode, IRQ, klik ganda).

Proyek Dadu
Tidak ada lagi dadu yang hilang ketika main board game: setiap kali kamu menekan tombol, angka acak dari 1 sampai 6 muncul di layar 7 segmen. Setiap tekanan memberi tepat satu hasil, dan hasilnya juga
Artikel lainnya
Aplikasi BlueGrays
Rakit rangkaian ini langkah demi langkah di ponselmu
Skema pengkabelan, kode, dan daftar komponen dalam satu layar. 200+ proyek Arduino, ESP32, dan Pico siap dibuat.
Pindai dengan ponselmu
Arahkan kamera ke kode ini dan toko aplikasi di ponselmu akan terbuka.
atau buka toko aplikasi

