back to top

Sesli Asistan için Fiziksel Arayüz

Günümüzde sesli asistanlar, akıllı cihazlarla etkileşim kurmanın en yaygın yollarından biri haline geldi. Ancak yalnızca sesli komutlarla çalışmak yerine, görsel geri bildirim sağlayan fiziksel bir arayüz ekleyerek kullanıcı deneyimini daha sezgisel hale getirmek mümkün. Bu projede, sesli bir asistanın fiziksel bir arayüzle nasıl desteklenebileceğini ele alacağız.

Projenin Amacı

Projemiz, sesli bir asistana fiziksel bir geri bildirim arayüzü kazandırmayı amaçlamaktadır. Kullanıcılar, sesli komutlar verirken ekranda görsel bildirimler alacak ve RGB LED halkasıyla etkileşim deneyimi artırılacaktır. Böylece sesli asistanın komutları algıladığı ve işlem yaptığı süreç daha anlaşılır hale gelecektir.

Kullanılan Malzemeler

Bu projede aşağıdaki bileşenlere ihtiyacınız olacak:

Devre Şeması ve Bağlantılar

Bu projede kullanılan bileşenlerin bağlantıları şu şekildedir:

  • NodeMCU – WS2812 NeoPixel Halka:
    • 5V → VIN
    • GND → GND
    • D1 → D4
  • NodeMCU – OLED Ekran:
    • VDD → 3V
    • VCC → GND
    • SDA → D2
    • TCL → D1

3D Baskı ve Tasarım

Fiziksel arayüzü destekleyen bir kasa tasarlamak için tinylab 3D PLA Filament kullanarak bir 3D baskı gerçekleştirilmiştir. Kasa, projenin bileşenlerini güvenli bir şekilde barındıracak şekilde tasarlanmıştır. Gövde bölümü, OLED ekranın ve WS2812 halka LED’in düzgün bir şekilde monte edilmesini sağlarken, alt ve üst kapaklar sayesinde bileşenlerin korunması ve estetik bir görünüm kazanması amaçlanmıştır. Üst kapak, gerektiğinde kolayca çıkarılabilir şekilde tasarlanmış olup, bakım veya güncellemeler sırasında iç bileşenlere erişim imkanı sunar. Alt kapak ise devre kartını ve bağlantıları güvenli bir şekilde yerinde tutarak projenin sağlamlığını artırır.

Yazılım ve Kodlama

NodeMCU kartı üzerine yüklenen kod, sesli asistandan gelen komutları işleyerek, OLED ekranda görüntüleme ve LED halkasında ışık animasyonları oluşturma işlemini gerçekleştirir. Arduino IDE kullanılarak geliştirilen kodun ana işlevleri şunlardır:

  1. Wi-Fi Bağlantısı Kurma: ESP8266’nın sesli asistan ile bağlantı kurmasını sağlar.
  2. Komutları Algılama: Kullanıcının verdiği sesli komutları işler.
  3. OLED Ekrana Bilgi Gönderme: Algılanan komutları ekranda gösterir.
  4. LED Halka Animasyonu: Asistanın aktif olduğunu göstermek için RGB LED halkasında dinamik ışık efektleri oluşturur.

Kodlar: 

#include <ESP8266WiFi.h>         // ESP8266 Wi-Fi kütüphanesi

#include <ESP8266HTTPClient.h>   // HTTP istemcisi

#include <Adafruit_GFX.h>        // GFX kütüphanesi

#include <Adafruit_SSD1306.h>    // OLED ekran kütüphanesi

#include <ArduinoJson.h>         // JSON ayrıştırma için kütüphane

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_NeoPixel.h>

// Wi-Fi ayarları

const char* ssid = ""; // Wi-Fi ağ adı

const char* password = ""; // Wi-Fi şifresi

// OpenWeatherMap API bilgileri

const char* apiKey = "";    // OpenWeatherMap API anahtarı

const char* city = "Istanbul";          // Şehir

const char* country = "TR";             // Ülke kodu

// API URL'sini oluştur

String apiUrl = "http://api.openweathermap.org/data/2.5/weather?q=" + String(city) + "," + String(country) + "&appid=" + String(apiKey) + "&units=metric";

// OLED ekran boyutu

#define SCREEN_WIDTH 128

