Kode program pembacaan sensor garis & grid counter

Hsalaman ini memberikan informasi tentang cara kerja pembacaan sensor garis dan sensor grid counter menggunakan bahasa pemrograman C/C++ pada Arduino Uno. Pembacaan output rangkaian sensor dilakukan pada pin 2, 7, 11, dan 12 dengan penjelasan beberapa potongan kode program. 
Posisi sensor pada grid linefollower
Gambar 1. Posisi sensor pada grid line follower


Kode Program Inisialisasi Semua port Arduino Uno yang digunakan sebagai input/output pada rangkaian Grid Line Follower

// ================================================================
#define pinStart  13
#define sensor3   2
#define sensor2   7
#define sensor1  11
#define sensor4  12

void inisialisasiPort(void)

{
int Pins[11] = {sensor1, sensor2, sensor3, sensor4, pinStart, 9, 10, A0, A1, A2, A3} ;
 for (int i = 0; i < 12; i++)
 {
    if (i <= 4 )
      { 
          pinMode(Pins[i], INPUT_PULLUP); 
       }
      else
      { 
          pinMode(Pins[i], OUTPUT);
         digitalWrite(Pins[i], HIGH);  
       }
 }
while (digitalRead(pinStart)==1)
  {}
}

Penjelasan kode program inisialisasi port di atas :

#define pinStart  13
Kode program ''#define <nama> <pin>' di atas bertujuan untuk mengganti nama pin dengan nama yang lebih mudah untuk diingat.  Contoh, agar lebih nyaman menggunakan 


while (digitalRead(pinStart)==1)
dari pada menggunakan
while (digitalRead(13)==1)

Selain itu jika ingin mengganti pin yang akan digunakan cukup dengan mengganti pin pada kode 'define <nama> <pin>' saja dari pada harus mengganti nama pin pada semua kode yang telah  di-tulis.

void inisialisasiPort(void)
{
  //Program inisialisasi port Arduino Uno
}
Prosedur inisialisasiPort di atas bertujuan untuk menjalankan blok kode program yang ditulis dalam prosedur tersebut, jika prosedur tersebut dipanggil maka semua blok kode program didalamnya akan dieksekusi atau dikerjakan.

int Pins[11] = {sensor1, sensor2, sensor3, sensor4, pinStart, 9, 10, A0, A1, A2, A3} ;
Kode program ini merupakan array dari semua pin Arduino Uno yang akan digunakan. Penulis lebih suka menggunakan teknik ini karena lebih singkat dalam melakukan inisialisasi port dari pada menuliskan kode inisialisasi setiap port yang mengakibatkan penulisan program bisa lebih panjang. 

for (int i = 0; i < 12; i++)
 {
    if (i <= 4 )
      {
           pinMode(Pins[i], INPUT_PULLUP); 
       }
      else
      { 
          pinMode(Pins[i], OUTPUT);
         digitalWrite(Pins[i], HIGH); 
      }
  while (digitalRead(pinStart)==1)
     {}
 }
Program di atas digunakan untuk menentukan port yang akan digunakan sebagai output atau input. Caranya adalah melakukan inisialisasi dengan perintah 'pinMode(<pin>, <output atau input>)' dari nama pin yang disebut pada array dengan cara menggunakan perintah loop 'for' sebanyak jumlah pin yang digunakan.

pinMode(Pins[i], OUTPUT);
Kode program untuk menentukan bahwa pin Arduino yang digunakan sebagai input atau output. Pins[i] merupakan data array pin Arduino Uno. Jika tidak menggunakan array langsung saja ditulis pin yang digunakan.

digitalWrite(Pins[i], HIGH); 
Merupakan kode program untuk membuat pin Arduino menjadi 1 atau pada pin tersebut akan mengeluarkan tegangan hampir +5Volt. 

while (digitalRead(pinStart)==1)
  {}
Kode program while di atas berarti saat nilai pinStart adalah 1 maka program akan berhenti pada while terus menurus sampai nilai variabel pinStart bernilai 0. Pada rangkaian grid line follower pin Arduino 13 terhubung pada tombol push button yang digunakan untuk menjalankan grid line follower.


