JWS Universal (Jadwal Waktu Shalat) 1 – 8 panel

Jadwal Waktu Shalat (JWS) adalah media informasi di rumah ibadah Masjid/Mushalla/Surau yang menampilkan informasi waktu-waktu Shalat.

Dalam perkembangannya Jam Waktu Shalat berfungsi sebagai :

  1. Menampilkan Jadwal / Waktu Shalat wajib dan sunat
  2. Menampilkan informasi tanggal Masehi, Hijriah, Pasaran Jawa, dan penanggalan khusus seperti penanggalan Minang
  3. Menampilkan Ayat Al-Quran, Doa
  4. Informasi Tartil, Tarhim, Azan, Iqamah
  5. Pengingat / alarm waktu masuk Shalat dan selesai Iqamah
  6. Memutar Suara/Musik Tartil, Tarhim disertai kontrol hidup/mati amplifier
  7. Perhitungan jadwal berdasarkan posisi matahari, masukan manual, data jadwal online harian.

Diagram alir Jawdal waktu-waktu Shalat :

 

Skema Jam waktu shalat universal:

 

Tampilan aplikasi (apk) JWS Semesin Universal:

 

contoh tampilan jadwal shalat 3 panel :

 

Koding / sketch JWS semesin:

/*
   JWS Semesin 1 - 8 panel

   Fitur yang tidak aktif
   1. Tampilan tanggal Hijriah
   2. Tampilan tanggal Jawa
   3. Tampilan tanggal Minang
   4. Pesan selama tartil
   5. Pesan selama tarhim
   6. Pesan selama Iqamah

*/

#define serialDebug                       false
#define modeDemo                          false

#define namaMesjid                        "JWS"

//defenisi pin
#define pinMP3Busy                        2
#define pinRelayAmpli                     3
#define pinBuzzer                         4
#define RTCDetikIRQ                       A3

#define relayOn                           LOW

#define I2CEEPROM_ADDRESS                 0x57

//setting
#define periodaAlarmWaktuShalatMasuk      100//milidetik
#define periodaAlarmWaktuAkhirIqamah      300//milidetik

#define pixelLebarPanel                   32
#define pixelTinggiPanel                  16

//variabel Setting
#define kecepatanMinimal                  10
#define skalaKecepatan                    10

#define tokenSetting                      32
#define lamaAksesApk                      10L * 60 * 1000

#define jumlahNyalaPadam                  5
#define jumlahTextInformasi               10

#define fontNamaMesjid                    Arial14
#define fontJamDanMenitUtama              angka6x14
#define fontSimbolGambar                  simbolGambar

#include <Wire.h>
#include <EEPROM.h>
#include <DMD_Semesin.h>
#include <RTC_Semesin.h>
#include <DFPlayer_Mini_Mp3.h>
#include <BluetoothApk.h>

#include <fonts/angka6x14.h>
#include <fonts/SystemFont5x7Ramping.h>
#include <fonts/Arial14.h>
#include <fonts/simbolGambar.h>

#include "fungsi.h"
#include "definisi.h"
#include "konstanta.h"
#include "setting.h"
#include "WaktuShalat.h"

const uint8_t *alamatFont[] = {
  Arial14,
  SystemFont5x7Ramping,
};

SPIDMD dmd(8, 1);//max jumlah panel = 8
RTC_DS3231 rtc;
DateTime now;

//Status
bool RTCValid = true;
byte modeOperasi = modeInformasi;
bool statusAlarm;
bool tampilJamMenitDetik = false;
long millisRunningText;
uint8_t kecepatanRunningText;
uint8_t kecepatanRunningEfek;

uint16_t hitungMundurTartil;
uint16_t hitungMundurTarhim;
uint16_t hitungMundurAzan;//terhitung sejak waktu masuk
uint16_t hitungMundurIqamah;//terhitung sejak selesai azan

bool pesanSetelahAzan;
bool pesanSebelumShalat;
uint16_t hitungMundurPeringatanSimbol;
uint16_t hitungMundurShalat;

bool initHitungMundurTartil;
bool initHitungMundurTarhim;
bool initHitungMundurAzan;
bool initHitungMundurIqamah;
bool initHitungMundurPeringatanSimbol;
bool initHitungMundurShalat;

uint8_t hitungMundurAlarmIqamah;//kali

int8_t indexWaktuIbadah;
int8_t indekInformasi;

//efek
uint16_t lamaTampilText;
bool initTampil;

bool tampilanInformasiSambung;

byte indekTampilan = jumlahInformasi;
EfekMarque efekMarque;

uint16_t lebarText;
uint8_t tinggiText;

byte detikSebelumnya = 60;
byte menitSebelumnya = 60;
byte tanggalSebelumnya = 0;

