I2C bağlantı şemasını ve kullanılacak fonksiyonları öğrendiğimize göre, artık küçük bir örnek ile I2C'yi daha iyi anlayabiliriz. Bu örnekte iki adet Arduino Uno kullanılacaktır. Arduino Uno'lardan birisi master birisi de slave görevinde bulunacaktır.
Master görevindeki Arduino, slave görevindeki Arduino'ya bağlı LED'leri kontrol edecek ve slave görevindeki Arduino'dan veri alacak. Slave görevindeki Arduino, master görevindeki Arduino'dan gelen veriyi yorumlayacak. Gelen veriye göre de LED'leri kontrol edecek ve diğer Arduino'ya veri yollayacak.
Bu uygulamayı yapmak için ihtiyacımız olan malzemeler:
- 2 x Arduino
- 2 x 4.7K ohm direnç
- 1 x LED
- 1 x 220 ohm direnç
- 1 x Breadboard
Not: Devredeki iki Arduino'da ayrı ayrı veya aynı besleme kaynağından beslenmelidir. Eğer Arduino'lar ayrı kaynaklardan besleniyorsa, toprak hatlarının birleştirilmesi gerektiğini unutmayın. Slave üzerinden gelen mesajları okumak için Master görevindeki Arduino'yu bilgisayara bağlayarak Seri Monitörü açın.
Master görevindeki Arduino kodu:
/* I2C haberleşmesinde Master olarak görev yapan Arduino kodu */
#include <Wire.h>
/*
* I2C fonksiyonlarını kullanabilmek için
* Wire.h kütüphanesini projemize ekledik
*/
void setup()
{
Wire.begin();
/* I2C haberleşmesi master olarak başlatıldı */
Serial.begin(9600);
/* Bilgisayara veri yazdırabilmek için seri haberleşme başlatıldı */
}
void loop()
{
Wire.beginTransmission(1);
/* 1 adresine sahip Slave (köle) cihazına veri yollanacağı bildiriliyor */
Wire.write("a");
/* a karakteri slave cihaza yollanıyor */
Wire.endTransmission();
/* Yollanacak verilerin bittiği bildiriliyor */
/* a karakteri slave cihazda LED'i yak anlamına gelecektir */
delay(1000);
Wire.beginTransmission(1);
/* 1 adresine sahip Slave (köle) cihazına veri yollanacağı bildiriliyor */
Wire.write("b");
/* b karakteri slave cihaza yollanıyor */
Wire.endTransmission();
/* Yollanacak verilerin bittiği bildiriliyor */
/* b karakteri slave cihazda LED'i sondur anlamına gelecektir */
delay(1000);
Wire.requestFrom(1, 7);
/* 1 adresine sahip slave (köle) cihazından 7 BYTE'lık veri bekleniyor */
char gelenKarakter;
/* I2C hattından gelen veriler gelenKarakter değişkenine yazdırılacak */
while(Wire.available()){
/* I2C hattında yeni veri olduğu sürece döngü devam edecek */
gelenKarakter = Wire.read();
/* I2C hattından gelen veriler okunuyor */
Serial.print(gelenKarakter);
/* Gelen veriler ekrana yazdırılıyor */
}
Serial.println();
delay(1000);
}
Master görevindeki Arduino kodunda öncelikle I2C fonksiyonlarının kullanılabilmesi için Wire.h kütüphanesi çalışmaya dahil edilmiştir. Daha sonra haberleşme Wire.begin() komutuyla master olarak başlatıldı. Slave cihazdan gelecek verilerin ekrana yazdırılabilmesi için Serial.begin(9600) komutu ile Arduino ve bilgisayar arasındaki iletişim başlatıldı.
Loop fonksiyonu içinde, bir saniye aralıklarla slave cihaza 'a' ve 'b' karakterleri yollandı. Bu karakterler slave cihazda işlenerek LED'in konumu değiştirilecek. Bu karakterlerin yollanabilmesi için öncelikle Wire.beginTransmission(1) fonksiyonuyla hangi slave cihaza veri aktarılacağı seçildi. Tüm veriler cihaza yollandıktan sonra Wire.endTransmission(); komutuyla cihaza veri aktarımının bittiği bildirildi.
Slave cihazdan veri alınmak istendiği için Wire.requestFrom(1, 7); komutu kullanıldı. Bu komutla slave cihaz 7 byte'lık veriyi master cihaza aktaracağını anladı. Yeni veri geldiği sürece işlemin devam edebilmesi için, while döngüsünün koşulu Wire.available() yapılır. I2C data hattından gelen veriler Wire.read() fonksiyonuyla okunarak seri porta yollandı.
Slave görevindeki Arduino kodu
/* Slave (köle) görevindeki Arduino'nun kodu */
#include <Wire.h>
/*
* I2C fonksiyonlarını kullanabilmek için
* Wire.h kütüphanesini projemize ekledik
*/
const int LED = 13;
/* LED 13. pinde bulunmaktadır */
void setup()
{
Wire.begin(1);
/* I2C haberleşmesi, haberleşme adresi 1 olan bir slave cihaz olarak başlatıldı */
Wire.onRequest(istekGeldiginde);
/*
Master olan cihaz bu Arduino'dan veri istediğinde gerçekleşecek işlem seçildi
*/
Wire.onReceive(veriGeldiginde);
/*
Master olan cihazdan bu Arduino'ya veri geldiğinde yapılacak işlem seçildi
*/
pinMode(LED,OUTPUT);
/* LED pini çıkış olarak ayarlandı */
}
void loop()
{
/*
* Tüm işlemler veri isteği geldiğinde veya yeni veri geldiğinde
* yapılacağı için loop fonksiyonunun içi boş bırakılmıştır
*/
delay(1);
}
void veriGeldiginde(int veri)
{
/* I2C hattında bu cihaz için yeni veri olduğunda bu fonksiyon çalışır */
char gelenKarakter;
/* Hattaki veri okunarak gelenKarakter değişkenine kaydedilir */
while(Wire.available()){
gelenKarakter = Wire.read();
}
/* Eğer gelen veri 'a' ise LED yakılır, 'b' ise LED söndürülür */
if(gelenKarakter == 'a')
digitalWrite(LED,HIGH);
else if(gelenKarakter == 'b')
digitalWrite(LED,LOW);
}
void istekGeldiginde()
{
/*
* Eğer master bu cihazdan veri istiyor ise master cihaza "Merhaba" verisi yollanılır
* Eğer bu bir sensör olsaydı "merhaba" yerine sıcaklık veya ivme verisi yollanıyor olacaktı
*/
Wire.write("Merhaba");
}
Slave görevindeki Arduino kodunda öncelikle I2C fonksiyonlarının kullanılabilmesi için Wire.h kütüphanesi çalışmaya dâhil edildi. Daha sonra haberleşme Wire.begin(1) komutuyla 1 adresine sahip slave cihaz olarak başlatıldı. Master cihazından veri geldiğinde "veriGeldiginde()" fonksiyonu, istek geldiğinde "istekGeldiginde()" fonksiyonunun çalışması için "Wire.onReceive(veriGeldiginde)" ve "Wire.onRequest(istekGeldiginde)" fonksiyonları kullanıldı.
Programın ana yapısı bu iki fonksiyon ile çalışır. Arduino'ya master cihazdan yeni veri geldiğinde bu veri okunarak 'gelenKarakter' değişkenine yazdırılır. Gelen karakter eğer 'a' harfine eşitse LED yakılır, 'b' harfine eşitse LED söndürülür. Eğer master cihazdan veri isteği geldiyse, master cihaza "Merhaba" yazısı geri döndürülür. Eğer bu Arduino bir sensör olsaydı, burada "Merhaba" yazısı yerine ortam sıcaklığını veya ivme verisini döndürecekti.
İki Arduino arasında I2C ile nasıl haberleşme ağı kurulacağını öğrendik. I2C sadece mikro denetleyiciler arasında haberleşmeyi sağlamaz, aynı zamanda sensörlerle de haberleşmeyi sağlar. Bir hat üzerine bağlanmış birden fazla sensör, Arduino tarafından kolaylıkla okunabilir. Böylece sensör sayısı artmasına rağmen devredeki karmaşıklık ve kablo sayısı artmamış olur.