I2C adalah protokol komunikasi serial sinkron, artinya dia menggunakan sinyal clock untuk sinkronasi saat transfer data, I2C biasa digunakan pada perangkat display seperti LCD, OLED juga digunakan pada modul sensor seperi RTC dan Akselerometer. Komunikasi I2C hanya memakai 2 kabel yaitu SDA (Serial data) untuk transaksi data dan SCL (Serial Clock) adalah jalur sinyal clock untuk sinkronasi transfer data, data dikirim dalam bentuk paket data, dimana jumlah data yang dikirimkan terbatas dalam satu kali transfer, juga memerlukan bit tambahan sebagai penanda awal dan akhir paket data.
I2C adalah protokol komunikasi serial low speed dan biasa digunakan untuk komunikasi jarak dekat dan tidak direkomendasikan untuk komunikasi jarak jauh. keunggulan dari komunikasi I2C adalah koneksinya yang hanya menggunakan 2 kabel dan banyaknya channel yang bisa terhubung dengan komunikasi I2C, ini terjadi karena I2C menggunakan sistem address untuk berkomunikasi antara master dan slave. setiap slave memiliki address/ID unik, sehingga ketika master akan mengirim data, kita hanya perlu memanggil address slave yang akan menerima datanya.
Komponen protokol komunikasi I2C
Komponen komunikasi I2C hanya terdiri dari master dan slave, master dan slave dihubungkan oleh I2C Bus sehingga jaringan I2C bisa menghubungkan beberapa master dan slave dalam satu jaringan. Komponen-komponen yang terhubung pada jaringan I2C bus harus memiliki logic level yang sama. mari kita bahas lebih detail komponen protokol I2C
- Master
Master bisa mengirim data dan menerima data, sehingkan slave bisa merespon berdasarkan permintaan dari master. Data tidak bisa dikirim secara bersamaan dan harus dikirim secara bergatian.
- Slave
Setiap slave memiliki address, yaitu sebuah kode unik sebagai identitas dari suatu slave, dengan begitu master bisa mengirim data ke slave tertentu dengan dengan cara memanggil address slave tersebut.
I2C Bus
I2C bus adalah 2 jalur yang menghubungkan semua perangkat i2c dalam satu jaringan, jalur ini adalah SDA (serial data) dan SCL (Serial Clock). Jalur SDA berfungsi untuk mengirim dan menerima data ke/dari slave, sedangkan SCL digunakan sebagai jalur yang membawa sinyal clock untuk sinkironisasi komunikasi, kemudian terdapat rangkaian pull up resistor yang berfungsi untuk membuat kedua jalur berada pada kondisi HIGH, ini disebabkan karena kedua jalur tersebut menggunakan tipe output open drain, sehingga dia memerlukan rangkaian pullup resistor, kenapa pullpup resistor ? itu karena jalur SDA dan SCL aktif saat kondisi LOW (Active LOW), pullup resistor bertanggung jawab untuk membuat jalur berada pada kondisi HIGH, nilai resistor yang digunakan biasanya mulai dari 2KΩ untuk kecepatan tinggi (400kbps) dan 10kΩ untuk kecepatan rendah (100kbps)
Gambar diatas menunjukan struktur internal dari perangkat I2C, didalamnya terdapat buffer untuk membaca data masuk, dan FET (Field Effect Transistor) untuk transmisi data, kita bisa membuat kondisi jalur menjadi LOW dengan memberikan arus pada Gate transistor, dengan begitu arus dari vcc akan terhubung ke Ground dan menyebabkan jalur menjadi LOW.
Jika ingin membuat kondisi jalur menjadi HIGH, kita tinggal menghilangkan arus pada Gate transisitor, maka jalur dari vcc ke GDN akan tertutup, saat itu jalur akan berada dalam kondisi floating, karena ada rangkaian pullup, jalur akan terhubung ke vcc sehingga jalur akan menjadi HIGH.
- Logic Level
Logic level output dari arduino adalah 5 volt, perangkat I2C bisa beroperasi pada logic level selain 5 volt tergantung dari datasheet perangkat I2C tersebut. jika perangkat I2C memiliki logic level 3,3 volt, maka output 5 volt dari arduino bisa merusak perangkat I2C.
Cara Kerja
transaksi data pada I2C mirip dengan komunikasi serial UART dimana data dikirim dalam bentuk paket. paket data tersebut terdiri dari 7 bit address, R/W bit, ACK (Acknowledge bit), 8 bit data, susunannya bisa dilihat pada gambar dibawah:
Ketika master akan memulai transaksi data, master akan ngubah kondisi jalur SDA menjadi LOW kemudian mengubah jalur SCL menjadi LOW, ini adalah start condition, semua slave akan aktif dan menunggu master mengirim address bit.
- Setelah melalui start condition master akan mengirim address bit, address bit akan mentukan dengan slave mana transaksi data dilakukan, semua slave dalam I2C bus akan membandingkan dan mencocokan address nya sendiri dengan address yang dikirim oleh master. urutan address bit dimulai dari most significant bit (MSB) dan diakhiri oleh least significant bit (LSB) dan hanya terdiri dari 7 bit karena bit ke 8 digunakan sebagai bit R/W, bit ini menunjukan apakah master akan melakukan pengiriman data (Logic LOW) atau pembacaan data (Logic HIGH).
Selanjutnya adalah ACK (Acknowledge bit)/NACK (Not Acknowledge bit), bit ini digunakan oleh slave untuk mengindikasikan bahwa dia sudah menerima address bit yang dikirim master, address bit yang dikirim oleh master ke I2C bus akan dicocokan dengan masing-masing slave, jika address dari salah satu slave cocok dengan address yang dikirim oleh master, nilai bit ini akan di set menjadi “0” oleh slave, namun jika tidak nilai bit ini akan tetap “1” (default) yang berarti slave tidak berhasil menerima address bit yang dikirim oleh master, ada beberapa penyebab ini bisa terjadi, bisa jadi slave sibuk, perintah tidak dipahami, address tidak ada yang cocok atau slave tidak bisa lagi menerima data, dsb. Biasanya setelah ACK bit pertama, master bisa mengirim lagi address bit jika satu data yang sama akan dikirim ke banyak slave.
Selanjutnya adalah addresing internal register. Internal register adalah lokasi memory slave yang menyimpan data tertentu, contoh sensor akselerometer ADX345, sensor ini memiliki address perangkat I2C dan address register untuk menyimpan data pengukuran akselerasi axis X , Y dan Z, jadi jika kita ingin membaca data pengukuran di axis X, maka master perlu mengirim address perangkat kemudian mengirim address internal register X-axis. address register ini bisa diketahui dari datasheet perangkat I2C nya.
- Selanjutnya adalah pengiriman data. Data yang dikirim adalah sebanyak 8 bit, pengirim nya bisa master atau slave tergantung dari mode yang diatur pada R/W bit. setelah 8 bit data dikirim, kemudian diikuti oleh ACK bit, nilai ACK bit akan di set menjadi “0” oleh reciever jika data tersebut sudah berhasil diterima, namun jika tidak berhasil diterima, nilai ACK bit akan tetap “1”
- Terakhir adalah stop condition. setelah semua data sudah berhasil dikirim, transfer data akan dihentikan oleh stop condition, stop condition adalah kondisi dimana jalur SDA berubah dari LOW ke HIGH, dan kondisi jalur SCL berapa pada kondisi HIGH
Jika dilihat secara keseluruhan proses, begini gambaran tranfer data protokol komunikasi I2C.
Fungsi-Fungsi Komunikasi I2C pada Arduino
untuk menggunakan komunikasi I2C di arduino kita memerlukan library “#include <wire.h>. Berikut ditambah dengan fungsi sering untuk malakukan transmisi data dengan protokol komunikasi I2C :
Wire.begin()
Fungsi ini digunakan untuk menginisiasI perangkat I2C sebagai master atau slave. Untuk inisiasi slave kita perlu menuliskan address I2C didalam parameter sytax nya, Cukup dengan memanggil sintax “Wire.begin()” maka transfer data dengan protokol I2C akan aktif, ada dua jenis penulisan syntax yang bisa kita gunakan.
Wire.begin(); // Inisiasi perangkat I2C sebagai master Master
Wire.begin(0x0A); // Inisiasi perangkat I2C sebagai Slave dengan Address = 0x0A
Wire.requestFrom()
Fungsi `Wire.requestFrom()`Digunakan oleh master untuk melakukan request atau menerima data dari slave. data yang sudah di request tersebut bisa dibaca dengan fungsi Wire.read(). fungsi ini memiliki 3 parameter:
Wire.requestFrom(address, jumlah byte)
Wire.requestFrom(address, jumlah byte,stop)
Parameter :
- Address : Address perangkat I2C yang diajak melakukan transaksi data
- Jumlah Byte : Jumlah byte yang diminta untuk dikirim
- stop : nilai true atau false. nilaitrue akan mengirim instruksi berhenti setelah request data dan memutus sambungan ke I2C bus, nilai falseakan mengirim pesan restart secara terus menerus setelah request data dan tetap tersambung dengan I2C bus.
Return value fungsi ini adalah jumlah byte yang dikirim dari slave.
Wire.available()
Fungsi ini digunakan untuk melihat jumlah byte yang tersedia untuk dibaca oleh fungsi wire.read(). pada master fungsi ini ditempatkan setelah fungsi wire.requestFrom() sedangkan pada slave fungsi ini ditempatkan didalam Wire.onRecieve(). dengan menggunakan fungsi ini, kita bisa melihat apakah ada data yang tersedia pada buffer I2C atau tidak sebelum kita memanggil fungsi Wire.read().
Wire.beginTransmission
Fungsi ini digunakan untuk memulai transmisi data dengan slave dengan memanggil address slave tersebut, jika Bus terhubung dengan banyak slave, maka kita perlu menulis address perangkat pada parameter syntax ini.
Wire.beginTransmission();
Wire.beginTransmission(address);
Wire.read()
fungsi akan membaca byte data yang di transmisikan dari slave ke master setelah fungsi Wire.requestFrom(), atau membaca data yang di transmisikan dari master ke slave
Wire.write()
Fungsi ini digunakan untuk mengirim data dari master ke slave atau sebaliknya, fungsi ini biasanya ditempatkan diantara fungsi Wire.beginTransmission() dan Wire.endTransmission(). Dengan fungsi ini, kita bisa mengirim data 1 byte, data string, data array dan data custom yang kita tentukan sendiri panjang datanya, dengan mengikuti syntax ini :
Wire.write(value)
Wire.write(string)
Wire.write(data, length)
Parameter :
- value : data dikirim dalam bentuk 1 byte
- string : data dikirim dalam bentuk String
- data : data dikirim dalam bentuk byte array
- length : jumlah data yang dikirim
Wire.endTransmission(true/false)
Fungsi ini digunakan untuk mengakhiri transmisi data dengan peripheral yang dimulai dengan fungsi Wire.beginTransmission() dan mengirim byte data yang masih antri karena fungsi Wire.write()
Wire.end()
Fungsi ini digunakan untuk Non-aktifkan library wire.h, fungsi ini berguna saat kita ingin menggantu mode perangkat dari master ke slave atau sebaliknya saat program berjalan tanpa melakukan restart mikrokontroller. Untuk menganktifkan kembali library wire, kita harus memanggil kembali fungsi Wire.begin().
Sekian teori dasar komunikasi data menggunakan protokol I2C pada Arduino, nantinya saya akan buat contoh penggunaan nyata menggunakan arduino pada artikel lain. Semoga bermanfaat
I always appreciate the diversity of subjects you cover on your website. There’s always something fresh to discover.