Arduino ile zaman ayarlı çalar saat projesi

EPI PXyer

Hectopat
Katılım
29 Mayıs 2022
Mesajlar
173
Çözümler
1
Daha fazla  
Sistem Özellikleri
i7 12650h
RTX4050
16gb ram
512gb ssd
Cinsiyet
Erkek
Meslek
Elektronik
XL6009, DS3231, 4 ohm 10W 2 adet hoparlör, pot ile pam8610, dfplayer, Arduino Nano, IP5310, TM1637, iki tane 3000 mAh 18650 pil.

Ben bir proje yapıyorum.
Bu proje hem saati gösterecek hem de sıcaklığı ayrıca ayarlanan saatte alarm çalacak. Ve birçok fonkiyon olmasını istiyorum bunun içinde Arduino Nano kullanacağız.
Malzemeler:
  • 2 adet 18650 vtc6 pil.
  • 2'li paralel pil yatağı.
  • IP5310.
  • X6009e1.
  • DS3231.
  • Tm1637.
  • Arduino Nano.
  • Dfplayer.
  • Potansiyometreli pam8610.
  • 2 adet 4ohm 10W 75mm çapında.

Devrede kullanılacak malzemeler bunlar.

2 adet paralel bağlı vtc6 3.7v pil 'IP5310' tarafından Type-C yoluyla şarj edilecek.
Piller 3.7v olsa bile IP5310 modülü 5V çıkış verebiliyor.
IP5310 modülünden çıkış alıp 'XL6009E1' modüle gireceğiz burada 5Volt'u, 12volt yapacağız. Voltajın sağlığı için Boost konvertör çıkışına 680mikro farad 35v kondansatör ve 104 kodlu seramik kondansatör kullanacağım.
Boost konvertör çıkışından alacağımız voltaj ile PAM8610 modülü besleyeceğiz.

Tekrardan IP5310 modülüne dönelim. Tekrardan IP5310 modülünden çıkış alıp 5 volt ile çoklu sıralı klemense enerji vereceğiz (her bir sıralı klemens birbirine köprülü) bu arada vcc hattı için 5 klemens, gnd hattı için 5 klemens kullanacağım.
IP5310 modülünden aldığımız 5V ve gnd çıkışını klemenslere bağlayacağız. ( 5V hattı vcc klemensine, gnd hattı ise gnd klemensine).

Daha sonra sırasıyla.
+ DS3231.
+TM1637
+Dfplayer
+Arduino Nano.

Bu birimlerin vcc ve gnd hattı klemenslerden bağlantı yapılarak beslenecek. Ayrıca diğer bilgi ve analog pinleri Arduino'ya bağlanacak.

Dfplayer'den çıkacak DAC-l ve DAC-r bacakları PAM8610 modülüne girecek. İki adet hoparlör de pam8610'dan beslenecek.

Şimdi devrede istenilen şeylere gelelim:

