Anda di sini

Elektronika

Penggunaan Detak (Clock) dan Prescaler Pada Proses Sampling

Kusuma Wardana - 20 November 2015 14:21:11 0

Mari amati apa yang tertulis pada datasheet mikrokontroler sebagai berikut:

By default, the successive approximation circuitry requires an input clock frequency between 50 kHz and 200 kHz to get maximum resolution.

Rekomendasi dari pabrikan mengatakan bahwa kecepatan detak yang direkomendasikan adalah antara 50 kHz sampai dengan 200 kHz pada resolusi maksimum 10-bit. Kecepatan yang lebih tinggi daripada 200 kHz akan menurunkan akurasi. Umumnya, mikrokontroler Arduino menggunakan clock sebesar 16 MHz, dan umumnya ADC akan memiliki sumber clock yang sama dengan mikrokontroler. Nilai ini jauh lebih besar dari yang dibutuhkan oleh ADC, yaitu maksimum hanya 200 kHz. Oleh karena itu, terdapat suatu prescaler pada mikrokontroler. Prescaler ini yang akan membagi nilai clock sumber yang digunakan oleh mikrokontroler. Nilai prescaler dapat diatur menggunakan 3 bit ADPS, yaitu ADPS0, ADPS1 dan ADPS2. Amatilah Gambar 3, berikut.

Gambar 3. ADC Prescaler

Nilai prescaler yang disediakan adalah 2, 4, 8, 16, 32, 64, dan 128. Nilai-nilai ini yang akan digunakan untuk membagi detak (clock) sumber. Karena kita menggunakan clock 16 MHz pada Arduino kita, maka diperoleh nilai-nilai detak hasil pembagian sebagai berikut:

16 MHz / 2 = 8 MHz
16 MHz / 4 = 4 MHz
16 MHz / 8 = 2 MHz
16 MHz / 16 = 1 MHz
16 MHz / 32 = 500 kHz
16 MHz / 64 = 250 kHz
16 MHz / 128 = 125 kHz

Karena clock ADC yang direkomendasikan berada diantara 50 kHz dan 200 kHz, maka prescaler yang tepat digunakan adalah sebesar 128. Nilai 128 ini diperoleh dengan mengatur ADPS2, ADPS1 dan ADPS0 masing-masing bernilai 1. Tabel selengkapnya untuk mengatur nilai pada ADPS diperlihatkan pada Tabel 1.

Tabel 1. Seleksi Nilai ADPS

Berdasarkan pembagian di atas, jika kita menggunakan prescaler sebesar 128, maka kecepatan ADC sebesar 125 kHz. Bagaimana caranya agar kita dapat menaikkan kecepatan ADC kita? Caranya adalah menurunkan clock sumber. Misalnya kecepatan clock dari 16 MHz kita turunkan menjadi 12 MHz, dan precaler diturunkan menjadi 64. Maka, kecepatan ADC sekarang menjadi 12 MHz/64 = 187 kHz. Nilai ini lebih besar 187 - 125 = 62 kHz daripada perhitungan kita sebelumnya. Namun, menurunkan clock sumber berarti menurunkan kecepatan mikrokontroler. Inilah yang menjadi untung-rugi (trade-off) dari desain kita. Lagipula, sangat tidak praktis untuk mencabut clock yang sudah terpasang dengan baik di Arduino kita dan menggantinya dengan yang baru.

Mari kita kembali ke nilai 125 kHz di atas (clock sumber 16 MHz dan prescaler 128). Karena ADC kita membutuhkan waktu 13 detak dalam sekali konversi, maka banyaknya sampel yang bisa dikonversi oleh ADC harus dibagi lagi sebanyak 13 dari kecepatan ADC, yaitu 125/13 = 9.6 kSa/s (kilo sampel per detik). Untuk aplikasi khusus, misalnya untuk pencuplikan gelombang suara, maka nilai maksimal bandwidth ADC harus dibagi dua lagi, yaitu 9,6/2 = 4,8 kHz. Hal ini sesuai dengan hukum Nyquist, yaitu frekuensi sampling paling tidak dua kali lipat dari frekuensi tertinggi gelombang tercuplik untuk menghindari aliasing.

Mari kita amati ke Arduino kita. Perintah untuk menggunakan ADC adalah analogRead(). Pertanyaan kita, berapa sebenarnya kecepatan sampling dari sintaks analogRead() ini?

Jika kita menginstal software Arduino, mari kita amati file wiring.c (biasanya berada pada C:\Program Files\arduino-1.0.4-windows\arduino-1.0.4\hardware\arduino\cores\arduino\wiring.c). Tentunya letakknya disesuaikan dengan tempat dimana kita menginstal dan versi software Arduino kita. Kalau kita buka wiring.c dan amati dibagian paling bawah dari kumpulan koding tersebut, diperoleh keterangan sebagai berikut:

