Translate

Pencacah Naik 4 Masukan Dengan Keluaran Serial Pada MCS51



Alhamdulillah, akhirnya selesai juga....

Artikel ini ditujukan untuk beberapa Sobatku yang sudah bersedia memberikan respon positif dan sudah barang tentu sebagai ucapan terima kasih karena bersedia melirik pada blogger sederhana ini. Adalah merupakan sebuah kehormatan yang tak terkira nilainya dapat menerima komentar maupun pesan melalui e-mail.

Mohon maaf juga karena beberapa waktu ini sempat vakum dari kegiatan tulis-menulis artikel karena kesibukan pekerjaan yang cukup menyita waktu.



Pencacah naik (up counter) yang akan kita bahas merupakan pencacah dekade menggunakan format BCD. Pada contoh aplikasi berikut, rangkaian dapat mencacah dalam 5 digit atau 0 sampai 99999. Namun bukan merupakan kendala jika ingin menambah jumlah digit lebih dari 5. Sobat bisa dengan mudah menambahkan jumlah digit sebanyak register yang ada. Bagaimana? Menarik bukan. Hal ini bisa dilaksanakan karena secara prinsip kerja dalam pencacahan, kita akan menggunakan register dari mikrokontroler untuk mencacah dengan kombinasi perintah INC A (increment) dan DA A (decimal adjust) melalui register akumulator.

Rangkaian yang akan kita buat dan sudah penulis realisasikan pada sistem pencacah HASIL pada sebuah pabrik yang tentunya karena alasan etika tidak disebutkan. Rangkaian memiliki masukan sebanyak 4 saluran yang secara independen akan menaikkan cacahan. Masing-masing masukan terhubung pada sakelar PUSH-ON di mana jika ditekan akan menaikkan cacahan sejumlah masukan yang ditekan meskipun secara bersamaan. Jadi jika salah satu ditekan maka cacahan akan bertambah satu dan jika ada 4 sakelar ditekan bersamaan maka cacahan akan bertambah 4 karena setiap masukan bersifat independen dan merupakan akumulasi dari tiap masukan yang ditekan.

Sebagai catatan jika menginginkan jumlah masukan lebih dari 4, maka hal tersebut bukan merupakan masalah. Sama halnya dengan jumlah digit maksimum yang diinginkan. Untuk jelasnya kita lihat blok diagram kerja rangkaian kita.

Pada gambar diagram di atas terdapat 4 saluran masukan yang masing-masing akan menghasilkan nilai +1 atau cacahan naik (pada aplikasi program) jika dipicu. Hasil cacahan dari setiap masukan akan diakumulasi untuk kemudian ditampilkan pada keluaran. Ternyata oh ternyata, penulis memutuskan bentuk keluaran dari hasil cacahan dalam bentuk format data serial.

Sebagai tambahan saja, maka hasil cacahan akan disimpan dalam memori menggunakan AT93C46 sehingga tidak akan hilang meskipun catu daya dipadamkan di mana proses pencacahan dapat dilanjutkan dilain waktu. Dalam aplikasi yang penulis tujukan adalah dalam proses kerja di pabrik di mana pada waktu istirahat makan maka perangkat bisa di matikan sementara waktu istirahat untuk menghemat energi listrik.

Tentu Sobat ada yang bertanya, kenapa keluarannya berbentuk serial?

Jawabnya sederhana saja.

Pada aplikasi yang sudah dibuat dan direalisasikan, saat desain ini dibuat, terdapat 2 buah tampilan, yaitu TARGET dan HASIL. Masing-masing memiliki jumlah digit yang sama. Sudah barang tentu memiliki rangkaian yang sama. Dan untuk keluwesan dalam pengembangan selanjutnya maka nantinya peraga juga dapat fleksibel apakah ingin menggunakan peraga LED 7 segmen atau LCD atau bahkan menggunakan komputer atau diinginkan dalam rangkaian jaringan di mana terdapat lebih dari satu pencacah dan terhubung dengan PC. Sebagai bocoran saja, pengembangan dari rangkaian di atas selanjutnya, ternyata dari pihak pengguna menginginkan tambahan tampilan WAKTU. Nah, jadi tidak perlu membuat rangkaian baru kan. Cukup menambah peraga digit dan sedikit modifikasi aplikasi programnya saja, selesai.
Sebelum bertele-tele dalam pembahasannya, Yuk kita lihat rangkaian lengkap pencacah yang dimaksud.



