/*
L293D ile LCD GÖSTERGELİ MOTOR SÜRÜCÜ
  Özellikler
    1 Saat yönü ya da tersine motor döndürme özelliği
    2 PWM ile ayarlanabilir hız özelliği
    3 Ayak pedalı ya da ön panel tuşu ile bekletme ve çalıştırma özelliği
    4 LCD ekran ile Yön, çalışma/bekleme PWM oranı ve olması gereken çıkış gerilimi.
  LCD Bağlantıları
    LCD RS      -> D06  12
    LCD Enable  -> D05  11
    LCD D4      -> D03  5
    LCD D5      -> D02  4
    LCD D6      -> D01  3
    LCD D7      -> D00  2
    LCD R/W     -> GND
    LCD V0      -> GND
    +5V ve GND
  KOMUTLAR
    HIZ ARTTIRMA                 -> A0   23
    HIZ AZALTMA                  -> A1   24
    MOTOR HAREKET YÖNÜ           -> A2   25
    MOTOR BEKLEME/ÇALIŞTIRMA     -> A3   26
    * Tüm butonlar dahili pull up modunda. Harici direnç kullanılmadı.
  ÇIKIŞLAR
    GÜÇ KAYNAĞI AKİVASYON       -> D08  14
    L293D PWM (ENABLE)          -> D09  15
    L293D IN1 (SAAT YÖNÜ)       -> D10  16
    L293D IN2 (SAAT YÖNÜ TERSİ) -> D11  17
DİKKAT BU NOT SADECE BENDEKİ MEVCUT ENTEGRE İÇİN GEÇERLİDİR.
Uno üzerindeki 328'in D4 portu çalışmıyor
*/
#include <LiquidCrystal.h>
LiquidCrystal lcd(6, 5, 3, 2, 1, 0);
/********************************* BAŞLANGIÇ DEĞERLERİ *********************************/
int PWMOrani = 100;           // İlk çalıştırmada ne kadar hızlı başlacak 1-100
int PWMOraniAdim = 5;         // PWM oranının yüzde olarak değişim değeri 1-100
int GucKaynagi = 32;          // Uygulanan harici gerilim
int DonusYonu = 1;            // Dönüş yönü 1 ileri 2 geri
int BaslatDurdur = 1;         // 1 durdurur 2 başlatır
/******************************* BAŞLANGIÇ DEĞERLERİ SON *******************************/
/*************************************** AYARLAR ***************************************/
const int HariciPSU = 8;            // GÜÇ KAYNAĞI AKİVASYON        -> D08  14
const int En = 9;                   // L293D PWM (ENABLE)           -> D09  15
const int In1 = 10;                 // L293D IN1 (SAAT YÖNÜ)        -> D10  16
const int In2 = 11;                 // L293D IN2 (SAAT YÖNÜ TERSİ)  -> D11  17
const int HizYukariButton = A0;     // HIZ ARTTIRMA                 -> A0   23
const int HizAsagiButton = A1;      // HIZ AZALTMA                  -> A1   24
const int YonButton = A2;           // MOTOR HAREKET YÖNÜ           -> A2   25
const int BaslatDurdurButton = A3;  // MOTOR BEKLEME/ÇALIŞTIRMA     -> A3   26
const int Kontrast = A5;            // LCD PARLAKLIK AYARI          -> A5   28
int volt = GucKaynagi;
int PWM = PWMOrani * 255 / 100;
/************************************* AYARLAR SON *************************************/
/******************************* TÜRKÇE/ÖZEL KARAKTERLER *******************************/
byte buyuku[] = {B01010,B10001,B10001,B10001,B10001,B10001,B01110,B00000};  // Ü
byte kucuko[] = {B01010,B00000,B01110,B10001,B10001,B10001,B01110,B00000};  // ö
byte buyukc[] = {B01110,B10001,B10000,B10000,B10001,B01110,B00100,B00000};  // Ç
byte buyuks[] = {B01111,B10000,B10000,B01110,B00001,B11110,B00100,B00000};  // Ş
/******************************* TÜRKÇE/ÖZEL KARAKTERLER *******************************/
void selamlama() {
  lcd.setCursor(0,0);
  lcd.print("PWM HIZ KONTROLU");
  lcd.setCursor(15,0);
  lcd.write(byte(0));
  lcd.setCursor(0,1);
  lcd.print("<--   v1.0   -->");
  delay(3000);
  lcd.clear();
}
void ilkEkran() {
  lcd.setCursor(0,0);
  lcd.print("Y");
  lcd.setCursor(1, 0);
  lcd.write(byte(1));
  lcd.setCursor(2, 0);
  lcd.print("n");
  lcd.setCursor(4,0);
  lcd.print("iLERi");
  lcd.setCursor(12,0);
  lcd.print("%");
  lcd.setCursor(13,0);
  lcd.print(PWMOrani);
  lcd.setCursor(0,1);
  lcd.print("BEKLEMEDE");
  lcd.setCursor(13,1);
  lcd.print(volt);
  lcd.setCursor(15,1);
  lcd.print("V");
}
void PWMOraniYazdir() {
  lcd.setCursor(12,0);
  lcd.print("    ");
  if (PWMOrani < 10) {
    lcd.setCursor(14,0);
    lcd.print("%");
    lcd.setCursor(15,0);
    lcd.print(PWMOrani);
  } else if (PWMOrani < 100) {
    lcd.setCursor(13,0);
    lcd.print("%");
    lcd.setCursor(14,0);
    lcd.print(PWMOrani);
  } else {
    lcd.setCursor(12,0);
    lcd.print("%");
    lcd.setCursor(13,0);
    lcd.print(PWMOrani);
  }
}
void VoltYazdir() {
  lcd.setCursor(13,1);
  lcd.print("  ");
  if (volt < 10) {
    lcd.setCursor(14,1);
    lcd.print(volt);
  } else {
    lcd.setCursor(13,1);
    lcd.print(volt);
  }
}
void HiziGuncelle() {
  if (BaslatDurdur == 2) {
    analogWrite(En, PWM);
    lcd.setCursor(0, 1);
    lcd.write(byte(2));
    lcd.setCursor(1, 1);
    lcd.print("ALI");
    lcd.setCursor(4, 1);
    lcd.write(byte(3));
    lcd.setCursor(5, 1);
    lcd.print("IYOR");
  }
  if (BaslatDurdur == 1) {
    analogWrite(En, LOW);
    lcd.setCursor(0, 1);
    lcd.print("BEKLEMEDE");
  }
}
void setup() {
  // özel karakter "Ü" oluştur
  lcd.createChar(0, buyuku);
  // özel karakter "ö" oluştur
  lcd.createChar(1, kucuko);
  // özel karakter "Ç" oluştur
  lcd.createChar(2, buyukc);
  // özel karakter "Ş" oluştur
  lcd.createChar(3, buyuks);
  
  lcd.begin(16, 2);
  pinMode(Kontrast, 125);
  pinMode(HizYukariButton, INPUT_PULLUP);
  pinMode(HizAsagiButton, INPUT_PULLUP);
  pinMode(YonButton, INPUT_PULLUP);
  pinMode(BaslatDurdurButton, INPUT_PULLUP);
  pinMode(HariciPSU, OUTPUT);
  pinMode(En, OUTPUT);
  pinMode(In1, OUTPUT);
  pinMode(In2, OUTPUT);
  digitalWrite(HariciPSU, LOW);
  digitalWrite(En, LOW);
  digitalWrite(In1, HIGH);
  digitalWrite(In2, LOW);
  lcd.clear();
  selamlama();
  ilkEkran();
}
void loop() {
  if (digitalRead(HizYukariButton) == 0) {
    if (PWMOrani < 100) {
      PWMOrani = PWMOrani + PWMOraniAdim;
      volt = PWMOrani * GucKaynagi / 100 ;
      PWM = PWMOrani * 255 / 100;
      PWMOraniYazdir();
      VoltYazdir();
      HiziGuncelle();
    }
    delay(300);
  }
  if (digitalRead(HizAsagiButton) == 0) {
    if (PWMOrani > 1) {
      PWMOrani = PWMOrani - PWMOraniAdim;
      volt = PWMOrani * GucKaynagi / 100 ;
      PWM = PWMOrani * 255 / 100;
      PWMOraniYazdir();
      VoltYazdir();
      HiziGuncelle();
    }
    delay(300);
  }
  if (digitalRead(YonButton) == 0) {
    switch (DonusYonu) {
      case 1:
        digitalWrite(In1, LOW);
        delay(1500);
        digitalWrite(In2, HIGH);
        DonusYonu = 2;
        lcd.setCursor(4, 0);
        lcd.print("GERi ");
        break;
      case 2:
        digitalWrite(In1, HIGH);
        delay(1500);
        digitalWrite(In2, LOW);
        DonusYonu = 1;
        lcd.setCursor(4, 0);
        lcd.print("iLERi");
        break;
    }
    delay(300);
  }
  if (digitalRead(BaslatDurdurButton) == 0) {
    switch (BaslatDurdur) {
      case 1:
        BaslatDurdur = 2;
        digitalWrite(HariciPSU, HIGH);
        delay(1000);
        HiziGuncelle();
        break;
      case 2:
        BaslatDurdur = 1;
        HiziGuncelle();
        digitalWrite(HariciPSU, LOW);
        break;
    }
    delay(300);
  }
}