TM1637 modülünde saat ve sıcaklık gösterilmesini istiyorum. 5 saniye saat gösterilirken 3 saniye sıcaklığı göstermesini istiyorum. (24'lü saat birimi kullanılacak ayrıca sıcaklık birimi derece olsun )

Aynı zamanda devrede 3 adet buton kullanılacak bu botunlar sırasıyla.
+Mod
+Up
+Down

Mod butonuna ilk defa basıldığında saat kısmı yanıp sönmeye başlayacak örneğin: ( --: 24 ) gibisinden ve daha sonra up veya down butonları ile yukarı ya da aşağı saat ayarı yapılabilecek.

Daha sonra tekrar mod butonuna basılınca dakika kısmı yanıp sönmeye başlayacak. Dakika kısmını da up veya down butonuyla ayarlayabileceğiz.

3.defa mod butonuna tıklayınca ayarladığımız saat kaydedilecek.

+ Ayarlanan saat geldiğinde iki adet hoparlörden alarm çalacak.

Dfplayer içerisinde bulunan SD karta 4 adet ses dosyası atılacak. Alarm vakti geldiğinde hangisi seçili ise o alarm çalacak.

Mod butonuna 3 saniye basıldığında sıradaki alarm seçilsin. Örneğin: (0001.MP3, 0002.MP3, 0003.MP3, 0004.MP3 )

Bizde 0001.MP3 dosyası seçili ise mod butonuna 3 saniye basılı tutunca 0002.MP3 dosyası seçilsin. Seçildiğinde anlamamız için ekranda AL2 yazsın yani 2.alarm aktifse al2. üçüncü alarm aktifse AL3 gibi.

Alarm çalarken ekran fade efektiyle maximum ve minimum şekilde 1sn aralıkla yanıp sönecek.

Ve alarm bittiğinde ekran parlaklığı sabit 5 değerinde yanacak.

Alarm için 2 dk süre vermiştik. Fakat 2 dakika içerisinde alarmın 15 saniye çalıp 2 sn susmasını istiyorum ve 2 dakika boyunca bu şekilde döngüde olacak. Alarm bittiğinde her şey normale dönecek. Saat ve sıcaklık DS3231 modülü tarafından gösterilecek.

Bu tüm fonksiyonların Arduino'nun EEPROM belleğine yazdıracağız ki bilgiler sistem kapandıktan sonra silinmesin. Ayrıca güç tasarrufu için IP5310 modülünün b+ girişine bir adet on-off
Switch koyacağım. Tüm sistem 2 adet paralel vtc6 ile beslenecek.

Arkadaşlar asıl olay şimdi başlıyor bu projede iki adet paralel bağlı vtc6 pil kullandım dedim fakat TP4056 ile şarj etmeye çalıştığım an TP4056 cayır cayır yanmaya başlıyor nedenini anlamadım ve iki pilin zorlanacağını asla düşünmedim ve iki pilin de voltajlarını sabitleyip o şekilde de denedim ama durum değişmedi maalesef şarj modülünü değişmeye karar verdim gidip IP5310 şarj modülü satın aldım ve onunla deneyeceğim. Ayrıca 5V 3a çıkış verebildiği için Arduino Nano dahil (DS3231, TM1637, dfplayer ) IP5310'dan beslenecek. Sizce sistem işleyişi iyi mi yoksa verilebilecek tavsiye var mı?

Kod kısmında berbat olduğum için haliyle chatgpt'den yardım aldım sistemi size yazdığım şekilde ona da yazıp gönderdim o da tüm herşeyi dikkate alarak bir kod yazdı :

#include <Wire.h>
#include <RTClib.h>
#include <TM1637Display.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <EEPROM.h>

#define CLK 2
#define DIO 3
#define UP_BUTTON 4
#define DOWN_BUTTON 5
#define MOD_BUTTON 6

#define MAX_ALARM_SAYISI 5

TM1637Display display(CLK, DIO);
RTC_DS3231 rtc;

SoftwareSerial mySoftwareSerial(7, 8); // RX, TX
DFRobotDFPlayerMini mp3;

// EEPROM adresleri
#define ALARM_HOUR_ADDR 0
#define ALARM_MINUTE_ADDR 1
#define SELECTED_ALARM_ADDR 2

int alarmHour = 7;
int alarmMinute = 0;
int seciliAlarmNo = 1;
bool alarmCaliyor = false;
bool alarmSesliMi = false;
unsigned long alarmBaslangicZamani = 0;
unsigned long alarmDuruZamani = 0;
unsigned long alarmEkranGostermeZamani = 0;

// Buton kontrolü
unsigned long debounceDelayMod = 20;
unsigned long debounceDelayUpDown = 30;
int lastModState = HIGH, lastUpState = HIGH, lastDownState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long modButtonPressTime = 0;
bool modLongPressHandled = false;

// Alarm Ayarları
bool saatAyariYapiliyor = false;
bool dakikaAyariYapiliyor = false;
unsigned long sonModButtonPressTime = 0;

void setup() {
Serial.begin(9600);
display.setBrightness(5);

if (!rtc.begin()) {
Serial.println("RTC modülü bulunamadı");
while (1);
}

// rtc.adjust(DateTime(2025, 5, 10, 12, 45, 0)); // Gerekirse saat ayarı

if (!mp3.begin(mySoftwareSerial)) {
Serial.println("DFPlayer başlatılamadı");
while (1);
}

pinMode(UP_BUTTON, INPUT_PULLUP);
pinMode(DOWN_BUTTON, INPUT_PULLUP);
pinMode(MOD_BUTTON, INPUT_PULLUP);

alarmHour = EEPROM.read(ALARM_HOUR_ADDR);
alarmMinute = EEPROM.read(ALARM_MINUTE_ADDR);
seciliAlarmNo = EEPROM.read(SELECTED_ALARM_ADDR);
if (seciliAlarmNo < 1 || seciliAlarmNo > MAX_ALARM_SAYISI) seciliAlarmNo = 1;
}

void loop() {
butonKontrol();
alarmKontrol();
ekranGuncelle();
}

void butonKontrol() {
int modState = digitalRead(MOD_BUTTON);
int upState = digitalRead(UP_BUTTON);
int downState = digitalRead(DOWN_BUTTON);

unsigned long suan = millis();

if (modState == LOW) {
if (modButtonPressTime == 0) modButtonPressTime = suan;

if ((suan - modButtonPressTime > 3000) && !modLongPressHandled) {
seciliAlarmNo = (seciliAlarmNo % MAX_ALARM_SAYISI) + 1;
EEPROM.write(SELECTED_ALARM_ADDR, seciliAlarmNo);
Serial.print("Alarm değiştirildi: AL");
Serial.println(seciliAlarmNo);

String alarmStr = "AL" + String(seciliAlarmNo);
uint8_t seg[4] = {0};
encodeStringManual(alarmStr, seg);
display.setSegments(seg);
delay(1000);

modLongPressHandled = true;
}
} else {
modButtonPressTime = 0;
modLongPressHandled = false;
}

if (modState == LOW && lastModState == HIGH && suan - lastDebounceTime > debounceDelayMod) {
if (saatAyariYapiliyor) {
saatAyariYapiliyor = false;
EEPROM.write(ALARM_HOUR_ADDR, alarmHour);
EEPROM.write(ALARM_MINUTE_ADDR, alarmMinute);
Serial.println("Alarm saati kaydedildi.");
} else if (dakikaAyariYapiliyor) {
dakikaAyariYapiliyor = false;
EEPROM.write(ALARM_HOUR_ADDR, alarmHour);
EEPROM.write(ALARM_MINUTE_ADDR, alarmMinute);
Serial.println("Alarm dakikası kaydedildi.");
} else {
saatAyariYapiliyor = true;
}
lastDebounceTime = suan;
}
lastModState = modState;

if (upState == LOW && lastUpState == HIGH && suan - lastDebounceTime > debounceDelayUpDown) {
if (saatAyariYapiliyor) {
alarmHour = (alarmHour + 1) % 24;
display.showNumberDecEx(alarmHour * 100 + alarmMinute, 0b11100000, true);
} else if (dakikaAyariYapiliyor) {
alarmMinute = (alarmMinute + 1) % 60;
display.showNumberDecEx(alarmHour * 100 + alarmMinute, 0b11100000, true);
}
lastDebounceTime = suan;
}
lastUpState = upState;

if (downState == LOW && lastDownState == HIGH && suan - lastDebounceTime > debounceDelayUpDown) {
if (saatAyariYapiliyor) {
alarmHour = (alarmHour - 1 + 24) % 24;
display.showNumberDecEx(alarmHour * 100 + alarmMinute, 0b11100000, true);
} else if (dakikaAyariYapiliyor) {
alarmMinute = (alarmMinute - 1 + 60) % 60;
display.showNumberDecEx(alarmHour * 100 + alarmMinute, 0b11100000, true);
}
lastDebounceTime = suan;
}
lastDownState = downState;
}

void alarmKontrol() {
DateTime now = rtc.now();

if (!alarmCaliyor && now.hour() == alarmHour && now.minute() == alarmMinute && now.second() == 0) {
alarmCaliyor = true;
alarmBaslangicZamani = millis();
alarmDuruZamani = millis();
alarmEkranGostermeZamani = millis();
mp3.play(seciliAlarmNo);
}

if (alarmCaliyor) {
unsigned long suan = millis();

if (suan - alarmBaslangicZamani < 120000) {
if (suan - alarmDuruZamani >= (alarmSesliMi ? 15000 : 2000)) {
if (alarmSesliMi) {
mp3.stop();
} else {
mp3.play(seciliAlarmNo);
}
alarmSesliMi = !alarmSesliMi;
alarmDuruZamani = suan;
}
} else {
mp3.stop();
alarmCaliyor = false;
display.setBrightness(5);
}
}
}

void ekranGuncelle() {
DateTime now = rtc.now();
unsigned long suan = millis();

if (alarmCaliyor && suan - alarmEkranGostermeZamani < 10000) {
String alarmStr = "AL" + String(seciliAlarmNo);
uint8_t seg[4] = {0};
encodeStringManual(alarmStr, seg);
display.setSegments(seg);
} else {
display.showNumberDecEx(now.hour() * 100 + now.minute(), 0b01000000, true);
}
}

// 'A', 'L', '1' gibi karakterleri 7 segment'e çevir
void encodeStringManual(String str, uint8_t seg[4]) {
for (int i = 0; i < 4; i++) {
char c = (i < str.length()) ? str : ' ';
switch (c) {
case 'A': seg = 0b01110111; break;
case 'L': seg = 0b00111000; break;
case '0': seg = display.encodeDigit(0); break;
case '1': seg = display.encodeDigit(1); break;
case '2': seg = display.encodeDigit(2); break;
case '3': seg = display.encodeDigit(3); break;
case '4': seg = display.encodeDigit(4); break;
case '5': seg = display.encodeDigit(5); break;
case '6': seg = display.encodeDigit(6); break;
case '7': seg = display.encodeDigit(7); break;
case '8': seg = display.encodeDigit(8); break;
case '9': seg = display.encodeDigit(9); break;
default: seg = 0x00; break;
}
}
}

Bu kodlarda bir hata yok ama yine de eksik var mı bilmiyorum anlayan bir arkadaş yardım ederse sevinirim saygılar..
 
Son düzenleme:
Bu siteyi kullanmak için çerezler gereklidir. Siteyi kullanmaya devam etmek için çerezleri kabul etmelisiniz. Daha Fazlasını Öğren.…