Ada sedikit modifikasi pada rangkaian atas dari desain aslinya. Pada desain aslinya penulis menggunakan IR (infrared) sensor untuk penyetelan pada gerbang P32 dan menggantinya dengan sakelar tekan untuk RESET.

Otak dari rangkaian pencacah adalah mikrokontroler AT89C2051. Untuk masukannya dibuat dengan komparator dengan LM339 yang terdiri dari 4 buah. Jika diinginkan bisa menjadi 8 masukan dan tentu jumlah LM339 juga menjadi 2 buah. Seperti sudah dibahas di atas maka untuk menyimpan data cacahan digunakan memori AT93C46. Memori digunakan untuk informasi UNIT NUMBER yang berguna pada aplikasi jaringan dan tentu informasi HASIL cacahan.

Penggunaan komparator di atas dimaksudkan untuk mengurangi resiko riple pada sakelar. Adanya ambang histerisis dan filter kapasitif memungkinkan resiko tersebut tereliminasi alias aman. Apalagi jika masukan terkoneksi menggunakan kabel yang cukup jauh dari lokasi perangkat.

Dalam implementasi, masukan tidak harus berupa sakelar PUSH ON. Masukan bisa saja berupa sensor apa saja yang penting sifatnya normally opened atau dalam keadaan idle harus terbuka. Penulis sudah coba dengan MC (magnetic contact) dan Beam Sensor (active infra red). Mengasikkan juga saat mencoba-coba beragam jenis sensor untuk masukan.

Dalam keadaan normal di mana COMMON dari masukan adalah VCC maka tegangan masukan adalah -5 volt yang terhubung pada masukan membalik (-). Masukan juga terhubung pada resistor PULL DOWN (R1) bernilai 4k7 (nilai ini bisa Sobat ganti antara 2k2 sampai 47k sesuai selera menurut implementasinya). Tegangan referensi pada masukan tak membalik (+) adalah hasil bagi dari R2, R3 dan R4 yang masing-masing bernilai 47k. Karena pada keadaan normal masukan (-) lebih rendah dari masukan (+) maka keluaran komparator (open collector) adalah CUT OFF. Perhitungan sederhananya akan menghasilkan tegangan referensi sebesar 2/3 dari VCC di mana VCC adalah 5 volt sehingga VREF adalah 3,333 volt. Nilai ini muncul jika keluaran tidak terhubung pada gerbang mikrokontroler atau terhubung pada port P10 dan atau P11. Jika terhubung pada gerbang lainnya yang memiliki resistor Pull-up 50k maka nilai VREF secara perhitungan sederhana menjadi mendekati ¾ dari VCC atau 3,75 volt. Hal ini jangan dijadikan masalah yang berarti karena tidak terlalu mempengaruhi hasil kerjanya, percaya saja deh.

Kemudian jika masukan terhubung singkat pada COMMON maka tegangan masukan (-) akan lebih tinggi dari masukan (+) yang menyebabkan keluaran komparator menjadi SATURASI. Ini akan mengubah VREF menjadi 1/3 dari VCC yaitu 1,667 volt pada semua jenis port dari mikrokontroler. Dari proses tersebut maka ada ambang histerisis sebesar 1,667 volt di mana bisa disimpulkan bahwa nilai besaran UTP (upper trip point) adalah 3,333 volt atau 3,75 volt dan LTP (lower trip point) adalah 1,667 volt.

Rasanya, pembahasan untuk kemudi masukan menggunakan komparator sudah cukup jelas. Sekarang kita memasuki pembahasan pada program aplikasi yang harus dijalankan oleh mikrokontroler AT89C2051 atau AT89S2051. Penyerderhanaan program dapat dilihat berikut ini:

