Jika instruksi delay (250); besaran waktu yang ditunjukkan pada delay tersebut adalah?

Sebelumnya kita telah belajar bagaimana cara menyalakan LED pada Arduino di alamat yang berbeda menggunakan Timer. Pada tutorial kali ini, kita akan belajar bagaimana menyalakan dan mematikan LED pada satu alamat setiap 500 ms menggunakan Timer.

Apa yang saya gunakan

  • Atmel Studio
  • Arduino Uno
  • A B USB Type Cable
  • ATmega 328P Datasheet

Sebelum memulai tutorial ini, pastikan kita sudah mengatur agar Atmel Studio kita dapat meng-upload program ke Arduino.

Index

Contoh Program

Apabila kita bandingkan dengan program sebelumnya akan terlihat mirip. Namun disini penulis akan menjelaskan kembali maksud dari tiap baris program tersebut.

Sebelum kita memulai mengetik instruksi, kita harus menentukan library apa yang akan digunakan. Berhubung disini kita menggunakan ATmega328P maka library tersebut yang akan kita gunakan.

Selanjutnya, kita mulai membuat variabel temp, count, overflow, dan overflow2. Dimana setiapnya berisi R16, R17, R24, dan R25 secara berurutan. Sehingga misalkan kita membuat instruksi LDI temp, 3 itu sama saja dengan LDI R16, 3. Hal ini boleh saja tidak kita lakukan dan langsung menyebutkan register mana yang kita pakai. Namun, untuk mempermudah dan mengetahui fungsi dari tiap register yang dipakai maka penulis gunakan variabel tersebut.

Perhatikan baris program .ORG 0x0000, maksud dari instruksi di atas yaitu menunjukkan pada alamat mana instruksi tersebut dijalankan. 0x0000 merupakan alamat memori pada ATmega328P, disinilah kita harus menggunakan datasheet agar mengetahui maksud dari alamat tersebut. Bila anda belum memilikinya, cek kembali ke link yang sudah saya sematkan.

Buka halaman 27, Bila anda perhatikan Figure 8–2 disitu terdapat gambar dari peta memori yang terdiri dari Application Flash Section dan Boot Flash Section. Ketika anda menjalankan program, maka instruksi yang pertama kali dijalankan selalu dimulai dari alamat 0x0000. Baru kemudian dilanjutkan ke alamat berikutnya.

Bila kita perhatikan cuplikan program di atas, di bawah instruksi .ORG 0x0000 terdapat instruksi RJMP RESET . Ketika program dijalankan, instruksi tersebutlah yang pertama kali dijalankan karena ia berada di alamat memori 0x0000. Setelah menjalankan instruksi tersebut maka program akan melompat ke baris berlabel RESET:yang berada di empat baris di bawahnya, yaitu berada di alamat 0x0100.

Kenapa 2 baris di bawahnya dilompati? Disinilah kita mulai memahami bagaimana cara kerja interrupt. Buka halaman 74, perhatikan Table 12–6. Pada kolom ke 2 yaitu Program Address, disana terdapat daftar alamat memori dari 0x0000 sampai 0x0032 dan kolom ke 3 source merupakan isi dari alamat tersebut. Kita fokus pada alamat 0x0020, bila kita perhatikan isi dari alamat tersebut adalah TIMER0 OVF yang dijelaskan pada kolom berikutnya yaitu Timer/Counter0 Overflow. Maksudnya adalah, ketika terjadi overflow pada TCNT0 (Timer/Counter Register) maka program akan melompat ke alamat tersebut. Kita akan bahas lebih dalam nanti.

Pada saat instruksi RJMP RESET dijalankan, program akan melompat ke label RESET: seperti yang terdapat pada baris ke 2 dari cuplikan program di atas. Setelah itu ia akan menjalankan instruksi di baris berikutnya. LDI temp, 1 berfungsi untuk memasukkan nilai 1 pada R16 yang sudah kita beri nama temp sebelumnya. Kemudian instruksi STS TIMSK0, temp berarti kita mengaktifkan bit ke 0 dari TIMSK0(Timer/Counter0 Mask Interrupt Register) yaitu TOIE0(Timer/Counter0 Overflow Interrupt Enable). Buka halaman 118 nomor 15.9.6 untuk lebih jelasnya.

