Arduino Alarmlı Dereceli Takvim Saat

Çok fonksiyonlu Arduino saat yapalım. Takvimi olsun, sıcaklık ölçsün alarmlı olsun, ayarlanabilsin.

Projem daha önce Arduino Alarmlı Butonlu Saat Takvim yazımda verdiğim programın daha da geliştirilmiş versiyonu.
Bu uygulamada alarm simgesi ve derece simgesi gibi özel karakterler de gerçekleştirildi. Proje tek başına pek çok öğretici özelliğe sahip. DS1302 Saat modülünü bağlama veri alma, kaydetme, alarm, ayar fonksiyonları, DSB20 sıcaklık modülünü bağlama, veri alış-verişi. Aktif Buzzer kullanımı. LCD ekranda karakter oluşturma gibi pek çok deneyimi bir arada sunuyor.
Özel karakterleri oluştururken LCD KarakterMatik - DC programından yararlandım. Oldukça pratik ve kullanışlı.
Program ile ilgili gerekli açıklamalar program içerisinde verildiği için burada üzerinde durmayacağım. Arzu ederseniz pin bağlantılarını kendinize göre değiştirebilirsiniz.


 DEVRE ŞEMASI

GENEL GÖRÜNÜM

 DS18B20

 BUZZER MODÜL

 DS1302 RTC MODÜL

  DS1302 RTC MODÜL

 LCD

ARDUINO IDE KODU:

/*******************************************************************************
   Kodla Gitsin
 *Arduino Alarmlı Saat, I2C LCD, DS1302 RTC (real-time clock - gerçek zaman saati))
 *Version 1.1  Türkçeleştirildi, I2C LCD eklendi, Alarm tonu eklendi, Sıcaklık ölçer eklendi - Kodla  Gitsin
   https://kodlagitsin.blogspot.com/
   Version 1.0  Copyright (C) 2018 One Transistor <https://www.onetransistor.eu>      
   https://www.onetransistor.eu/2018/12/alarm-clock-with-ds1302-rtc.html
   https://raw.githubusercontent.com/onetransistor/arduino-projects/master/ds1302_alarm_clock/ds1302_alarm_clock.ino
   DS1302 communication from https://github.com/NeiroNx/RTCLib   
*********************************************************************************/
#define RTC_CLK 4 // clock   ds1302
#define RTC_DAT 3 // data    ds1302
#define RTC_RST 2 // enable  ds1302

#define BTN_AL  5 // alarm butonu
#define BTN_DN  6 // aşağı ayar butonu
#define BTN_UP  7 // yukarı ayar butonu
#define BTN_SET 8 //ayar butonu
#define BTN_AP  9 //arka plan ışığı
#define alarm_Buzz_Ses 11 //buzzer
#define LED1   12 //led1

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C  lcd(0x27,2,1,0,4,5,6,7);

#include <OneWire.h> 
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 10 // DS18B20 ısı sensörü veri kablosu pin 2'ye takılı
OneWire oneWire(ONE_WIRE_BUS); 
DallasTemperature sensors(&oneWire);

unsigned long timeUpdate = 0;
unsigned long zamanButon = 0;
unsigned long zamanAlarm = 0;
bool butonBas = false;
byte alarmAktif = 0;
bool alarmSw = 1;
byte ayarModu = 0;
byte ayarAlarm = 0;
byte secim=1;

