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
Yorum Gönder