$mod51

Saklar1           bit   p1.0
Saklar2           bit   p1.1
Saklar3           bit   p1.2
Saklar4           bit   p1.3
IR_Sensor         bit   p3.2
DIO         bit   p3.3
RST         bit   p3.4
CLK         bit   p3.5

Gerbang P10 sampai P13 didefinisikan sebagai saluran masukan seperti baris di atas sebagai Saklar1-4. Selanjutnya P32 juga didefinisikan sebagai masukan. Di atas P32 tertulis sesuai versi aslinya sebagai IR_Sensor tapi pada artikel ini dialih fungsikan sebagai tombol RESET. Sementara P33 sampai P35 untuk antarmuka dengan EEPROM AT93C46 untuk menyimpan data cacahan.

BuffHasil   data  08h

RegBit0           data  28h
      BitSaklar1  bit   RegBit0.0
      BitSaklar2  bit   RegBit0.1
      BitSaklar3  bit   RegBit0.2
      BitSaklar4  bit   RegBit0.3

RegBit1           data  29h
      BitAngka    bit   RegBit1.4
      Fail        bit   RegBit1.7

Register RAM pada mikrokontroler yang digunakan adalah BuffHasil pada 08H untuk mengolah dan menyimpan cacahan sebanyak 5 byte. Untuk proses pencacahan juga digunakan register bit yaitu 28H dan 29H.

RegStack    equ   38h

ROM_Memori  equ   0

Usai menetapkan lokasi Stack Pointer dan alokasi memori pada EEPROM, maka kita bisa menuliskan program yang akan dijalankan dimulai dengan inisialisasi untuk fitur komunikasi serial. Isi register TH1 dan TL1 adalah E8H untuk buadrate 1200 bps. Inisialisasi dilanjutkan ke alamat berinisial Inisialisasi agar tidak memangkas lokasi interupsi serial pada 0023H.

org   0000h
      mov   sp, #RegStack-1
      mov   p1, #255
      mov   p3, #255
      mov   RegBit, #0
      mov   pcon, #0
      mov   tmod, #20h
      mov   scon, #50h
      mov   ie, #90h
      mov   tl1, #0e8h
      mov   th1, #0e8h
      setb  tr1
      ajmp  Inisialisasi

Sebenarnya lokasi 0023H di bawah ini tidak dijalankan dan bisa ditiadakan jika diinginkan. Tapi dari pada ada kesalahan maka penulis tetap masukkan.

org   0023h
      reti

Program berikutnya adalah subrutin yang dijalankan untuk mengirim data cacahan melalui gerbang serial. Kode pertama yang dikirim adalah karakter “B” yang merupakan identitas peraga nantinya. Kode tersebut boleh saja diganti dengan “A”. Penjelasannya akan dapat dilihat pada bagian peraga nanti.

KirimHasil:
      mov   a, #'B'
      acall KirimSerial
      mov   r1, #BuffHasil

Register R1 berisi alamat register cacahan yang akan ditampilkan atau dikirim. Register R0 adalah jumlah 4 digit pertama yang akan dikirim. Proses menggunakan register R0 dimaksudkan untuk menghilangkan tampilan “0” diawal digit. Sehingga jika nilai cacahan sebagai contoh adalah “123” dan bukan ditampilkan sebagai “00123” di mana nilai “0” diawal akan digantikan dengan spasi. Sementara itu digit terakhir wajib ditampilkan meski nilai cacahan 0.

      KirimDisplay:
            mov   r0, #4
            clr   BitAngka

            AngkaSpasi:
                  mov   a, @r1
                  jb    BitAngka, DataAngka
                  jz    DataSpasi
                  setb  BitAngka

                  DataAngka:
                        orl   a, #30h
                        ajmp  KirimAngka

                  DataSpasi:
                        orl   a, #20h

                        KirimAngka:
                              inc   r1
                              acall KirimSerial
                              djnz  r0, AngkaSpasi
                              mov   a, @r1
                              orl   a, #30h
                              acall KirimSerial
                              ret