#if defined(ADCSRA)
    // set a2d prescale factor to 128
    // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
    // XXX: this will not work properly for other clock speeds, and
    // this code should use F_CPU to determine the prescale factor.
    sbi(ADCSRA, ADPS2);
    sbi(ADCSRA, ADPS1);
    sbi(ADCSRA, ADPS0);
 
    // enable a2d conversions
    sbi(ADCSRA, ADEN);
#endif

Sesuai dugaan kita, prescaler yang digunakan adalah 128. Hal ini terbukti dari sintaks sbi (set bit) yang dikerjakan pada ADPS2, ADPS1 dan ADPS0. Sesuai dengan Tabel 1, maka jika ketiga bit ini diset (diberi nilai 1), maka prescaler yang dihasilkan adalah 128. Melihat kenyataan ini, sintaks analogRead(), Arduino kita dibatasi mencuplik sebanyak 9.6 kSa/s, atau jika kita bulatkan menjadi 9.000 sampel perdetik. Jika kita menggunakan Arduino Uno, maka inilah opsi yang kita peroleh. Untuk beberapa seri mikrokontroler keluarga Xmega keluaran Atmel, kita diperkenankan untuk memperoleh kecepatan yang lebih tinggi.

Namun, adakah cara lain untuk meningkatkan clock pada Arduino Uno kita?

Mari kita amati petunjuk pada datasheet (AVR120: Characterization and Calibration of the ADC on an AVR), sebagai berikut:

The ADC accuracy also depends on the ADC clock. The recommended maximum ADC clock frequency is limited by the internal DAC in the conversion circuitry. For optimum performance, the ADC clock should not exceed 200 kHz. However, frequencies up to 1 MHz do not reduce the ADC resolution significantly.

Dikatakan bahwa frekuensi ADC sampai 1 MHz tidak mengurangi resolusi ADC terlalu signifikan. Namun, jika di atas 1 MHz tidak dijamin oleh pabrikan. Dengan demikian, kita dapat mengambil kesimpulan kalau clock ADC kita naikkan sampai maksimal 1 MHz tidak menjadi persoalan. Melihat kenyataan ini, dengan clock sebesar 16 MHz, kita dapat memilih prescaler yaitu sebesar 16, 32, 64 dan 128.

Mari kita coba mengamati bagaimana jika prescaler kita mainkan dalam pemrograman Arduino. Seperti yang sudah dibahas sebelumnya, prescaler diatur pada bit ADPS2, ADPS1, dan ADPS0 pada register ADCSRA. Dengan demikian, nilai ketiga bit inilah yang digunakan untuk mengubah kecepatan sampling dari ADC kita.

Sekarang kita akan memprogram Arduino untuk membaca sampel sebanyak 50 kali, dan menghitung berapa waktu yang diperlukan untuk proses konversi tersebut. Waktu yang dibutuhkan akan dikeluarkan melalui serial monitor. Sebuah potensiometer kita masukkan di pin A0.

// Array berikut digunakan untuk menyimpan data
unsigned long nilaiADC[50];
unsigned long waktu_mulai[50];
unsigned long waktu_berhenti[50];
 
void setup() {
  //kecepatan serial
  Serial.begin(9600);  
}
 
void loop() {  
  unsigned int i;
   
  // catat waktu mulai dan berhenti
  //simpan hasilnya di memori
  for(i=0;i<50;i++) {
    waktu_mulai[i] = micros();
    nilaiADC[i] = analogRead(0);
    waktu_berhenti[i] = micros();
  }
 
  // tampilkan hasilnya ke serial monitor  
  for(i=0;i<50;i++) {
    Serial.print(" Nilai ADC = ");
    Serial.print(nilaiADC[i]);
    Serial.print(" Waktu konversi = ");
    Serial.print(waktu_berhenti[i] - waktu_mulai[i]);
    Serial.print(" us\n");
  }
  delay(5000);
}

Dari waktu konversi diperoleh nilai 116 mikrodetik, atau 0.116 milidetik tiap sampel, atau 0.000116 detik tiap sampel. Dengan demikian, frekuensi sampling yang digunakan adalah (1/0.000116) = 8.620, 689 Hz, atau sekitar 8.6 kHz. Jika merujuk pada kecepatan pengambilan sampel nilai ini dikatakan sebagai 8.6 kSa/s. Nilai ini mendekati dugaan awal kita, yaitu tanpa modifikasi prescaler, kecepatan dari analogRead() mendekati nilai 9.6 kSa/s. Nilai ini sedikit lebih kecil karena penggunaan sintaks micros() juga membutuhkan waktu eksekusi.

