#define namaSekolah "Nama Sekolah"
#define SQWPin A3
#define pinRelay 8
#define relayOn LOW
#include <avr/sleep.h>
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>
#include "RTC.h"
#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define tokenEEPROM 0x83
SoftwareSerial bluetooth(2, 3);
SoftwareSerial mp3Serial(4, 5);
LiquidCrystal_I2C lcd(0x3F, 16, 2);
struct
Waktu
{
byte jam;
byte menit;
};
struct
TabelMataPelajaran
{
byte aktif;
Waktu waktu;
byte hariAktif;
byte mingguAktif;
byte kegiatan;
};
const
char
kegiatanText[][17] PROGMEM = {
"- "
,
"Jam Pelajaran 1 "
,
"Jam Pelajaran 2 "
,
"Jam Pelajaran 3 "
,
"Jam Pelajaran 4 "
,
"Jam Pelajaran 5 "
,
"Jam Pelajaran 6 "
,
"Jam Pelajaran 7 "
,
"Jam Pelajaran 8 "
,
"Jam Pelajaran 9 "
,
"Jam Pelajaran 10"
,
"Jam Pelajaran 11"
,
"Jam Pelajaran 12"
,
"Jam Pelajaran 13"
,
"Jam Pelajaran 14"
,
"Jam Pelajaran 15"
,
"Masuk "
,
"Upacara "
,
"Istirahat "
,
"Istirahat1 "
,
"Istirahat2 "
,
"Istirahat3 "
,
"Selesai istiraht"
,
"Kepramukaan "
,
"Khusus "
,
"Pulang "
,
"Pulang Jum'at "
,
"Pulang Sabtu "
,
"Musik 1 "
,
"Musik 2 "
,
"Musik 3 "
,
"Musik 4 "
,
"Musik 5 "
,
"Musik 6 "
,
"Hadits 1 "
,
"Hadits 2 "
,
"Hadits 3 "
,
"Hadits 4 "
,
"Hadits 5 "
,
"Hadits 6 "
,
};
enum
_kegiatan
{
TidakAda,
JamPelajaran1,
JamPelajaran2,
JamPelajaran3,
JamPelajaran4,
JamPelajaran5,
JamPelajaran6,
JamPelajaran7,
JamPelajaran8,
JamPelajaran9,
JamPelajaran10,
JamPelajaran11,
JamPelajaran12,
JamPelajaran13,
JamPelajaran14,
JamPelajaran15,
Masuk,
Upacara,
Istirahat,
Istirahat1,
Istirahat2,
Istirahat3,
SelesaiIstirahat,
Kepramukaan,
Khusus,
Pulang,
PulangJumat,
PulangSabtu,
Musik1,
Musik2,
Musik3,
Musik4,
Musik5,
Musik6,
Hadits1,
Hadits2,
Hadits3,
Hadits4,
Hadits5,
Hadits6,
};
enum
PengaturanAndroid
{
cekAses,
pengaturanJadwal,
pengaturanWaktu,
};
char
karakterMusik[8] = {
0b00000,
0b00100,
0b00110,
0b00101,
0b00101,
0b00100,
0b11100,
0b11100
};
byte karakterDetik1[8] = {
0b00000,
0b00000,
0b00000,
0b00100,
0b00000,
0b00000,
0b00000,
0b00000
};
byte karakterDetik2[8] = {
0b00000,
0b00000,
0b00100,
0b01010,
0b00100,
0b00000,
0b00000,
0b00000
};
byte karakterDetik3[8] = {
0b00000,
0b00100,
0b01010,
0b10001,
0b01010,
0b00100,
0b00000,
0b00000
};
byte karakterSetting[8] = {
0b00100,
0b00100,
0b00100,
0b01110,
0b00100,
0b10001,
0b01010,
0b00100
};
volatile
bool
interupsiDetik;
byte indexMataPelajaran;
RTC_DS3231 rtc;
DateTime now;
bool
rtcValid;
byte indexPengaturanJadwal = 0;
#define hariAktifSenin 1<<6
#define hariAktifSelasa 1<<5
#define hariAktifRabu 1<<4
#define hariAktifKamis 1<<3
#define hariAktifJumat 1<<2
#define hariAktifSabtu 1<<1
#define hariAktifMinggu 1<<7
char
namaHari[][7] = {
"Minggu"
,
"Senin"
,
"Selasa"
,
"Rabu"
,
"Kamis"
,
"Jum'at"
,
"Sabtu"
};
#define _hariAktif(Sen,Sel,Rab,Kam,Jum,Sab,Mgu) (Mgu<<7)|(Sen<<6)|(Sel<<5)|(Rab<<4)|(Kam<<3)|(Jum<<2)|(Sab<<1)
#define _mingguAktif(Mgu1,Mgu2,Mgu3,Mgu4,Mgu5,Mgu6) (Mgu1<<7)|(Mgu2<<6)|(Mgu3<<5)|(Mgu4<<4)|(Mgu5<<3)|(Mgu6<<2)
#define _waktu(Jam, Menit) {Jam, Menit}
#define Aktif 1
#define TidakAktif 0
TabelMataPelajaran jadwalBelajar[40];
Waktu waktu;
char
bufWaktu[40];
byte detikSebelumnya = 60;
byte tanggalSebelumnya = 0;
Waktu jadwalBerikutnya;
byte menitBel;
bool
statusBel;
bool
statusPengingat;
byte jadwalBerikutnyaKegiatan;
void
setup() {
digitalWrite(pinRelay, !relayOn);
pinMode(pinRelay, OUTPUT);
pinMode(SQWPin, INPUT_PULLUP);
Serial.begin(9600);
Serial.println(F(
"Bel Sekolah Dengan Kontrol Android"
));
Serial.println();
Wire.begin();
Wire.beginTransmission(0x3F);
if
(Wire.endTransmission())
{
lcd = LiquidCrystal_I2C(0x27, 16, 2);
}
lcd.begin();
lcd.command (0x40 | (0 << 3));
for
(byte i = 0; i < 8; i++)
lcd.write (karakterDetik1[i]);
lcd.command (0x40 | (1 << 3));
for
(byte i = 0; i < 8; i++)
lcd.write (karakterDetik2[i]);
lcd.command (0x40 | (2 << 3));
for
(byte i = 0; i < 8; i++)
lcd.write (karakterDetik3[i]);
lcd.command (0x40 | (3 << 3));
for
(byte i = 0; i < 8; i++)
lcd.write (karakterDetik2[i]);
lcd.command (0x40 | (4 << 3));
for
(byte i = 0; i < 8; i++)
lcd.write (karakterMusik[i]);
lcd.command (0x40 | (5 << 3));
for
(byte i = 0; i < 8; i++)
lcd.write (karakterSetting[i]);
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print(
"Bel Sekolah"
);
lcd.setCursor(0, 1);
lcd.print(namaSekolah);
mp3Serial.begin(9600);
bluetooth.begin (9600);
bluetooth.listen();
mp3_set_serial (mp3Serial);
mp3_set_volume (15);
rtc.begin();
if
(rtc.lostPower())
{
Serial.println(F(
"RTC lost power, lets set the time!"
));
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
rtc.writeSqwPinMode(DS3231_SquareWave1Hz);
if
(EEPROM.read(
sizeof
(jadwalBelajar)) != tokenEEPROM)
{
nilaiAwal();
EEPROM.write(
sizeof
(jadwalBelajar), tokenEEPROM);
Serial.println(
"setting awal"
);
}
EEPROM.get(0, jadwalBelajar);
cekJadwalHariIni();
delay(1000);
lcd.clear();
Serial.println(F(
"Sistem bel sekolah dimulai"
));
}
void
loop() {
if
(digitalRead(SQWPin))
{
if
(rtcValid)
{
rtcValid =
false
;
now = rtc.now();
uint16_t
unixJadwalBerikutnya = (jadwalBerikutnya.jam * 60) + jadwalBerikutnya.menit;
uint16_t
unixWaktu = (now.jam * 60) + now.menit;
if
(!now.detik)
{
if
(jadwalBerikutnyaKegiatan && (jadwalBerikutnya.jam == now.jam) && (jadwalBerikutnya.menit == now.menit))
{
lcd.setCursor(6, 1);
lcd.print((
char
)4);
lcd.setCursor(0, 0);
lcd.print((__FlashStringHelper *)kegiatanText[jadwalBerikutnyaKegiatan]);
mp3_play (jadwalBerikutnyaKegiatan);
Serial.println((__FlashStringHelper *)kegiatanText[jadwalBerikutnyaKegiatan]);
menitBel = jadwalBerikutnya.menit;
statusBel =
true
;
statusPengingat =
false
;
}
else
if
(jadwalBerikutnyaKegiatan && (unixWaktu == unixJadwalBerikutnya - 1))
{
statusPengingat =
true
;
digitalWrite(pinRelay, relayOn);
Serial.println(
"Pengingat bel masuk 1 menit lagi"
);
}
}
if
(menitBel != now.menit)
{
if
(statusBel)
{
lcd.setCursor(6, 1);
lcd.print(
' '
);
digitalWrite(pinRelay, !relayOn);
cariJadwal();
statusBel =
false
;
tanggalSebelumnya = 0;
}
}
if
(statusPengingat)
{
lcd.setCursor(1, 1);
if
(now.detik % 2)
{
sprintf
(bufWaktu,
"%02d:%02d"
, jadwalBerikutnya.jam, jadwalBerikutnya.menit);
lcd.print(bufWaktu);
}
else
{
lcd.print(
" "
);
}
}
if
(detikSebelumnya != now.detik)
{
sprintf
(bufWaktu,
"%02d:%02d:%02d"
, now.jam, now.menit, now.detik);
lcd.setCursor(8, 1);
lcd.print(bufWaktu);
lcd.setCursor(0, 1);
lcd.print((
char
)(now.detik % 4));
sprintf
(bufWaktu,
"%02d:%02d:%02d %s, %02d/%02d/%02d"
, now.jam, now.menit, now.detik, namaHari[now.hari - 1], now.tanggal, now.bulan, now.tahun - 2000);
Serial.println(bufWaktu);
}
if
(tanggalSebelumnya != now.tanggal)
{
tanggalSebelumnya = now.tanggal;
lcd.clear();
lcd.print(namaHari[now.hari - 1]);
lcd.print(
','
);
sprintf
(bufWaktu,
"%02d/%02d/%02d"
, now.tanggal, now.bulan, now.tahun - 2000);
lcd.setCursor(8, 0);
lcd.print(bufWaktu);
cariJadwal();
}
}
}
else
{
rtcValid =
true
;
}
cekBluetooth();
}
void
cekBluetooth()
{
uint8_t
tokenMulai;
uint8_t
perintah;
uint8_t
parameter;
uint8_t
panjang1;
uint8_t
panjang2;
char
c;
uint8_t
i, j;
uint8_t
tokenSelesai;
byte bufferSerial[100];
byte *alamat;
if
(bluetooth.available())
{
tokenMulai = bluetoothRead();
if
(tokenMulai == 0xFD)
{
panjang1 = bluetoothRead();
panjang2 = bluetoothRead();
if
(panjang2 == 254 - panjang1)
{
if
(panjang1 >=
sizeof
(bufferSerial))
{
panjang1 =
sizeof
(bufferSerial);
}
uint16_t
timeOut = 0xFFF;
i = 0;
do
{
if
(bluetooth.available())
{
c = bluetoothRead();
bufferSerial[i++] = c;
}
}
while
((i < panjang1 + 3) && (timeOut--));
perintah = bufferSerial[0];
parameter = bufferSerial[1];
tokenSelesai = bufferSerial[i - 1];
if
(tokenSelesai == 0x00)
{
delay(10);
bluetooth.write(254);
switch
(perintah)
{
case
cekAses:
bluetooth.write(1);
bluetooth.write(254);
break
;
case
pengaturanJadwal:
lcd.setCursor(6, 1);
lcd.print((
char
)5);
memcpy
((byte*)&jadwalBelajar[parameter], bufferSerial + 2,
sizeof
(TabelMataPelajaran));
if
(parameter == (
sizeof
(jadwalBelajar) /
sizeof
(TabelMataPelajaran)) - 1)
{
EEPROM.put(0, jadwalBelajar);
Serial.println(
"Jadwal diterima"
);
lcd.setCursor(6, 1);
lcd.print(
' '
);
tanggalSebelumnya = 0;
}
break
;
case
pengaturanWaktu:
memcpy
((byte*)&now, bufferSerial + 2,
sizeof
(DateTime));
rtc.adjust(now);
tanggalSebelumnya = 0;
Serial.println(
"Setting waktu diterima"
);
break
;
}
}
else
{
bluetooth.write(252);
}
}
}
}
}
byte bluetoothRead()
{
uint16_t
timeOut = 0xFFF;
while
(!bluetooth.available() && timeOut--);
return
bluetooth.read();
}
void
nilaiAwal()
{
byte i = 0;
jadwalBelajar[i++] = {Aktif, _waktu( 6, 45 ), hariAktifSenin , _mingguAktif(1, 0, 0, 0, 0, 0), Upacara};
jadwalBelajar[i++] = {Aktif, _waktu( 6, 45 ), hariAktifSenin , _mingguAktif(0, 1, 1, 1, 1, 1), JamPelajaran1};
jadwalBelajar[i++] = {Aktif, _waktu( 6, 45 ), _hariAktif(0, 1, 1, 1, 1, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran1};
jadwalBelajar[i++] = {Aktif, _waktu( 7, 30 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran2};
jadwalBelajar[i++] = {Aktif, _waktu( 8, 15 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran3};
jadwalBelajar[i++] = {Aktif, _waktu( 9, 0 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran4};
jadwalBelajar[i++] = {Aktif, _waktu( 9, 45 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), Istirahat};
jadwalBelajar[i++] = {Aktif, _waktu( 10, 15 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran5};
jadwalBelajar[i++] = {Aktif, _waktu( 11, 0 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran6};
jadwalBelajar[i++] = {Aktif, _waktu( 11, 45 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), Istirahat};
jadwalBelajar[i++] = {Aktif, _waktu( 12, 30 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran7};
jadwalBelajar[i++] = {Aktif, _waktu( 13, 15 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran8};
jadwalBelajar[i++] = {Aktif, _waktu( 14, 0 ), _hariAktif(1, 1, 1, 0, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran9};
jadwalBelajar[i++] = {Aktif, _waktu( 14, 45 ), _hariAktif(1, 1, 1, 0, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran10};
jadwalBelajar[i++] = {Aktif, _waktu( 14, 0 ), hariAktifKamis, _mingguAktif(1, 1, 1, 1, 1, 1), Kepramukaan};
jadwalBelajar[i++] = {Aktif, _waktu( 14, 45 ), hariAktifKamis, _mingguAktif(1, 1, 1, 1, 1, 1), Khusus};
jadwalBelajar[i++] = {Aktif, _waktu( 15, 30 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1, 1), Pulang};
jadwalBelajar[i++] = {Aktif, _waktu( 7, 25 ), hariAktifJumat, _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran2};
jadwalBelajar[i++] = {Aktif, _waktu( 8, 5 ), hariAktifJumat, _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran3};
jadwalBelajar[i++] = {Aktif, _waktu( 8, 45 ), hariAktifJumat, _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran4};
jadwalBelajar[i++] = {Aktif, _waktu( 9, 25 ), hariAktifJumat, _mingguAktif(1, 1, 1, 1, 1, 1), Istirahat};
jadwalBelajar[i++] = {Aktif, _waktu( 9, 55 ), hariAktifJumat, _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran5};
jadwalBelajar[i++] = {Aktif, _waktu( 10, 35 ), hariAktifJumat, _mingguAktif(1, 1, 1, 1, 1, 1), JamPelajaran6};
jadwalBelajar[i++] = {Aktif, _waktu( 11, 15 ), hariAktifJumat, _mingguAktif(1, 1, 1, 1, 1, 1), PulangJumat};
EEPROM.put(0, jadwalBelajar);
}
void
cekJadwalHariIni()
{
Serial.println(
"Jadwal hari ini"
);
for
(byte i = 0; i <
sizeof
(jadwalBelajar) /
sizeof
(TabelMataPelajaran) ; i++)
{
Serial.print(jadwalBelajar[i].aktif);
Serial.print(
'\t'
);
Serial.print(jadwalBelajar[i].waktu.jam);
Serial.print(
'\t'
);
Serial.print(jadwalBelajar[i].waktu.menit);
Serial.print(
'\t'
);
Serial.print(jadwalBelajar[i].hariAktif, HEX);
Serial.print(
'\t'
);
Serial.print(jadwalBelajar[i].mingguAktif, HEX);
Serial.print(
'\t'
);
Serial.print(jadwalBelajar[i].kegiatan);
Serial.print(
'\t'
);
char
buf[20];
memcpy_P(buf, kegiatanText[jadwalBelajar[i].kegiatan],
sizeof
(kegiatanText[0]));
Serial.print(buf);
Serial.println();
}
}
void
cariJadwal()
{
uint16_t
unixWaktu = (now.jam * 60) + now.menit;
byte hariKeDiTanggal1 = ((now.hari + 7 - (now.tanggal % 7)) % 7) + 1;
byte SeninKe = ((now.tanggal + ((hariKeDiTanggal1 + 4) % 7)) / 7);
byte mingguKe = ((now.tanggal + hariKeDiTanggal1 + 6 - 1) / 7);
Serial.print(
"SeninKe = "
);
Serial.println(SeninKe);
Serial.print(
"mingguKe = "
);
Serial.println(mingguKe);
uint16_t
unixTerkecil = UINT16_MAX;
jadwalBerikutnyaKegiatan = 0;
Waktu waktuTerkecil;
for
(byte i = 0; i <
sizeof
(jadwalBelajar) /
sizeof
(TabelMataPelajaran); i++)
{
if
(
(jadwalBelajar[i].aktif) &&
(jadwalBelajar[i].hariAktif & (1 << (8 - now.hari))) &&
(jadwalBelajar[i].mingguAktif & (1 << (8 - mingguKe)))
)
{
uint16_t
unixJadwal = (jadwalBelajar[i].waktu.jam * 60) + jadwalBelajar[i].waktu.menit;
if
(unixWaktu < unixJadwal)
{
if
(unixTerkecil > unixJadwal)
{
unixTerkecil = unixJadwal;
jadwalBerikutnya.jam = jadwalBelajar[i].waktu.jam;
jadwalBerikutnya.menit = jadwalBelajar[i].waktu.menit;
jadwalBerikutnyaKegiatan = jadwalBelajar[i].kegiatan;
}
}
}
}
if
(jadwalBerikutnyaKegiatan)
{
Serial.print(
"Bel berikutnya : "
);
Serial.print((__FlashStringHelper *)kegiatanText[jadwalBerikutnyaKegiatan]);
Serial.print(
" "
);
Serial.print(jadwalBerikutnya.jam);
Serial.print(
":"
);
Serial.println(jadwalBerikutnya.menit);
lcd.setCursor(1, 1);
sprintf
(bufWaktu,
"%02d:%02d"
, jadwalBerikutnya.jam, jadwalBerikutnya.menit);
lcd.print(bufWaktu);
}
else
{
lcd.setCursor(1, 1);
lcd.print(
"--:--"
);
}
}