long millisAlarm;

bool status;

BluetoothApk bluetoothApk(&Serial, "JWS2 SEMESIN.COM");
long millisAksesApk;
bool aksesApk;

uint16_t counterAlamat = 0;
uint16_t counterAlamatSebelumnya = 0;
uint16_t parameterSebelumnya = 0;

byte lebarJamUtama = 32;

byte lebarJadwalShalat = 32;
byte modeTampilanJadwal;
char buffer[72];
uint16_t offsetJadwalEEPROM;
bool runningTextAktif;

JamDanMenitJadwal jadwalBerikutnya;
JamDanMenitAlarm alarmBerikutnya;
int8_t hitungMundurAlarm;
bool initHitungMundurAlarm;
bool statusRelayAmpli;

void setup() {

  pinMode(pinBuzzer, OUTPUT);
  digitalWrite(pinRelayAmpli, !relayOn);
  pinMode(pinRelayAmpli, OUTPUT);
  pinMode(pinMP3Busy, INPUT_PULLUP);

  Serial.begin(9600);
  Serial.println(F("JWS Semesin 1-8 panel"));
  Serial.println(F("https://www.project.semesin.com"));

  mp3_set_serial (Serial);
  mp3_set_volume (15);


#if serialDebug
  Serial.println(F("Inisialisasi"));
#endif

  rtc.begin();

  if (rtc.lostPower())
  {
#if serialDebug
    Serial.println(F("RTC tidak jalan"));
#endif
    write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, 0x00);
  }
  write_i2c_register(DS3231_ADDRESS, DS3231_CONTROL, DS3231_SquareWave1Hz);

  if (EEPROM.read(offsetof(Setting, token)) != tokenSetting)
  {
    pengaturanAwal();
  }

  updateUkuranTampilan();
  dmd.waitInterruptOver = false;
  dmd.begin();
  dmd.clearScreen();
  dmd.setBrightness(25.5 * EEPROM.read(offsetof(Setting, kecerahanStandar)));

  kecepatanRunningEfek = skala2kecepatanRunning(EEPROM.read(offsetof(Setting, kecepatanEfek)));

#if serialDebug
  Serial.println(F("Sistem mulai"));
#endif

  dmd.selectFont(fontNamaMesjid);
  dmd.drawString(1, 1, namaMesjid);

  delay(3000);
  dmd.clearScreen();

  statusRelayAmpli = digitalRead(pinMP3Busy);
}


void loop() {

....... file lengkap bisa didownload melalui link dibawah

file JWS universal:

JWS Semesin v2.1

catatan:
* untuk RTC DS3231, pin-SQW harus terpasang pada pin-A3 (arduino)
* jika menggunakan pcb jws (versi manapun) ada kemungkinan tidak cocok dan perlu modifikasi

Mengirim data melalui jaringan Wifi menggunakan ESP01 dengan metode POST (kasus IOT ThingSpeak)

ESP8266 adalah modul Wi-Fi dengan fitur TCP/IP yang lengkap dan bisa dihubungkan dengan mikrokontroler melalui protokon AT-Command. TCP/IP (Transmission Control Protocol / Internet Protocol)  adalah protokol komunikasi antara dua perangkat yang terhubung dengan sebuah metode paket termasuk metode pengalamatan dan metode transmisi dalam jaringan internet.

Dalam komunikasi TCP/IP dikenal beberapa metode request/permintaan yaitu : HEAD, GET, POST, PUT, DELETE, TRACE, OPTIONS, CONNECT, PATCH.

Metode POST  sering digunakan untuk mengirimkan data-data ter-enkripsi dan langsung ke server sehingga lebih menjamin kerahasiaan data. berbeda dengan metode GET yang mengirimkan requeat dalam bentuk URL.

Skematik ESP8266/ESP01 (+Arduino Uno) request metode post:

Sketch/koding pemrograman komunikasi ESP01 + arduino dengan server menggunakan metode POST :

char ssid[]             = "xxxx";            // your network SSID (name)
char pass[]             = "xxxxxxxx";        // your network password

char server[]           = "api.thingspeak.com";
byte port               = 80;
char APIKey[]           = "XXXXXXXXXXXXXX";
uint32_t periodeKirim   = 20000;

#include <WiFiEsp.h>
#include <SoftwareSerial.h>

SoftwareSerial SerialEsp(10, 11);
WiFiEspClient client;
int status = WL_IDLE_STATUS;     // the Wifi radio's status
uint32_t millisKirim;
bool statusKirim;

void setup()
{
  Serial.begin(9600);
  Serial.println("Mengirim data melalui jaringan Wifi menggunakan ESP01 dengan metode POST");
  Serial.println("https://www.project.semesin.com/");
  Serial.println();

  SerialEsp.begin(115200);
  SerialEsp.println("AT+UART_DEF=9600,8,1,0,0");
  delay(500);
  SerialEsp.begin(9600);

  WiFi.init(&SerialEsp);

  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
  }
  millisKirim = millis();
}