Mari sekarang kita maenkan prescaler-nya. Kita mempunyai pilihan nilai selain 128 yaitu 16, 32 dan 64. Mari kita modif program kita yang sebelumnya. Kita gunakan prescaler sebesar 64, dan potensiometer saya putar agar diperoleh variasi hasil. Programnya adalah sebagai berikut:

// Array berikut digunakan untuk menyimpan data
unsigned long nilaiADC[50];
unsigned long waktu_mulai[50];
unsigned long waktu_berhenti[50];
 
// Tentukan nilai-nilai Prescaler
// Lakukan pengaturan pada bit ADPS2 sampai ADPS0
const unsigned char PS_16 = (1 << ADPS2);
const unsigned char PS_32 = (1 << ADPS2) | (1 << ADPS0);
const unsigned char PS_64 = (1 << ADPS2) | (1 << ADPS1);
const unsigned char PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
 
void setup() {
  //kecepatan serial
  Serial.begin(9600); 
  // Lakukan inisialisasi. 
  // Hapus pengaturan oleh library Arduino
  ADCSRA &= ~PS_128; 
  // pilih prescaler yang digunakan.
  // Saat ini gunakan nilai 64
  ADCSRA |= PS_64; 
}
 
void loop() {  
  unsigned int i;
   
  // catat waktu mulai dan berhenti
  //simpan hasilnya di memori
  for(i=0;i<50;i++) {
    waktu_mulai[i] = micros();
    nilaiADC[i] = analogRead(0);
    waktu_berhenti[i] = micros();
  }
 
  // tampilkan hasilnya ke serial monitor  
  for(i=0;i<50;i++) {
    Serial.print(" Nilai ADC = ");
    Serial.print(nilaiADC[i]);
    Serial.print(" Waktu konversi = ");
    Serial.print(waktu_berhenti[i] - waktu_mulai[i]);
    Serial.print(" us\n");
  }
  delay(5000);
}

Amati bahwa waktu konversi sebesar 60 mikrodetik = 0,00006 detik, atau setara dengan 16 kSa/s. Ya, hasil kita masih cukup masuk akal. Hasil konversi juga cukup stabil. Bagaimana kalau kita naikkan sampai batas toleransi yang diperbolehkan? Kita gunakan prescaler paling kecil yaitu 16. Dengan mengganti satu baris koding, yaitu ADCSRA |= PS_64; menjadi ADCSRA |= PS_16; kita peroleh hasil sebagai berikut:

Kecepatan tercepat yang diperoleh adalah 20 mikrodetik, dan ini setara dengan 50 kSa/s. Terdapat variasi lebih banyak pada Nilai ADC yang diperoleh. Ini menunjukkan ADC semakin tidak stabil. Namun demikian, variasi tidak terlalu timpang. Bisa kita tarik kesumpulan bahwa dengan resolusi maksimal ADC, yaitu 10-bit, maka kecepatan maksimum yang dapat dicapai adalah 50 kSa/s. Hasil yang cukup mengesankan ketimbang kecepatan 'default' Arduino, yaitu sekitar 9 kSa/s.

Yup... semoga artikel ini berguna.

Referensi:

[1] Wardana, N.K., 2012. Studi Penerapan Mikrokontroler Sebagai Data Logger Sinyal Suara. Seminar Astechnova Teknik Fisika UGM
[2] Berg, GVD. 2014. Advanced Arduino ADC - Faster analogRead(). http://www.microsmart.co.za/technical/2014/03/01/advanced-arduino-adc/
[3] Anonim. 2015. Analog-to-digital converter.http://en.wikipedia.org/wiki/Analog-to-digital_converter
[4] Anonim. 2006. AVR120: Characterization and Calibration of the ADC on an AVR. Atmel Corporation
[5] Anonim. 2009. Datasheet ATmega328P. Atmel Corporation
[6] Anonim. 2014. Analog Sampling Basics. National Instruments http://www.ni.com/white-paper/3016/en/pdf

6.048
Image

Kusuma Wardana

I Nyoman Kusuma Wardana, yang akrab dipanggil Kusuma, lahir dan besar di Bali. Ia tinggal di Desa Wisata Ubud, dan lebih banyak melaksanakan aktivitasnya di Denpasar. Profesinya adalah sebagai staf pengajar di Jurusan Teknik Elektro, Politeknik Negeri Bali. Saat ini Ia menjadi salah satu penulis di tutorkeren.com.

Artikel Menarik Lainnya
Mari Gabung

Halo Emo 51 , Ada yang ingin disampaikan? Jangan sungkan untuk gabung diskusi ini. Silahkan Login dulu atau Daftar baru.