Ini prosedur program mengirim informasi data secara serial melalui gerbang P31.

KirimSerial:
      clr   ea
      mov   sbuf, a
      jnb   ti, $
      clr   ti
      setb  ea
      ret

Berikut adalah lanjutan dari program inisialisasi dengan memeriksa kondisi masukan saklar pada saat awal unit dihidupkan. Proses dilanjutkan dengan mengambil nilai cacahan yang tersimpan pada EEPROM.

Inisialisasi:
      jnb   Saklar1, $
      jnb   Saklar2, $
      jnb   Saklar3, $
      jnb   Saklar4, $
      acall AT93C46_RESET
      mov   dptr, #ROM_Memori
      mov   r0, #BuffHasil
      mov   r1, #5
      acall BacaData
      mov   r5, #32

      IniTund1:
            mov   r6, #255

            IniTund2:
                  mov   r7, #255
                  djnz  r7, $
                  djnz  r6, IniTund2
                  djnz  r5, IniTund1

Sebelum data cacahan dikirim, diberikan tundaan selama beberapa detik menggunakan register R5, R6 dan R7 seperti di atas, untuk memberi kesempatan peraga juga menyelesaikan proses inisialisasi.

IniDisplay:
      acall KirimHasil

Hasil cacahan pada kondisi “idle” akan terus disegarkan selang beberapa saat dengan proses tunda seperti dialokasikan dengan register di bawah ini, masih sama menggunakan R5, R6 dan R7.

AppMulai:
      mov   r5, #64

      Mulai1:
            mov   r6, #255

            Mulai2:
                  mov   r7, #255

Gerbang IR_Sensor adalah tombol RESET. Jika ditekan akan memberi masukan berlogika rendah dan memaksa program menjalankan subrutin ResetHasil. Jika tidak ditekan atau logika tinggi maka proses pemeriksaan saklar akan dijalankan pada AppSaklar1.

      AppSensor:
            jb    IR_Sensor, AppSaklar1
            acall ResetHasil
            ajmp  AppMulai

      AppSaklar1:
            jb    Saklar1, AkhirSaklar1
            jb    BitSaklar1, AppSaklar2
            setb  BitSaklar1
            acall TambahHasil
            ajmp  AppSaklar2

            AkhirSaklar1:
                  clr   BitSaklar1

Proses pada AppSaklar1 sampai 4 adalah mirip. Jika diinginkan ini bisa ditambah sampai dengan 8 dengan mengubah konfigurasi awal dan rangkaiannya tentu. Jika gerbang Saklar(n) rendah maka BitSaklar(n) akan diperiksa jika tinggi maka diabaikan untuk proses pencacahan naiknya, tapi jika rendah maka akan diset tinggi untuk kemudian menjalankan subrutin TambahHasil. Kondisi gerbang Saklar(n) tinggi akan mereset BitSaklar(n) pada AkhirSaklar(n).

            AppSaklar2:
                  jb    Saklar2, AkhirSaklar2
                  jb    BitSaklar2, AppSaklar3
                  setb  BitSaklar2
                  acall TambahHasil
                  ajmp  AppSaklar3

                        AkhirSaklar2:
                              clr   BitSaklar2

            AppSaklar3:
                  jb    Saklar3, AkhirSaklar3
                  jb    BitSaklar3, AppSaklar4
                  setb  BitSaklar3
                  acall TambahHasil
                  ajmp  AppSaklar4

                  AkhirSaklar3:
                        clr   BitSaklar3

            AppSaklar4:
                  jb    Saklar4, AkhirSaklar4
                  jb    BitSaklar4, AppSaklar1
                  setb  BitSaklar4
                  acall TambahHasil
                  ajmp  MulaiKembali

                  AkhirSaklar4:
                              clr   BitSaklar4

Proses pemeriksaan status saklar sampai di sini, selanjutnya adalah menjalankan rutin tunda untuk pengiriman data serial secara periodik.

            MulaiKembali:
                  djnz  r7, AppSensor
                  djnz  r6, Mulai2
                  djnz  r5, Mulai1
                  ajmp  IniDisplay

