Arduino Wire kütüphanesi, I2C haberleşme yöntemiyle donanımsal olarak senkron seri haberleşme sağlayan kütüphanedir. Bu kütüphane ile bir clock hattı ve bir veri hattı kullanarak 2 ya da daha fazla cihaz ile donanımsal senkron seri haberleşme sağlanabilir. Wire kütüphanemizin çalışma mantığı, bir önceki dersimizde bahsettiğimiz shiftIn ve shiftOut fonksiyonlarımızın çalışma mantığı ile aynıdır. Ancak wire kütüphanesi donanımsal bir kütüphane olduğu için daha hızlı haberleşme sağlamaktadır. Arduino UNO kartımız için wire kütüphanesi ile haberleşme sağlayabileceğimiz pinler A4(SDA) ve A5(SCL) pinleridir. SDA pinimiz veri aktarımı için kullandığımız data hattımız, SCL pinimiz ise cihazlarımızın senkronizasyonu olarak kullanmamız gereken clock hattımızdır.
I2C haberleşme yöntemi ile birden fazla cihaz haberleşme sağlayabilir ancak, bir cihaz veri gönderirken diğer cihazlar veri yolunun boşalmasını beklemek zorundadır. Ay nı anda 2 cihaz veri gönderirse, data hattında çakışma meydana gelecektir.
I2C haberleşme bağlantısı aşağıdaki gibi olmalıdır;
Wire kütüphanemizi kullanabilmek için öncelikle #include <Wire.h> komutu ile wire kütüphanemizi projemize dahil etmeliyiz.
Wire kütüphanemizde 9 temelfonksiyonumuz bulunmaktadır
begin() fonksiyonumuz senkron seri (Wire) haberleşmesini başlatan fonksiyonumuzdur. begin() fonksiyonu setup() yapımız içerisinde yalnızca 1 kez çağrılır. Eğer fonksiyona herhangi bir parametre girilmemişse, cihazımız Master olarak çalışacak demektir. Eğer 0 ile 127 arasında bir değer girilmişse, cihazımız slave olarak çalışacak demektir ve master cihazın komutlarını uygulayacaktır. 0 ile 127 arasındaki değer slave cihazımızın kimliğini belirtecektir.
Sözdizimi: Wire.begin(adres);
adres : slave cihaz adresi (isteğe bağlı) 7 bit (kullanılmamışsa cihaz master olarak çalışacaktır)
Geriye dönüş değeri yoktur.
Kullanım:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <Wire.h> void setup() { Wire.begin(); // MASTER Cihaz için haberleşmeyi başlatır Wire.begin(4); // SLAVE Cihaz için haberleşmeyi başlatır ve Cihaz kimliğini belirtir /* * Bir cihaz hem master, hem de slave olarak çalışmaz! * Bu nedenle MASTER cihaz için yalnızca Wire.begin() * slave cihaz için yalnızca Wire.begin(cihazAdresi) * komutu kullanılır! */ } |
beginTransmission() fonksiyonu Master cihazdan Slave cihaza veri göndermeye başlamak için cihaz adresinin set edildiği fonksiyondur. Bu fonksiyon ile veri gönderilecek cihazın adresi belirtildikten sonra veri göndermeye başlanabilir.
Sözdizimi: Wire.beginTransmission(adres);
adres : veri gönderilecek slave cihazın adresi
beginTransmission fonksiyonu geriye herhangi bir değer döndürmez.
beginTransmission fonksiyonu ile başlatılan veri iletimini sonlandırmak için kullanılır. endTransmission() fonksiyonu herhangi bir parametre almaz ve geriye değer döndürmez.
Sözdizimi: endTransmission();
Master ve Slave cihaz için veri gönderme fonksiyonudur. write fonksiyonu master cihazdan slave cihaza ya da slave cihazdan master cihaza veri göndermek için kullanılır. write fonksiyonu Wire yöntemi ile 1 byte değerindeki veri, string ya da byte dizisi gönderilebilir.
Sözdizimi:
Wire.write(value);
Wire.write(string);
Wire.write(dizi, uzunluk);
value : 1 byte değerindeki veri (byte)
string : metin türünden karakter dizisi
dizi : gönderilecek byte dizisi
lenght : gönderilecek byte dizisi uzunluğu
Örnek olarak Master cihazdan Slave cihaza bir veri gönderelim:
1 2 3 4 5 6 7 8 9 10 11 12 |
#include <Wire.h> // Wire kütüphanesini projeye dahil et void setup() { Wire.begin(); // Wire haberleşmesini başlat } void loop() { Wire.beginTransmission(5); // 5 numaralı aktarma başlat Wire.write("Koddefteri.Net"); // Cihaza "Koddefteri.Net" metnini gönder Wire.endTransmission(); // Altarmayı tamamla delay(1000); } |
available fonksiyonu, wire haberleşme yöntemi ile okunmaya hazır mevcut byte sayısını almak için kullanılır. Herhangi bir parametre almaz, geriye tampon bellekteki okunmaya hazır byte sayısının integer türü değerini döndürür.
Sözdizimi: Wire.available();
Wire.read() fonksiyonu wire yöntemi ile gönderilen bir veriyi okumak için kullanılan fonksiyondur. read fonksiyonu herhangi bir parametre almaz. Geriye alınan 1 byte değerindeki veriyi döndürür. Eğer bir byte değerinden fazla veri alınmış ise, bir döngü yardımı ile alınan veriler diziye aktarılabilir. Hem Master cihazda hem de Slave cihazda veri okumak için kullanılır.
Sözdizimi: Wire.read();
Bu fonksiyonumuz Slave cihaz için Master cihazdan veri aldığında çalışacak fonksiyonu belirtmek için kullanılır. Yani Master cihazdan bir veri gönderdiğimizde Slave cihazda veriyi alacak olan fonksiyonu belirtmek için kullanılır.
Sözdizimi: Wire.onReceive(fonksiyonum);
fonksiyonum : Master cihazdan veri geldiğinde slave cihazda çalışacak fonksiyon
Örnek olarak yukarıda master cihazdan gönderdiğimiz veriyi aşağıdaki kodlarla slave cihazdan okuyup seri porta yazdıralım.
Slave cihaz kodları:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include <Wire.h> // Wire kütüphanesini projeye dahil et void setup() { Serial.begin(9600); // seri portu 96000 baud rate ile başlat Wire.begin(5); // Wire haberleşmeyi 5 nolu slave cihaz ID'si ile başlat Wire.onReceive(veriOku); // Wire ile gelen veriler veriOku fonksiyonu ile okunacak } void loop() { delay(100); } void veriOku(){ while(Wire.available()>0){ // Eğer gelen veri varsa char veri = Wire.read(); // cihaza gelen veriyi oku ve "veri" değişkenine aktar Serial.print(veri); // veri değişkeni değerini seri porta yazdır } } |
onRequest() fonksiyonu, Master cihaz Slave cihazdan veri talebinde bulunduğunda, slave cihazda çalışacak fonksiyonu belirtmek için kullanılır. onRequest() fonksiyonu, istek durumunda çalışacak olan fonksiyonu parametre olarak alır ve geriye değer döndürmez.
Sözdizimi: Wire.onRequest(istekFonksiyonu);
istekFonksiyonu : Master cihaz Slave cihazdan veri talep ettiğinde, slave cihazda çalışacak olan fonksiyon.
Master cihaz tarafından, slave cihazdan byte okuma isteğinde bulunmak için kullanılmaktadır.
Sözdizimi: Wire.requestFrom(adres, miktar, durak);
adres : veri istenecek slave cihaz adresi (7 bitlik cihaz adresi)
miktar : talep edilen byte sayısı
durak : istekten sonra veri yolunun durumu (boolean – True ise istekten sonra veriyolu serbest bırakılarak stop komutu gönderilir, False ise veriyolu açık tutularak master cihazın başka bir slave cihaza istekte bulunması engellenir.
Geriye byte cinsinden Slave cihazdan gönderilen bayte sayısını döndürür.
Örnek olarak master cihaz veri isteğinde bulunduğunda A0 pininden okunan analog değerleri gönderen fonksiyonu yazalım;
Öncelikle Master cihaz için 1 saniye aralıklarla slave cihazın A0 pininden analog değeri çekip seri porta yazdıran programımızı yazalım:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <Wire.h> // Wire kütüphanemizi projemize dahil ediyoruz byte alinan[2]; // Alınan veriyi hafızada tutmak için 2 indisli dizemiz void setup() { Wire.begin(); // Wire haberleşmeyi Master olarak başlat Serial.begin(9600); // Seri haberleşmeyi 9600 baud rate ile başlat } void loop() { Wire.requestFrom(1,2); // 1 numaralı slave cihaza 2 byte okuma isteği gönder if(Wire.available()){ // eğer gelen veri var ise int gelen = Wire.available();// Gelen byte sayısını gelen değişkenine aktar for(int i = 0; i<gelen; i++){ // gelen byte sayısı kadar döngüyü devam ettir alinan[i] = Wire.read(); // her döngüde 1 byte oku ve alinan dizisine aktar } word sonuc = word(alinan[0], alinan[1]); // okunan 2 byte veriyi bir word veriye dönüştür Serial.print("Okunan : "); // Seri porta Okunan yaz aynı satırdan devam et Serial.println(sonuc); // sonucu seri porta yaz delay(1000); // 1 saniye bekle } } |
Şimdi de slave cihazın okuma isteğine cevap veren yani A0 pininden değeri okuyup master cihaza gönderen programı yazalım:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <Wire.h> // Kütüphanemizi programımıza dahil ediyoruz void setup(){ Wire.begin(1); // Cihaz slave olarak çalışacak ve ID adresi 1 olacak Wire.onRequest(cevap); // İstek geldiğinde cevap fonksiyonu çalışacak } void loop(){ delay(100); } void cevap(){ // isteğe cevap verecek fonksiyonumuz word oku = analogRead(0); // A0 pininden değeri oku ve 16 bitlik oku değişkenine aktar delay(10); // 10 milisaniye bekle byte okunan[] = {highByte(oku), lowByte(oku)}; // okunan veriyi 2 byte böl ve okunan dizisine aktar Wire.write(okunan, 2); // okunan 2 byte değerindeki veriyi master cihaza gönder } |
Kodlarımızı yazıp kartımıza yüklüyoruz ve aşağıdaki bağlantıyı yapıp çalıştırıyoruz.
Slave cihazdaki potansiyometreyi oynadıkça 1 sn aralıklarla seri porta gelen değerin değiştiğini izleyebilirsiniz: