(Top)
1 Timer
2 Fungsi Delay
3 Contoh Program
3.1 Program Timer Millis
3.2 Program Timer Interrupt
3.3 Hasil dan Analisis
4 Repository Kode Program
Sebagai programmer Arduino, kita pasti sudah pernah menggunakan timer bahkan tanpa kita sadari.
Hal ini terjadi karena banyak bagian hardware low-level yang diabstraksi dengan library Arduino.
Ada banyak fungsi Arduino yang menggunakan timer seperti delay
, millis
, micros
, dan delayMicroseconds
.
Semua fungsi tersebut menggunakan timer.
Timer pada dasarnya berisi register untuk menyimpan nilai hitungan angka. Jika timer tersebut 8-bit, maka akan menghitung dari 0-255, atau disebut count-up timer seperti pada Figure 1. Timer juga bisa menghitung secara mundur dari 255-0, atau disebut count-down timer. Setiap hitungan naik atau turun dilakukan setiap periode clock timer tersebut.
Sebagai contoh, jika kita menggunakan clock timer 1 MHz, maka berapa maksimum waktu yang dapat dihitung oleh timer 8-bit? Dengan 1 MHz clock, maka periodenya adalah 1\mu s. Maksimum waktu yang dapat dihitung timer 8-bit adalah 256\cdot 1\mu s=256\mu s.
Pada module timer biasanya terdapat prescaler yang berfungsi untuk memperlambat clock timer agar maksimum hitungan timer bisa lebih panjang. Sebagai contoh, prescaler /2 akan memperlambat clock setengahnya, jika kita menggunakan clock timer 1 MHz, maka akan menjadi 500kHz. Oleh karena itu maksimum hitungan timer menjadi 256\cdot 2\mu s=512\mu s.
Dengan library Arduino, kita tidak perlu repot mengkonfigurasi timer secara low-level karena itu sudah dilakukan oleh library. Kita hanya perlu mengerti prinsip kerja dan cara menggunakannya saja.
Fungsi delay
merupakan cara paling sederhana untuk menggunakan timer.
Fungsi tersebut memiliki satu argumen input yaitu nilai milliseconds.
Selain delay
ada juga fungsi delayMicroseconds
yang memiliki satu argumen input yaitu nilai microseconds.
void delay(uint32_t ms);
void delayMicroseconds(uint32_t us);
Jika fungsi tersebut dipanggil, CPU akan berhenti dan menunggu (tidak bisa melakukan eksekusi task lain) sampai hitungan timer tersebut selesai.
Untuk program sederhana, hal ini tidak menjadi masalah, tetapi untuk program yang membutuhkan respon cepat, maka fungsi delay
dapat mengganggu.
Pada contoh program ini, kita akan mempelajari dua contoh penggunaan timer selain fungsi delay
yaitu timer millis dan timer interrupt.
Contoh program ini menggunakan dua buah LED.
LED merah berkedip setiap 200 ms dan LED hijau setiap 2000 ms.
Untuk dapat menjalankan contoh program ini diperlukan beberapa komponen:
Timer millis merupakan timer dengan tipe data unsigned long 32-bit. Timer ini menghitung naik setiap periode 1 ms. Oleh sebab itu diberi nama millis. Timer ini akan kembali lagi ke 0 (rollover) setelah 2^{32}\cdot 1 ms=4294967296 ms\approx 49.7 days. Diperlukan waktu sekitar 50 hari sampai timer millis kembali lagi ke 0. Timer millis akan mulai menghitung ketika board dinyalakan.
Listing 2 menampilkan contoh program timer millis. Berikut ini penjelasan cara kerja program tersebut:
previousMillis
). Variable ini akan berisi nilai millis pada iterasi sebelumnya ketika periode delay terpenuhi.
currentMillis
. Nilai tersebut merupakan nilai millisecond sejak board dinyalakan.
currentMillis
dengan previousMillis
. Jika iya, maka kondisi LED merah akan di-invert (mati menjadi nyala dan sebaliknya). Setelah itu nilai previousMillis
perlu di-update dengan nilai currentMillis
.
// LED pin
#define RED_LED_PIN 25
#define GREEN_LED_PIN 26
unsigned long previousMillisRedLed = 0;
unsigned long previousMillisGreenLed = 0;
void setup()
{
// Konfigurasi GPIO pin sebagai output untuk LED
pinMode(RED_LED_PIN, OUTPUT);
pinMode(GREEN_LED_PIN, OUTPUT);
// Set nilai LED ke kondisi off
digitalWrite(RED_LED_PIN, HIGH);
digitalWrite(GREEN_LED_PIN, HIGH);
}
void loop()
{
// Membaca nilai timer milliseconds
unsigned long currentMillis = millis();
// Jika waktu timer untuk red LED sudah berlalu selama 200 ms
if ((currentMillis-previousMillisRedLed) >= 200)
{
// Simpan nilai millis saat ini untuk referensi pada loop berikutnya
previousMillisRedLed = currentMillis;
// Invert nilai LED
digitalWrite(RED_LED_PIN, !digitalRead(RED_LED_PIN));
}
// Jika waktu timer untuk green LED sudah berlalu selama 2000 ms
if ((currentMillis-previousMillisGreenLed) >= 2000)
{
// Simpan nilai millis saat ini untuk referensi pada loop berikutnya
previousMillisGreenLed = currentMillis;
// Invert nilai LED
digitalWrite(GREEN_LED_PIN, !digitalRead(GREEN_LED_PIN));
}
}
Figure 3 mengilustrasikan kode program timer millis untuk program LED berkedip tanpa fungsi delay pada Listing 2. Pada setiap iterasi loop dilakukan pengecekan apakah nilai current millis sudah lebih besar sebanyak periode yang diinginkan (pada gambar tersebut yaitu 1000 ms) dari nilai previous millis. Jika kondisi terpenuhi, maka itu berarti waktu sudah berlalu sebanyak 1000 ms, kemudian nilai previous millis akan di-update dengan nilai current millis untuk iterasi berikutnya.
Timer interrupt merupakan interrupt yang dihasilkan oleh timer setiap periode waktu tertentu. Figure 4 mengilustrasikan cara kerja timer interrupt. Setiap hitungan timer mencapai nilai yang sudah didefinisikan, maka interrupt akan di-generate. Di dalam kode ISR interrupt tersebut, kita dapat melakukan suatu task yang akan dieksekusi secara periodik.
Listing 3 menampilkan contoh program timer interrupt. Berikut ini penjelasan cara kerja program tersebut:
ticker.h
yang diperlukan untuk membuat timer interrupt.
Ticker
untuk LED merah dan hijau.
attach_ms
untuk mengkofigurasi objek ticker dengan interval interrupt-nya dan fungsi ISR-nya. LED merah menghasilkan interrupt setiap 200 ms, dan LED hijau setiap 2000 ms.
#include <ticker.h>
// LED pin
#define RED_LED_PIN 25
#define GREEN_LED_PIN 26
Ticker timerRedLed;
Ticker timerGreenLed;
void timerRedLed_isr()
{
// Invert nilai LED
digitalWrite(RED_LED_PIN, !digitalRead(RED_LED_PIN));
}
void timerGreenLed_isr()
{
// Invert nilai LED
digitalWrite(GREEN_LED_PIN, !digitalRead(GREEN_LED_PIN));
}
void setup()
{
// Konfigurasi GPIO pin sebagai output untuk LED
pinMode(RED_LED_PIN, OUTPUT);
pinMode(GREEN_LED_PIN, OUTPUT);
// Set nilai LED ke kondisi off
digitalWrite(RED_LED_PIN, HIGH);
digitalWrite(GREEN_LED_PIN, HIGH);
// Set ticker untuk generate interrupt setiap 200 ms
timerRedLed.attach_ms(200, timerRedLed_isr);
// Set ticker untuk generate interrupt setiap 2000 ms
timerGreenLed.attach_ms(2000, timerGreenLed_isr);
}
void loop()
{
}
Dapat kita lihat di fungsi loop pada program timer interrupt tidak ada kode apapun, sehingga CPU akan idle ketika tidak ada interrupt, dan bisa kita digunakan untuk eksekusi task lain.
Figure 5 menampilkan hasil dari program timer millis dan timer interrupt. Keduanya akan menghasilkan hasil yang sama. Perbedaanya yaitu pada flow kode tersebut dieksekusi.
Figure 6 berisi perbandingan timing diagram eksekusi CPU untuk fungsi delay, timer millis, dan timer interrupt. Contoh tersebut merupakan LED berkedip setiap 1 detik. Pada fungsi delay, CPU akan menunggu sampai fungsi delay selesai dan tidak bisa melakukan task lain. Pada timer millis, CPU hanya perlu melakukan pengecekan millis apakah target sudah tercapai atau belum, setelah itu CPU bisa melakukan task lain. Pada timer interrupt, CPU benar-benar idle tanpa perlu melakukan pengecekan millis dan bisa melakukan task lain.
Pada program timer millis, kode LED akan dieksekusi di fungsi loop, sedangkan pada program timer interrupt, kode LED akan dieksekusi di fungsi ISR.
Kode program untuk timer millis dan timer interrupt dapat didapatkan di repository ini: timer-millis dan timer-interrupt.