Nah, subrutin mencacah naik dijalankan pada TambahHasil. Biar aman nilai bit CY (carry flag) dan AC (auxilliary carry) direset ke rendah.

TambahHasil:
      clr   cy
      clr   ac

Pencacahan naik dari register diawali dari LSB atau digit terakhir yaitu BuffHasil+4 atau lokasi 0CH. Meskipun perintah INC bisa dijalankan pada register 0CH tapi sebaiknya menggunakan register akumulator karena akan dilanjutkan dengan perintah DA untuk mengubahnya dalam format BCD. Jadi jika nilai akumulator adalah 0AH maka akan berubah menjadi 10H. Jika seperti ini maka register B diperlukan untuk menyimpan nible MSB untuk proses pada register cacahan selanjutnya. Sebelum hasil cacahan pada akumulator dikembalikan ke register BuffHasil maka nilai pada nible MSB dibersihkan terlebih dahulu. Nible MSB juga perlu dipindahkan dengan perintah SWAP menjadi nible LSB.

      mov   a, BuffHasil+4
      inc   a
      da    a
      mov   b, a
      anl   a, #0fh
      mov   BuffHasil+4, a
      xch   a, b
      swap  a
      anl   a, #0fh
      xch   a, b

Nah, proses pencacahan pada register BuffHasil(n) selesai. Untuk register selanjutnya yaitu BuffHasil(n-1) adalah serupa dengan di atas.

      mov   a, BuffHasil+3
      add   a, b
      da    a
      mov   b, a
      anl   a, #0fh
      mov   BuffHasil+3, a
      xch   a, b
      swap  a
      anl   a, #0fh
      xch   a, b
      mov   a, BuffHasil+2
      add   a, b
      da    a
      mov   b, a
      anl   a, #0fh
      mov   BuffHasil+2, a
      xch   a, b
      swap  a
      anl   a, #0fh
      xch   a, b
      mov   a, BuffHasil+1
      add   a, b
      da    a
      mov   b, a
      anl   a, #0fh
      mov   BuffHasil+1, a
      xch   a, b
      swap  a
      anl   a, #0fh
      xch   a, b
      mov   a, BuffHasil
      add   a, b
      da    a
      mov   b, a
      anl   a, #0fh
      mov   BuffHasil, a
      xch   a, b
      swap  a
      anl   a, #0fh

Proses mencacah naik dari kelima register sudah selesai. Jika register melampaui nilai 99999 maka hasilnya adalah reset menjadi 00000. Setelah proses mencacah maka akan dilanjutkan dengan menyimpan hasil cacahan.

      jnz   ResetHasil
      mov   dph, #0
      ajmp  SimpanHasil

Catatan:

Untuk jumlah digit lebih besar maka BuffHasil bisa diperluas. Jika diinginkan untuk pencacahan sampai 10 digit maka dibutuhkan 10 register dan proses di atas harus diawali pada BuffHasil+9. Dari konfigurasi di atas maka Sobat bisa mencacah hingga 32 digit di mana bisa dimulai dengan BuffHasil+31 dan seterusnya sehingga nilai maksimum cacahan adalah 99.999.999.999.999.999.999.999.999.999.999. Mungkin saja cacahan sebesar itu diperlukan, tergantung implementasi Sobat saja.

Berikut adalah subrutin untuk me-RESET nilai cacahan yaitu mengisi nilai seluruh register dengan 00H. Dan setiap perubahan dari isi register cacahan akan disimpan dalam EEPROM.

      ResetHasil:
            mov   r0, #BuffHasil
            mov   r1, #5

            PeriksaBuffHasil:
                  mov   a, @r0
                  jnz   ResetBuffHasil
                  inc   r0
                  djnz  r1, PeriksaBuffHasil
                  ret

            ResetBuffHasil:
                  mov   BuffHasil, #0
                  mov   BuffHasil+1, #0
                  mov   BuffHasil+2, #0
                  mov   BuffHasil+3, #0
                  mov   BuffHasil+4, #0

            SimpanHasil:
                  mov   dptr, #ROM_Memori
                  mov   r0, #BuffHasil
                  mov   r1, #5
                  acall SimpanData
                  acall KirimHasil
                  ret