void loop()
{
  if (millisKirim < millis())
  {
    millisKirim = millis() + periodeKirim;
    
    // hubungkan ke jaringan wifi jika belum tersambung atau terputus (auto reconnect)
    if (WiFi.status() != WL_CONNECTED)
    {
      Serial.print("Menghubungkan ke jaringan SSID: ");
      Serial.println(ssid);
      while (WiFi.status() != WL_CONNECTED)
      {
        WiFi.begin(ssid, pass);
        Serial.print(".");
        delay(5000);
      }
      printWifiStatus();
      Serial.println("Berhasil terhubung ke jaringan");
    }


    if (WiFi.status() == WL_CONNECTED)
    {
      Serial.println();
      Serial.println("Menghubungkan dengan server...");
      if (client.connect(server, port))
      {
        Serial.println();
        Serial.println("Terhubung dengan server.");

        char content[30];
        sprintf(content, "field1=%d", millis() % 100);

        client.println("POST /update HTTP/1.1");
        client.println("Host: api.thingspeak.com");
        client.println("User-Agent: tslib-arduino/1.5.0");
        client.print("X-THINGSPEAKAPIKEY: ");
        client.println(APIKey);
        client.println("Content-Type: application/x-www-form-urlencoded");
        client.print("Content-Length: ");
        client.println(strlen(content));
        client.println("Connection: close");
        client.println();

        client.print(content);

        statusKirim = true;
      }
    }
  }

  if (statusKirim)
  {
    while (client.available())
    {
      char c = client.read();
      Serial.write(c);
    }

    if (!client.connected()) 
    {
      Serial.println();
      Serial.println("Memutuskan hubungan dengan server...");
      delay(10);
      client.stop();

      statusKirim = false;
    }
  }
}