Kode Program Pembacaan Sensor1, Sensor2 dan Sensor3 pada Arduino Uno
Di bawah ini adalah adalah contoh program pembacaan semua sensor pada grid line follower :

uint8_t bacaSensor()
{
 uint8_t data, nilai = 0;
 data = digitalRead(sensor1);
  if (data == 0)
     { nilai = 0b000000110; }
  if (data == 1)
     { nilai = 0b00000111; }
  data = digitalRead(sensor2);
  if (data == 0)
     { nilai = 0b00000101 & nilai; }
  if (data == 1)
     { nilai = 0b00000111 & nilai; }
  data = digitalRead(sensor3);
  if (data ==  0)
     { nilai = 0b00000011 & nilai; }
  if (data == 1)
      {nilai = 0b00000111 & nilai; }
  return nilai;
}

Panjelasan kode program pembacaan sensor pada Arduino Uno
Sensor1 diletakan pada posisi kanan, sensor2 di posisi tengan, sensor3 pada posisi kiri. Sudut pandang sensor dilihat dari atas. Variabel 'pinStart' menunjukan pin pada Arduino Uno yang dihunungkan pada pin13 dan pada gambar rangkaian pin 13 terhubung dengan saklar push button untuk menjalankan line follower.  

Rangkaian sensor dibuat sedemikikian rupa sehingga jika sensor photodiode mendeteksi adanya garis putih maka output komparator menjadi 0 atau mendekati 0 sehingga memberikan inputan 0 pada rangkaian Arduino Uno.

Penulis membuat semua program pembacaan sensor adalah aktif low dimana jika ada inputan 0 dari rangkaian sensor maka berarti program menganggap bahwa pada rangkaian sensor tersebut telah mendeteksi garis putih. 

Kode program uint8_t bacaSensor() merupakan fungsi pembacaan sensor dengan nilai balik yang memuat data hasil pembacaan sensor1, sensor2 dan sensor3 yang semuanya merupakan sensor garis. 
Pembacaan sensor dilakukan satu persatu setiap pin yaitu : sensor1 dibaca, kemudian  sensor2 dibaca lalu sensor3 dibaca. Hasil pembacaan setiap sensor digabung menjadi satu kesatuan dalam nilai 8 bit sehingga lebih mudah untuk dibuat kode program percabangan 'if' untuk menentukan kecepatan motor atau untuk tujuan lainnya.
Contoh : data = digitalRead(sensor1);, saat sensor1 bernilai 0 maka penulis membuatnya menjadi bernilai 0b00000110. Nilai 0b00000110 menandakan sensor1 bernilai 0 yang berarti bahwa yang mendeteksi garis putih adalah sensor1, sensor 2 dan 3 lainnya bernilai 1 karena dianggap belum dilakukan pembacaan sensor atau dianggap tidak melakukan pendeteksian garis putih. Jika sensor1 tidak mendeteksi garis putih atau bernilai 1 maka variabel data dibuat bernilai 0b00000111. Jika sensor1, sensor2 dan sensor3 mendeteksi adanya garis putih maka variabel data dibuat bernilai 0b00000000. Jika sensor 2 dan 3 saja yang mendeteksi garis maka variabel data dibuat bernilai 0b00000001