#define SCREEN_HEIGHT 32

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)

#define SCREEN_ADDRESS 0x3C 

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define LED_PIN 2       

#define LED_COUNT 16    

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {

  // Seri iletişim başlatılıyor

  Serial.begin(115200);

  strip.begin();           // NeoPixel başlatılıyor

  strip.show();            

  delay(1000);

  dsadhqwuıhdauıhwauhhduıwadıuwadjkawndwmna

  for (int brightness = 0; brightness <= 2; brightness++) 

  {

    for (int i = 0; i < LED_COUNT; i++) {

      strip.setPixelColor(i, strip.Color(brightness, 0, 0)); // Kırmızı renkte ve artan parlaklık

    }

    strip.show();

    delay(10); 

  }

  // OLED ekran başlatma

  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS))

  {

    Serial.println("SSD1306 ekran başlatılamadı!");

    while (true);

  }

  display.display();

  display.clearDisplay();

  // Wi-Fi bağlanma

  Serial.println("Wi-Fi'ye bağlanılıyor...");

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {

    delay(1000);

    Serial.print(".");

  }

  // Bağlantı başarılı

  display.clearDisplay();

  display.setTextColor(SSD1306_WHITE);

  display.setTextSize(1);

  display.setCursor(0, 0);

  display.println("Wifi baglanti basarili!");

  display.display();

  Serial.println("\nWi-Fi bağlantısı başarılı!");

  Serial.print("IP Adresi: ");

  Serial.println(WiFi.localIP());

  delay(2000);

  display.clearDisplay();

  display.setTextColor(SSD1306_WHITE);

  display.setTextSize(3);

  int16_t x1, y1;

  uint16_t textWidth, textHeight;

  display.getTextBounds(":)", 0, 0, &x1, &y1, &textWidth, &textHeight);

  int x = (SCREEN_WIDTH - textWidth) / 2;

  int y = (SCREEN_HEIGHT - textHeight) / 2;

  display.setCursor(x, y);

  display.print(":)");  // Metni ekrana yazdır

  display.display();

}

void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *width, uint16_t *height);

void loop() {

  if (Serial.available()) {

    char data = Serial.read();

    if(data == 'p')

    {

      if (WiFi.status() == WL_CONNECTED) 

      {

        WiFiClient client;

        HTTPClient http;

        // HTTP isteği gönder

        Serial.println("API'ye bağlanılıyor...");

        http.begin(client, apiUrl);

        int httpResponseCode = http.GET();

        // Yanıt başarılıysa

        if (httpResponseCode == HTTP_CODE_OK) 

        {

          String payload = http.getString();

          Serial.println("Veri alındı:");

          Serial.println(payload);

          // JSON ayrıştırma

          DynamicJsonDocument doc(1024);

          DeserializationError error = deserializeJson(doc, payload);

          if (error) 

          {

            Serial.print("JSON Ayrıştırma Hatası: ");

            Serial.println(error.f_str());

            return;

          }

          const char* weather = doc["weather"][0]["main"]; // Hava durumu

          float temp = doc["main"]["temp"];               // Sıcaklık

          int humidity = doc["main"]["humidity"];         // Nem oranı

          Serial.println(weather);

          Serial.println(temp);

          Serial.println(humidity);

          display.clearDisplay();

          display.setTextColor(SSD1306_WHITE);

          display.setTextSize(1);

          display.setCursor(0, 0);

          display.println("Hosgeldiniz!");

          display.display();

          delay(2000);

          display.clearDisplay();

          display.setCursor(0, 0);

          display.println("Sehir: Istanbul");

          display.print("Durum: ");

          display.println(weather);

          display.print("Sicaklik: ");

          display.print(temp);

          display.println(" C");

          display.print("Nem: ");

          display.print(humidity);

          display.println(" %");

          display.display();

        }

        else 

        {

          Serial.print("HTTP Hatası: ");

          Serial.println(httpResponseCode);

        }

        http.end();

      } 

      else 

      {

        Serial.println("Wi-Fi bağlantısı kaybedildi!");

      }

    }

    if (data == 'b')

    {

      turnOffAllLEDs();

      animateToRed();  

      fadeToRedOff();   

      fadeToWhite();    

    }

    else if (data == 'c') 

    {

      speechAnimation();

    }

    else if (data == 'v') 

    {

      fadeToOrangeOff();

    }

  }

}