void printWifiStatus()
{
  // print the SSID of the network you're attached to
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength
  long rssi = WiFi.RSSI();
  Serial.print("Signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Library :

 

Hex Serial Monitor dengan Visual C#

Serial monitor seperti pada putty, hyper terminal, arduino IDE sangat bermanfaat untuk memonitor atau mengontrol perangkat yang sedang dikembangkan/development. Serial monitor juga bisa digunakan untuk proses debug untuk mencari kesalahan algoritma, misalnya dengan memberikan informasi nilai variabel ataupun informasi step by step percabangan.

Penggunaan serial monitor untuk keperluan debug haruslah memberikan informasi detail. Proses debug perangkat digital sangat berhubungan dengan format hexadesimal (hex) dan komunikasi binary.

Fitur Hex Serial Monitor:

  1. Data Serial yang diterima di tampilkan dalam format tabel hexa, juga disertai string.
  2. Baris baru dengan pilihan 0x00 dan 0x0A
  3. Kirim data serial dalam format :
    • String
    • 2 karakter, contohnya 12AB34BC = 0x12, 0xAB, 0x34, 0xBC
    • separator spasi, contoh : 12 AB 34 BC
    • separator koma, contoh : 12, AB,34, BC
    • awalan 0x
    • awalan $, contoh : $12$AB $34  $BC

Fungsi utama software ini adalah untuk berkomunikasi melalui serial port dalam mode binary dan ditampilkan dalam format hexa desimal.

tampilan Hexadecimal serial monitor menggunakan c#:

 

Kode software visual c# hex serial monitor:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace Hex_serial_monitor
{
    public partial class Form1 : Form
    {
        public int baris = 0;
        public int kolom = 0;
        String strKolom;


        public Form1()
        {
            InitializeComponent();
        }

        public delegate void AddDataDelegate();
        public AddDataDelegate delegateSerial;

        private void Form1_Load(object sender, EventArgs e)
        {
            string[] ports = SerialPort.GetPortNames();

            comboBoxCOMPort.Items.Clear();
            foreach (string port in ports)
            {
                comboBoxCOMPort.Items.Add(port);
            }
            if (comboBoxCOMPort.Items.Count > 0)
            {
                comboBoxCOMPort.SelectedIndex = 0;
            }

            this.delegateSerial = new AddDataDelegate(updateSerial);

            dataGridView1.Rows.Clear();
            dataGridView1.Rows.Add();
            dataGridView1.Rows[baris].Cells[0].Value = baris.ToString("X2");
            strKolom = "";

            radioButtonAscii.Checked = true;
            //checkBox0.Checked = true;

        }
        private void updateSerial()
        {
            while (serialPort1.BytesToRead > 0)
            {
                int data = serialPort1.ReadByte();
                dataGridView1.Rows[baris].Cells[kolom + 1].Value = data.ToString("X2");

                if ((data >= ' ') && (data < 128))
                {

                    strKolom += (char)data;
                }
                else
                {
                    strKolom += ' ';
                }


                dataGridView1.Rows[baris].Cells[17].Value = strKolom;

                kolom++;
                if (((data == 0) && (checkBox0.Checked)) ||
                    ((data == 0x0A) && (checkBox0A.Checked)) || 
                    (kolom == 16))
                {
                    kolom = 0;
                    baris++;
                    dataGridView1.Rows.Add();
                    dataGridView1.Rows[baris].Cells[0].Value = baris.ToString("X2");
                    strKolom = "";
                }
                if (checkBoxAutoScroll.Checked)
                {
                    dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.RowCount - 1;
                }
            }
            textBoxKirim.Focus();
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            dataGridView1.Invoke(this.delegateSerial, new Object[] { });
        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            dataGridView1.Rows.Clear();
            kolom = 0;
            baris = 0;
            dataGridView1.Rows.Add();
            dataGridView1.Rows[baris].Cells[0].Value = baris.ToString("X2");
            strKolom = "";
        }

        private void buttonConnect_Click(object sender, EventArgs e)
        {
            if (buttonConnect.Text == "Connect")
            {
                serialPort1.PortName = comboBoxCOMPort.Text;
                serialPort1.Open();
                if (serialPort1.IsOpen)
                {
                    buttonConnect.Text = "Disconnect";
                }
            }
            else
            {
                if (serialPort1.IsOpen)
                {
                    serialPort1.Close();
                    buttonConnect.Text = "Connect";
                }

            }

        }

        private void buttonKirim_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                if (radioButtonAscii.Checked)
                {
                    serialPort1.WriteLine(textBoxKirim.Text + "\r\n");
                }
                else if (radioButton2Character.Checked)
                {
                    if (textBoxKirim.Text.Length % 2 == 0)
                    {
                        int jumlahHex = textBoxKirim.Text.Length / 2;
                        byte[] hex = new byte[jumlahHex];

                        for (int i = 0; i < jumlahHex; i++)
                        {
                            String str2Hex = textBoxKirim.Text.Substring(i * 2, 2);
                            hex[i] = (byte)int.Parse(str2Hex, System.Globalization.NumberStyles.HexNumber);

                        }
                        serialPort1.Write(hex, 0, jumlahHex);
                    }
                }
                else if (radioButtonSpace.Checked)
                {
                    String[] strHexSplit = textBoxKirim.Text.Split(' ');
                    byte[] hex = new byte[strHexSplit.Length];

                    for (int i = 0; i < strHexSplit.Length; i++)
                    {
                        String strHex = strHexSplit[i].Substring(0, 2);
                        hex[i] = (byte)int.Parse(strHex, System.Globalization.NumberStyles.HexNumber);
                    }
                    serialPort1.Write(hex, 0, strHexSplit.Length);
                }
                else if (radioButtonComma.Checked)
                {
                    String[] strHexSplit = textBoxKirim.Text.Split(',');
                    byte[] hex = new byte[strHexSplit.Length];

                    for (int i = 0; i < strHexSplit.Length; i++)
                    {
                        String strHex = strHexSplit[i].Substring(0, 2);
                        hex[i] = (byte)int.Parse(strHex, System.Globalization.NumberStyles.HexNumber);
                    }
                    serialPort1.Write(hex, 0, strHexSplit.Length);
                }
                else if (radioButton0x.Checked)
                {
                    String[] strHexSplit = textBoxKirim.Text.Split('x');
                    byte[] hex = new byte[strHexSplit.Length];

                    for (int i = 0; i < strHexSplit.Length; i++)
                    {
                        String strHex = strHexSplit[i].Substring(0, 2);
                        hex[i] = (byte)int.Parse(strHex, System.Globalization.NumberStyles.HexNumber);
                    }
                    serialPort1.Write(hex, 0, strHexSplit.Length);
                }
                else if (radioButtonDollar.Checked)
                {
                    String[] strHexSplit = textBoxKirim.Text.Split('$');
                    byte[] hex = new byte[strHexSplit.Length];

                    for (int i = 0; i < strHexSplit.Length; i++)
                    {
                        String strHex = strHexSplit[i].Substring(0, 2);
                        hex[i] = (byte)int.Parse(strHex, System.Globalization.NumberStyles.HexNumber);
                    }
                    serialPort1.Write(hex, 0, strHexSplit.Length);
                }
                
            }
        }
    }
}

 

File Hexa Serial monitor berbasis c#