byte ay_gun_sayisi[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const char* ay_isimleri[13] = {"...", "Oca", "Sub", "Mar", "Nis", "May", "Haz", "Tem", "Agu", "Eyl", "Eki", "Kas", "Ara"};
const char* gun_isimleri[8] = {"...", "Ptsi", "Sali", "Cars", "Pers", "Cuma", "Ctsi", "Paza"};
//byte karakter[8] = {satir1, satir2, satir3, satir4, satir5, satir6, satir7, satir8} // LCD KarakterMatik - DC kullanabilirsiniz. 
byte karakter0[8] = {0x0,0x0,0x4,0xE,0xE,0x1F,0x4,0x0};   // alarm karakterimizin kodlarını tanımlıyoruz ===============
byte karakter1[8] = {0x1C,0x14,0x1C,0x0,0x0,0x0,0x0,0x0}; //derece karakterimizin kodlarını tanımlıyoruz ===============

byte saat, dakika, saniye; // hour, minute, second  (saat, dakika, saniye)
byte gun, ay, yil; // day, month, year      (gün, ay, yıl)
byte haf_gun;      // day of the week            (haftanın kaçıncı günü)
byte al_etkin, al_saat, al_dakika; // alarm: etkin,alarm: saat,aarm:dakika

static byte bcd2bin (byte val) {
  return val - 6 * (val >> 4);
}

static byte bin2bcd (byte val) {
  return val + 6 * (val / 10);
}

void rtc_kaydet(byte val) //===================================  rtc_kaydet  ===================================
{
  pinMode(RTC_DAT, OUTPUT);
  shiftOut(RTC_DAT, RTC_CLK, LSBFIRST, val);
}

void rtc_yaz_reg(byte addr, byte val) //=====================  rtc_yaz_reg  ===============================
{
  digitalWrite(RTC_RST, HIGH);
  rtc_kaydet(addr);
  rtc_kaydet(val);
  digitalWrite(RTC_RST, LOW);
}

byte rtc_oku() {
  pinMode(RTC_DAT, INPUT);
  byte value = 0;
  for (byte i = 0; i < 8; i++) {
    value |= (digitalRead(RTC_DAT) << i);
    digitalWrite(RTC_CLK, HIGH);
    digitalWrite(RTC_CLK, LOW);
  }
  return value;
}

byte rtc_oku_reg(byte addr) {
  digitalWrite(RTC_RST, HIGH);
  rtc_kaydet(addr);
  byte val = rtc_oku();
  digitalWrite(RTC_RST, LOW);
  return val;
}

void rtc_oku_zaman()  //===================================  rtc_oku_zaman  ==========================================
{  
  digitalWrite(RTC_RST, HIGH);
  rtc_kaydet(0xBF); // veri bloğu okuma modu

  byte ss_reg = rtc_oku();
  if (bitRead(ss_reg, 7)) {// saat durdu
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("RTC calismiyor");
    lcd.setCursor(0, 1);
    lcd.print("Saati ayarla");
    return; // TO DO
  }

  saniye = bcd2bin(ss_reg & 0x7F);
  dakika = bcd2bin(rtc_oku());
  saat = bcd2bin(rtc_oku());
  gun = bcd2bin(rtc_oku());
  ay = bcd2bin(rtc_oku());
  haf_gun = bcd2bin(rtc_oku());
  yil = bcd2bin(rtc_oku());
  digitalWrite(RTC_RST, LOW);
  
}

void initTimeDisplay() //========================================  initTimeDisplay  =========================================
{
  lcd.clear();
  lcd.setCursor(2, 0); lcd.print(':');
  lcd.setCursor(5, 0); lcd.print(':');
  lcd.setCursor(2, 1); lcd.print('.');
  lcd.setCursor(6, 1); lcd.print('.');
 // lcd.setCursor(11, 1); lcd.print('.');


   
}

void guncelleLCD() //========================================  guncelleLCD ===============================================
{
  rtc_oku_zaman();

  lcd.setCursor(3, 0);
  if (dakika < 10) lcd.print('0');
  lcd.print(dakika, DEC);

  lcd.setCursor(0, 0);
  if (saat < 10) lcd.print('0');
  lcd.print(saat, DEC);

  

  lcd.setCursor(0, 1);
  if (gun < 10) lcd.print('0');
  lcd.print(gun, DEC);

  
  lcd.setCursor(3, 1);
  lcd.print(ay_isimleri[ay]);
   

  lcd.setCursor(7, 1);
  lcd.print(yil + 2000, DEC);
 //lcd.print(yil , DEC);

  lcd.setCursor(12, 1);
  lcd.print(gun_isimleri[haf_gun]);
  
  //lcd.setCursor(0, 0); 
 //lcd.write(byte(0));//özel karakterimizi ekrana yazdırıyoruz========================================================
 // lcd.setCursor(15, 0); 
 //  al_etkin ? lcd.write(byte(0)) : lcd.print(' ');  
  // al_etkin ? lcd.print('*') : lcd.print(' ');
  //al_etkin ? lcd.write(byte(0)) : lcd.print(' '); 


    
}

void degiskenleriKur() {  //zaman ayarları ===============  degiskenleriKur  ================================================0
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Ayar");
  lcd.setCursor(0, 1);
  lcd.print("< >");

  rtc_yaz_reg(0x8E, 0x00);

  switch (ayarModu) {
    case 1: // year     
      lcd.setCursor(7, 0);
      lcd.print("Yil");
      lcd.setCursor(6, 1);
      lcd.print(yil + 2000, DEC);
      break;
    case 2: // month
      rtc_yaz_reg(0x8C, bin2bcd(yil));

      lcd.setCursor(7, 0);
      lcd.print("Ay");
      lcd.setCursor(6, 1);
      lcd.print(ay_isimleri[ay]);
      break;
    case 3: // day
      rtc_yaz_reg(0x88, bin2bcd(ay));

      lcd.setCursor(7, 0);
      lcd.print("Gun");
      lcd.setCursor(6, 1);
      if (gun < 10) lcd.print('0');
      lcd.print(gun, DEC);
      break;
    case 4: // day of week
      rtc_yaz_reg(0x86, bin2bcd(gun));

      lcd.setCursor(7, 0);
      lcd.print("Haf.Gunu");
      lcd.setCursor(6, 1);
      lcd.print(gun_isimleri[haf_gun]);
      break;
    case 5: // hour
      rtc_yaz_reg(0x8A, bin2bcd(haf_gun));

      lcd.setCursor(7, 0);
      lcd.print("Saat");
      lcd.setCursor(6, 1);
      if (saat < 10) lcd.print('0');
      lcd.print(saat, DEC);
      break;
    case 6: // minutes
      rtc_yaz_reg(0x84, bin2bcd(saat));

      lcd.setCursor(7, 0);
      lcd.print("Dakika");
      lcd.setCursor(6, 1);
      if (dakika < 10) lcd.print('0');
      lcd.print(dakika, DEC);
      break;
    case 7:
      rtc_yaz_reg(0x82, bin2bcd(dakika));
      rtc_yaz_reg(0x80, 0x00); // saatin durmadığından ve saniyeleri sıfırladığından emin ol
    default:
      ayarModu = 0;
      rtc_yaz_reg(0x8E, 0x80); // yazma koruması
      initTimeDisplay();
      
      guncelleLCD();  
        
  }
}  
void degiskenleriAyarla(char a = 1) //========================  degiskenleriAyarla ============================================
{
  lcd.setCursor(6, 1);
  lcd.print("    ");
  lcd.setCursor(6, 1);
  char t;

  switch (ayarModu) {
    case 1: // year
      t = yil; t += a;
      if ((t >= 0) && (t < 100)) yil = t;
      lcd.print(yil + 2000, DEC);
      break;
    case 2: // month
      t = ay; t += a;
      if ((t > 0) && (t <= 12)) ay = t;
      lcd.print(ay_isimleri[ay]);
      break;
    case 3: // day
      t = gun; t += a;
      if ((t > 0) && (t <= ay_gun_sayisi[ay])) gun = t;
      if (gun < 10) lcd.print('0');
      lcd.print(gun, DEC);
      break;
    case 4: // day of week
      t = haf_gun; t += a;
      if ((t > 0) && (t <= 7)) haf_gun = t;
      lcd.print(gun_isimleri[haf_gun]);
      break;
    case 5: // hour
      t = saat; t += a;
      if ((t >= 0) && (t < 24)) saat = t;
      if (saat < 10) lcd.print('0');
      lcd.print(saat, DEC);
      break;
    case 6: // minutes
      t = dakika; t += a;
      if ((t >= 0) && (t < 60)) dakika = t;
      if (dakika < 10) lcd.print('0');
      lcd.print(dakika, DEC);
      break;
  }

  switch (ayarAlarm) {  
    case 1: // enable
      al_etkin = 1 - al_etkin;
      al_etkin ? lcd.print("Evet ") : lcd.print("Hayir");  break;
    case 2: // hour
      t = al_saat; t += a;
      if ((t >= 0) && (t < 24)) al_saat = t;
      if (al_saat < 10) lcd.print('0');
      lcd.print(al_saat, DEC);
      break;
    case 3: // minutes
      t = al_dakika; t += a;
      if ((t >= 0) && (t < 60)) al_dakika = t;
      if (al_dakika < 10) lcd.print('0');
      lcd.print(al_dakika, DEC);
      break;
  }
}

void tumDegiskenleriAyarla() //============================  tumDegiskenleriAyarla  ===========================================
{
  lcd.clear();
  lcd.setCursor(0, 0);
  //lcd.print("Alarm");
  lcd.print(" ");
  lcd.write(byte(0));
  lcd.setCursor(0, 1);
  lcd.print("< >");

  rtc_yaz_reg(0x8E, 0x00);

  switch (ayarAlarm) {
    case 1: // alarm etkin
      lcd.setCursor(6, 0);
      lcd.print("Etkin");
      lcd.setCursor(6, 1);
      al_etkin ? lcd.print("Evet ") : lcd.print("Hayir");
      
      break;
    case 2: // alarm saat
      rtc_yaz_reg(0xC0, al_etkin);
      if (al_etkin == 0) { // devre dışı, al_saat ve al_dakika için sorma
        ayarAlarm = 0;
        rtc_yaz_reg(0x8E, 0x80); // yazma koruması
        initTimeDisplay();
        guncelleLCD();
        return;       
      }
      lcd.setCursor(6, 0);
      lcd.print("Saat");
      lcd.setCursor(6, 1);
      if (al_saat < 10) lcd.print('0');
      lcd.print(al_saat, DEC);
      break;
    case 3: // alarm dakika
      rtc_yaz_reg(0xC2, al_saat);

      lcd.setCursor(6, 0);
      lcd.print("Dakika");
      lcd.setCursor(6, 1);
      if (al_dakika < 10) lcd.print('0');
      lcd.print(al_dakika, DEC);
      break;
    case 4:
      rtc_yaz_reg(0xC4, al_dakika);
    default:
      ayarAlarm = 0;
      rtc_yaz_reg(0x8E, 0x80); // yazma koruması
      initTimeDisplay();
    
      guncelleLCD();
      
  }
}
void setup()   //============================ SETUP  ============================================== 
{
//rtc_yaz_reg(0xC0, 0);// dikkat   alarm aktif için sıfırlama
 sensors.begin(); 
     
  
  pinMode(LED1, OUTPUT); //led i ayarlıyoruz
  //Serial.begin(9600);
  
  pinMode(RTC_RST, OUTPUT);
  pinMode(RTC_CLK, OUTPUT);
  pinMode(RTC_DAT, INPUT);
  digitalWrite(RTC_RST, LOW);

  pinMode(BTN_AL, INPUT_PULLUP);
  pinMode(BTN_DN, INPUT_PULLUP);
  pinMode(BTN_UP, INPUT_PULLUP);
  pinMode(BTN_SET, INPUT_PULLUP);
   pinMode(BTN_AP, INPUT_PULLUP);
  pinMode(alarm_Buzz_Ses, OUTPUT);
  digitalWrite(alarm_Buzz_Ses, LOW);
  delay(1000);

  lcd.begin(16, 2);
     lcd.setBacklightPin(3,POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.createChar(0, karakter0); //özel karakterimizi lcd'ye yüklüyoruz========================================================
  lcd.createChar(1, karakter1); //özel karakterimizi lcd'ye yüklüyoruz========================================================
reklam();

  // get alarm info
  al_etkin = rtc_oku_reg(0xC1);
  al_saat = rtc_oku_reg(0xC3);
  al_dakika = rtc_oku_reg(0xC5);

  if ((al_saat > 23) || (al_dakika > 59)) {
    al_etkin = 0;
    al_saat = 0;
    al_dakika = 0;
  }
  
  initTimeDisplay();
  guncelleLCD();
}

void loop()    //==================================== ANA DÖNGÜ ===============================================
{
  unsigned long simdiki = millis();

  if ((simdiki >= timeUpdate + 1000) && (ayarModu + ayarAlarm == 0)) {
    if (saniye == 0) {
      guncelleLCD();
      if (al_etkin && (saat == al_saat) && (dakika == al_dakika)) alarmAktif = true;
      else alarmAktif = false;
    }
    // display seconds     (saniye göster)  
    
    lcd.setCursor(6, 0);
    if (saniye < 10) lcd.print('0');
    lcd.print(saniye, DEC);
    
    lcd.setCursor(9, 0); 
    al_etkin ? lcd.write(byte(0)) : lcd.print(' ');  
    //========================================= SERİ PORT EKRANI KONTROL BÖLÜMÜ ===================================================
    // isteğebağlı aktive edilip seri port ekranından kontrol edilebilir.
     /*   
      Serial.print("tarih: ");
      Serial.print(gun);
      Serial.print(":");
      Serial.print(ay);
      Serial.print(":");
      Serial.print(yil);
       
      Serial.print("  saat: ");
      
      Serial.print(saat);
      Serial.print(":");
      Serial.print(dakika);
      Serial.print(":");
      Serial.println(saniye);

      if (saat==14 && saniye==0)   Serial.println("alarma alarma alarma");
      if (saat==14 && saniye==20)  Serial.println("alarma alarma alarma");
      if (saat==14 && saniye==40)  Serial.println("alarma alarma alarma");
      */
   //========================================= SERİ PORT EKRANI KONTROL BÖLÜMÜ BİTTİ =================================================== 
sicaklik();
if (digitalRead(BTN_AP) == LOW) ekran_ac_kapa();

    // increment seconds  (saniye artışı)
    saniye++;
    if (saniye == 60) saniye = 0;
    timeUpdate = simdiki;     
  }
  if (simdiki >= zamanButon + 10) {
    if ((digitalRead(BTN_SET) == LOW) && (ayarAlarm == 0)) {
      butonBas = true;
      ayarModu++;
      degiskenleriKur();
    }
    if ((digitalRead(BTN_UP) == LOW) && (ayarModu || ayarAlarm)) {
      butonBas = true;
      degiskenleriAyarla(1);
    }
    if ((digitalRead(BTN_DN) == LOW) && (ayarModu || ayarAlarm)) {
      butonBas = true;
      degiskenleriAyarla(-1);
    }
    if ((digitalRead(BTN_AL) == LOW) && (ayarModu == 0)) {
      butonBas = true;
      if (alarmAktif) {
        alarmAktif = 0;
        digitalWrite(alarm_Buzz_Ses, LOW);
        lcd.setCursor(8, 0); lcd.print(" "); 
        lcd.setCursor(10, 0); lcd.print(" ");
      }
      else {
        ayarAlarm++;
        tumDegiskenleriAyarla();
      }
    }
    zamanButon = simdiki;
    if (butonBas) {
      zamanButon += 200; // 200 ms tuş basma araları
      butonBas = false;
    }
  }
  if (simdiki >= zamanAlarm + 300) {
    if (alarmAktif) { 
    lcd.setBacklight(HIGH);  // Alarm çalarken LCD arka plan ışığı kapalıysa açar
    bep_bep();               // alarm sesi
     // digitalWrite(alarm_Buzz_Ses, alarmSw);
      lcd.setCursor(8, 0);
      alarmSw ? lcd.print("<") : lcd.print(" ");
      lcd.setCursor(10, 0);
      alarmSw ? lcd.print(">") : lcd.print(" ");
      alarmSw = 1 - alarmSw;
      zamanAlarm = simdiki;
    }
    else
      digitalWrite(alarm_Buzz_Ses, LOW);       
      digitalWrite(LED_BUILTIN, LOW);//digital 13 deki led i söndür
  }


}
void reklam()    //================ GİRİŞ EKRANI === REKLAM ===============================================                  
{
  lcd.setCursor(0, 0);
lcd.print("  Kodla Gitsin  ");
lcd.setCursor(0, 1);
lcd.print("US-EL Electronic");
delay(1000);
lcd.setCursor(0, 0);
lcd.print("                ");
lcd.setCursor(0, 1);
lcd.print("                ");
  }
  void ekran_ac_kapa(){   //alarmı durdur, lcd ışığını aç/kapat

if ((digitalRead(BTN_AP) == LOW) && (ayarModu == 0)) {
        butonBas = true;
  if (alarmAktif) {
        alarmAktif = 0;
        digitalWrite(alarm_Buzz_Ses, LOW);
        lcd.setCursor(8, 0); lcd.print(" ");  //alarmı kapatınca sinyali silme
        lcd.setCursor(10, 0); lcd.print(" "); //alarmı kapatınca sinyali silme
          alarmAktif = 0;
         BTN_AP==HIGH;
        //delay(3000);    
      }
  else{
      switch (secim) {
            case 1: // alarm enabled
                   lcd.setBacklight(LOW);
                   secim=secim+1;
            break;
            case 2: // alarm enabled
                   lcd.setBacklight(HIGH);
                   secim=1;    
            break;   }     }     }   
 }
    void bep_bep(){     // alarm sesi
      //alarm bep bep
        digitalWrite(LED1, HIGH); //digital 13 deki led i yak      
    tone(alarm_Buzz_Ses, 2000, 250); //1000...2000 ton       250...1000 süre
    delay(250);  //duraklama
    digitalWrite(alarm_Buzz_Ses, LOW);
    digitalWrite(LED1, LOW);
    delay(500);  
      }

      void sicaklik(){   // sıcaklık sensörü oku/yaz
  sensors.requestTemperatures(); // Sıcaklık değerleri almak için hattaki cihazlara sıcaklık talep komutu gönderiliyor
   // Aynı veriyolunda birden fazla DS18B20 bulunabilir..  
   // ByIndex(0), hattaki ilk IC'yi ifade eder...ByIndex(1)...ByIndex(2)...
  lcd.setCursor(11, 0);
  lcd.print(sensors.getTempCByIndex(0)+27,1); // <== 27 değeri normalde yok/benim ds18B20 arızalıolduğu için deneme-yanılma ile bu değeri ekledim <==
  lcd.write(byte(1));
        }

    
KULLANILAN PROGRAMLAR: Arduino Ide 1.8.9

Yorumlar