void turnOffAllLEDs()

{

  for (int i = 0; i < LED_COUNT; i++) 

  {

    strip.setPixelColor(i, strip.Color(0, 0, 0)); 

  }

  strip.show();

}

void animateToRed()

{

  for (int i = 0; i < LED_COUNT; i++) 

  {

    strip.setPixelColor(i, strip.Color(255, 0, 0));

    strip.show();

    delay(30);

  }

}

void fadeToRedOff() 

{

  for (int step = 255; step >= 0; step--) 

  {

    for (int i = 0; i < LED_COUNT; i++) 

    {

      uint8_t red = step; // Kırmızı değeri azalır

      strip.setPixelColor(i, strip.Color(red, 0, 0)); // Kırmızıdan sönme

    }

    strip.show();

    delay(5); // Kırmızıyı sönme hızını ayarlayabilirsiniz

  }

}

// Kırmızıdan beyaza animasyonlu geçiş

void fadeToWhite() 

{

  for (int step = 0; step <= 255; step++) 

  {

    for (int i = 0; i < LED_COUNT; i++) 

    {

      // Kırmızıdan beyaza geçiş (kırmızı azalır, beyaz artar)

      uint8_t red = 255 - step; // Kırmızı yavaşça azalır

      uint8_t white = step;     // Beyaz yavaşça artar

      strip.setPixelColor(i, strip.Color(white, white, white)); // Beyaz renk

    }

    strip.show();

    delay(5); // Geçiş hızı

  }

}

void speechAnimation() 

{

      // Turuncu renge geçiş yap

  for (int i = 0; i < LED_COUNT; i++) 

  {

    strip.setPixelColor(i, strip.Color(255, 150, 0)); // Turuncu

  }

  strip.show();

  delay(50);  // Turuncuya geçiş için kısa bir süre

  for (int i =0;i <= 5; i++)

  {

    // Parlaklık seviyesini hızla artırıp azaltarak animasyon yap

    for (int brightness = 200; brightness <= 255; brightness += 15) 

    {  // Parlaklığı %20'den %100'e kadar artır

      for (int i = 0; i < LED_COUNT; i++) 

      {

        strip.setPixelColor(i, strip.Color(brightness, 150, 0)); // Turuncu renk (R:255, G:165, B:0)

      }

      strip.show();

      delay(70);  // Hızlı geçiş için kısa bir süre

    }

    for (int brightness = 255; brightness >= 200; brightness -= 15) 

    {  // Parlaklığı %100'den %20'ye kadar azalt

      for (int i = 0; i < LED_COUNT; i++)

      {

        strip.setPixelColor(i, strip.Color(brightness, 150, 0)); // Turuncu renk

      }

      strip.show();

      delay(70);  // Hızlı geçiş için kısa bir süre

    }

  }

}

void fadeToOrangeOff() 

{

  for (int step = 150; step >= 0; step--) 

  {

    for (int i = 0; i < LED_COUNT; i++) 

    {

      // Kırmızıdan azalırken, yeşil ve mavi komponentleri sıfır

      uint8_t orange = step; // Kırmızı değeri azalır

      strip.setPixelColor(i, strip.Color(orange, orange, 0)); // Kırmızıdan sönme

    }

    strip.show();

    delay(5); // Kırmızıyı sönme hızını ayarlayabilirsiniz

  }

Projenin Sonuçları

Projemiz sayesinde, sesli asistanların kullanıcı deneyimini artıran fiziksel geri bildirim mekanizmaları geliştirilebilir. OLED ekran ve WS2812 LED halkası sayesinde komutların algılanıp algılanmadığını görmek mümkün hale gelir. Böylece sadece sesli yanıt yerine görsel destek ile kullanım daha keyifli hale getirilir.

Bu tarz projeler, akıllı ev sistemleri ve IoT tabanlı asistanlar için önemli bir gelişim alanı sunmaktadır. Projenizi geliştirerek kendi sesli asistan ara yüzünüzü oluşturabilirsiniz!

Keyifli Seyirler!

Son Çıkan Yazılar

CEVAP VER

Lütfen yorumunuzu giriniz!
Lütfen isminizi buraya giriniz