Subrutin selanjutnya adalah berkenaan dengan proses baca-tulis pada EEPROM AT93C46.

SimpanData:
      acall AT93C46_EWEN

      SimpData:
            mov   a, @r0
            acall AT93C46_WRITE
            inc   r0
            inc   dptr
            djnz  r1, SimpData
            ret

BacaData:
      acall AT93C46_READ
      mov   @r0, a
      inc   r0
      inc   dptr
      djnz  r1, BacaData
      ret

AT93C46_RESET:
      clr   CLK
      setb  RST
      clr   RST
      ret

WriteSerialBit:
      push  acc
      push  07H
      mov   r7, #8

      NxtWRBit:
            rlc   a
            jc    WRBitH
            clr   DIO
            ajmp  WRClk

            WRBitH:
                  setb  DIO

      WRClk:
            clr   CLK
            setb  CLK
            djnz  r7,NxtWRBit
            pop   07H
            pop   acc
            ret

ReadSerialBit:
      push  07H
      clr   a
      mov   r7, #8
      setb  DIO

      RDClk:
            clr   CLK
            setb  CLK
            jb    DIO, RDBitH
            clr   c
            ajmp  ShiftInBit

            RDBitH:
                  setb  c

      ShiftInBit:
            rlc   a
            djnz  r7, RDClk
            pop   07H
            ret

CheckEEPROM:
      push  07H
      push  06H
      push  05H
      mov   r5, #2
      mov   r7, #255
      mov   r6, #255
      clr   Fail
      setb  DIO
      clr   RST
      setb  RST

      WaitBusy:
            clr   CLK
            setb  CLK
            jb    DIO, WaitTimer1
            mov   r5, #2
            ajmp  WaitReady

            WaitTimer1:
                  djnz  r7, WaitBusy
                  mov   r7, #255
                  djnz  r5, WaitBusy
                  setb  Fail
                  ajmp  Ready

      WaitReady:
            clr   CLK
            setb  CLK
            jnb   DIO, WaitTimer2
            ajmp  Ready

            WaitTimer2:
                  djnz  r6, WaitReady    
                  mov   r6, #255
                  djnz  r5, WaitReady
                  setb  Fail

      Ready:
            pop   05H
            pop   06H
            pop   07H
            ret

AT93C46_WRITE:
      push  acc
      setb  RST
      mov   a, #00000010b
      acall WriteSerialBit
      mov   a, dpl
      orl   a, #10000000b
      acall WriteSerialBit
      pop   acc
      acall WriteSerialBit
      acall CheckEEPROM
      clr   RST
      ret

AT93C46_READ:
      push  07H
      push  06H
      mov   r6, #2
      mov   r7, #255
      clr   Fail
      setb  RST
      mov   a, #00000011b
      acall WriteSerialBit
      mov   a, dpl
      anl   a, #01111111b
      acall WriteSerialBit
      setb  DIO

      Dummy:
            jb    DIO, WaitTimer3
            ajmp  DataReady

            WaitTimer3:
                  djnz  r7, Dummy  
                  mov   r7, #255
                  djnz  r6, Dummy
                  setb  Fail
                  ajmp  EndReadEEPROM

            DataReady:
                  acall ReadSerialBit

      EndReadEEPROM:
            clr   RST
            pop   06H
            pop   07H
            ret

AT93C46_EWEN:
      push  acc
      setb  RST              
      mov   a, #00000010b
      acall WriteSerialBit
      mov   a, #01100000b
      acall WriteSerialBit
      clr   RST
      pop   acc
      ret

AT93C46_EWDS:
      push  acc
      setb  RST
      mov   a, #00000010B
      acall WriteSerialBit
      mov   a, #00000000B
      acall WriteSerialBit
      clr   RST
      pop   acc
      ret

end



Sudah ya, terima kasih sudah membaca artikel aku. Semoga bermanfaat dan bisa diterapkan oleh sobat semua.

Salam....