Apabila kita perhatikan pada gambar di datasheet, TIMSK0 terdiri dari 8 bit dimana di dalam bit tersebut terdapat OCIE0B, OCIE0A, dan TOIE0. Kemudian perhatikan angka kecil di bawah tulisan tersebut, semuanya adalah 0. Itu adalah nilai default dari bit tersebut atau berarti OFF. Kita fokus pada isi dari bit ke 0 yaitu TOIE0. Disitu dijelaskan bahwa apabila TOIE0 bernilai 1, maka ia akan aktif dan apabila terjadi overflow ia akan melakukan interrupt lalu program lompat ke alamat dimana terdapat TIMER0 OVF.

Agar interrupt dapat terjadi, mengaktifkan TIMSK0 tidak cukup, kita juga harus mengaktifkan Global Interrupt supaya interrupt dapat dilakukan. Yaitu dengan instruksi SEI atau Set Enable Interrupt.

Selanjutnya, buka halaman 117 nomor 15.9.3. Fungsi dari TCNT0 yaitu sebagai counter sesuai dengan namanya. Selama program berjalan, isi TCNT0 akan terus bertambah sama halnya bagaimana jarum detik bekerja. Meski program melakukan looping tanpa henti, isi TCNT0 akan tetap bertambah. Meski kita diam, jarum detik terus berputar. Begitulah cara kerjanya, tapi bila kita perhatikan pada gambar di datasheet, TCNT0 terdiri dari 8 bit itu berarti ia mampu menampung nilai hingga 255.

Bagaimana bila isi TCNT0 telah mencapai 255? Inilah yang dinamakan overflow. Kondisi dimana ketika TCNT0 tak mampu lagi menampung nilai lebih dari 255. Dosen saya mengumpamakan TCNT0 ibarat sebuah tandon yang kosong. 255 merupakan volume max dari tandon tersebut. Apabila volume airnya sudah mencapai lebih dari 255 maka tandon itu akan tumpah atau bisa disebut overflow.

Pada cuplikan program di atas, kita memasukkan nilai -250 ke TCNT0 atau sama dengan 255–250 yaitu 5. Maka kalo kita analogikan dengan tandon, tandon tersebut sudah terisi air dengan volume 5, dan kurang 250 lagi untuk mencapai volume maksimumnya.

Untuk mengetahui maksud dari program di atas, buka datasheet halaman 116 nomor 15.9.2. Perhatikan isi dari TCCR0B yang terdiri dari 8 bit. Semua bit telah terisi kecuali bit ke 5 dan 4. Itu artinya kita bisa mengaktifkan bit manapun kecuali bit ke 5 dan 4 karena kosong. Pada cuplikan program di atas, kita memasukkan nilai 3 ke TCCR0B yang artinya kita mengaktifkan bit ke 0 dan 1 yaitu CS00 dan CS01. Apa maksudnya itu? Coba perhatikan baris terakhir dari halaman tersebut, disana dijelaskan bahwa CS merupakan Clock Select yang digunakan Timer/Counter.

Pada halaman berikutnya, dijelaskan lebih lanjut mengenai CS yaitu pada Table 15–9. Bila kita perhatikan, setiap bit yang aktif memiliki arti sendiri yang dijelaskan pada kolom Description. Pada saat kita mengaktifkan CS00 dan CS01 maka kita akan menggunakan prescaler 64. Apa itu prescaler? Misal clock dari ATmega328P yaitu 16MHz, maka kecepatan clock-nya 1/16MHz sama dengan 0.0625us dan nilai dari TCNT0 akan bertambah 1 setiap 0.0625 us. Apabila kita menggunakan prescaler, maka kecepatan clock-nya menjadi [prescaler] x 0.0625us atau karena disini kita menggunakan prescaler 64 maka 64 x 0.0625us = 4us. Bisa disimpulkan isi TCNT0 bertambah 1 setiap 4 us.

Kita kembali ke analogi tandon, sebelumnya kita sudah memiliki tandon yang sudah terisi air dengan volume sebesar 5. Sekarang kita ingin mengisinya lagi dengan keran agar volume air memenuhi tandon. Keran inilah yang kita sebut TCCR0B. Lalu disini kita telah mengatur sedemikian rupa debit keran air agar volume air bertambah 1 setiap 4 us. Dari sini kita bisa mengetahui berapa waktu yang dibutuhkan agar tandon bisa terisi penuh, yaitu
(255–5) x 4us = 1 ms. Tandon akan terisi penuh atau overflow setiap 1 ms.

Cuplikan program di atas berfungsi untuk men-set PORTD ke 0 sebagai output untuk LED yang akan kita nyalakan. SBI sendiri berarti Set Bit in I/O Register jadi dengan instruksi ini kita mengaktifkan register I/O yang akan dipakai.

