Tanggal 5 Juli 2008, bertempat di SMK Sandikta, berlangsung acara seminar dan workshop Linux fundamental. Acara berlangsung dari pukul 10.00 sampai 17.00. Pembukaan berupa sambutan dari ketua KPLI Bekasi (Pak Yasser) dan Kepsek Sandikta. Lalu dilanjutkan dengan seminar yang dibawakan oleh Anjar Hardiena (perwakilan dari AWALI dan developer distro Linux Zencafe). Setelah selesai seminar, acara selanjutnya adalah layar tancap film Pirates of Silicon Valley sambil dimoderasi oleh saudara Hartato. Anak-anak Sandikta hanya mengetahui tokoh Bill Gates saja, jadi Steve Jobs dan Steve Wozniak memang kalah pamor dikalangan pelajar . Selesai layar tancap, workshop Linux pun segera dimulai. Karena jumlah peserta yang membludak hingga ribuan (lebay ), maka workshop dibagi menjadi dua tempat. Sebagian di bengkel TKJ dan sebagian lagi di lab komputer atas. Sebenarnya distro yang ingin dipakai dalam workshop adalah BlankOn 3 (Lontara), tapi pas tester malam sebelumnya instalasi Zencafe lebih cepat (10 – 15 menit) untuk PC di lab yang hampir seragam specnya. Jadi peserta dapat dua modul dan dua CD, BlankOn dan Zencafe (plus bonus CD OpenSUSE untuk yang bisa jawab quiz). Instrukturnya pun instruktur dadakan, yaitu Saya sendiri dan Hartato . Selain mendapatkan modul dan CD, peserta juga mendapatkan majalah infolinux dan sertifikat. Fiuh, akhirnya acara perdana bisa berjalan cukup lancar. Anggota KPLI Bekasi yang hadir dan membantu terlaksananya acara :
Hari ini gw berangkat ke kampus dari rumah Gie karena ada acara makan bareng. Well, gak masalah tempatnya dimana (maklum, suku krismon). Tau-taunya kita makan di Hanamasa, yosshhh!! Sebelumnya Prof. Dr. Meriaudeau Fabrice datang ke bengkel dan say hi (sepertinya kita bertemu beliau baru sekitar setahun yang lalu dan saat itu bengkel robot masih di gd 2, lt 2 sebelah sektor). OK, karena formasi 9 inti anak bengkel dah lengkap, kita langsung caw ke margo city buat cuci mata. Eh di margo kami bertemu lagi dengan Prof. Dr. Meriaudeau Fabrice lagi lihat-lihat kacamata. Di Hanamasa, sudah ada staff yang sudah menunggu. Ngomong-ngomong soal hanamasa, gw makan terakhir kali di hanamasa juga bareng anak-anak (IDFUSI Yogi). Nih, si dodi sempet moto kaum duafa yang sedang makan.
Yang paling tengah dan depan serta duduk sendirian itu namanya Mamank King. Herbivora yang gak doyan ayam goreng, tapi doyan sate ayam (serius). Harusnya empat meja tersebut terisi semua, sebagian sudah pulang sebagian lagi sedang mengambil makanan. Hmm.. makan-makan lagi kayaknya tanggal 14 Juni ! . Jalan-jalan lagi mungkin tanggal 28 Juni, untuk anak-anak yang baru join.. PREPARE YOURSELF GUYS!!
Jam di dinding bengkel menunjukkan pukul 03.30. Wew, akhirnya gw bisa tidur normal dan bangun pagi (1 point untuk kembali normal). Kalau dipikir-pikir sudah beberapa minggu ini tidur gw berantakan. Rekor gak tidur beberapa hari gw belakangan ini terpecahkan di minggu ini (berapa hari ya Met?). Satu lagi adalah rekor menginap di kampus. Seingat gw, berangkat malam rabu dan insyaAllah gw mau pulang hari minggu ini. Dulu, waktu persiapan KRCI 2007, gw berempat sempat menginap di kampus sampai 4 hari. OK, ada satu lagi. Sabtu kemarin adalah hari tanpa bersantai. Biasanya gw ada waktu beberapa menit untuk ngelamun jorok (2 point untuk kembali normal). Sabtu paginya gw tidur waktu shubuh dan bangun jam 07.00, ngumpulin nyawa terus berangkat ke Balairung untuk lomba (gak mandi juga sih). Oia satu lagi, rekor gak mandi beberapa hari !. Anak-anak berangkat ke Balairung sekitar jam 08.00. Karena gw ada janji jam 10.30 dengan seseorang untuk membicarakan masalah pekerjaan, gw cabut lagi dari Balairung ke Gd PP jam 12.30 dan telat karena macet yang dibuat oleh mahasiswa pendemo yang sotoy (ngaret berapa jam coba?). Mana belum sempat bikin CV. Akhirnya gw ngubek CV di inbox abang gw dan edit 5 menit CV tersebut tanpa gw cek lagi (yang ada justru banyak kesalahan typo). Fiuh, mungkin akan bertambah lagi kesibukan gw sebagai programmer part time (1 cara supaya bisa normal. One more thing. Gw juga gak tau.. Knp info gawean dari ‘dia’ bisa gw terima begitu saja saat lg sibuknya KRCI. Biasanya klo ada yg pasti2 nawarin gw jd programmer gw masih belum bisa terima. Mudah2an aj dia tau klo apapun yg dia infokan pasti gw terima baik2, even just part time). Pas gw lagi ngobrol sama orang yang menginterview, mata gw sesekali menutup beberapa detik (sumpeh capek banget). Selesai interview dan penjelasan singkat project, gw balik lagi ke Balairung. Ternyata untuk KRCI ada 3x trial (gw kira hanya sekali). Pas gw datang, anak-anak nyuruh gw nyelesain codingannya Genin-6. Gw tanya ama Rum mengenai situasi terakhir dan problemnya. Setelah blablabla, akhirnya gw putusin untuk memberinya navigasi wall follower sambil scanning UV Tron yang pakai pelindung. Dank, Rum take this event as a learning process! . Tapi untuk divisi berkaki, tim Chunin-6 memegang juara II untuk regional II ini, jadi masih ada wakil dari gundar untuk acara puncaknya nanti. Gw jadi inget kata Anto mengenai impian untuk dapat berada di basecamp peserta. Same with me sebenarnya. Terakhir gw nonton KRI/KRCI itu pas tahun 2006 (soalnya KRI/KRCI 2007 bertempat di Surabaya) dan saat itu gw hanya bisa mengagumi robot-robot yang tampil. Kalau di bangku penonton gw ngeliat basecamp peserta di pinggiran arena kayaknya asyik banget. Saat itu gw cuma berpikir “Well, i hope someday i’ll be there”. Alhamdulillah tercapai juga. Oh ya, ada satu lagi event yang mungkin masih bisa diikuti, yaitu Roboline Contest. Hehe.. Line Follower Robot lagi tuh.
Selesai event ini mudah-mudahan aktivitas gw kembali normal. Eh, bosan juga gw menulis “all by myself” di blog gw. Narsis gak sih? Mungkin setelah ini frekuensi category “my life” harus gw kurangin. Oh ya, gw ada beberapa hutang postingan berseri untuk 6 PING, webservices dan UV Tron. Satu lagi.. ah terlihat banget bullshit gw.. skripsi. Target sidang Agustus and dont be a butthead again dex. Udah ah, shalat shubuh dulu (tumben).
Info: Bagi yang kemarin merasa senang dengan tewasnya soulmate gw.. ternyata “she” lives again. Jadi setelah gw copot HD VAIO dan gw cari converter ke USB-nya ternyata gak ada masalah di HD gw. Terus gw pasang lagi tuh HD dan gw baca “Bismillah”.. eng ing eng.. terdengar bunyi deh “te ni no net”, lalu muncul lah GRUB. Welcome back honey!! Gw janji bakal rajin bersihin dirimu dari debu-debu. Gie, pinjem cairan pembersih lo!!
Well, today is the end of my VAIO.. (still not sure). Goodbye skripsi, repository project, tutorial, 3gp bokep (hayah). Harusnya gw panik sih kehilangan data pentagon di VAIO gw, tapi karena problem di luar lebih banyak gw jadi bingung harus gimana lagi (melirik baygon). Egh, robot KRCI masih belum beres juga (cayo dadank). Well, dank kita lihat saja hari sabtu. Eh, gw hari ini cukur rambut lho. Lumayan untuk mengurangi gelar dekiler. Udah ah, lanjut ngerjain robot dulu.
Saya tulis ini sebagai awalan sebelum memulai interfacing dengan CMPS03 dengan cara I2C. Sebenarnya saya dulu sempat menulis mengenai I2C di text file di komputer, tapi entah kemana file itu sekarang. OK langsung saja, I2C (Inter-Integrated Circuit), dibaca aytusi, merupakan jalur komunikasi serial multi-master yang dikembangkan oleh Philips, sekarang menjadi tanggung jawab NXP (perusahaan semikonduktor yang didirikan Philips). Ada beberapa versi spesifikasi yang dikeluarkan. Versi awal yang dibuat pada tahun 1982 hanya dapat mencapai kecepatan 100 Kbit/s (standard mode) dan pengalamatan hanya sebesar 7 bit. Hingga tahun 1992 (versi 1.0) kecepatan masih mencapai 100 Kbit/s, namun ada penambahan mode (Fast-mode) yang dapat mencapai kecepatan 400 Kbit/s (Fast-mode hanya kompatibel dengan versi terdahulu (downward)). Versi 2.0 (tahun 1998) menjadikan jalur I2C standar de facto yang diimplementasikan lebih dari 1000 IC yang berbeda dan dilisensikan ke 50 lebih perusahaan. Modifikasi versi 2.0 ini meliputi penambahan mode High-speed mode (Hs-mode) yang dapat meningkatkan bit rate sampai 3.4 Mbit/s. Perangkat dengan Hs-mode dapat berkomunikasi dengan perangkat lainnya (dalam satu jalur I2C) yang memiliki bit rate antara 0 s/d 3.4 Mbit/s (jadi kompatibel dengan Hs-mode dan standard mode). Tahun 2000 keluar lagi versi 2.1 dan saat tulisan ini saya buat spesifikasi I2C saat ini sudah mencapai versi 3.0. Menurut saya seharusnya I2C ini masuk ke dalam materi kuliah yang berhubungan dengan interfacing. Saya tidak tahu apakah I2C pernah dibahas pada saat mata kuliah interfacing, karena saya jarang masuk kuliah.
Sebenarnya jalur I2C banyak digunakan di PC, telpon selular, radio mobil, TV, sistem terintegrasi di rumah dan perkantoran dan bahkan kartu berganda di blade server. Apa sih yang membuat I2C begitu menarik dan banyak digunakan di perangkat digital? Well, dengan I2C kita hanya membutuhkan dua jalur untuk berkomunikasi antar perangkat. Kita tidak memerlukan address decoder untuk mengimplementasi jalur I2C. Nah dua jalur tersebut adalah SDA (Serial Data) dan SCL (Serial Clock). SCL merupakan jalur yang digunakan untuk mensinkronisasi transfer data pada jalur I2C, sedangkan SDA merupakan jalur untuk data. Beberapa perangkat dapat terhubung ke dalam jalur I2C yang sama dimana SCL dan SDA terhubung ke semua perangkat tersebut, hanya ada satu perangkat yang mengontrol SCL yaitu perangkat master. Jalur dari SCL dan SDA ini terhubung dengan pull-up resistor yang besar resistansinya tidak menjadi masalah (bisa 1K, 1.8K, 4.7K, 10K, 47K atau nilai diantara range tersebut). Kurang lebih gambarnya seperti ini:
Dengan adanya pull-up disini, jalur SCL dan SDA menjadi open drain, yang maksudnya adalah perangkat hanya perlu memberikan output 0 (LOW) untuk membuat jalur menjadi LOW, dan dengan membiarkannya pull-up resistor sudah membuatnya HIGH. Kembali ke I2C, umumnya dalam I2C ada satu perangkat yang berperan menjadi master (meskipun dimungkinkan beberapa perangkat, dalam jalur I2C yang sama, menjadi master) dan satu atau beberapa perangkat slave. Dalam jalur I2C, hanya perangkat master yang dapat mengontrol jalur SCL yang berarti transfer data harus diinisialisasi terlebih dahulu oleh perangkat master melalui serangkaian pulsa clock (slave tidak bisa, tapi ada satu kasus yang disebut clock streching). Tugas perangkat slave hanya merespon apa yang diminta master. Slave dapat memberi data ke master dan menerima data dari master setelah server melakukan inisialisasi. Misalkan microcontroller (uC) adalah perangkat master yang terhubung dalam satu I2C dengan perangkat-perangkat slave seperti modul pengendali motor servo, modul kompas dan sensor lainnya. Nah uC dapat mengontrol pergerakan servo dengan memberikan data ke modul servo, mendapatkan data kompas dengan memerintahkan modul kompas agar mengirimkan data. Semua itu hanya dibutuhkan 2 jalur dengan tambahan 2 resistor sebagai pull-up. Lalu bagaimana membedakan slave tersebut adalah modul servo atau modul kompas? Menggunakan pengalamatan tentunya, dimana setiap perangkat slave itu mempunyai alamat yang unik.
Sebelum saya bahas lebih jauh mengenai pengalamatan, saya akan bahas dulu mengenai sinyal-sinyal yang digunakan dalam protokol I2C. Sebagaimana telah dijelaskan sebelumnya, bahwa master terlebih dahulu menginisialisasi sebelum memulai transfer data antara slave-nya. Inisialisasi diawali dengan sinyal START (transisi high ke low pada jalur SDA dan kondisi high pada jalur SCL, lambang S pada gambar 2), lalu transfer data dan sinyal STOP (transisi low ke high pada jalur SDA dan kondisi high pada jalur SCL, lambang P pada gambar 2) untuk menandakan akhir transfer data.
Gambar 2. Sinyal untuk START dan STOP (sumber: UM10204 I2C-bus specification and user manual)
Banyaknya byte yang dapat dikirimkan dalam satu transfer data itu tidak ada aturannya. Jika transfer data yang ingin dilakukan sebesar 2 byte, maka pengiriman pertama adalah 1 byte dan setelah itu 1 byte. Setiap byte yang di transfer harus diikuti dengan bit Acknowledge (ACK) dari si penerima, menandakan data berhasil diterima. Byte yang dikirim dari pengirim diawali dari bit MSB. Saat bit dikirim, pulsa clock (SCL) di set ke HIGH lalu ke LOW. Bit yang dikirim pada jalur SDA tersebut harus stabil saat periode clock (SCL) HIGH. Kondisi HIGH atau LOW dari jalur data (SDA) hanya dapat berubah saat kondisi sinyal SCL itu LOW.
Gambar 3. Transfer bit pada jalur I2C (sumber: UM10204 I2C-bus specification and user manual)
Setiap pulsa clock itu dihasilkan (di jalur SCL) untuk setiap bit (di jalur SDA) yang ditransfer. Jadi untuk pengiriman 8 bit akan ada 9 pulsa clock yang harus dihasilkan (1 lagi untuk bit ACK). Kronologi sebelum perangkat penerima memberikan sinyal ACK adalah sebagai berikut: saat pengirim selesai mengirimkan bit ke-8, pengirim melepaskan jalur SDA ke pull-up (ingat penjelasan open drain di atas) sehingga menjadi HIGH. Nah saat kondisi tersebut terjadi, penerima harus memberikan kondisi LOW ke SDA saat pulsa clock ke-9 berada dalam kondisi HIGH.
Gambar 4. Data (byte) transfer pada jalur I2C (sumber: UM10204 I2C-bus specification and user manual)
Jika SDA tetap dalam kondisi HIGH saat pulsa clock ke-9, maka ini didefinisikan sebagai sinyal Not Acknowledge (NACK). Master dapat menghasilkan sinyal STOP untuk menyudahi transfer, atau mengulang sinyal START untuk memulai transfer data yang baru. Ada 5 kondisi yang menyebabkan NACK:
Tidak adanya penerima dengan alamat yang diminta pada jalur, sehingga tidak ada perangkat yang merespon ACK.
Penerima tidak dapat menerima atau mengirim karena sedang mengeksekusi fungsi lain dan tidak siap untuk memulai komunikasi dengan master.
Pada saat transfer data, penerima mendapatkan data atau perintah yang tidak dimengerti oleh penerima.
Pada saat transfer data, penerima tidak dapat menerima lagi byte data yang dikirimkan.
Penerima-master perlu memberi sinyal pengakhiran transfer data ke penerima-slave.
Penjelasan di atas adalah sekilas mengenai protokol sinyal yang saya ambil dari spesifikasi I2C. Bagaimana untuk pengalamatan pada perankat-perangkat yang terhubung dalam jalur I2C? Pengalamatan dalam I2C bisa 7 bit atau 10 bit. Pengalamatan 10 bit jarang digunakan dan juga tidak dibahas di sini. Semua perangkat (uC dan modul-modul) yang terhubung ke dalam jalur I2C yang sama dapat dialamati sebanyak 7 bit. Ini berarti sebuah jalur I2C dengan pengalamatan 7 bit dapat menampung 128 (2^7) perangkat. Saat mengirimkan data alamat (yang 7 bit itu), kita tetap mengirim data 1 byte (8 bit). 1 bit lagi digunakan untuk menginformasikan perangkat slave apakah master menulis (write) data ke slave atau membaca (read) data dari slave. Jika bit tersebut 0, maka master menulis data ke slave. Jika bit tersebut 1, maka master membaca data dari slave. Bit ini (untuk infomasi tulis/baca) merupakan LSB, sedangkan sisanya adalah data alamat 7 bit. Berikut adalah contoh sinyal yang dimulai dengan data alamat lalu data yang ingin ditransfer ke alamat tersebut:
Gambar 5. Sinyal alamat dan data (sumber: UM10204 I2C-bus specification and user manual)
Sebaiknya saat mengalamati perangkat-perangkat dalam I2C anggap saja menggunakan 8-bit. Jika menggunakan 7 bit justru akan membingungkan. Misal diberikan alamat 0×14 (dalam penghitungan 7 bit), maka untuk menulis ke alamat 0×14 kita harus memberikan byte 0×28 dengan menggesernya 1 bit (bit 0 pada LSB berarti menulis). Contoh yang memudahkan adalah CMPS03 yang memiliki alamat 0xC0 (perhitugan 8 bit). Untuk menulis ke CMPS03 kita menggunakan 0xC0 dan untuk membaca dari CMPS03 kita menggunakan 0xC1.
Saya rasa penjelasan di atas sudah dapat (sedikit) merepresentasikan protokol fisikal I2C. Bagaimana dari perangkat lunak (software) untuk mengimplementasikan protokol I2C di atas? Saya akan mengambil contoh dari rutin Peter Fleury dan dari rutin I2C CodeVisionAVR (yang menggunakan bahasa C). Hal yang pertama kali terjadi dalam komunikasi ini adalah server mengirimkan sinyal START (lihat gambar 2). Ini akan menginformasikan perangkat-perangkat slave yang terhubung dalam jalur I2C bahwa akan ada transfer data yang ingin dilakukan oleh master dan para slave harus siap memantau siapa yang akan dipanggil alamatnya. Selanjutnya master akan mengirimkan data berupa alamat slave yang ingin diakses. Perangkat slave yang sesuai dengan alamat yang diberikan master akan meneruskan transaksi data, slave lainnya dapat mengacuhkan transaksi tersebut dan menunggu sampai sinyal berikutnya. Setelah mendapatkan slave dengan alamat tersebut, saatnya master memberitahukan alamat internal atau nomor register yang ingin ditulis atau dibaca dari slave tersebut. Jumlah lokasi atau nomor register tersebut tergantung pada perangkat slave yang diakses. Ada beberapa yang memiliki dan ada beberapa yang tidak. Misal CMPS03, modul ini memiliki 16 lokasi dengan penomoran 0-15. Contoh lain adalah SFR08 (modul sensor ultrasonic) dengan 36 register internal yang bisa diakses. Setelah mengirim data berupa alamat slave dan kemudian data alamat internal register slave yang ingin diakses, kini saatnya master mengirim byte data. Master dapat melanjutkan mengirim byte data ke slave dan byte-byte akan ditampung di register setelahnya karena slave secara otomatis akan menaikkan alamat internal register setelah setiap byte. Ketika master selesai menulis semua data ke slave, master akan mengirim sinyal STOP untuk mengakhiri transaksi data. Jadi untuk menulis ke slave langkahnya adalah:
Mengirim sinyal START
Mengirim alamat slave serta operasi yang akan dilakukan (LSB)
Mengirim nomor internal register yang ditulis
Mengirim byte data
Mengirim sinyal STOP
Misalkan kita memiliki SFR08 dengan alamat default dari pabrik 0xE0. Untuk mulai memancarkan gelombang ultrasonic SFR08 kita harus menulis data 0x51ke register command di alamat 0×00, seperti:
Mengirim sinyal START
Mengirim data 0xE0 (alamat I2C dari SFR08 dengan operasi tulis)
Mengirim data 0×00 (Alamat internal dari register command)
Mengirim data 0×51 (Perintah untuk mulai memancarkan)
Mengirim sinyal STOP
Bagaimana untuk membaca? Ini agak sedikit ribet. Sebelum membaca data dari slave, master harus memberitahu alamat internal mana yang ingin dibaca. Jadi operasi baca dari slave sebenarnya dimulai dulu dengan operasi tulis. Ini sama seperti operasi tulis. Master mengirim sinyal START, alamat I2C slave dengan LSB utk operasi tulis/baca dan nomor internal register yang ingin ditulis. Setelah itu master mengirim sinyal START lagi (terkadang disebut ‘restart’) dan alamat I2C slave lagi – tapi kali ini set LSB ke 1 untuk operasi baca. Lalu master dapat mulai membaca banyak byte data yang diinginkan dan menyudahi transaksi dengan mengirimkan sinyal STOP. Misal untuk membaca data byte arah mata angin dari modul CMPS03:
Mengirim sinyal START
Mengirim data 0xC0 (alamat I2C dari CMPS03 dengan LSB 0 untuk operasi tulis)
Mengirim data 0×01 (alamat internal dari register untuk baca byte kompas)
Mengirim sinyal START lagi
Mengirim data 0xC1 (alamat I2C dari CMPS03 dengan LSB 1 untuk operasi baca)
Membaca byte data dari CMPS03
Mengirim sinyal STOP
Rentetan bit untuk pembacaan CMPS03 kurang lebih seperti gambar di bawah ini:
Gambar 6. Pembacaan byte dari CMPS03 (sumber: http://www.robot-electronics.co.uk/images/i2c.GIF)
Sejauh ini contoh di atas adalah komunikasi I2C secara sederhana, ada satu yang cukup ribet. Saat master membaca data dari slave, maka slave lah yang mengirimkan bit-bit di jalur SDA, tapi tetap master yang mengontrol pulsa clock di jalur SCL. Bagaimana jika slave belum siap mengirimkan data? Dengan perangkat semacam EEPROM, hal ini bukan masalah, tapi jika perangkat slave adalah microprocessor atau microcontroller yang juga mengeksekusi instruksi lainnya hal ini bisa menjadi masalah. uC yang merupakan perangkat slave perlu mengeksekusi rutin interrupt, menyimpan register kerja saat itu, mencari tahu alamat yang diminta master untuk dibaca, ambil data dari alamat tersebut dan memberikannya ke register pengirim. Hal ini membutuhkan beberapa uS untuk dapat terjadi, sementara master memberikan pulsa clock di jalur SCL yang mana slave belum bisa merepson. Protokol I2C menyediakan solusi untuk ini: Slave diperbolehkan untuk membuat jalur SCL LOW. Hal ini disebut dengan clock stretching. Ketika slave mendapatkan perintah baca dari master, slave dapat membuat jalur SCL LOW. Slave uC lalu mendapatkan data yang diminta, memberikannya ke register pengirim dan membiarkan kembali jalur SCL agar pull-up resistor kembali membuatnya HIGH. Dari sisi master, jalur SCL akan diberi sinyal HIGH lalu akan dibaca apakah jalur tersebut benar-benar HIGH. Jika masih dalam kondisi LOW maka itu adalah ulah slave dan master harus menunggu sampai kondisi HIGH kembali. Untungnya perangkat keras pada kebanyakan port I2C uC dapat menangani hal ini secara otomatis.
Untuk implemetasi kode I2C saya mengambil contoh rutin I2C untuk AVR oleh Peter Fleury dan dari rutin-rutin I2C yang diberikan CodeVisionAVR. Karena hanya ada dua jalur, maka definisikan 2 pin untuk SCL dan SDA:
;*****AdapttheseSCAandSCLportandpindefinitiontoyourtarget!!;#define SDA 4 // SDA Port D, Pin 4
#define SCL 5 // SCL Port D, Pin 5
#define SDA_PORT PORTD // SDA Port D
#define SCL_PORT PORTD // SCL Port D
;******;--maptheIOregisterbackintotheIOaddressspace#define SDA_DDR (_SFR_IO_ADDR(SDA_PORT) - 1)
#define SCL_DDR (_SFR_IO_ADDR(SCL_PORT) - 1)
#define SDA_OUT _SFR_IO_ADDR(SDA_PORT)
#define SCL_OUT _SFR_IO_ADDR(SCL_PORT)
#define SDA_IN (_SFR_IO_ADDR(SDA_PORT) - 2)
#define SCL_IN (_SFR_IO_ADDR(SCL_PORT) - 2)
Untuk menginsialisasi port yang digunakan sebagai SCL dan SDA kita perlu menset pin tersebut dengan memanggil rutin di bawah ini sekali:
Empat rutin di bawah ini menyediakan pensinyalan sederhana untuk START, STOP, operasi baca dan operasi tulis.
i2c_start:
sbi SDA_DDR,SDA ;force SDA low
rcall i2c_delay_T2 ;delay T/2
rcall i2c_write ;write address
ret
i2c_stop:
sbi SCL_DDR,SCL ;force SCL low
sbi SDA_DDR,SDA ;force SDA low
rcall i2c_delay_T2 ;delay T/2
cbi SCL_DDR,SCL ;release SCL
rcall i2c_delay_T2 ;delay T/2
cbi SDA_DDR,SDA ;release SDA
rcall i2c_delay_T2 ;delay T/2
ret
i2c_write:
sec ;set carry flag
rol r24 ;shift in carry and out bit one
rjmp i2c_write_first
i2c_write_bit:
lsl r24 ;if transmit register empty
i2c_write_first:
breq i2c_get_ack
sbi SCL_DDR,SCL ;force SCL low
brcc i2c_write_low
nop
cbi SDA_DDR,SDA ;release SDA
rjmp i2c_write_high
i2c_write_low:
sbi SDA_DDR,SDA ;force SDA low
rjmp i2c_write_high
i2c_write_high:
rcall i2c_delay_T2 ;delay T/2
cbi SCL_DDR,SCL ;release SCL
rcall i2c_delay_T2 ;delay T/2
rjmp i2c_write_bit
i2c_get_ack:
sbi SCL_DDR,SCL ;force SCL low
cbi SDA_DDR,SDA ;release SDA
rcall i2c_delay_T2 ;delay T/2
cbi SCL_DDR,SCL ;release SCL
i2c_ack_wait:
sbis SCL_IN,SCL ;wait SCL high (in case wait states are inserted)
rjmp i2c_ack_wait
clr r24 ;return 0
sbic SDA_IN,SDA ;if SDA high -> return 1
ldi r24,1
rcall i2c_delay_T2 ;delay T/2
clr r25
ret
i2c_readNak:
clr r24
rjmp i2c_read
i2c_readAck:
ldi r24,0x01
i2c_read:
ldi r23,0x01 ;data = 0x01
i2c_read_bit:
sbi SCL_DDR,SCL ;force SCL low
cbi SDA_DDR,SDA ;release SDA (from previous ACK)
rcall i2c_delay_T2 ;delay T/2
cbi SCL_DDR,SCL ;release SCL
rcall i2c_delay_T2 ;delay T/2
i2c_read_stretch:
sbis SCL_IN, SCL ;loop until SCL is high (allow slave to stretch SCL)
rjmp i2c_read_stretch
clc ;clear carry flag
sbic SDA_IN,SDA ;if SDA is high
sec ; set carry flag
rol r23 ;store bit
brcc i2c_read_bit ;while receive register not full
i2c_put_ack:
sbi SCL_DDR,SCL ;force SCL low
cpi r24,1
breq i2c_put_ack_low ;if (ack=0)
cbi SDA_DDR,SDA ; release SDA
rjmp i2c_put_ack_high
i2c_put_ack_low: ;else
sbi SDA_DDR,SDA ; force SDA low
i2c_put_ack_high:
rcall i2c_delay_T2 ;delay T/2
cbi SCL_DDR,SCL ;release SCL
i2c_put_ack_wait:
sbis SCL_IN,SCL ;wait SCL high
rjmp i2c_put_ack_wait
rcall i2c_delay_T2 ;delay T/2
mov r24,r23
clr r25
ret
Sedangkan untuk CodeVisionAVR cukup mudah, tapi kita tidak tahu detail implementasi kode setiap rutin jadi cukup dengan mendefinisikan dan memanggil fungsi yang tersedia. Karena dibutuhkan dua jalur, kita hanya membutuhkan 2 pin pada uC AVR. Untuk menggunakan rutin I2C AVR definisikan pin untuk SCL dan SDA:
Ada 5 fungsi yang bisa digunakan setelah pemanggilan header , yaitu:
void i2c_init(void) untuk menginsialisasi jalur I2C.
unsigned char i2c_start(void) untuk memberikan sinyal START, akan mengembalikan nilai 1 jika jalur berada dalam keadaan bebas atau 0 jika sedang sibuk.
unsigned char i2c_stop(void) untuk memberikan sinyal STOP.
unsigned char i2c_read(unsigned char ack) untuk membaca byte dari slave. Parameter ack digunakan untuk menentukan apakah sinyal ACK diperlukan setelah menerima byte dari slave. Jika ack diset ke 0 maka tidak ada sinyal ACK setelah pembacaan byte, jika 1 akan ada sinyal ACK setelah pembacaan.
unsigned char i2c_write(unsigned char data) untuk menulis byte dari slave. Parameternya merupakan byte yang ingin ditulis. Fungsi ini akan mengembalikan nilai 1 jika slave mensinyalkan ACK dan 0 jika tidak ada sinyal ACK dari slave.
Contoh penggunaannya untuk membaca byte dari register 1 CMPS03:
Bertambah sudah keputusasaan gw. Ternyata hidup tanpa listrik itu lumayan menderita. Kebetulan gw mau mengusahakan bercakap sambung dengan seseorang dan tanpa diduga ada gangguan koneksi internet. Niat ingin menginap di kampus pun gw rundungkan. Tapi karena supir kampus-bekasi ingin menginap, ya gw dengan berat hati ikut menginap (shit, demi menghemat ongkos T19, P9B dan K05 gw rela menginapkan diriku ini). Ya tak apalah, sedikitnya gw masih bisa mengoprek sesuatu tanpa perlu koneksi internet. OK, gw bisa melalui beberapa jam di kampus tanpa ada internet dan sedang ingin menulis draft buat di blog, serta beberapa oprekan lainnya. Jam dinding menunjukkan pkl 24.00. Beberapa menit kemudian.. Lampu mati!! Damn, gw coding di laptop agung gak ngeliat keyboard (dimana asdf coba?). Akhirnya penerangan yang ada adalah layar laptop agung, sebuah senter dan beberapa bara dari pembakaran Marlboro dan A Mild. Mmhh.. gw coba cek keluar untuk memastikan apakah hanya gedung 3 saja yang mati. Gile pas gw liat ke bank DKI dan perpus, kampus seperti Silent Hill. Jadi bukan hanya kampus Gundar saja yang mati lampu (sepertinya). Soalnya pas gw liat kosan cewe sebelah toilet karywan bank DKI, ternyata juga mati. Sekarang apa yang bisa gw lakuin di situasi seperti ini? Ngantuk pun belum kunjung datang, yah terpaksa gw mendongeng diantara mahluk hidup yang masih hidup saat itu. Dongeng hal gaib menjadikan suasana lebih terasa bukan.
Besok (7 Mei 2008) akan ada kuliah umum robotika, tepatnya Gd. 3 lt. 4 Kampus Depok (D340) jam 08.30 – 12.00. Gw dan kawan CERC lainnya akan memanfaatkan momen ini untuk mensosialisasikan klub robotika kampus. Mudah-mudahan bisa menjadi sarana kondusif untuk menarik minat mahasiswa/i Gundarama untuk menggeluti robotika. Well, gw gak prepare materi, jadi sepertinya CERC hanya akan sharing dan tanya jawab saja. OK, c u there.
OK, besok CERC akan jalan-jalan ke Bandung, sekarang anak-anak (pkl 21.30) CERC sedang googling buat nyari hotel. Err, gw gak bawa pakaian ganti dan handuk lagi, soalnya tidak ada yang konfirmasi besok berangkat, masa iya sampai hari sabtu gw gak ganti baju ama CD. Yogi dah gw SMS buat cari gitar, Anto dah gw pesenin bawain baju buat gw. OK, tinggal nyari sikat gigi dan handuk. OK mbel, kita berangkat besok!!
Misalkan kita mempunyai susunan sensor, tampak atas, seperti berikut:
(4) ------ (3) - (2) -(1) ------ (0)
Dimana angka menunjukkan pin uC, katakanlah pada PORT C. Jadi kita menggunakan pin PORTC.0 untuk sensor paling kanan,
PORTC.1 untuk sensor tengah kanan, dst hingga PORTC.4 untuk sensor paling kiri. Untuk mempermudah, saya biasanya menggunakan
data mapping. Jadi kondisi sensor akan di mapping dengan data PWM motor. Katakanlah sensor line tracer itu aktif low,
jadi pin uC akan membaca logika 0 saat mengenai garis. Oke, karena ada 5 sensor maka akan ada 2^5 = 32 kemungkinan kondisi sensor.
Saya hanya akan membuat kedua robot bergerak maju, sehingga bisa di buat kontroler motor untuk bergerak satu arah saja.
Saya akan membuat beberapa nilai sensor (dalam hexa) saja sebagai contoh, sisanya bisa diimpementasikan sendiri. Berikut tabelnya:
Saya mengimplementasikan PWM dengan menggunakan interrupt timer pada uC, dimana nilai 0xff adalah PWM full speed (100%)
dan motor akan berhenti dengan nilai 0. Pada kasus saya, motor kanan dan kiri akan mempunyai nilai PWM yang berbeda untuk
kecepatan aktual yang terlihat sama, jika dilihat pada tabel untuk membuat motor maju lurus nilai PWM kanan dan kiri berbeda 15 desimal.
Jika merujuk ke sunsunan sensor, nilai 0×11 menunjukkan tiga sensor tengah mengenai garis, sehingga PWM motor diberi hampir full agar
bergerak maju lurus. Kondisi 0×17 mengharuskan robot bergerak serong kiri dan kondisi 0x1E mengharuskan robot banting kanan.
Dengan cara mapping nilai sensor dari PINC dengan data PWM kita sudah mengimplementasikan sistem kontrol proportional,
dimana gain motor akan mempunyai proporsi sesuai nilai sensor yg diinput ke PINC. Untuk menulisnya dengan bahasa C,
saya akan menggunakan array untuk menampung data PWM, berikut potongan programnya:
/**
* isikan data PWM motor kiri dan kanan
* sesuai dengan 32 kondisi sensor
*/unsignedcharPWMKiri[32]={0x00,0x00,...}unsignedcharPWMKanan[32]={0x00,0x00,...}unsignedcharstate;voidscan(){state=PINC&0x1F;//baca PINC.0 - PINC.4
/**
* beri nilai PWM motor kiri dengan
* data PWMKiri dan PWMkanan
* dimana indexnya adalah kondisi sensor
*/PWMKiriVal=PWMKiri[state];PWMKananVal=PWMKanan[state];}
Untuk menambahkan kontrol derivative, kita perlu menggunakan delta PWM. Kita perlu mencatat data PWM sebelumnya.
Kita bisa mengubah fungsi scan menjadi:
//variabel untuk menampung nilai PWM sebelumnya
unsignedcharlast_state,d;//jika dipanggil tanpa argumen, fungsi scan hanya sistem kontrol proportional
voidscan(d=false){state=PINC&0x1F;//jika dipanggil dengan scan(1), aktifkan fungsi proportioal-derivative
if(d){PWMKiriVal=PWMKiri[state](PWMKiri[state]-PWMKiri[last_state]);PWMKananVal=PWMKanan[state](PWMKanan[state]-PWMKanan[last_state]);}else{//sistem proportional saja
/* beri nilai PWM motor kiri dan kanan
* dimana indexnya adalah kondisi sensor
*/PWMKiriVal=PWMKiri[state];PWMKananVal=PWMKanan[state];}last_state=state;}
Sistem derivative di atas hanya gambaran bagaimana menerapkan sistem kontrol PD, dan agak redundant jika digunakan dalam robot
sederhana dengan 5 sensor. Dalam mendesain sistem derivative perlu diperhatikan apakah penyimpangan error dalam kondisi sistem
itu cukup signifikan untuk membuat sistem bergerak stabil jika ditambahkan ke dalam sistem kontrol. Jika masih bingung apa itu sistem PID,
coba di googling. Sebagai pendahuluan coba baca artikel PID di Wikipedia.