Tutorial Belanja komponen

Tutorial › Memulai dengan Arduino

Bab 4: Bahasa Arduino tanpa pusing

BAB 4
04

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

DIRANGKAI SEKALI UNTUK SATU BAB20 MENIT · MUDAH

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.

ATMEGA328P L TX RX ON UNO SCL SDA AREF GND 13 12 ~11 ~10 ~9 8 7 ~6 ~5 4 ~3 2 TX1 RX0 POWER ANALOG IN DIGITAL (PWM~) 2 3 4 5 6 7 GND GND+−+−115510101515202025253030jihgfedcba+
Kaki panjang LED di kolom 4, 9, 14, 19, 24 (baris g), disambung kabel dari pin 3 sampai 7. Kaki pendek ke resistor 220 Ω yang langsung menancap di rel biru atas.

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.

CEK_RANGKAIAN.INO
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.

ATURANCONTOH
Setiap perintah diakhiri titik komadelay(500);
Kelompok perintah diapit kurung kurawalvoid loop() { ... }
Huruf besar dan kecil itu bedadigitalWrite benar, digitalwrite salah
Komentar satu baris diawali //// ini tidak dijalankan
Komentar beberapa baris/* ... */
Spasi dan baris kosong bebasdipakai 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.

jumlahKedip
int
12
suhu
float
28.5
lampuNyala
bool
true
huruf
char
'A'
int jumlahKedip = 12;      // tipe, nama, isi awal
float suhu = 28.5;
bool lampuNyala = true;
char huruf = 'A';

jumlahKedip = jumlahKedip + 1;   // isinya sekarang 13
TIPEISIRENTANG DI UNO
intbilangan bulat−32.768 sampai 32.767
longbilangan bulat besarsekitar ±2,1 miliar
unsigned longbulat besar, tidak negatif0 sampai sekitar 4,29 miliar
bytebulat kecil0 sampai 255
floatbilangan berkomasekitar 6 sampai 7 digit ketelitian
boolbenar atau salahtrue / false
charsatu hurufditulis dengan petik satu: 'A'
Stringteksditulis dengan petik dua: "Halo"

Bilangan berkoma di program ditulis dengan titik, bukan koma: 28.5, bukan 28,5.

KOTAK YANG MELUBER

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

HITUNGARTICONTOHHASIL
+ − * /tambah, kurang, kali, bagi7 / 23 (lihat catatan)
%sisa bagi7 % 21
++ / --tambah / kurang satun++n jadi n + 1
+=tambahkan ke dirinyan += 5sama dengan n = n + 5
BANDINGKANARTILOGIKAARTI
==sama dengan&&dan
!=tidak sama dengan||atau
< >kurang dari, lebih dari!bukan / kebalikan
<= >=kurang/lebih atau sama dengan
7 DIBAGI 2 KOK 3?

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.

JEBAKAN NOMOR SATU: = DAN ==

= 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.

IF_ELSE.INO
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);
  }
}
  1. 1Tiga tekanan pertama (0, 1, 2) menyalakan LED pin 3.
  2. 2else if baru diperiksa kalau syarat pertama salah. Jadi syarat tekan < 6 ini sebenarnya berarti "3 sampai 5". Mulai tekanan keenam, else yang jalan.
COBA UBAH

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.

LED_BERJALAN.INO
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);
  }
}
  1. 1Isi kurung for ada tiga bagian, dipisah titik koma: mulai dari pin = 3, ulangi selama pin <= 7, dan setiap selesai satu putaran pin++. 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
}
COBA UBAH

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.

FUNGSI_KEDIP.INO
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. 1void berarti fungsi ini tidak mengembalikan hasil apa pun, cuma mengerjakan sesuatu. Di dalam kurung ada parameter: nilai yang dikirim saat fungsi dipanggil.
  2. 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.

ARRAY_POLA.INO
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);
  }
}
  1. 1Isi array diambil dengan nomor urut di dalam kurung siku. Nomornya mulai dari 0: led[0] adalah 3, led[4] adalah 7. Tidak ada led[5].
  2. 2Array kedua menyimpan urutan nyala: luar, luar, dalam, dalam, tengah. Mengganti pola cukup mengubah satu baris ini.
AWAS

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?"

DUA_KEDIP_MILLIS.INO
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);
  }
}
  1. 1Waktu disimpan dalam unsigned long, karena dalam beberapa puluh detik angka milidetik sudah melewati batas int.
  2. 2"Kalau sudah lewat 500 milidetik sejak terakhir berganti", ganti keadaan LED dan catat waktunya. Bentuk pengurangan sekarang - terakhirA ini sengaja dipakai, karena tetap benar walaupun millis() 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.

CATATAN

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.

COBA UBAH

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.

CONTOH: LUPA TITIK KOMA
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.

PESANBIASANYA ARTINYA
expected ';' before ...Titik koma lupa di baris sebelumnya.
'xxx' was not declared in this scopeNama 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 inputAda 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 directoryLibrary belum dipasang (lihat 2.6).
PERBAIKI YANG PALING ATAS DULU

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.