Pewaktu otomatis dengan arduino (aplikasi pemberi pakan ikan)

Pewaktu otomatis adalah perangkat bekerja menggunakan real time clock (RTC) sebagai basis waktu dan menghasilkan output aksi tepat pada waktu yang ditentukan.

setting waktu alarm

program ini akan setiap detik menmbandingkan/mencek apakah waktu alarm sama sama dengan waktu saat ini, untuk menentukan waktu alarm dalam contoh ini menggunakan 2 waktu alarm dengan cara mengatur variabel pada bagian ini :


#define waktuMakan1 DateTime(0, 1, 1, 8, 0, 0, 0)//jam 8 pagi
#define waktuMakan2 DateTime(0, 1, 1, 17, 0, 0, 0)//jam 5 sore

kelas date time diisi nilai tahun, bulan, tanggal, jam, menit, detik, hari.
namun untuk pengplikasian di sketch pemberi makanan ikan ini hanya diset bagian jam, menit dan detik dengan tujuan nilai waktu ini berulang setiap hari.

Waktu makan ikan

Pada contoh ini perangkat akan menggerakkan servo pemberi makan ikan pada jam 8 pagi dan jam 5 sore.

skema pemberi makan ikan menggunakan arduino :

 

koding/program feeder ikan berbasis arduino:

#define pinServoMakanan               A0

#define waktuBukaServo                1000//milidetik
#define servoBuka                     20//derajat
#define servoTutup                    60//derajat

#define waktuMakan1                   DateTime(0, 1, 1,  8, 0, 0, 0)//jam 8 pagi
#define waktuMakan2                   DateTime(0, 1, 1, 17, 0, 0, 0)//jam 5 sore

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "Sodaq_DS3231.h"
#include <Servo.h>

LiquidCrystal_I2C lcd(0x3F, 16, 2);//coba juga 0x27
Servo servoMakanIkan;

byte detikSebelumnya;

void setup() {
  Serial.begin(9600);
  Serial.println("Pemberi pakan ikan otomatis");
  Serial.println("https://www.semesin.com/project");
  
  servoMakanIkan.attach(pinServoMakanan);
  servoMakanIkan.write(servoTutup);

  Wire.begin();
  rtc.begin();

  lcd.begin();
  lcd.backlight();

  lcd.print("Pemberi ");
  lcd.setCursor(0, 1);
  lcd.print("pakan ikan");
  delay(3000);
  lcd.clear();

  Serial.println("Sistem mulai");
}

