Bahasa Arduino tanpa pusing
Di Bab 3 kamu sudah memakai if, bool, dan const tanpa banyak penjelasan. Bab ini berhenti sebentar dari merangkai untuk membahas bahasanya. Semua contoh memakai satu rangkaian yang sama, jadi cukup dirangkai sekali di awal, lalu kamu bisa fokus ke kode.
DI BAB INI KAMU BAKAL BISA
- memahami aturan tulis program Arduino
- memakai variabel dan memilih tipe datanya
- menghitung dan membandingkan
- membuat keputusan dengan if
- mengulang dengan for dan while
- membuat fungsi sendiri
- memakai array
- menunggu tanpa delay dengan millis()
- membaca pesan error
YANG DIBUTUHKAN
- rangkaian latihan di 4.0: 5 LED + 5 resistor 220 Ω di pin 3 sampai 7, tombol di pin 2
4.0Rangkaian latihan
Rangkaian ini dipakai di semua contoh Bab 4. Lima LED di pin 3, 4, 5, 6, 7, dan satu tombol di pin 2 seperti di Bab 3.4.
Kali ini resistor dipasang di kaki pendek LED, antara LED dan GND. Hasilnya sama saja: yang penting di jalur dari pin ke GND ada satu resistor. Cara ini menghemat kabel karena resistornya langsung menancap di rel.
void setup() { for (int pin = 3; pin <= 7; pin++) pinMode(pin, OUTPUT); } void loop() { for (int pin = 3; pin <= 7; pin++) digitalWrite(pin, HIGH); }
Program pendek di atas menyalakan kelima LED sekaligus. Kalau ada yang tidak menyala, cek arah LED dan kabelnya sebelum lanjut.
Bentuk for di situ akan dijelaskan di 4.5.
4.1Aturan menulis
Arduino diprogram dengan bahasa C++. Bahasanya ketat: komputer tidak bisa menebak maksudmu kalau ada satu tanda yang salah. Untungnya aturan dasarnya sedikit.
| ATURAN | CONTOH |
|---|---|
| Setiap perintah diakhiri titik koma | delay(500); |
| Kelompok perintah diapit kurung kurawal | void loop() { ... } |
| Huruf besar dan kecil itu beda | digitalWrite benar, digitalwrite salah |
Komentar satu baris diawali // | // ini tidak dijalankan |
| Komentar beberapa baris | /* ... */ |
| Spasi dan baris kosong bebas | dipakai supaya enak dibaca |
Komentar adalah catatan untuk manusia. Arduino mengabaikannya. Pakai untuk menjelaskan kenapa sebuah baris ada, misalnya
// tunggu pantulan tombol reda. Kamu sendiri yang paling berterima kasih saat membuka program itu lagi bulan depan.
Isi di dalam kurung kurawal biasanya ditulis menjorok ke dalam (indentasi). Arduino tidak peduli, tapi matamu akan peduli. Menu Tools › Auto Format (Ctrl + T) merapikan indentasi seluruh program dalam sekali klik.
4.2Variabel & tipe data
Variabel adalah kotak berlabel untuk menyimpan nilai. Setiap kotak punya tiga hal: tipe (jenis isi yang boleh disimpan), nama, dan isinya.
int jumlahKedip = 12; // tipe, nama, isi awal float suhu = 28.5; bool lampuNyala = true; char huruf = 'A'; jumlahKedip = jumlahKedip + 1; // isinya sekarang 13
| TIPE | ISI | RENTANG DI UNO |
|---|---|---|
int | bilangan bulat | −32.768 sampai 32.767 |
long | bilangan bulat besar | sekitar ±2,1 miliar |
unsigned long | bulat besar, tidak negatif | 0 sampai sekitar 4,29 miliar |
byte | bulat kecil | 0 sampai 255 |
float | bilangan berkoma | sekitar 6 sampai 7 digit ketelitian |
bool | benar atau salah | true / false |
char | satu huruf | ditulis dengan petik satu: 'A' |
String | teks | ditulis dengan petik dua: "Halo" |
Bilangan berkoma di program ditulis dengan titik, bukan koma: 28.5, bukan 28,5.
int di Uno cuma muat sampai 32.767. Kalau isinya ditambah 1 lagi, dia tidak error,
tapi berputar ke −32.768, seperti odometer motor yang kembali ke nol. Untuk menghitung waktu dalam milidetik, yang cepat sekali besar,
selalu pakai unsigned long. Ini yang akan kita lakukan di 4.8.
Konstanta: variabel yang tidak boleh berubah
Kalau sebuah nilai tidak akan pernah berubah, misalnya nomor pin, tambahkan const di depannya. Kalau tanpa sengaja kamu
mengubahnya di tengah program, Verify akan menolak. Nama konstanta biasa ditulis huruf besar semua supaya mudah dibedakan.
const int LED_MERAH = 3; const int TOMBOL = 2;
Di mana variabel ditulis itu penting
Variabel yang ditulis di luar setup() dan loop() bisa dipakai di mana saja dan isinya bertahan selama papan
menyala. Variabel yang ditulis di dalam loop() dibuat ulang setiap putaran, jadi isinya kembali ke awal terus.
Itu sebabnya di proyek 3.5, lampuNyala ditulis di luar.
4.3Menghitung & membandingkan
| HITUNG | ARTI | CONTOH | HASIL |
|---|---|---|---|
+ − * / | tambah, kurang, kali, bagi | 7 / 2 | 3 (lihat catatan) |
% | sisa bagi | 7 % 2 | 1 |
++ / -- | tambah / kurang satu | n++ | n jadi n + 1 |
+= | tambahkan ke dirinya | n += 5 | sama dengan n = n + 5 |
| BANDINGKAN | ARTI | LOGIKA | ARTI |
|---|---|---|---|
== | sama dengan | && | dan |
!= | tidak sama dengan | || | atau |
< > | kurang dari, lebih dari | ! | bukan / kebalikan |
<= >= | kurang/lebih atau sama dengan |
Kalau kedua angka bilangan bulat, hasil pembagian ikut bulat, dan koma di belakangnya dibuang
(bukan dibulatkan). 7 / 2 hasilnya 3, 1 / 3 hasilnya 0. Supaya hasilnya berkoma, salah satu angka harus berkoma:
7 / 2.0 hasilnya 3.5.
= artinya isi: n = 5 mengisi n dengan 5.
== artinya apakah sama: n == 5 bertanya, isinya bernilai true atau false. Kalau kamu menulis
if (n = 5), Arduino tidak bertanya, tapi mengisi n dengan 5, dan if-nya selalu dianggap benar. Program tetap lolos Verify,
jadi kesalahan ini susah ditemukan.
4.4Mengambil keputusan
if menjalankan sekelompok perintah hanya kalau syaratnya benar. else if memberi syarat cadangan, dan else
menangkap sisanya. Contoh: lampu yang menyala tergantung berapa kali tombol sudah ditekan.
const int TOMBOL = 2; int tekan = 0; void setup() { pinMode(TOMBOL, INPUT_PULLUP); for (int pin = 3; pin <= 7; pin++) pinMode(pin, OUTPUT); } void loop() { if (digitalRead(TOMBOL) == LOW) { tekan++; delay(300); // satu tekan = satu hitungan } for (int pin = 3; pin <= 7; pin++) digitalWrite(pin, LOW); if (tekan < 3) {1 digitalWrite(3, HIGH); } else if (tekan < 6) {2 digitalWrite(5, HIGH); } else { digitalWrite(7, HIGH); } }
- 1Tiga tekanan pertama (0, 1, 2) menyalakan LED pin 3.
- 2
else ifbaru diperiksa kalau syarat pertama salah. Jadi syarattekan < 6ini sebenarnya berarti "3 sampai 5". Mulai tekanan keenam,elseyang jalan.
Tambahkan satu syarat lagi supaya setelah tekanan kesembilan semua LED menyala. Lalu buat supaya hitungan kembali ke nol setelah
tekanan kedua belas: tambahkan if (tekan >= 12) tekan = 0; di tempat yang tepat.
4.5Mengulang dengan for & while
Menyalakan lima LED satu per satu bisa ditulis sepuluh baris. Dengan for, cukup tiga.
void setup() { for (int pin = 3; pin <= 7; pin++) { pinMode(pin, OUTPUT); } } void loop() { for (int pin = 3; pin <= 7; pin++) {1 digitalWrite(pin, HIGH); delay(150); digitalWrite(pin, LOW); } }
- 1Isi kurung
forada tiga bagian, dipisah titik koma: mulai daripin = 3, ulangi selamapin <= 7, dan setiap selesai satu putaranpin++. Jadi isinya dijalankan untuk pin 3, 4, 5, 6, 7, lalu berhenti.
Hasilnya cahaya yang berlari dari kiri ke kanan. Variabel pin di situ hanya hidup di dalam for; di luarnya, nama
itu tidak dikenal.
while: ulangi selama syaratnya benar
while dipakai kalau kamu tidak tahu berapa kali harus mengulang, hanya tahu kapan berhenti. Contoh paling berguna:
menunggu tombol ditekan.
while (digitalRead(TOMBOL) == HIGH) { // diam saja di sini sampai tombol ditekan }
Buat cahaya berlari bolak-balik: setelah sampai pin 7, kembali ke pin 3. Petunjuk: tambahkan for kedua yang mulai dari
pin = 6, berjalan selama pin >= 4, dan memakai pin--.
4.6Bikin fungsi sendiri
setup(), loop(), digitalWrite(), dan delay() semuanya fungsi: sekumpulan perintah
yang diberi nama. Kamu bisa membuat fungsimu sendiri untuk pekerjaan yang diulang-ulang.
void kedip(int pin, int kali, int jeda) {1 for (int i = 0; i < kali; i++) { digitalWrite(pin, HIGH); delay(jeda); digitalWrite(pin, LOW); delay(jeda); } } void setup() { for (int pin = 3; pin <= 7; pin++) pinMode(pin, OUTPUT); } void loop() { kedip(3, 3, 100);2 kedip(5, 2, 300); kedip(7, 1, 800); }
- 1
voidberarti fungsi ini tidak mengembalikan hasil apa pun, cuma mengerjakan sesuatu. Di dalam kurung ada parameter: nilai yang dikirim saat fungsi dipanggil. - 2Memanggil fungsi: LED pin 3 berkedip 3 kali cepat. Urutan nilainya harus sama dengan urutan parameter.
Fungsi yang mengembalikan hasil
Ganti void dengan tipe hasilnya, lalu pakai return:
bool tombolDitekan() { return digitalRead(2) == LOW; } // dipakai seperti ini: if (tombolDitekan()) { ... }
Nama fungsi seperti tombolDitekan() membuat if-nya bisa dibaca seperti kalimat. Itu alasan utama membuat fungsi: program
jadi pendek dan menjelaskan dirinya sendiri.
4.7Array: banyak nilai, satu nama
Rangkaian latihan kebetulan memakai pin berurutan, 3 sampai 7, jadi for bisa langsung menghitung pinnya. Di proyek sungguhan,
pin sering tidak berurutan. Array menyimpan beberapa nilai dalam satu nama, berbaris dengan nomor urut.
int led[] = {3, 4, 5, 6, 7};1 int pola[] = {0, 4, 1, 3, 2};2 void setup() { for (int i = 0; i < 5; i++) pinMode(led[i], OUTPUT); } void loop() { for (int i = 0; i < 5; i++) { digitalWrite(led[pola[i]], HIGH); delay(200); digitalWrite(led[pola[i]], LOW); } }
- 1Isi array diambil dengan nomor urut di dalam kurung siku. Nomornya mulai dari 0:
led[0]adalah 3,led[4]adalah 7. Tidak adaled[5]. - 2Array kedua menyimpan urutan nyala: luar, luar, dalam, dalam, tengah. Mengganti pola cukup mengubah satu baris ini.
Arduino tidak menolak kalau kamu mengambil led[5] atau led[10] dari array berisi lima. Dia akan mengambil
isi memori sembarang di sebelahnya, dan programmu berperilaku aneh tanpa pesan error. Pastikan batas for selalu
i < jumlah isi.
4.8Menunggu tanpa membeku
Selama delay(1000) berjalan, Arduino tidak melakukan apa-apa lagi: tombol tidak dibaca, LED lain tidak diurus. Untuk satu LED
itu tidak masalah. Untuk dua LED yang berkedip dengan kecepatan berbeda, delay() tidak bisa dipakai.
Solusinya adalah millis(): jam di dalam Arduino yang menghitung milidetik sejak papan menyala. Daripada tidur, Arduino
mengecek jam setiap putaran loop(): "sudah waktunya belum?"
unsigned long terakhirA = 0;1 unsigned long terakhirB = 0; bool nyalaA = false; bool nyalaB = false; void setup() { pinMode(3, OUTPUT); pinMode(7, OUTPUT); } void loop() { unsigned long sekarang = millis(); if (sekarang - terakhirA >= 500) {2 terakhirA = sekarang; nyalaA = !nyalaA; digitalWrite(3, nyalaA); } if (sekarang - terakhirB >= 130) { terakhirB = sekarang; nyalaB = !nyalaB; digitalWrite(7, nyalaB); } }
- 1Waktu disimpan dalam
unsigned long, karena dalam beberapa puluh detik angka milidetik sudah melewati batasint. - 2"Kalau sudah lewat 500 milidetik sejak terakhir berganti", ganti keadaan LED dan catat waktunya. Bentuk
pengurangan
sekarang - terakhirAini sengaja dipakai, karena tetap benar walaupunmillis()suatu saat kembali ke nol.
LED pin 3 berkedip pelan, LED pin 7 berkedip cepat, dan keduanya tidak saling mengganggu. Karena loop() tidak pernah tidur,
kamu bisa menambahkan pembacaan tombol di dalamnya dan tombol akan langsung terasa responsif.
millis() kembali ke nol setelah sekitar 49,7 hari papan menyala tanpa henti. Dengan bentuk pengurangan seperti
di atas, perpindahan itu tidak menimbulkan masalah. Yang bermasalah adalah bentuk if (millis() > target), jadi hindari.
Tambahkan LED ketiga (pin 5) yang berkedip setiap 1000 milidetik, juga tanpa delay(). Lalu tambahkan: selama tombol
ditekan, LED pin 6 menyala. Perhatikan betapa cepat reaksinya dibanding program yang memakai delay().
4.9Membaca pesan error
Setiap programmer, termasuk yang sudah puluhan tahun, melihat pesan error setiap hari. Bedanya cuma satu: mereka membacanya. Pesan error dari Arduino IDE muncul di panel Output saat Verify atau Upload, dan baris yang bermasalah ikut disorot merah di editor.
sketch_oct20a.ino: In function 'void loop()': sketch_oct20a.ino:6:3: error: expected ';' before 'delay' Compilation error: expected ';' before 'delay'
Angka 6:3 berarti baris 6, kolom 3. Tapi perhatikan: titik koma yang hilang biasanya ada di akhir baris sebelumnya,
karena Arduino baru sadar ada yang kurang saat bertemu perintah berikutnya.
| PESAN | BIASANYA ARTINYA |
|---|---|
expected ';' before ... | Titik koma lupa di baris sebelumnya. |
'xxx' was not declared in this scope | Nama variabel/fungsi salah ketik, beda huruf besar-kecil, atau variabel dipakai di luar tempat ia dibuat. |
... did you mean 'digitalWrite'? | Salah ketik, dan IDE sudah menebak yang benar. Ikuti sarannya. |
expected '}' at end of input | Ada kurung kurawal buka yang lupa ditutup. |
expected unqualified-id before ... | Ada perintah yang tertulis di luar fungsi, biasanya karena kelebihan }. |
LiquidCrystal_I2C.h: No such file or directory | Library belum dipasang (lihat 2.6). |
Satu kesalahan bisa memancing belasan pesan error di bawahnya. Selalu baca dan perbaiki pesan pertama, lalu Verify lagi. Sering kali sisanya ikut hilang. Dan kalau buntu, klik Tools › Auto Format: indentasi yang mendadak berantakan biasanya menunjuk tempat kurung kurawal yang salah.