Bir önceki yazımızda ESP-NOW protokolünü kullanarak iki adet ESP32 kartı ile tek yönlü iletişim gerçekleştirmiştik. Bu yazımızda da bir önceki yazımızdaki kodumuzu revize ederek bir RGB LED ‘i kontrol edeceğiz. Ancak bu sefer farklı kartların birbirleri ile haberleşmesini istediğimiz için bir adet ESP32 kartı ile bir adet ESP32-CAM kartını haberleştireceğiz. Siz dilerseniz tekrar önceki yazıdaki gibi iki adet ESP32 geliştirme kartı kullanabilirsiniz.
Eğer bu projeyi yapmayı amaçlıyorsanız “ Yeni başlayanlar için ESP-NOW ” adlı blog yazımı incelemenizi tavsiye ederim. Koddaki ESP-NOW protokolüne ait tüm komutların açıklamaları o blog yazımda mevcut.
1. Adım: İhtiyaç Listesi
İsteğe bağlı ESP kartları
ESP32-Wroom-32 Wifi ve Bluetooth Geliştirme Kartı: https://www.robo90.com/esp32-wroom-32-wifi-ve-bluetooth-gelistirme-karti
Altyazı
Eğer elinizde ESP32-CAM modülünüz yoksa veya satın almak istemiyorsanız bu yazılımların hepsi ESP32 işlemcisine sahip tüm cihazlarda çalışacaktır. ESP32-CAM modülü de adından da anlaşılabileceği gibi ESP32 işlemcisi taşımaktadır. Sadece ESP32-CAM modülünün bacak sayısı daha az olduğu için verici kodunda çıkışını 0 ve 5V yani HIGH ve LOW yapabildiğiniz herhangi bir pini değiştirip ESP32 kartında da aynı yazılımı kullanabilirsiniz. Ancak minimum 2 adet ESP kartı olmalı.
ESP32-CAM Wifi Bluetooth Geliştirme Kartı ve OV2640 Kamera Modülü: https://www.robo90.com/esp32-cam-wifi-bluetooth-gelistirme-karti-ve-ov2640-kamera-modulu
Gerekli Yan Malzemeler
10mm RGB LED 4 Bacaklı Ortak Katot: https://www.robo90.com/10mm-rgb-led-4-bacakli-ortak-katot
Mini Breadboard – 170 Pin – Yeşil – Çıkıntısız: https://www.robo90.com/mini-breadboard-170-pin-yesil-cikintisiz
220R Direnç Paketi – 1/4 W – 10 Adet: https://www.robo90.com/220r-direnc-paketi-1-4-w-10-adet
40lı Ayrılabilen Dişi-Erkek Jumper Kablo – 20cm – Arduino Uyumlu: https://www.robo90.com/40li-ayrilabilen-disi-erkek-jumper-kablo-20cm-arduino-uyumlu
6X6 8mm Tach Buton (2 Bacak): https://www.robo90.com/6×6-8mm-tach-buton-2-bacak
2. Adım: Nasıl Kodlarız ?
Verici ( TX ) kodu
Kodun Tamamı;
#include <esp_now.h>
#include <WiFi.h>
//kanal belirliyoruz alıcı ve verici aynı kanalda olmalı
#define CHANNEL 1
#define BUTTON_PIN 21 // GIOP21 pin connected to button
#define BUTTON_PIN_1 19 // GIOP21 pin connected to button
#define BUTTON_PIN_2 18 // GIOP21 pin connected to button
//Alıcının MAC adresini esp_now_peer_info yapısına tanıttığımız kod
esp_now_peer_info_t slave;
//göndermek istediğimiz veri
uint8_t data=0;
int lastState = LOW; // the previous state from the input pin
int currentState; // the current reading from the input pin
int lastState_1 = LOW; // the previous state from the input pin
int currentState_1; // the current reading from the input pin
int lastState_2 = LOW; // the previous state from the input pin
int currentState_2; // the current reading from the input pin
void setup ()
{
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(BUTTON_PIN_1, INPUT_PULLUP);
pinMode(BUTTON_PIN_2, INPUT_PULLUP);
Serial.begin(115200);
WiFi.mode(WIFI_STA);
esp_now_init();
esp_now_register_send_cb(OnDataSent);
ScanForSlave();
esp_now_add_peer(&slave);
}
void loop(){
currentState = digitalRead(BUTTON_PIN);
if (lastState == HIGH && currentState == LOW)
esp_now_send(slave.peer_addr, &data, sizeof(data));
else if (lastState == LOW && currentState == HIGH)
Serial.println("The button is released");
lastState = currentState;
currentState_1 = digitalRead(BUTTON_PIN_1);
if (lastState_1 == HIGH && currentState_1 == LOW){
data=1;
esp_now_send(slave.peer_addr, &data, sizeof(data));
}
else if (lastState_1 == LOW && currentState_1 == HIGH){
Serial.println("The button is released");
data=0;
}
lastState_1 = currentState_1;
currentState_2 = digitalRead(BUTTON_PIN_2);
if (lastState_2 == HIGH && currentState_2 == LOW){
data=2;
esp_now_send(slave.peer_addr, &data, sizeof(data));
}
else if (lastState_2 == LOW && currentState_2 == HIGH){
Serial.println("The button is released");
data=0;
}
lastState_2 = currentState_2;
}
//CallBack fonksiyonu
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status ) {
Serial.print("Datayı gönderdim->");
Serial.println(data);
}
void ScanForSlave()
{
int16_t scanResults = WiFi.scanNetworks(); // Scan only on one channel
for (int i = 0; i < scanResults; ++i)
{
// Print SSID and RSSI for each device found
String SSID = WiFi.SSID(i);
String BSSIDstr = WiFi.BSSIDstr(i);
// Check if the current device starts with `Slave`
if (SSID.indexOf("RX") == 0)
{
int mac[6];
if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
for (int ii = 0; ii < 6; ++ii ) {
slave.peer_addr[ii] = (uint8_t) mac[ii];
}
}
slave.channel = CHANNEL; // pick a channel
slave.encrypt = 0; // no encryption
break;
}
}
}
Gördüğünüz gibi bir önceki yazımızdaki tüm ESP-NOW komutlarını bu yazımızda da kullandık. Farklı olarak “ #define BUTTON_PIN 21 ” ile butonlarımızı tanımladık. Sonrasında “ lastState ” ve “ currentState ” gibi değişlenlerle butonlara bastığımız anı ve çektiğimiz anı kaydetmek için tanımladık. Setup kısmında ise “ pinMode(BUTTON_PIN, INPUT_PULLUP); ” komutu sayesinde BUTTON_PIN pinini giriş olarak belirledik ve PULL_UP yaptık. Bu sayede butonumuza dışarıdan bir direnç yardımıyla pull up yapmamıza gerek kalmadı.
Sonrasında loop kısmında “ currentState = digitalRead(BUTTON_PIN); ” komutu ile currentState değişkenimizi BUTTON_PIN pinimize yani IO21 numaralı pinimize eşitledik. Diğer butonlar için de aynı işlemi yaptık.
currentState = digitalRead(BUTTON_PIN);
if (lastState == HIGH && currentState == LOW)
esp_now_send(slave.peer_addr, &data, sizeof(data));
else if (lastState == LOW && currentState == HIGH)
Serial.println("The button is released");
lastState = currentState;
Kodumuzun yukarıdaki kısmında ise eğer BUTTON_PIN yani IO21 numaraya bağlı butonumuza basılırsa “ esp_now_send(slave.peer_addr, &data, sizeof(data)); ” komutumuzun çalışması gerektiğini kodladık. Bir önceki blog yazımızdan hatırlarsak bu kod “ slave.peer_addr ” MAC adresine sahip alıcı cihazımıza “ &data, sizeof(data) ” komutları ile data verimizi ve datamızın boyutunu gönderir. Diğer buton kodlamalarında ise data verisini “ data=1; ” kodu sayesinde bir sayısına eşitleriz. Bu değer her buton için farklıdır. Bu sayede alıcı cihaza hangi butona basıldıysa onun numarasını gönderebiliriz ve ona göre RGB LED’ imizi kontrol edebiliriz.
Sonradan “ else if ” komutu ile butondan parmağımızı çektiğimizi algılarız ve tekrar “ data “ değişkenimizi sıfıra eşitleriz. Bu sayede herhangi bir karışıklık olmasının önüne geçeriz.
Verici kodumuz bu kadardı. Şimdi alıcı kodumuzu inceleyelim.
Alıcı ( RX ) kodu
Kodun tamamı:
#include <esp_now.h>
#include <WiFi.h>
#define CHANNEL 1
#define LED_PIN 12
#define LED_PIN_1 13
#define LED_PIN_2 15
int data_1;
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_AP);
WiFi.softAP("RX_1","RX_1_Password",CHANNEL, 0);
esp_now_init();
esp_now_register_recv_cb(OnDataRecv);
pinMode(LED_PIN, OUTPUT);
pinMode(LED_PIN_1, OUTPUT);
pinMode(LED_PIN_2, OUTPUT);
}
void loop() {
if(data_1==0){
digitalWrite(LED_PIN,HIGH);
delay(1000);
digitalWrite(LED_PIN,LOW);
}
digitalWrite(LED_PIN,HIGH);
if(data_1==1){
digitalWrite(LED_PIN_1,HIGH);
delay(1000);
digitalWrite(LED_PIN_1,LOW);
}
if(data_1==2){
digitalWrite(LED_PIN_2,HIGH);
delay(1000);
digitalWrite(LED_PIN_2,LOW);
}
}
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len){
data_1=*data;
Serial.print(data_1);
}
Alıcı kodumuzda da bu sefer RGB LED pinlerinin ESP kartımızın hangi pinleri ile kontrol edeceğimizi tanımladık. Sonrasında ise tekrar data_1 adlı bir değişken oluşturduk. Bunu neden yaptığıma değineceğim.
Setup kısmında ise LED pinlerimizin pin durumlarını çıkış olarak ayarladık. Sonrasında önceki yazımızda bahsettiğimiz ESP-NOW komutlarımızı çalıştırdık.
OnDataRecv fonksiyonuna bakacak olursak da önceki blog yazısından da hatırlayacağımız gibi data değişkeni bize geliyordu. Bu değişkeni ise bir arttırıp seri monitöre yazdırıyorduk. Şimdi ise bu değişkenden gelen verileri kontrol ederek RGB LED yakıp söndüreceğimiz için bu değişkeni kendi blog satırından loop satırına almamız gerekir. Ancak değişken sadece OnDataRecv fonksiyonu içerisinde tanımlanmıştır. Bunun önüne geçmek için kütüphaneleri de tanımladığımız tüm fonksiyonların dışındaki alana bir “ data_1 ” değişkeni tanımlayıp data değişkenini bu değişkene eşitledim. Bu sayede gelen verileri diğer tüm fonksiyonlarda kullanabileceğim. Sonrasında da “ Serial.print(data_1); ” komutu ile alıcı cihazımıza gelen verileri seri monitöre yazdıralım.
Loop kısmında ise daha önceden oluşturduğumuz data_1 değişkenini kullanaraka if komutları oluşturduk. Hatırlarsanız verici kısmında butonlara basıldığında sırasıyla 0, 1 ve 2 komutları alıcı cihazımıza geliyordu. Bu verileri kullanarak eğer data_1 değişkeni 1 sayısına eşitse RGB LED’in kırmızı bacağını kontrol et, eğer data_1 değişkeni 0 a eşitse mavi LED ‘i kontrol et gibi if komutları yazabiliriz.
Şimdi ise kodlarımızı sırasıyla alıcı ve verici cihazlarımıza yüklemeniz gerekmekte. Eğer daha önce ESP32 veya ESP32-CAM modüllerine kod yüklemediyseniz ve nasıl yükleneceğini bilmiyorsanz sırasıyla aşağıdaki blog yazılarımı da inceleyebilirsiniz. Bu yazımda kodun nasıl yükleneceğine değinmeyeceğim.
Donanım Kısmı ve Blog Şeması
Eğer bu kısma kadar geldiyseniz harika bir iş çıkardınız. Şimdi devre şemamızı sırasıyla alıcı ve verici cihazlarımız için inceleyelim.
Verici Devre Şeması
Gördüğünüz gibi yukarıdan aşağıya doğru sırasıyla D21, D19, D18 pinlerini butonlara bağladık. Sonrasında butonların diğer bacaklarını da ESP32 kartımızın GND bacağına bağladık. Bu sayede butona basğtığımızda seçtiğimiz pinler GND ‘ye çekilerek butona basıldığını anlayacağız. Şimdi Alıcı cihazımızın devre şemasını inceleyelim. ( Fotoğraf 1.0 )
Alıcı Devre Şeması
Gördüğünüz gibi sırasıyla RGB LED’imizin pinlerini ESP32-CAM modülünün IO12, IO13, IO15 numaralı pin bacaklarına bağladık. RGB LED imiz ortak katot yapısına sahip olduğu için bir direnç yardımıyla ESP32-CAM modülümüzün GND bacağına bağladık. Bu sayede seçtiğimiz pinlerden herhangi birsini HIGH yaparsak ( yani 0V’dan 5V ) RGB LED in kırmızı mavi ve yeşil renklerinden birisi yanacaktır. Alıcı cihazımızın devre şeması da bu kadardı. Şimdi isterseniz projemizi test kısmına geçelim. ( Fotoğraf 1.1 )
Test Kısmı
Şimdi iki cihazımız da ayrı ayrı bilgisayarıma bağlı ve ayrı Arduino IDE programında açıklar. Bu sayede hangi verinin nereye nasıl gittiğini görebileceğim.
Ve evet ! İlk butona bastığım anda mavi LED’imin yandığını görebiliyorum. ( Fotoğraf 1.2 ) Şimdi sırasıyla diğer butonlara basarak diğer LED’leri kontrol edelim. Yeşil ledi kontrol etmek için ortadaki butona bastığımda; ( Fotoğraf 1.3 )
Gördüğünüz gibi ortadaki butona basınca yeşil RGB LED’i yanıyor ve verici seri monitöründe 1 datasını gönderdiğini gösteriyor. ( Fotoğraf 1.3- 1.4 ) Alıcı monitöründe ise 1 datasının geldiğini görebiliyoruz. Şimdi aynı durumu kırmızı LED için de inceleyelim.
Ve evet ! Gördüğünüz gibi butona bastığım anda 2 datası verici cihazdan alıcı cihaza gönderildi ve alıcı cihazın da seri monitöründe 2 datası göründü. ( Fotoğraf 1.5– 1.6 ) Fotoğrafa bacakak olursak da kırmızı ışığın yandığını gözlemleyebiliriz.
Bu projemiz bu kadardı. İki adet ESP32 cihazını kablosuz haberleştirerek yapabileceklerinizi bir düşünsenize. Ne kadar fazla. Bunun gibi daha fazla projeyi görmek istiyorsanız aşağıdaki bağlantıdan tüm projelerimi görebilirsiniz.
Diğer proje yazıları: https://blog.robo90.com/kategori/projeler/
Bir sonraki bloğumda ise ESP mesh Networking kavramını inceleyeceğim.