void loop() {

  DateTime now = rtc.now();
  if (detikSebelumnya != now.second())
  {
    char buf[17];
    sprintf(buf, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
    lcd.setCursor(4, 0);
    lcd.print(buf);

    detikSebelumnya = now.second();

    uint32_t epoch = now.get() % 86400;//hanya jam menit detik

    if ((epoch == waktuMakan1.get()) ||
        (epoch == waktuMakan2.get()))
    {
      char buf[17];
      sprintf(buf, "Pakan = %02d:%02d", now.hour(), now.minute());
      lcd.setCursor(0, 1);
      lcd.print(buf);

      servoMakanIkan.write(servoBuka);
      delay(waktuBukaServo);
      servoMakanIkan.write(servoTutup);

    }
  }
}

 

Bel sekolah dengan pengaturan melalui tombol

Bel sekolah merupakan pengingat waktu terjadwal yang menandai pergantian antar waktu pelajaran di sekolah. Ber sekolah juga memiliki penjawalan mingguan dan bulanan.

Perangkat bel sekolah otomatis bisa diaplikasikan menggunakan arduino sebagai unit prosesornya, tidak seperti bel sekolah digital berbasis komputer yang menyimpan jadwal dalam harddisk, bel sekolah digital arduino menyimpan data jadwal pelajaran didalam EEPROM. Data Jadwal disimpan dalam format/struktur berikut :

  • Aktif
  • Jam
  • Menit

Guna mengatur data jadwal tersebut, perangkat bel sekolah ini dilengkapi dengan tombol-tombol dengan fungsi [menu], [tambah], [kurang] dan [ok].

serta penggunaan LCD sebagai tampilan waktu sekarang dan tampilan jadwal apabila waktunya telah tepat.

skema bel sekolah dengan pengaturan melalui tombol/button:

komponen yang digunakan :

  1. Arduino uno
  2. RTC DS3231
  3. LCD i2C
  4. push button 4x

sketch/koding bel sekolah arduino :

#define pinTombolMenu       5
#define pinTombolTambah     4
#define pinTombolKurang     3
#define pinTombolOk         2

#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include "RTC_Semesin.h"

LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
RTC_DS3231 rtc;
char namaHari[][7] = {"Minggu", "Senin", "Selasa", " Rabu", "Kamis", "Jum'at", "Sabtu"};
char textMenuUtama[][17] = {
  "Bel masuk +pel 1",
  "Ganti pel 2     ",
  "Bel istirahat   ",
  "Bel masuk +pel 3",
  "Ganti pel 4     ",
  "Bel pulang      ",
  "Set Jam         ",
};
char textAktif[][6] = {"Mati ", "Aktif"};

char bufWaktu[40];

struct Jadwal
{
  bool aktif;
  byte jam;
  byte menit;
};

Jadwal jadwal[6] = {{0, 7, 0}, {0, 7, 0}, {0, 7, 0}, {0, 7, 0}, {0, 7, 0}, {0, 7, 0},} ;
Jadwal jadwalSet;

void setup()
{
  pinMode(pinTombolMenu, INPUT_PULLUP);
  pinMode(pinTombolTambah, INPUT_PULLUP);
  pinMode(pinTombolKurang, INPUT_PULLUP);
  pinMode(pinTombolOk, INPUT_PULLUP);

  Serial.begin (9600);
  Serial.println(F("Bel sekolah dengan pengaturan melalui tombol"));
  Serial.println(F("https://www.semesin.com/project"));

  if (! rtc.begin()) {
    Serial.println(F("Modul RTC tidak ditemukan"));
    while (1);
  }

  if (rtc.lostPower())
  {
    Serial.println(F("Waktu RTC di set ulang"));
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  lcd.begin();
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Nama");
  lcd.setCursor(0, 1);
  lcd.print("Judul");

  //  delay(3000);

  if (EEPROM.read(0) != 0x48)
  {
    simpanJadwal();
    EEPROM.write(0, 0x48);
  }
  else
  {
    ambilJadwal();
  }
  Serial.println("Bel sekolah dimulai");
}

byte detikSebelumnya = 60;
byte menitSebelumnya = 60;
byte menuLevel = 0;
byte menuIndex[2];
DateTime setWaktu;

void loop()
{
  DateTime now = rtc.now();
  if (detikSebelumnya != now.detik)
  {
    detikSebelumnya = now.detik;
    if (!menuLevel)
    {
      sprintf(bufWaktu, "Pukul : %02d:%02d:%02d", now.jam, now.menit, now.detik);
      lcd.setCursor(0, 0);
      lcd.print(bufWaktu);
      sprintf(bufWaktu, "%s, %02d/%02d/%02d", namaHari[now.hari - 1], now.tanggal, now.bulan, now.tahun - 2000);
      lcd.setCursor(0, 1);
      lcd.print(bufWaktu);

    }
    if (menitSebelumnya != now.menit)
    {
      menitSebelumnya = now.menit;
      for (byte i = 0; i < 6; i++)
      {
        if (jadwal[i].aktif)
        {
          if ((jadwal[i].jam == now.jam) && (jadwal[i].menit == now.menit))
          {
            lcd.setCursor(0, 0);
            lcd.print("  Bel Sekolah   ");
            lcd.setCursor(0, 1);
            lcd.print(textMenuUtama[i]);
            delay(10000);
          }
        }
      }
    }
  }

  if (!digitalRead(pinTombolMenu))
  {
    delay(100);
    if (!digitalRead(pinTombolMenu))
    {
      if (menuLevel == 0)
      {
        menuLevel = 1;
        menuIndex[0] = 0;
      }
      else
      {
        menuLevel = 0;
        lcd.noBlink();
      }
      tampilanMenu();
      while (!digitalRead(pinTombolMenu));
    }
  }
  if (!digitalRead(pinTombolTambah))
  {
    delay(100);
    if (!digitalRead(pinTombolTambah))
    {
      if (menuLevel == 1)
      {
        menuIndex[0]++;
        if (menuIndex[0] >= sizeof(textMenuUtama) / sizeof(textMenuUtama[0]))
        {
          menuIndex[0] = 0;
        }
        tampilanMenu();
      }
      if (menuLevel == 2)
      {
        if (menuIndex[0] == 6)
        {
          switch (menuIndex[1])
          {
            case 0:
              setWaktu.jam++;
              if (setWaktu.jam >= 24)
              {
                setWaktu.jam = 0;
              }
              break;
            case 1:
              setWaktu.menit++;
              if (setWaktu.menit >= 24)
              {
                setWaktu.menit = 0;
              }
              break;
            case 2:
              setWaktu.detik++;
              if (setWaktu.detik >= 60)
              {
                setWaktu.detik = 0;
              }
              break;
          }
        }
        else
        {
          switch (menuIndex[1])
          {
            case 0:
              jadwalSet.aktif = !jadwalSet.aktif;
              break;
            case 1:
              jadwalSet.jam++;
              if (jadwalSet.jam >= 24)
              {
                jadwalSet.jam = 0;
              }
              break;
            case 2:
              jadwalSet.menit++;
              if (jadwalSet.menit >= 60)
              {
                jadwalSet.menit = 0;
              }
              break;
          }
        }
        tampilanMenu();
      }
      delay(100);
    }
  }
  if (!digitalRead(pinTombolKurang))
  {
    delay(100);
    if (!digitalRead(pinTombolKurang))
    {
      if (menuLevel == 1)
      {
        if (menuIndex[0] == 0)
        {
          menuIndex[0] = sizeof(textMenuUtama) / sizeof(textMenuUtama[0]) - 1;
        }
        else
        {
          menuIndex[0]--;
        }
        tampilanMenu();
      }
      if (menuLevel == 2)
      {
        if (menuIndex[0] == 6)
        {
          switch (menuIndex[1])
          {
            case 0:
              if (setWaktu.jam == 0)
              {
                setWaktu.jam = 23;
              }
              else
              {
                setWaktu.jam--;
              }
              break;
            case 1:
              if (setWaktu.menit == 0)
              {
                setWaktu.menit = 59;
              }
              else
              {
                setWaktu.menit--;
              }
              break;
            case 2:
              if (setWaktu.detik == 0)
              {
                setWaktu.detik = 59;
              }
              else
              {
                setWaktu.detik--;
              }
              break;
          }
        }
        else
        {
          switch (menuIndex[1])
          {
            case 0:
              jadwalSet.aktif = !jadwalSet.aktif;
              break;
            case 1:
              if (jadwalSet.jam == 0)
              {
                jadwalSet.jam = 23;
              }
              else
              {
                jadwalSet.jam--;
              }
              break;
            case 2:
              if (jadwalSet.menit == 0)
              {
                jadwalSet.menit = 59;
              }
              else
              {
                jadwalSet.menit--;
              }
              break;
          }
        }
        tampilanMenu();
      }
      delay(100);
    }
  }
  if (!digitalRead(pinTombolOk))
  {
    delay(100);
    if (!digitalRead(pinTombolOk))
    {
      if (menuLevel == 1)
      {
        menuLevel = 2;
        menuIndex[1] = 0;
        if (menuIndex[0] == 6)
        {
          setWaktu = rtc.now();
          tampilanMenu();
          lcd.setCursor(4, 1);
          lcd.blink();
        }
        else
        {
          jadwalSet.aktif = jadwal[menuIndex[0]].aktif;
          jadwalSet.jam = jadwal[menuIndex[0]].jam;
          jadwalSet.menit = jadwal[menuIndex[0]].menit;
          tampilanMenu();
          lcd.setCursor(2, 1);
          lcd.blink();
        }
      }
      else if (menuLevel == 2)
      {
        menuIndex[1]++;
        if (menuIndex[0] == 6)
        {
          switch (menuIndex[1])
          {
            case 1:
              tampilanMenu();
              lcd.setCursor(7, 1);
              lcd.blink();
              break;
            case 2:
              tampilanMenu();
              lcd.setCursor(10, 1);
              lcd.blink();
              break;
            case 3:
              menuLevel = 1;
              rtc.adjust(setWaktu);
              tampilanMenu();
              lcd.noBlink();
              break;
          }
        }
        else
        {
          switch (menuIndex[1])
          {
            case 1:
              tampilanMenu();
              lcd.setCursor(8, 1);
              lcd.blink();
              break;
            case 2:
              tampilanMenu();
              lcd.setCursor(11, 1);
              lcd.blink();
              break;
            case 3:
              menuLevel = 1;
              jadwal[menuIndex[0]].aktif = jadwalSet.aktif;
              jadwal[menuIndex[0]].jam = jadwalSet.jam;
              jadwal[menuIndex[0]].menit = jadwalSet.menit;
              simpanJadwal();
              lcd.noBlink();
              tampilanMenu();
              break;
          }
        }
        while (!digitalRead(pinTombolOk));
        delay(500);
      }
    }
  }
}
void tampilanMenu()
{
  if (menuLevel == 1)
  {
    lcd.setCursor(0, 0);
    lcd.print("   Menu Utama   ");
    lcd.setCursor(0, 1);
    lcd.print(textMenuUtama[menuIndex[0]]);
  }
  else if (menuLevel == 2)
  {
    if (menuIndex[0] == 6)
    {
      lcd.setCursor(0, 0);
      lcd.print(textMenuUtama[menuIndex[0]]);
      sprintf(bufWaktu, "    %02d:%02d:%02d    ", setWaktu.jam, setWaktu.menit, setWaktu.detik);
      lcd.setCursor(0, 1);
      lcd.print(bufWaktu);
    }
    else
    {
      lcd.setCursor(0, 0);
      lcd.print(textMenuUtama[menuIndex[0]]);
      sprintf(bufWaktu, "  %s %02d:%02d   ", textAktif[jadwalSet.aktif], jadwalSet.jam, jadwalSet.menit);
      lcd.setCursor(0, 1);
      lcd.print(bufWaktu);
    }
  }
}

void ambilJadwal()
{
  byte *alamat = (byte*)jadwal;
  for (byte i = 1; i < sizeof(jadwal) + 1; i++)
  {
    *alamat++ = EEPROM.read(i);
  }
}
void simpanJadwal()
{
  byte *alamat = (byte*)jadwal;
  for (byte i = 1; i < sizeof(jadwal) + 1; i++)
  {
    EEPROM.update(i, *alamat++);
  }
}

library yang digunakan:

Bel sekolah arduino dengan kontrol android 2 (upgrade lcd)

Bel sekolah adalah pengingat waktu yang digunakan di sekolah sebagai penanda pergantian jadwal.

Bel sekolah digital bisa di aplikasikan dalam bentuk:

    1. Aplikasi komputer
      adalah aplikasi yang ditanam dalam komputer dan bisa dijalankan secara otomatis. sistem ini mudah dalam pengaturan, memiliki data jadwal sangat besar,  peringatan admin, backup, update suara mudah, perekan suara, kunci aplikasi dll. Kelemahannya adalah komputer dan aplifier suara harus tetap hidup dan bergantung kepada adanya daya listrik/ups termasuk biaya listrik, pesan sponsor pada aplikasi gratis,  biaya pengadaan dan perawatan komputer.
    2. Aplikasi android
      Aplikasi / apk android memiliki sama dengan aplikasi komputer dan aplikasi android dapat terhubung dengan  sistem tata suara melalui bluetooth dan kabel audio. kekurangannya adalah device android harus selalu berada dekat dengan sistem (selalu standby)
    3. Aplikasi perangkat mandiri
      Sistem bel sekolah otomatis dapat dibangun dengan perangkat mandiri menggunakan microkontroller dengan biaya murah dan bisa dikembangkan untuk keperluan lainnya seperti :

      • bisa menggunakan baterai sebagai daya cadangannya
      • Pendeteksi gempa dan peringatan
      • Notifikasi sms ke pengajar
      • Mekanuisme kunci pagar
      • Panggilan melalui microphone yang tertuju langsung ke kelas tertentu
      • dan lain-lain sesuai kebutuhan

      Kekurangan sistem ini adalah ruang penyimpanan data jadwal dan suara terbatas, pengaturan jadwal yang sulit melalui tombol/keypad.

Dalam proyek ini menggabungkan perangkat mandiri dengan platform arduino yang dikombinasikan dengan aplikasi/apk android sebagai kontrolnya.

Skema bel sekolah otomatis dengan kontrol android:

komponen bel sekolah arduino control android:

  • Arduino Uno
  • Bluetooth HC-05
  • RTC DS3231
  • LCD 1602 + I2C backpack
  • modul Relay 1 channel
  • DF Player mini mp3
  • Speaker

tampilan Aplikasi bel sekolah android :

sketch/aplikasi bel sekolah bluettoth android :

#define namaSekolah   "Nama Sekolah"

#define SQWPin        A3
#define pinRelay      A3
#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); // RX, TX
SoftwareSerial mp3Serial(4, 5); // RX, TX
LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display

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       ",
  "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) (Mgu1<<7)|(Mgu2<<6)|(Mgu3<<5)|(Mgu4<<4)|(Mgu5<<3)
#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(F("https://www.semesin.com/project"));
  Serial.println();

  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 (0x30);

  if (! rtc.begin()) 
  {
    Serial.println(F("Modul RTC tidak ditemukan"));
    while (1);
  }

 // 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"));

  rtc.adjust(DateTime(2019, 9, 12, 5, 9, 43, 45));

}

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;
        }
      }

      //tampilan
      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);//data tidak benar
        }
      }
    }
  }
}
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), Upacara};
  jadwalBelajar[i++] = {Aktif, _waktu(  6, 45 ), hariAktifSenin                 , _mingguAktif(0, 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), JamPelajaran1};

  jadwalBelajar[i++] = {Aktif, _waktu(  7, 30 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(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), JamPelajaran3};
  jadwalBelajar[i++] = {Aktif, _waktu(  9, 0  ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(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), Istirahat};
  jadwalBelajar[i++] = {Aktif, _waktu( 10, 15 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(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), JamPelajaran6};
  jadwalBelajar[i++] = {Aktif, _waktu( 11, 45 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(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), JamPelajaran7};
  jadwalBelajar[i++] = {Aktif, _waktu( 13, 15 ), _hariAktif(1, 1, 1, 1, 0, 0, 0), _mingguAktif(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), JamPelajaran9};
  jadwalBelajar[i++] = {Aktif, _waktu( 14, 45 ), _hariAktif(1, 1, 1, 0, 0, 0, 0), _mingguAktif(1, 1, 1, 1, 1), JamPelajaran10};

  jadwalBelajar[i++] = {Aktif, _waktu( 14, 0  ), hariAktifKamis,            _mingguAktif(1, 1, 1, 1, 1), Kepramukaan};
  jadwalBelajar[i++] = {Aktif, _waktu( 14, 45 ), hariAktifKamis,            _mingguAktif(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), Pulang};

  jadwalBelajar[i++] = {Aktif, _waktu(  7, 25 ), hariAktifJumat,            _mingguAktif(1, 1, 1, 1, 1), JamPelajaran2};
  jadwalBelajar[i++] = {Aktif, _waktu(  8, 5  ), hariAktifJumat,            _mingguAktif(1, 1, 1, 1, 1), JamPelajaran3};
  jadwalBelajar[i++] = {Aktif, _waktu(  8, 45 ), hariAktifJumat,            _mingguAktif(1, 1, 1, 1, 1), JamPelajaran4};
  jadwalBelajar[i++] = {Aktif, _waktu(  9, 25 ), hariAktifJumat,            _mingguAktif(1, 1, 1, 1, 1), Istirahat};
  jadwalBelajar[i++] = {Aktif, _waktu(  9, 55 ), hariAktifJumat,            _mingguAktif(1, 1, 1, 1, 1), JamPelajaran5};
  jadwalBelajar[i++] = {Aktif, _waktu( 10, 35 ), hariAktifJumat,            _mingguAktif(1, 1, 1, 1, 1), JamPelajaran6};
  jadwalBelajar[i++] = {Aktif, _waktu( 11, 15 ), hariAktifJumat,            _mingguAktif(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); //senin pertama
  byte mingguKe = ((now.tanggal + hariKeDiTanggal1 + 6) / 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("--:--");
  }


}

library arduino bel sekolah dengan bluetooth dan aplikasi android yang digunakan :

Suara mp3 bel sekolah arduino dengan bluetooth:

mp3.zip

aplikasi apk android untuk bel sekolah arduino (evaluasi):

Bel_sekolah_v1_Evaluasi.apk

cara penggunaan :

  1. Buat rangkaian arduino seperti skema dan upload sketch yang diberikan.
  2. Masukkan file suara dalam kartu memori/SD card (file mp3 dan folder mp3).
  3. install aplikasi bel sekolah v1 evaluasi di android (evaluasi = 10 jadwal yang aktif).

Seting waktu RTC otomatis dengan arduino

DS1307 dan DS3231 merupakan RTC (real time clock) yang umum digunakan dalam perancangan arduino. kedua RTC ini saling kompatibel untuk register waktunya, sedangkan register kontrol memiliki alamat berbeda. Selain itu DS3231 memiliki kelebihan dua alarm yang tidak dimiliki oleh DS1307.

Penggunaan RTC pertama kali, RTC harus disetting terlebih dahulu, cara setting DS3231 adalah dengan memberi nilai pada register waktunya, juga register kontrol atau register alarm (khusus DS3231).

Cara menyetting RTC DS3231 dan DS1307 umumnya membutuhkan dua sketch untuk menggunakan RTC ini yaitu setTime dan program utama. Program ‘set waktu’ harus dipisah untuk menghindari program me-‘set waktu’ setiap kali arduino reset.

Otomatisasi setting RTC bertujuan untuk membuat setting waktu berada dalam sketch utama sehingga lebih praktis terutama jika sketch akan bagikan ke publik atau pengguna lain.

Untuk mengetahui apakah RTC sudah disetting atau belum, digunakan 1 byte EEPROM untuk menyimpan status (dibaca tokenRTC), jika RTC sudah disetting maka sketch akan menulis dialamat alamatEEPROMCekToken pada EEPROM dengan nilai tokenRTC.

Ketika program dijalankan sketch akan menguji nilai tokenRTC, jika sama maka sketch tidak lagi melakukan setting waktu RTC.

Skema tulis waktu rtc otomatis (kompatibel DS1307):

sketch/program Atur waktu RTC otomatis (bisa digunakan langsung untuk DS1307 dan DS3231 tanpa library):

#include <EEPROM.h>
#include <Wire.h>
#include <Sodaq_DS3231.h>

#define alamatRTC 0x68
#define alamatEEPROMCekToken 0
#define tokenRTC 0xAA //<== rubah token jika ingin nilai baru

void setup() {
  Serial.begin(9600);
  Serial.println("Set waktu RTC otomatis dengan arduino");
  Serial.println("http://www.semesin.com/project/");
  Serial.println();

  Wire.begin();
  if (EEPROM.read(alamatEEPROMCekToken) != tokenRTC)
  {
    //Waktu compiler
    char bulan[12];
    byte indexBulan;
    int jam, menit, detik, tanggal, tahun;

    char *namaBulan[12] = {
      "Jan", "Feb", "Mar", "Apr", "May", "Jun",
      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    };
    sscanf(__TIME__, "%d:%d:%d", &jam, &menit, &detik);
    sscanf(__DATE__, "%s %d %d", bulan, &tanggal, &tahun);
    for (indexBulan = 0; indexBulan < 12; indexBulan++) {
      if (strcmp(bulan, namaBulan[indexBulan]) == 0)
        break;
    }
    uint8_t wday = hariDariTanggal(tanggal, indexBulan + 1, tahun);
    DateTime dt(tahun, indexBulan + 1, tanggal, jam, menit, detik, wday);
    rtc.setDateTime(dt);
    EEPROM.write(alamatEEPROMCekToken, tokenRTC);
    Serial.println("RTC sudah otomatis di setting (Sekali saja)");
  }
}

uint32_t old_ts;
void loop() {
  String strNamaHari[] = {"Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jum'at", "Sabtu"};
  DateTime now = rtc.now(); //get the current date-time
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.date(), DEC);
  Serial.print(' ');
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.print(' ');
  Serial.print(strNamaHari[now.dayOfWeek()-1]);
  Serial.println();

  while (1);
}
byte hariDariTanggal(byte tanggal, byte bulan, uint16_t tahun)
{
  uint16_t jumlahHariPerBulanMasehi[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  if (tahun >= 2000)
    tahun -= 2000;

  uint32_t jumlahHari = tahun * 365;
  uint16_t tahunKabisat = tahun / 4;
  for (byte i = 0; i < tahun; i++)
  {
    if (!(i % 4))
    {
      jumlahHari++;
    }
  }
  jumlahHari += jumlahHariPerBulanMasehi[bulan - 1];
  if ( (bulan >= 2) && !(tahun % 4))
  {
    jumlahHari++;
  }
  jumlahHari += tanggal;
  return ((jumlahHari + 5) % 7) + 1;
}

Library: Sodaq_DS3231.zip
Versi tanpa library : set_otomatis_rtc.ino

Jadwal Waktu Shalat (JWS) 2 & 3 Panel P10 Arduino Uno dengan kontroller Android melalui Bluetooth

Rancangan displai jadwal waktu sholat / JWS menggunakan arduino ini memanfaatkan I2C EEPROM 24C32 sebagai penyimpan data tampilan Infomasi text yang mampu menampung 4096 karakter. Chip 24C32 umumnya disertakan pada modul RTC DS1307 / DS3231 dengan jalur komunikasi yang sama dan alamat yang berbeda. Karena komunikasi I2C dikategorikan lambat, maka akses pembacaan memori ini diminimalisir dengan metode read on demand.

Display Jadwal Sholat Arduino

Perancangan JWS menggunakan Arduino atau JWS dengan kontroller running text harus mampu menangani hal-hal berikut :

  1. Waktu sholat berdasarkan perjalanan matahari yang berubah-ubah sepanjang tahun, sehingga dibutuhkan perhitungan khusus untuk menentukan posisi matahari secara matematis. Formula yang digunakan berasal dari islamicity, dengan penambahan variabel sudut-sudut matahari.
  2. Pengaturan yang komplek namun fleksibel mengharuskan JWS didesain mampu menyesuaikan tugasnya dengan beberapa parameter yang bisa di monitor atau diganti berkala. Seperti adanya kegiatan-kegiatan khusus sehingga JWS bisa beralih fungsi.

Kapasitas memory flash arduino uno (ATMega328) yang 32Kb masih menyisakan ruang untuk 3 set font diamping 1 font angka. Font-font ini berfungsi memberikan efek tulisan sehingga memungkinkan adanya penekanan informasi.

Efek JWS Arduino

Efek-efek tampilan diperlukan supaya kehadiran JWS lebih menghiasi dinding, bukan hanya sebagai papan informasi. efek yang di tambahkan :

  1. Wipe in – wipe out
  2. Marque
  3. Lukis gambar

JWS Bluetooth

Fasilitas pengaturan JWS dengan bluetooth:

  1. 10 teks informasi yang disimpan dalam memory 24C32 yang mampu menyimpan 4096 karakter.
  2. Font informasi bisa diatur terpisah (System Font 5×7,Arial 14,Arial Black 16) pada uno, dan bisa ditambahkan pada board yang memiliki memori lebih besar.
  3. Waktu padam dan nyala.
  4. Perhitungan waktu sholat dengan metode sudut matahari.
  5. Tampilan tanggal hijriah (bisa diatur dan dinonaktifkan).
  6. Efek wipe untuk tampilan waktu-waktu sholat.
  7. Efek tulisan gambar.
  8. Pengaturan bluetooth meliputi kecerahan DMD panel, kecepatan scroll.
  9. Token aplikasi apk, untuk mengantisipasi apabila ada komunikasi bluetooth yang tidak diinginkan yang mungkin akan merubah setting.
  10. Konfirmasi data setting diterima dan waktu padam/nyala ke apk android.
  11. Data yang diketik di apk disimpan dalam database android, jadi saat aplikasi ditutup data yang diketik tetap akan tampil saat aplikasi dibuka kembali.

Komponen yang digunakan dalam JWS Arduino bluetooth:

  1. Arduino Uno (Gunakan Arduino mega untuk memory yang lebih besar).
  2. RTC DS3231 (termasuk 24C32) kompatibel DS1307 (beda address)
  3. Bluetooth HC-05
  4. Panel P10 (2 panel)

Jika ingin upload sketch dari arduino ide, lepaskan dahulu pin ‘0’ / pin RX jika menggunakan bluetooth hardware serial.

Skema arduino JWS bluetooth:

Video bluetooth arduino JWS:

 

JWS Android

Screenshoot JWS Android bluetooth:

JWS bluetooth android ini menggunakan hardware SPI sebagai pengirim data ke running text, meskipun mengorbankan pin 12 (MISO) yang tidak bisa digunakan karena dikontrol oleh SPI.

Pengaturan JWS dengan arduino yang dibutuhkan :

  1. #define modeDemo pada baris atas digunakan jika ingin menjalankan JWS demo, hapus baris ini jika JWS digunakan normal.
  2. Pin Kontrol DMD hardware SPI : pinOE  harus dipasangkan pada pin PWM sebagai pengatur kecerahan. Sedangkan pinA, pinB, dan pinSCK bisa ditempatkan dimana saja.
  3. Jumlah panel.
  4. Perancangan ini dibuat dengan DS3231, jika menggunakan DS1307 harap diganti bagian alamat I2C-nya.
  5. Pin SQW (DS3231) diset sebagai penghasil pulsa dengan frekuensi 1 HZ sebagai interupsi bagi JWS bahwa detik telah berubah. dalam perancangan JWS arduino ini dihubungkan ke pin A3 namun bisa dipindahkan kemana saja.
  6. Jenis font bisa disesuaikan dengan kebutuhan, (#include-kan juga library font-nya). dengan merubah variabel berikut:
    #define fontWaktu               angka6x13
    #define fontInformasi           SystemFont5x7Ramping
    #define fontTanggal             SystemFont5x7Ramping
    #define fontNamaSholat          SystemFont5x7Ramping
    #define fontWaktuSholat         SystemFont5x7Ramping
    #define fontWaktuMasuk          SystemFont5x7Ramping
    #define fontAdzan               SystemFont5x7Ramping
    #define fontIqomah              SystemFont5x7Ramping
    #define fontMatikanHP           Arial14
    
  7. JWS ini dilengkapi sistem token, untuk RTC dan komunikasi bluetooth, apabila token yang digunakan cocok maka perintah untuk RTC dan bluetooth (setting variabel) akan dijalankan.

Sketch/koding header dan setup android bluetooth JWS:

#define modeDemo                0    //<<==================================== DEMO prinsip kerja 0 / 1

#define selisihImsak            10

//defenisi pin
#define pinA                    6
#define pinB                    7
#define pinOE                   9
#define pinSCK                  8

#define alarm                   5
#define RTCDetikIRQ             A3

//variabel Setting
#define jumlahKolomPanel        2  //panel
#define jumlahBarisPanel        1  //panel

#define lamaTampilWaktuSholat   10 // * 100 milidetik
#define lamaTampilInformasiJam  100 // * 100 milidetik

#define fontWaktu               angka6x13
#define fontInformasi           SystemFont5x7Ramping
#define fontTanggal             SystemFont5x7Ramping
#define fontJadwalSholat        SystemFont5x7Ramping
#define fontWaktuSholat         SystemFont5x7Ramping
#define fontWaktuMasuk          SystemFont5x7Ramping
#define fontAdzan               SystemFont5x7Ramping
#define fontIqomah              SystemFont5x7Ramping
#define fontMatikanHP           Arial14

#define RTC_ADDRESS             0x68
#define I2CEEPROM_ADDRESS       0x57  //Perhatikan alamat I2CEEPROM 0x50(ds1307 .. 0x57(ds3231)
#define RTC_CONTROL_REG         0x0E  //0x07 ds1307, 0x0E ds3231 


#include <Wire.h>
#include <SPI.h>
#include <avr/sleep.h>
#include <avr/pgmspace.h>
#include <EEPROM.h>
#include <SoftwareSerial.h>

#include <DMD2.h>

#include "fungsi.h"
#include "definisi.h"
#include "konstanta.h"
#include "rtc.h"
#include "prayer.h"
#include "i2cUmum.h"
#include "trigonometri.h"

#include <fonts/SystemFont5x7Ramping.h>
#include <fonts/Arial14.h>
#include <fonts/Arial_Black_16.h>
#include <fonts/angka6x13.h>
#include <fonts/AllahMuhammad.h>

const uint16_t alamatFont[] = {&SystemFont5x7Ramping, &Arial14, &Arial_Black_16};

struct Setting
{
  int8_t koreksiHijriah;
  int8_t jumlahAlarm;
  int8_t lamaAdzan;
  int8_t lamaIqomah[5];
  int8_t ulangMatikanHP;
  int8_t lamaSholat[5];
  int8_t lamaSholatJumat;
  int8_t kecepatanJalanInfoText;
  int8_t kecerahanJWS;
  int8_t padamJam;
  int8_t padamMenit;
  int8_t nyalaJam;
  int8_t nyalaMenit;
  int8_t tampilanHijriah;
  int8_t tampilanImsak;
  int8_t tampilanTerbit;
  int8_t tampilanDhuha;
  int8_t tampilanTerbenam;
  int8_t JumlahInfoTextAktif;
};

#if modeDemo
  Setting setting = {0, 5, 1, {5, 5, 5, 5, 5}, 1, {5, 5, 5, 5, 5}, 2, 50, 20, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1};
  char namaMesjid[panjangString] = "Musholla ...\0   ";
#else
  Setting setting;
  char namaMesjid[panjangString];
#endif

//variabel
const char strWaktu[] PROGMEM = "Waktu";
const char strSholat[] PROGMEM = "Sholat";
char strWaktuInformasi[9];
JamDanMenit waktuSholat[9];

EfekMarqueHorizontalkeKiri marqueKiri;
EfekTulis efekTulis;
uint8_t efekScrollOutDanWipeIn;

uint8_t marqueOut;
bool marqueTampilan;
uint8_t wipeInTampilan;
uint8_t wipeOutTampilan;
uint8_t efekTulisTampilan;


uint8_t indexNamaSholat;
uint16_t hitungMundurSholat;
uint16_t hitungMundurPesanSebelumSholat;
uint16_t hitungMundurIqomah;
uint16_t hitungMundurAdzan;
uint8_t hitungMundurAlarm;
uint16_t hitungMudurAlarmIqomah;

byte modeOperasi;
byte modeOperasiSebelumnya;

uint8_t menitSebelumnya = 60;
uint8_t hariSebelumnya = 32;

bool statusAlarm;

bool tampilkanMenit;
bool infoWaktu;
byte infoWaktuTop;
uint16_t lamaTampil = 0;
uint16_t indekTampilan;

char textWaktuJam[6];
char textTanggalHijriah[sizeof(strNamaHari[0]) + 2 + 3 + sizeof(strNamaBulanHijriah[0]) + 3 - 2];

uint8_t bluetoothData[32];
uint16_t indexParseSerial = 0;

byte indexInformasi = 1;
long mulaiMillis;
uint16_t AlamatI2CEEPROM;

int8_t indexSetting = 0;
byte indexSettingInfo;
bool tokenValid = false;
bool RTCValid = true;

byte tanggalHijriah;
byte bulanHijriah;
uint16_t tahunHijriah;

uint16_t AlamatI2CEEPROMSebelumnya;
bool nextEEPROMData = false;
byte EEPROMDataCounter;

bool modeSambungSebelumnya = false;

tanggalDanWaktu now;
tanggalDanWaktu settingWaktu;
byte settingWaktuIndex;

//Class variabel
#define l jumlahKolomPanel * 32
#define t jumlahBarisPanel * 16
SPIDMD dmd(jumlahKolomPanel, jumlahBarisPanel, pinOE, pinA, pinB, pinSCK);
DMDFrame dmdEfek(l, t);

DMD_TextBox boxKolom1(dmd, 0, 0, l / 2, t);
DMD_TextBox boxKolom2(dmd, l / 2, 0, l / 2, t);
DMD_TextBox boxBaris1(dmd, 0, 0, l, (t / 2) - 1);
DMD_TextBox boxBaris2(dmd, 0, t / 2, l, t / 2);

DMD_TextBox boxKolom2Baris1(dmd, l / 2, 0, l / 2, t / 2);
DMD_TextBox boxKolom2Baris2(dmd, l / 2, t / 2, l / 2, t / 2);

//Eeprom24C32_64 I2CEEPROM(EEPROM_ADDRESS);
HardwareSerial *bluetooth;

#define tokenRTC 0xA9
#define tokenBluetooth 0x4C
#define tokenSetInformasi "225654"
#define tokenSetSetting "963215"

void setup() {
  Serial.begin(9600);
  Serial.println("JWS Bluetooth");
  Serial.println("http://www.semesin.com/project/");
  Serial.println();

  bluetooth = &Serial;

  pinMode(alarm, OUTPUT);
  pinMode(RTCDetikIRQ, INPUT_PULLUP);

  //Interupsi setiap 1 detik
  Wire.begin();
  Wire.beginTransmission(RTC_ADDRESS);
  Wire.write(RTC_CONTROL_REG);
  Wire.write(0x00);//SQW freq, 1Hz
  Wire.endTransmission();

#if modeDemo
  prayerData = { -1576, 27343, 1792, 5120, 213, -1152, 1024, 4608, 0, 0, 0,0,0};
  settingWaktu = {50, 29, 4, 5, 7, 5, 2018};
  simpanRTC(RTC_ADDRESS, settingWaktu);
#endif

  if (EEPROM.read(alamatTokenRTC) != tokenRTC)
  {
    //Waktu compiler
    char Month[12];
    int Day, Year;
    uint8_t monthIndex;
    int Hour, Min, Sec;
    char *monthName[12] = {
      "Jan", "Feb", "Mar", "Apr", "May", "Jun",
      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    };
    sscanf(__TIME__, "%d:%d:%d", &Hour, &Min, &Sec);
    sscanf(__DATE__, "%s %d %d", Month, &Day, &Year);
    for (monthIndex = 0; monthIndex < 12; monthIndex++) {
      if (strcmp(Month, monthName[monthIndex]) == 0) break;
    }
    uint8_t wday = hariDariTanggal(Day, monthIndex + 1, Year);
    settingWaktu = {Sec, Min, Hour, wday, Day, monthIndex + 1, Year};
    simpanRTC(RTC_ADDRESS, settingWaktu);
    EEPROM.write(alamatTokenRTC, tokenRTC);
  }

#if !modeDemo
  if (EEPROM.read(alamatTokenBluetooth) == tokenBluetooth)
  {
    ambilSetting();
  }
#endif
  ambilHijriah();
  dmd.begin();

  set_sleep_mode(SLEEP_MODE_IDLE);
  sleep_enable();

  mulaiMillis = millis();
  modeOperasi = tampilWaktuSholat;

  while (!digitalRead(RTCDetikIRQ));
}

 

File-file yang digunakan dalam JWS android :

  1. definisi.h
  2. fungsi.h
  3. i2cUmum.h
  4. JWS_Semesin.ino
  5. konstanta.h
  6. prayer.h
  7. rtc.h
  8. trigonometri.h
  9. JWS_Bluetooth.apk
  10. file lengkap (.zip)

Rekomendasi Perakitan JWS Bluetooth Android:

  1. unzip DMD-semesin.zip ke foler libararies arduino
  2. unzip JWS_Semesin.zip (adalah folder sketch arduino beserta file pendukung dalam satu folder)
  3. Buka JWS_Semesin.ino dengan arduino IDE (pengujian dengan versi 1.8.5)
  4. Upload ke arduino
  5. Hubungkan tx Bluetooth
  6. Buka app JWS Bluetooth klik setting dan kirim pengaturan
  7. Selesai.

antisipasi masalah:

  1. Data EEPROM sebelumnya mungkin berpengaruh pada settingan, set dengan apk via bluetooth atau hapus dahulu dengan examples->EEPROM->eeprom_clear.
  2. #define modeDemo 1 untuk test / 0 untuk running
  3. Pastikan daya mencukupi (kalo tidak punya 5V > 5A hubungkan saja GND DMD ke GND Arduino tapi tidak Vcc +5V-nya)

nb: V1.0 -> Versi2.0

  1. Karakter informasi yang akan ditampilkan langsung diambil dari I2CEEPROM
  2. Penambahan pengaturan sudut-sudut waktu sholat.
  3. Penambahan efek grafis

catatan:

  • koordinat dalam mode derajat-menit –±dd° mm’–(menit = pecahan derajat*60/100)
    contohnya :
    lintang -6.78 -> -6-46′
    bujur 110.38 -> 110-22′
  • jika koordinat sudah sesuai, namun masih ada perbedaan waktu dengan jadwal yang diinginkan (mis: jadwal depag), maka geser bujur (ditambah/dikurang)
  • Jika sebagian jadwal shalat tidak akurat, maka geser derajat masing-masing jadwal shalat yang belum akurat
  • JWS ini belum menggunakan ikhtiyath, untuk mengantisipasinya bisa dengan menggeser derajat-menit bujur ±2 menit)

Hasil percobaan

by: Priadi Amfi

Hasil percobaan

by: Catur cahya

Hasil percobaan

by: Ochoy Thea

Bel Sekolah menggunakan tabel database fleksibel berbasis Arduino

Bel sekolah digital dimanfaatkan untuk menentukan waktu pertukaran kegiatan di sekolah-sekolah. Jadwal untuk sebuah sekolah berbeda dengan sekolah lainnya, baik perbedaan tingkat sekolah maupun zona waktunya. Selain itu terdapat juga perbedaan jadwal untuk masing masing hari, seperti senin pertama setiap bulan untuk upacara dan hari lainnya yang mempunyai kekhususan waktu. Bel sekolah digital berbasis arduino atau mikrokontroller lain memiliki kemampuan penjadwalan jam pelajaran tersebut. selain itu bel sekolah digital arduino juga mudah dalam pengembangan nantinya.

Dalam perancangan bel sekolah arduino ini dibatasi hanya sampai pengaplikasian tabel database arduino fleksibel yang bisa disesuaikan dengan kebutuhan. Bel sekolah berbasis arduino ini hanya berupa penerapan dasar saja yang bisa dikombinasikan dengan aplikasi Bel Sekolah fungsional lainnya.

Untuk pengembangannya bisa saja perangkat bel sekolah otomatis berbasis arduino ini ditambahkan sistem entri data dari bluetooth, wifi, PC dll. juga bisa ditambahkan sistem output multimedia seperti alarm, suara, running text, DMD dan lain-lain.

Kelebihan perancangan ini adalah:

  1. Tabel database jadwal fleksibel
  2. Pembacaan RTC dengan interupsi sehingga menghemat resource
  3. Pemanfaatan sleep mode

Komponen yang digunakan:

  1. Arduino Uno
  2. RTC DS3231

berikut skema / rangkaian bel sekolah dengan arduino:

dan program/sketch Arduino:

#include <DS3232RTC.h>
#include <avr/sleep.h>

#define SQWPin 12

struct Waktu
{ 
  byte jam; 
  byte menit; 
};

struct TabelMataPelajaran
{
  byte aktif;
  Waktu waktu;
  byte hariAktif;
  byte mingguAktif;
  byte kegiatan;
};

enum _kegiatan
{
  JamPelajaran1,
  JamPelajaran2,
  JamPelajaran3,
  JamPelajaran4,
  JamPelajaran5,
  JamPelajaran6,
  JamPelajaran7,
  JamPelajaran8,
  JamPelajaran9,
  JamPelajaran10,
  JamPelajaran11,
  JamPelajaran12,
  JamPelajaran13,
  JamPelajaran14,
  JamPelajaran15,
  Masuk,
  Upacara,
  Istirahat,
  SelesaiIstirahat,
  Kepramukaan,
  Khusus,
  Pulang,
  PulangJumat,
  PulangSabtu
};

volatile bool interupsiDetik;
byte indexMataPelajaran;

#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

String namaHari[] = {"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) (Mgu1<<7)|(Mgu2<<6)|(Mgu3<<5)|(Mgu4<<4)|(Mgu5<<3)
#define _waktu(Jam, Menit) {Jam, Menit}
#define Aktif 1
#define TidakAktif 0



TabelMataPelajaran jadwalBelajar[35];
Waktu waktu;
tmElements_t tm;

void setup() {
  byte i = 0;

  //Senin
  jadwalBelajar[i++] = {Aktif, _waktu(  6, 45 ), hariAktifSenin,            _mingguAktif(1,0,0,0,0), Upacara};
  jadwalBelajar[i++] = {Aktif, _waktu(  6, 45 ), hariAktifSenin,            _mingguAktif(0,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), JamPelajaran1};
  
  jadwalBelajar[i++] = {Aktif, _waktu(  7, 30 ), _hariAktif(1,1,1,1,0,0,0), _mingguAktif(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), JamPelajaran3};
  jadwalBelajar[i++] = {Aktif, _waktu(  9, 0  ), _hariAktif(1,1,1,1,0,0,0), _mingguAktif(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), Istirahat};
  jadwalBelajar[i++] = {Aktif, _waktu( 10, 15 ), _hariAktif(1,1,1,1,0,0,0), _mingguAktif(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), JamPelajaran6};
  jadwalBelajar[i++] = {Aktif, _waktu( 11, 45 ), _hariAktif(1,1,1,1,0,0,0), _mingguAktif(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), JamPelajaran7};
  jadwalBelajar[i++] = {Aktif, _waktu( 13, 15 ), _hariAktif(1,1,1,1,0,0,0), _mingguAktif(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), JamPelajaran9};
  jadwalBelajar[i++] = {Aktif, _waktu( 14, 45 ), _hariAktif(1,1,1,0,0,0,0), _mingguAktif(1,1,1,1,1), JamPelajaran10};

  jadwalBelajar[i++] = {Aktif, _waktu( 14, 0  ), hariAktifKamis,            _mingguAktif(1,1,1,1,1), Kepramukaan};
  jadwalBelajar[i++] = {Aktif, _waktu( 14, 45 ), hariAktifKamis,            _mingguAktif(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), Pulang};

  jadwalBelajar[i++] = {Aktif, _waktu(  7, 25 ), hariAktifJumat,            _mingguAktif(1,1,1,1,1), JamPelajaran2};
  jadwalBelajar[i++] = {Aktif, _waktu(  8, 5  ), hariAktifJumat,            _mingguAktif(1,1,1,1,1), JamPelajaran3};
  jadwalBelajar[i++] = {Aktif, _waktu(  8, 45 ), hariAktifJumat,            _mingguAktif(1,1,1,1,1), JamPelajaran4};
  jadwalBelajar[i++] = {Aktif, _waktu(  9, 25 ), hariAktifJumat,            _mingguAktif(1,1,1,1,1), Istirahat};
  jadwalBelajar[i++] = {Aktif, _waktu(  9, 55 ), hariAktifJumat,            _mingguAktif(1,1,1,1,1), JamPelajaran5};
  jadwalBelajar[i++] = {Aktif, _waktu( 10, 35 ), hariAktifJumat,            _mingguAktif(1,1,1,1,1), JamPelajaran6};
  jadwalBelajar[i++] = {Aktif, _waktu( 11, 15 ), hariAktifJumat,            _mingguAktif(1,1,1,1,1), PulangJumat};

  indexMataPelajaran = i;

  Serial.begin(9600);
  Serial.println("Bel Sekolah menggunakan tabel database flexibel berbaasis Arduino");
  Serial.println("Bisa ditambahkan input bluetooth, wifi, PC, komputer dll");
  Serial.println("Bisa ditambahkan output multimedia seperti suara, alarm, running text, dmd dll");
  Serial.println("http://www.semesin.com/project");
  
  byte ControlRegister;
  RTC.readRTC(0x0E,&ControlRegister,1);
  ControlRegister &= ~(0x07<<2);
  RTC.writeRTC(0x0E, &ControlRegister,1);

  *digitalPinToPCMSK(SQWPin) |= bit (digitalPinToPCMSKbit(SQWPin));
  PCIFR  |= bit (digitalPinToPCICRbit(SQWPin));
  PCICR  |= bit (digitalPinToPCICRbit(SQWPin));
 
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();

////Set waktu sekali saja
//  tm.Day = 1;
//  tm.Month = 4;
//  tm.Year = CalendarYrToTm(2018);
//  tm.Hour = 15;
//  tm.Minute = 24;
//  tm.Second = 00;
//
//  time_t t = makeTime(tm);
//  tm.Wday = dayOfWeek(t);
//  RTC.write(tm);
//  TampilkanWaktu();
}

ISR (PCINT0_vect)
{
  if(digitalRead(SQWPin))
  {
    interupsiDetik = true;
  }
}  

void loop() {
  
  
  if(interupsiDetik)
  {
    interupsiDetik = false;
    RTC.read(tm);
    
    if(tm.Second == 0)
    {
      TampilkanWaktu();//***
      
      byte hariKeDiTanggal1 = (((tm.Wday + 8)  - (tm.Day % 7)) % 7);
      byte SeninKe = ((tm.Day + 7 - hariKeDiTanggal1) / 7);
      byte mingguKe = ((tm.Day + 8 - hariKeDiTanggal1) / 7) + 1;
      
      for(byte i=0; i<indexMataPelajaran ;i++)
      {
        if(jadwalBelajar[i].aktif)
        {
          if((jadwalBelajar[i].waktu.jam == tm.Hour) && 
          (jadwalBelajar[i].waktu.menit == tm.Minute) && 
          (jadwalBelajar[i].hariAktif & (1<<(8-tm.Wday))) &&
          (jadwalBelajar[i].mingguAktif & (1<<(8-SeninKe))))
          {
            TampilkanWaktu();
            //Bisa ditambahkan sistem output
            switch(jadwalBelajar[i].kegiatan)
            {
              case JamPelajaran1:
                Serial.println("Jam Pelajaran 1");
                break;
              case JamPelajaran2:
                Serial.println("Jam Pelajaran 2");
                break;
              case JamPelajaran3:
                Serial.println("Jam Pelajaran 3");
                break;
              case JamPelajaran4:
                Serial.println("Jam Pelajaran 4");
                break;
              case JamPelajaran5:
                Serial.println("Jam Pelajaran 5");
                break;
              case JamPelajaran6:
                Serial.println("Jam Pelajaran 6");
                break;
              case JamPelajaran7:
                Serial.println("Jam Pelajaran 7");
                break;
              case JamPelajaran8:
                Serial.println("Jam Pelajaran 8");
                break;
              case JamPelajaran9:
                Serial.println("Jam Pelajaran 9");
                break;
              case JamPelajaran10:
                Serial.println("Jam Pelajaran 10");
                break;
              case JamPelajaran11:
                Serial.println("Jam Pelajaran 11");
                break;
              case JamPelajaran12:
                Serial.println("Jam Pelajaran 12");
                break;
              case JamPelajaran13:
                Serial.println("Jam Pelajaran 13");
                break;
              case JamPelajaran14:
                Serial.println("Jam Pelajaran 14");
                break;
              case JamPelajaran15:
                Serial.println("Jam Pelajaran 15");
                break;
              case Masuk:
                Serial.println("Masuk");
                break;
              case Upacara:
                Serial.println("Upacara");
                break;
              case Istirahat:
                Serial.println("Istirahat");
                break;
              case SelesaiIstirahat:
                Serial.println("Selesai istirahat");
                break;
              case Kepramukaan:
                Serial.println("Kepramukaan");
                break;
              case Khusus:
                Serial.println("Khusus");
                break;
              case Pulang:
                Serial.println("Jam pelajaran telah selesai, sampai jumpa esok hari");
                break;
              case PulangJumat:
                Serial.println("Jam pelajaran telah selesai, sampai jumpa minggu depan");
                break;
              case PulangSabtu:
                Serial.println("Jam pelajaran telah selesai, sampai jumpa minggu depan");
                break;
              default:
                Serial.println("Lainnya");
                break;
            }
          }
        }
      }
    }
  }
  delay(100);//Selesaikan Serial nge print, hapus saja jika tidak diperlukan
  sleep_mode();
}
void TampilkanWaktu()
{
  Serial.print("Waktu = ");
  print2digits(tm.Hour);
  Serial.write(':');
  print2digits(tm.Minute);
  Serial.write(':');
  print2digits(tm.Second);
  Serial.print(", Tanggal = ");
  Serial.print(namaHari[tm.Wday-1]);
  Serial.write(' ');
  Serial.print(tm.Day);
  Serial.write('/');
  Serial.print(tm.Month);
  Serial.write('/');
  Serial.print(tmYearToCalendar(tm.Year));
  Serial.println();
}

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}

contoh Bel Sekolah Arduino Uno dengan output modul mini MP3 DFPlayer (library DFPlayer_Mini_Mp3.h) dan software serial : Bel_Sekolah_tanpa_interupsi.ino

Bel sekolah bluetooth dengan kontrol android : disini

Membaca RTC DS1307 menggunakan interupsi SQW

RTC DS1307 memiliki pin keluaran/output SQW. Pin SQW berfungsi sebagai pembangkit sinyal digital yang frekuensinya bisa diatur pada 1, 4.096, 8.192, 32.768Hz.

Keluaran ini bisa dimanfaatkan oleh mikrokontroller untuk mendeteksi perubahan detik jika SQW diatur pada frekuensi 1Hz (saat pin SQW kondisi high).

penggunaan interupsi dalam mikrokontroller sangat bermanfaat karena:

  1. Menghentikan program yang sedang berjalan dan segera menjalankan baris program interupsi.
  2. Mengaktifkan mikrokontroller dari posisi sleep().
  3. Tidak memakai sumberdaya mikrokontroller, tidak seperti perintah delay() yang menyebabkan mikrokontroller melakukan proses perulangan di satu titik.

Kombinasi interupsi dan sleep() menjadikan kinerja mikrokontroler lebih efisien (hemat sumberdaya). Namun juga perlu diperhatikan bahwa penggunaan interupsi akan menghambat baris program lain, jadi pergunakan fungsi interupsi secepat mungkin.

fungsi interupsi SQW pada DS1307/interupsi SQW pada DS3231 adalah memliki register kontrol yang sama.

daftar interupsi pinChange:

  1. ISR (PCINT0_vect) pin change interrupt untuk D8 sampai D13
  2. ISR (PCINT1_vect) pin change interrupt untuk A0 sampai A5
  3. ISR (PCINT2_vect) pin change interrupt untuk D0 sampai D7

Skema RTC DS1307/DS3231 hemat energi dengan arduino:

berikut ini contoh sketch/program dari penggunaan RTC DS1307 menggunakan metode  interupsi:

#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <avr/sleep.h>

byte SQWPin = A3;
volatile bool interupsiDetik;

void setup() {
  Serial.begin(9600);
  Serial.println("Membaca DS1307 dengan metode interupsi SQW");
  Serial.println("http://www.semesin.com/project");

  //Mengaktifkan Pin SQW keluaran 1Hz pada DS1307
  Wire.beginTransmission(0x68);
  Wire.write((uint8_t)0x07);
  Wire.write(0x10);
  Wire.endTransmission();

  ////Mengaktifkan Pin SQW keluaran 1Hz pada DS3231
  //Wire.beginTransmission(0x68);
  //Wire.write((uint8_t)0x0E);
  //Wire.write(0x1C);
  //Wire.endTransmission();

  //Pendeteksi interupsi
  *digitalPinToPCMSK(SQWPin) |= bit (digitalPinToPCMSKbit(SQWPin));
  PCIFR  |= bit (digitalPinToPCICRbit(SQWPin));
  PCICR  |= bit (digitalPinToPCICRbit(SQWPin));

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
}

ISR (PCINT1_vect)
{
  if(digitalRead(SQWPin))
  {
    interupsiDetik = true;
  }
}  
 
void loop() {
  tmElements_t tm;
  if (interupsiDetik) 
  {
    interupsiDetik = false;

    RTC.read(tm);
    Serial.print("Time = ");
    print2digits(tm.Hour);
    Serial.write(':');
    print2digits(tm.Minute);
    Serial.write(':');
    print2digits(tm.Second);
    Serial.print(", Date (D/M/Y) = ");
    Serial.print(tm.Day);
    Serial.write('/');
    Serial.print(tm.Month);
    Serial.write('/');
    Serial.print(tmYearToCalendar(tm.Year));
    Serial.println();
  }

  sleep_mode();
}

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}