Dikarenakan kita hendak menyalakan LED dan mematikan LED dengan timer maka pada main program hanya kita isi dengan endless loop untuk menyibukkan program. Loop ini akan berulang selama 1 ms kemudian terjadi interrupt karena pada saat loop berjalan, isi TCNT0 ikut bertambah dan ketika terjadi overflow maka program akan langsung melompat ke alamat dimana terdapat TIMER0 OVF kemudian menjalakan instruksi di dalam alamat tersebut. Setelah itu, program akan kembali melanjutkan instruksi loop yang sempat ditinggalkan.

Setelah terjadi overflow, program akan melompat ke alamat 0x0020 lalu menjalankan instruksi pada alamat tersebut yaitu RJMP T0_OV_ISR kemudian program melompat ke baris berlabel T0_OV_ISR yang terdapat pada alamat 0x0200. Selanjutnya program akan mengerjakan instruksi yang terdapat pada alamat ini.

Pada baris berikutnya terdapat CPI count, 2 yang berfungsi untuk membandingkan apakah R17 bernilai 2, BRSH JUMPatau Branch If Same or Higher berarti apabila nilai count lebih dari atau sama dengan 2 maka program akan melompat ke baris berlabel JUMP: namun bila tidak maka akan melanjutkan instruksi di bawahnya yaitu INC overflow atau menambahkan isi R24 dengan 1.

Baris berikutnya, isi R24 dibandingkan dengan 250. Lalu BRNE PC+3 mengecek apabila isi R24 tidak sama dengan 250 maka program akan melompat 3 baris ke instruksi berikutnya yaitu CLR overflow2 atau mengosongkan isi R25. Apabila isi R24 sama dengan 250 maka akan dijalankan instruksi berikutnya yaitu CLR overflow dan INC count

Setelah itu barulah kemudian dijalankan instruksi SBI PORTD, 0untuk menyalakan LED 0. Lalu instruksi berikutnya RETI atau Return Interrupt berarti program akan kembali ke main program yang sempat ditinggalkan yang di dalamnya terdapat instruksi RJMP HERE.

Program di alamat 0x0200 akan dijalankan setiap kali terjadi overflow yaitu setiap 1 ms. Lalu bagaimana cara kita mendapatkan 500 ms? Disinilah kita membutuhkan R24 untuk menghitung jumlah overflow yang terjadi yaitu dengan instruksi INC overflow sehingga penulis beri nama register tersebut dengan overflow. Tetapi bukankah R24 hanya berukuran 8-bit dan hanya bisa menampung nilai hingga 255? Disinilah peran count atau R17 sebagai multiplier.

Bila kita perhatikan kembali cuplikan program di alamat 0x0200 pada baris pertama terdapat instruksi untuk membandingkan isi R17 dengan 2, apabila sama dengan 2 maka program akan melompat ke label tertentu. Sementara pada baris berikutnya isi R24 bertambah 1 lalu dibandingkan dengan 250, bila tidak sama maka akan melompat 3 baris dimana instruksi yang dilompati diantaranyaINC count dan CLR overflow. Dengan kata lain, isi R17 akan bertambah setiap 250 ms kemudian R24 kembali dikosongkan dan ketika isi R17 sama dengan 2 maka program akan melompat ke baris berlabel JUMP:.

Itu berarti total waktu yang dibutuhkan agar program melompat ke baris berlabel JUMP: yaitu 250 x 2 = 500ms. Disini kita sudah berhasil menyalakan LED dalam waktu 500ms. Ketika program melompat ke baris berlabel JUMP: terdapat instruksi yang mirip namun terdapat CBI PORTD, 0 yaitu untuk mematikan LED dengan total waktu yang sama yaitu 500 ms.

CHALLENGE:

  1. Coba tambahkan instruksi untuk menyalakan LED 0, LED 1, dan LED 2 secara bergantian degan jeda 500 ms menggunakan Timer.
  2. Buatlah program untuk menyalakan semua LED 0 hingga LED 7 secara berurutan kemudian mematikannya secara berurutan pula masing masing dengan jeda 60 ms.

Demikianlah penjelasan mengenai bagaimana cara menggunakan Timer untuk menyalakan LED selama 500 ms dengan interrupt. Silahkan memberikan respon bilamana terdapat penjelasan yang kurang. Penulis juga masih pelajar. Terima kasih dan semoga bermanfaat.

Video yang berhubungan

Postingan terbaru

LIHAT SEMUA