Urutan pembacaan sensor pada program di atas adalah sbb :
  1. Dilakukan pembacaan pada sensor1, jika output rangkaian sensor1 bernilai 0 (mendeteksi adanya garis putih) maka variabel 'data' menjadi 0 dan variabel 'nilai' dibuat menjadi 0b00000110, jika output rangkaian sensor1 bernilai 1 (tidak mendeteksi adanya garis putih) maka variabel 'data' bernilai 1 dan variabel nilai dibuat bernilai 0b00000111.
  2. Kemudian program membaca sensor2, jika rangkaian sensor2 mengeluarkan bit 0(mendeteksi garis putih) maka variabel 'data' bernilai 0 dan variabel 'nilai' dibuat menjadi 0b00000101 yang di 'and' kan dengan variabel nilai pada pembacaan sensor1, sehingga bisa ditulis menjadi nilai = nilai & 0b00000101. Jika sensor2 tidak membaca garis putih maka variabel data otomatis akan bernilai 1 dan variabel nilai menjadi 0b00000111 di 'and' kan dengan variabel pembacaan sensor1 sehingga bisa ditulis menjadi nilai = nilai & 0b00000111.
  3. Kemudian program membaca sensor3, jika rangkaian sensor3 mengeluarkan bit 0 (mendeteksi garis putih) maka variabel 'data' bernilai 0 dan variabel 'nilai' dibuat menjadi 0b00000011 yang di 'and' kan dengan variabel nilai pada pembacaan sensor2, sehingga bisa ditulis menjadi nilai = nilai & 0b00000011. Jika sensor3 tidak membaca garis putih maka variabel data otomatis akan bernilai 1 dan variabel nilai menjadi 0b00000111 di 'and' kan dengan variabel pembacaan sensor1 sehingga bisa ditulis menjadi nilai = nilai & 0b00000111.
  4. Setelah sensor 1, 2, 3 dibaca dan variabel 'nilai' dari hasil pembacaan masing-masing sensor digabung maka variabel nilai tersebut dikembalikan pada fungsi ''uint_8 bacaSensor()) dengan kode program ''return nilai; ' sehingga bisa dilakukan pembacaan sensor cukup dengan contoh kode program 'dataSensor = bacaSensor() ;' yang hasil dari pembacaan sensor disimpan pada variabel 'dataSensor'.
    Pembacaan Sensor Counter Grid (penghitung persimpangan)
    Pembacaan data sensor4 (counter grid) dilakukan saat vector interrupt timer overflow karena hasilnya lebih cepat dibanding menuliskannya pada loop karena pada loop program harus menunggu program lain selesai dikerjakan sebelum kode pemanggilan fungsi pembacaan sensor dieksekusi. Jika kode pembacaan sensor4 ditulis pada vector interrupt timer overflow, kode program akan selalu dieksekusi saat terjadi overflow pada counter yang selalu terjadi secara periodik dan cepat. Selain itu jika program masih mengerjakan program lain program akan melakukan interupsi dan mengerjakan pembacaan sensor lalu akan kembali ke program semula.

    Pemanggilan kode fungsi pembacaan sensor pada vector interupsi timer/counter2 mode overflow dapat dituliskan menjadi :

    ISR(TIMER2_OVF_vect)
    {
     dataSensor = bacaSensor() ;
    }

    Pembacaan sensor counter grid ini berbeda dari penjelasan sebelumnya karena untuk menghitung grid atau persimpangan tidak bisa menggunakan metode pembacaan biasa seperti pembacaan sensor garis putih yang telah dijelaskan sebelumnya karena sensor harus menghitung satu garis putih yang dilewati sebagai satu hitungan, jika menggunakan pembacaan biasa, mikrokontroler akan menghitung banyak sekali pada satu persimpangan yang dilewati.

    Penghitungan persimpangan dapat dilakukan menggunakan fitur external interrupt pada Arduino dimana program menghitung satu hitungan jika saat mikrokontroler mendeteksi ada perubahan logika 1 menjadi 0 atau 0 menjadi 1 pada terminal atau pin external interrupt tergantung pada pilihan konfigurasi. Penulis tidak menggunakan fitur tersebut karena dapat dibuat programnya tanpa menggunakan pin external interrupt tetapi kerjanya sangat mirip dengan external interrupt sehingga dapat menghemat pin external interrupt untuk tujuan lainnya. Kode program pembacaan persimpangan grid ditulis pada  vector interrupt timer/counter2 yang telah dijelaskan di atas.

    Berikut contoh penulisan program pembacaan sensor grid counter :


    volatile uint8_t flipflop =1, temp=0, counter=0;


    ISR(TIMER2_OVF_vect)
    {
     dataSensor = bacaSensor() ;
      temp =digitalRead(sensor4) ;
      if (temp == 1)
        {
           if (flipflop == 0)
            {
              flipflop = 1 ;
              counter++ ;
            }
        }
         if (temp == 0)
           flipflop = 0;

    }

    Penjelasan kode program pembacaan sensor grid counter
    Variabel global flipflop dan temp memiliki kode volatile didepannya bertujuan agar variabel global tersebut dapat diakses oleh blok kode program pada vector interrupt, karena tanpa kode volatile' variabel global tidak dapat dibaca oleh kode program pada blok vector interrupt.
    • Variabel global flipflop diberi nilai logika 1,  variabel global temp dan counter diberi nilai logika 0. 
    • Hasil pembacaan sensor4 disimpan pada variabel temp dengan perintah temp = digitalRead(sensor4);
    • Jika variabel temp (hasil pembacaan sensor4) bernilai 1 dan jika variabel flipflop bernilai 0, maka variabel flipflop diberi logika 1 dan variabel counter akan dijumlahkan dengan 1 dengan perintah counter++. Sebelum ada persimpangan yang dilewati penjumlahan variable counter tidak akan dilakukan karena tidak memenuhi persyaratan kondisi. 
    • Jika sensor4 mendeteksi adanya persimpangan maka variabel temp (hasil pembacaan sensor4) akan bernilai 0 dan variabel flipflop akan dibuat menjadi 0. Selama sensor masih mendeteksi adanya persimpangan (garis putih belum dilewati sepenuhnya) maka kondisi variabel flipflop dan temp akan selalu 0 yang menyebabkan penjumlahan variabel counter dengan 1 tidak bisa dilakukan.
    • Saat persimpangan sudah terlewati (sensor4 tidak mendeteksi garis persimpangan) maka variabel temp akan bernilai 1 sehingga kondisi variabel temp bernilai 1 dan variabel flipflop bernilai 0 tepenuhi lalu variabel flipflop  dibuat lagi bernilai 1 dan variabel counter ditambah dengan 1. Hal ini menyebabkan variabel counter bernilai 1. Setelah itu variabel counter tidak akan ditambah dengan 1 jika tidak melewati persimpangan lagi.
    • Setiap melewati persimpangan variabel counter akan selalu ditambahkan dengan 1. dan variabel counter inilah yang dijadikan sebagai acuan sebagai perhitungan jumlah persimpangan atau grid yang telah dilalui.
    Kode program lengkap dari penjelasan interrupt timer,  pembacaan sensor garis, pembacaan sensor counter grid adalah sbb :

    #include "Arduino.h"
    #define pinStart 13
    #define sensor3 2
    #define sensor2 7
    #define sensor1 11
    #define sensor4 12
    volatile uint8_t dataSensor = 0, temp = 0, flipflop = 1, counter = 0;
    void inisialisasiPort(void)
    {
    int Pins[11] = {sensor1, sensor2, sensor3, sensor4, pinStart, 9, 10, A0, A1, A2, A3} ;
     for (int i = 0; i < 12; i++)
     {
        if (i <= 4 )
          {
                        pinMode(Pins[i], INPUT_PULLUP); 
                  }
          else
          { 
                       pinMode(Pins[i], OUTPUT);
       digitalWrite(Pins[i], HIGH);
          }
     }
       while (digitalRead(pinStart)==1)
     {}
      TCCR1A = 0b10100011;  //phase correct PWM
      TCCR1B = 0b00001100;
       TCCR2B = 0b00000011; //source clock / 32
       TIMSK2 = 0b00000001 ;
       sei ();
    }

    ISR(TIMER2_OVF_vect)

    {
     dataSensor = bacaSensor() ;
      temp =digitalRead(sensor4) ;
      if (temp == 1)
        {
           if (flipflop == 0)
            {
              flipflop = 1 ;
              counter++ ;
            }
        }
         if (temp == 0)
           flipflop = 0;
    }

    uint8_t bacaSensor()

    {
     uint8_t data, nilai = 0;
     data = digitalRead(sensor1);
      if (data == 0)
         { nilai = 0b000000110; }
      if (data == 1)
         { nilai = 0b00000111; }

      data = digitalRead(sensor2);

      if (data == 0)
         { nilai = 0b00000101 & nilai; }
      if (data == 1)
         { nilai = 0b00000111 & nilai; }

      data = digitalRead(sensor3);

      if (data ==  0)
         { nilai = 0b00000011 & nilai; }
      if (data == 1)
          {nilai = 0b00000111 & nilai; }
      return nilai;
    }