JWS Jammer dengan Database Jadwal Waktu Shalat Bulanan

Jammer merupakan alat pengacak/blokir sinyal handphone/hp dapat digunakan di tempat ibadah untuk me-nonaktifkan perangkat cellular sehingga tidak bisa dipanggil/memanggil dengan tujuan menjaga tempat ibadah dari kebisingan dering ponsel.

Penggunaan jammer/jamming/repeater sinyal hp bisa mengganggu hak orang lain dan berpotensi melanggar undang-undang telekomunikasi, gunakan dengan bijak

Jadwal Shalat

Jadwal shalat berubah-ubah setiap hari tergantung posisi matahari dan bulan, hal ini membuat perangkat digital harus mampu mengikuti perubahan ini. Beberapa metode penggunaan jadwal shalat shalat digital :

  1. Jadwal manual, yaitu jadwal rata-rata dari setiap waktu-waktu shalat
  2. Jadwal database, yaitu jadwal yang tersimpan dalam tabel, bisa mingguan, bulanan atau tahunan
  3. Jadwal Matahari, yaitu penghitungan waktu shalat menggunakan posisi peredaran matahari, dengan memasukkan variabel posisi lintang, bujur, dan tanggal.
  4. Jadwal online, dengan mengambil data dari server online setiap hari.

Skema JWS Jammer menggunakan arduino:

Komponen yang digunakan dalam JWS Database Jadwal Waktu Bulanan:

  1. Arduino Uno
  2. LCD 1602 I2C Backpack
  3. RTC DS3231
  4. Relay untuk jammer
  5. 3x LED
  6. 3x TOmbol

Koding/program JWS Jadwal Bulanan:

#define pinLedMerah             5
#define pinLedHijau             6
#define pinLedBiru              7

#define pinTombolOtomatis       11
#define pinTombolManual         12
#define pinTombolJammer         13

#define pinJammer               4
#define relayOn                 LOW

#define waktuJammerShalat       20
#define waktuJammerShalatJumat  60
#define waktuJammerManual       20

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

LiquidCrystal_I2C lcd(0x3F, 16, 2);

struct waktu
{
  byte jam;
  byte menit;
};


const waktu jadwalShalat[][8] PROGMEM = {
  //Imsyak  Shubuh  Terbit  Dhuha Dzuhur  Ashr  Maghrib Isya
  {{ 4, 20}, { 4, 30}, { 5, 51}, { 6, 15}, {12, 7}, {15, 34}, {18, 20}, {19, 36}},
  {{ 4, 20}, { 4, 30}, { 5, 51}, { 6, 15}, {12, 8}, {15, 34}, {18, 20}, {19, 36}},
  {{ 4, 21}, { 4, 31}, { 5, 52}, { 6, 16}, {12, 8}, {15, 35}, {18, 21}, {19, 36}},
  {{ 4, 21}, { 4, 31}, { 5, 52}, { 6, 16}, {12, 9}, {15, 35}, {18, 21}, {19, 37}},
  {{ 4, 22}, { 4, 32}, { 5, 53}, { 6, 17}, {12, 9}, {15, 36}, {18, 21}, {19, 37}},
  {{ 4, 23}, { 4, 33}, { 5, 53}, { 6, 17}, {12, 9}, {15, 36}, {18, 22}, {19, 37}},
  {{ 4, 23}, { 4, 33}, { 5, 54}, { 6, 18}, {12, 10}, {15, 36}, {18, 22}, {19, 38}},
  {{ 4, 24}, { 4, 34}, { 5, 54}, { 6, 18}, {12, 10}, {15, 37}, {18, 23}, {19, 38}},
  {{ 4, 24}, { 4, 34}, { 5, 55}, { 6, 19}, {12, 11}, {15, 37}, {18, 23}, {19, 38}},
  {{ 4, 25}, { 4, 35}, { 5, 55}, { 6, 19}, {12, 11}, {15, 37}, {18, 23}, {19, 38}},
  {{ 4, 25}, { 4, 35}, { 5, 56}, { 6, 20}, {12, 12}, {15, 37}, {18, 24}, {19, 39}},
  {{ 4, 26}, { 4, 36}, { 5, 56}, { 6, 20}, {12, 12}, {15, 38}, {18, 24}, {19, 39}},
  {{ 4, 27}, { 4, 37}, { 5, 56}, { 6, 20}, {12, 12}, {15, 38}, {18, 24}, {19, 39}},
  {{ 4, 27}, { 4, 37}, { 5, 57}, { 6, 21}, {12, 13}, {15, 38}, {18, 25}, {19, 39}},
  {{ 4, 28}, { 4, 38}, { 5, 57}, { 6, 21}, {12, 13}, {15, 38}, {18, 25}, {19, 40}},
  {{ 4, 28}, { 4, 38}, { 5, 58}, { 6, 22}, {12, 13}, {15, 39}, {18, 25}, {19, 40}},
  {{ 4, 29}, { 4, 39}, { 5, 58}, { 6, 22}, {12, 14}, {15, 39}, {18, 25}, {19, 40}},
  {{ 4, 29}, { 4, 39}, { 5, 59}, { 6, 23}, {12, 14}, {15, 39}, {18, 26}, {19, 40}},
  {{ 4, 30}, { 4, 40}, { 5, 59}, { 6, 23}, {12, 14}, {15, 39}, {18, 26}, {19, 40}},
  {{ 4, 30}, { 4, 40}, { 5, 59}, { 6, 23}, {12, 15}, {15, 39}, {18, 26}, {19, 40}},
  {{ 4, 31}, { 4, 41}, { 6, 0}, { 6, 24}, {12, 15}, {15, 39}, {18, 26}, {19, 40}},
  {{ 4, 31}, { 4, 41}, { 6, 0}, { 6, 24}, {12, 15}, {15, 39}, {18, 26}, {19, 40}},
  {{ 4, 32}, { 4, 42}, { 6, 1}, { 6, 25}, {12, 16}, {15, 39}, {18, 27}, {19, 41}},
  {{ 4, 32}, { 4, 42}, { 6, 1}, { 6, 25}, {12, 16}, {15, 39}, {18, 27}, {19, 41}},
  {{ 4, 33}, { 4, 43}, { 6, 1}, { 6, 25}, {12, 16}, {15, 39}, {18, 27}, {19, 41}},
  {{ 4, 33}, { 4, 43}, { 6, 2}, { 6, 26}, {12, 16}, {15, 39}, {18, 27}, {19, 41}},
  {{ 4, 34}, { 4, 44}, { 6, 2}, { 6, 26}, {12, 17}, {15, 39}, {18, 27}, {19, 41}},
  {{ 4, 34}, { 4, 44}, { 6, 2}, { 6, 26}, {12, 17}, {15, 39}, {18, 27}, {19, 41}},
  {{ 4, 35}, { 4, 45}, { 6, 3}, { 6, 27}, {12, 17}, {15, 39}, {18, 27}, {19, 40}},
  {{ 4, 35}, { 4, 45}, { 6, 3}, { 6, 27}, {12, 17}, {15, 39}, {18, 27}, {19, 40}},
  {{ 4, 36}, { 4, 46}, { 6, 3}, { 6, 27}, {12, 17}, {15, 39}, {18, 27}, {19, 40}},
};
byte waktuUtama[] =  {1, 4, 5, 6, 7};
char namaHari[][8] = {"Minggu,", "Senin, ", "Selasa,", " Rabu, ", "Kamis, ", "Jumat, ", "Sabtu, "};
char namaWaktu[][16] = {"Imsyak", "Shubuh", "Terbit", "Dhuha", "Dzuhur", "Ashr", "Maghrib", "Isya"};

enum Mode
{
  otomatis,
  manual,
};

byte mode;
char buffer[32];
byte detikSebelumnya = 60;
byte menitSebelumnya = 60;
uint16_t unixRelay;
bool statusJammer;
DateTime now;

void setup()
{
  pinMode(pinLedMerah, OUTPUT);
  pinMode(pinLedHijau, OUTPUT);
  pinMode(pinLedBiru, OUTPUT);
  digitalWrite(pinJammer, !relayOn);
  pinMode(pinJammer, OUTPUT);

  pinMode(pinTombolOtomatis, INPUT_PULLUP);
  pinMode(pinTombolManual, INPUT_PULLUP);
  pinMode(pinTombolJammer, INPUT_PULLUP);

  Serial.begin(9600);
  Serial.println("JWS Jammer Sinyal HP dengan Jadwal Bulanan");
  Serial.println("https://www.project.semesin.com");

  Wire.begin();
  Wire.beginTransmission(0x3F);
  if (Wire.endTransmission())
  {
    lcd = LiquidCrystal_I2C(0x27, 16, 2);
  }
  lcd.begin();

  rtc.begin();
  now = rtc.now();
  if (now.year() == 2000)
  {
    //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);
    Serial.println("RTC sudah otomatis di setting (Sekali saja)");
  }

  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("JWS Bulanan");
  lcd.setCursor(0, 1);
  lcd.print("fitur : Jammer");

  delay(3000);
  lcd.clear();

  digitalWrite(pinLedHijau, HIGH);
  Serial.println("Sistem mulai");

}

void loop()
{
  now = rtc.now();

  uint16_t unixSekarang = now.hour() * 60 + now.minute();
  if (detikSebelumnya != now.second())
  {

    detikSebelumnya = now.second();
    if (!statusJammer)
    {
      sprintf(buffer, "%s %02d/%02d/%02d", namaHari[now.dayOfWeek() - 1], now.date(), now.month(), now.year() - 2000);
      lcd.setCursor(0, 0);
      lcd.print(buffer);
    }
    sprintf(buffer, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
    lcd.setCursor(4, 1);
    lcd.print(buffer);
  }
  if (menitSebelumnya != now.minute())
  {
    menitSebelumnya = now.minute();
    if (mode == otomatis)
    {
      for (byte i = 0; i < 5; i++)
      {
        if ((pgm_read_byte(&jadwalShalat[now.date() - 1][waktuUtama[i]].jam) == now.hour()) &&
            (pgm_read_byte(&jadwalShalat[now.date() - 1][waktuUtama[i]].menit) == now.minute()))
        {
          digitalWrite(pinLedMerah, HIGH);
          digitalWrite(pinJammer, relayOn);

          if ((i == 1) && (now.dayOfWeek() == 6)) //Dzuhur / jumatan
          {
            unixRelay = unixSekarang + waktuJammerShalatJumat;//menit
          }
          else
          {
            unixRelay = unixSekarang + waktuJammerShalat;//menit
          }
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("  J A M M E R   ");
          statusJammer = true;

          sprintf(buffer, "Waktu: %s", namaWaktu[waktuUtama[i]]);
          lcd.setCursor(0, 1);
          lcd.print(buffer);

          delay(5000);
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("  J A M M E R   ");
        }
      }
    }
    if (statusJammer)
    {
      if (unixSekarang == unixRelay)
      {
        statusJammer = false;
        digitalWrite(pinLedMerah, LOW);
        digitalWrite(pinJammer, !relayOn);
      }
    }
  }


  if (!digitalRead(pinTombolOtomatis))
  {
    delay(50);
    if (!digitalRead(pinTombolOtomatis))
    {
      mode = otomatis;
      digitalWrite(pinLedHijau, HIGH);
      digitalWrite(pinLedBiru, LOW);
      lcd.setCursor(0, 0);
      lcd.print("    M O D E     ");
      lcd.setCursor(0, 1);
      lcd.print("O T O M A T I S ");
      delay(3000);
      lcd.clear();
    }
  }
  if (!digitalRead(pinTombolManual))
  {
    delay(50);
    if (!digitalRead(pinTombolManual))
    {
      mode = manual;
      digitalWrite(pinLedHijau, LOW);
      digitalWrite(pinLedBiru, HIGH);
      lcd.setCursor(0, 0);
      lcd.print("    M O D E     ");
      lcd.setCursor(0, 1);
      lcd.print("  M A N U A L   ");
      delay(3000);
      lcd.clear();
    }
  }
  if (mode == manual)
  {
    if (!digitalRead(pinTombolJammer))
    {
      delay(50);
      if (!digitalRead(pinTombolJammer))
      {
        if (statusJammer)
        {
          digitalWrite(pinLedMerah, LOW);
          digitalWrite(pinJammer, !relayOn);
          statusJammer = false;
        }
        else
        {
          digitalWrite(pinLedMerah, HIGH);
          digitalWrite(pinJammer, relayOn);
          unixRelay = unixSekarang + waktuJammerManual;//menit
          statusJammer = true;
          lcd.setCursor(0, 0);
          lcd.print("  J A M M E R   ");
          lcd.setCursor(0, 1);
          lcd.print("  M A N U A L   ");
          delay(5000);
        }
        while (!digitalRead(pinTombolJammer));
        delay(50);
      }
    }
  }
}
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:

simulasi Gerak lurus berubah beraturan (GLBB) – Gerak jatuh bebas menggunakan arduino

Gerak lurus berubah beraturan (GLBB) adalah gerak lurus yang percepatannya tetap, artinya kecepatannya berubah beraturan. terdapat beberapa jenis GLBB yaitu :

  1. Gerak vertikal ke atas
  2. Gerak jatuh bebas
  3. Gerak vertikal ke bawah

untuk keperluan simulasi gerak lurus berubah beraturan diperlukan peralatan sebagai berikut :

  1. Arduino uno
  2. 3x sensor obstacle
  3. sensor ultrasonic
  4. Tombol

Dengan tata letak seperti berikut:

Skema simulasi GLBB menggunakan arduino:

sketch/koding simulasi gerak lurus berubah beraturan berbasis arduino:

#define tinggiSensorBawah   10//cm

#define pinTombolMulai      A0

#define pinSensorA          8
#define pinSensorB          9
#define pinSensorC          10

#include <Ultrasonic.h>

Ultrasonic ultrasonic(3, 2);

uint16_t nomor;

void setup() {
  pinMode(pinTombolMulai, INPUT_PULLUP);

  pinMode(pinSensorA, INPUT_PULLUP);
  pinMode(pinSensorB, INPUT_PULLUP);
  pinMode(pinSensorC, INPUT_PULLUP);

  Serial.begin(9600);
  Serial.println("Gerak Lurus Berubah Beraturan");
  Serial.println("https://www.project.semesin.com");

  Serial.println();
  Serial.println("Gerak Lurus Berubah Beraturan (jatuh bebas)");
  Serial.println("No\tJarak (cm)\tWaktu (s)\tPercepatan (cm/s2)");

}

void loop() {

  if (!digitalRead(pinTombolMulai))
  {
    delay(50);
    if (!digitalRead(pinTombolMulai))
    {
      while (!digitalRead(pinTombolMulai));

      uint16_t tinggi = 1.0 * ultrasonic.read() - tinggiSensorBawah;
      float jarakSensor = 1.0 * tinggi / 2;

      unsigned long waktuA, waktuB, waktuC;
      bool mulaiDiTitikA, mulaiDiTitikC = false;
      while (1)
      {
        if (!digitalRead(pinSensorA))
        {
          waktuA = micros();
          mulaiDiTitikA = true;
          break;
        }
        if (!digitalRead(pinSensorC))
        {
          waktuC = micros();
          mulaiDiTitikC = true;
          break;
        }
      }

      while (digitalRead(pinSensorB));
      waktuB = micros();

      while (1)
      {
        if (!digitalRead(pinSensorA))
        {
          waktuA = micros();
          break;
        }
        if (!digitalRead(pinSensorC))
        {
          waktuC = micros();
          break;
        }
      }

      float waktu_ac = abs(1.0 * waktuC - waktuA) / 1000000;//detik
      float waktu_ab = abs(1.0 * waktuB - waktuA) / 1000000;//detik
      float waktu_bc = abs(1.0 * waktuC - waktuB) / 1000000;//detik

      float kecepatan_ab = 0.5 * jarakSensor / waktu_ab;//cm/s
      float kecepatan_cb = 0.5 * jarakSensor / waktu_ab;//cm/s
      float kecepatan_bc = 0.5 * jarakSensor / waktu_bc;//cm/s

      float percepatan;
      if (mulaiDiTitikA)
      {
        percepatan = (1.0 * kecepatan_bc - kecepatan_ab) / waktu_bc;//cm/s2
      }
      if (mulaiDiTitikC)
      {
        percepatan = (1.0 * kecepatan_ab - kecepatan_bc) / waktu_ab;//cm/s2
      }

      char buffer[200];
      char strWaktu_ac[10];
      char strPercepatan[10];

      dtostrf(waktu_ac, 8, 2, strWaktu_ac);
      dtostrf(percepatan, 8, 2, strPercepatan);

      sprintf(buffer, "%d\t%d\t\t%s\t%s", nomor, tinggi, strWaktu_ac, strPercepatan);
      Serial.println(buffer);
      nomor++;

    }
  }
}

Library:

Timbangan tampilan seven segment menggunakan arduino

Penggunaan timbangan secara umum membutuhkan akurasi dan presisi. Dalam skala lebih luas sebaiknya unit timbangan juga informatif sehingga dapat diketahui hasilnya secara luas. Untuk keperluan ini, unit timbangan  harus memiliki sarana display yang memadai seperti menggunakan display dot mattrix, seven segment dan sebagainya.

Fitur timbangan

Fitur/fasilitas timbangan bisa bermacam sesuai kebutuhan. Dalam perancangan timbangan 7-segment ini memasukkan fitur-fitur penting diantaranya :

    1. Kalibrasi

Kalibrasi adalah kegiatan untuk memastikan timbangan memiliki akurasi dan presisi yang baik. dalam perancangan ini prosedur kalibrasinya sebagai berikut:

    • Posisi perangkat timbangan dalam keadaan mati
    • Letakkan beban tera 1Kg
    • Tekan dan tahan tombol [hold]
    • Hidupkan perangkat timbangan (akan muncul tulisan ‘load 1’ di tampilan seven segment)
    • lepas tombol [hold]
    • Tunggu hingga muncul tulisan ‘load 2’ di 7-segment
    • Letakkan beban tera 2.5 Kg
    • Tekan dan lepas tombol [hold]
    • Tunggu hingga muncul tulisan ‘siap’ didisplay 7-segment
    • Kalibrasi selesai
  1. tombol tare
  2. tombol hold
  3. Tampilan seven segment

Seven Segmen

Seven segment memiliki kelebihan dari display lainnya, diantaranya :

  1. Intensitas cahaya lebih terang (akan berkurang jika menggunakan sistem scanning)
  2. Mudah terbaca dari jarak jauh (lebih jelas)
  3. Jika menggunakan mikrokontroler, lebih sedikit menggunakan resources (memory dan waktu proses)
  4. Menggunakan komponen lebih sedikit (non module)
  5. Perbandingan cahaya vs daya terpakai lebih sedikit sehingga lebih hemat.

Dalam proyek timbangan informatif dengan display 7-segment berbasis arduino ini menggunakan komponen sebagai berikut:

Komponen yang digunakan dalam perancangan timbangan sevent segment menggunakan arduino:

  1. Arduino uno
  2. modul hx711 dan loadcell 5Kg
  3. IC uln2003
  4. 5x 7-Segment CC
  5. 2x Tombol

Skema timbangan tampilan seven segmen:

source code/program arduino timbangan seven segment:

 

#include "HX711.h"
#include <TimerOne.h>
#include <EEPROM.h>

#define CCorCA                1//0 = CC, 1 = CA (rangkaian dengan resistor)
#define tareSaatMulai         1

#define beratKalibrasi1Tera   1.0f  //Kg
#define beratKalibrasi2Tera   1.00f  //Kg
#define beratMaksimal         2.50 //Kg
#define jumlahSampling        5     //kali
#define frekuensiUpdateData   20    //kali per detik

//pin
HX711 scale(3, 2); // (DT, SCK)

#define pin1    A0
#define pin2    A1
#define pin3    A2
#define pin4    A3
#define pin5    A4

#define pinA    4
#define pinB    5
#define pinC    6
#define pinD    7
#define pinE    8
#define pinF    9
#define pinG    10
#define pinDot  11

#define pinTare 12
#define pinHold 13

#define dotBlank 6
#define dotAll   5

byte pin7Segment[] = {pinA, pinB, pinC, pinD, pinE, pinF, pinG};
byte pin7SegmentCommon[] = {pin1, pin2, pin3, pin4, pin5};
byte posisiTitik = dotBlank;

const char angka[] = {
  0b00111111,
  0b00000110,
  0b01011011,
  0b01001111,
  0b01100110,
  0b01101101,
  0b01111100,
  0b00000111,
  0b01111111,
  0b01100111,
  0b00000000,//blank
  0b01000000,//strip
  0b00111000,//L
  0b01011100,//o
  0b01011111,//a
  0b01011110,//d
  0b01101101,//S
  0b00000100,//i
  0b01110011,//p
  
};
#define Seg_blank 10
#define Seg_stip 11
#define Seg_L 12
#define Seg_o 13
#define Seg_a 14
#define Seg_d 15
#define Seg_S 16
#define Seg_i 17
#define Seg_p 18

//volatile uint32_t beratBCD = 0;
volatile uint8_t beratBCD[5];
volatile byte lastScanIndex = 0;
volatile byte index7Segment = 0;

long lastMillis;
long kirimDataMillis;
byte modeKalibrasi = 0;
long beratKalibrasi1;
long beratKalibrasi2;
float beratTerukur;
bool tahanNilai = false;
byte timbangBeratCounter = 0;

#define alamatKalibrasiM 0
#define alamatKalibrasiC 4

void setup() {
  Serial.begin(9600);
  Serial.println(F("Timbangan tampilan seven segment menggunakan arduino"));
  Serial.println(F("https://www.project.semesin.com"));
  
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  pinMode(pin4, OUTPUT);
  pinMode(pin5, OUTPUT);

  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
  pinMode(pinC, OUTPUT);
  pinMode(pinD, OUTPUT);
  pinMode(pinE, OUTPUT);
  pinMode(pinF, OUTPUT);
  pinMode(pinG, OUTPUT);
  pinMode(pinDot, OUTPUT);

  pinMode(pinTare, INPUT_PULLUP);
  pinMode(pinHold, INPUT_PULLUP);

  Timer1.initialize(2000);
  Timer1.attachInterrupt( timerIsr );

  float m,c;

  scale.power_up();
  
  //Mode kalibrasi
  if(!digitalRead(pinHold))
  {
    delay(50);
    if(!digitalRead(pinHold))
    {
      beratBCD[4] = Seg_L;
      beratBCD[3] = Seg_o;
      beratBCD[2] = Seg_a;
      beratBCD[1] = Seg_d;
      beratBCD[0] = 1;

      while(!digitalRead(pinHold))//lepas
      {
        while(!digitalRead(pinHold))
        {
          delay(50);
        }
      }
      delay(1000);
      beratKalibrasi1 = scale.read_average(10);

      beratBCD[0] = 2;
      while(digitalRead(pinHold))//tekan
      {
        while(digitalRead(pinHold))
        {
          delay(50);
        }
      }
      delay(1000);
      beratKalibrasi2 = scale.read_average(10);
      
      m = 1.0 * (beratKalibrasi2 - beratKalibrasi1) / ( beratKalibrasi2Tera - beratKalibrasi1Tera);
      c = beratKalibrasi2 - (1.0 * m * beratKalibrasi2Tera);

      EEPROM.put(alamatKalibrasiM, m);
      EEPROM.put(alamatKalibrasiC, c);    

      beratBCD[4] = Seg_S;
      beratBCD[3] = Seg_i;
      beratBCD[2] = Seg_a;
      beratBCD[1] = Seg_p;
      beratBCD[0] = Seg_blank;

      delay(500);
    }
  }
  
  EEPROM.get(alamatKalibrasiM, m);
  EEPROM.get(alamatKalibrasiC, c);

  scale.set_scale(m);
  scale.set_offset(c);

#if tareSaatMulai
  scale.tare();
#endif
  
  scale.power_down();
  lastMillis = millis();
  kirimDataMillis = millis();
}

void loop() {

  if(!tahanNilai)
  {
    if(millis() - lastMillis > 10)
    {
      scale.power_up();
      delay(10);
      beratTerukur += scale.get_units(1);
      if(timbangBeratCounter++ == jumlahSampling)
      {
        beratTerukur = beratTerukur * 100 / jumlahSampling;
        if(beratTerukur < 0)
        {
          beratBCD[0] = 0;
          beratBCD[1] = 0;
          beratBCD[2] = 0;
          beratBCD[3] = Seg_stip;
          beratBCD[4] = Seg_blank;
          posisiTitik = 2;
        }
        else if(beratTerukur <= (beratMaksimal*100))
        {
          uint32_t BCD = Convert_IntToBCD32(beratTerukur);
          if((BCD & 0x0F) <= 5)
          {
            beratBCD[0] = 0;
          }
          else
          {
            beratBCD[0] = 5;
          }
          beratBCD[1] = (BCD >> 4) & 0x0F;
          beratBCD[2] = (BCD >> 8) & 0x0F;
          beratBCD[3] = (BCD >> 12) & 0x0F;
          beratBCD[4] = (BCD >> 16) & 0x0F;
          posisiTitik = 2;
        }
        beratTerukur = 0;
        timbangBeratCounter = 0;
      }
      scale.power_down();
      
      lastMillis = millis();
    }
  }

  //Kirim data setiap 100ms
  if(millis() - kirimDataMillis > (1000/frekuensiUpdateData))
  {
    if(beratTerukur <= 0)
    {
      Serial.println("0.00");
    }
    else
    {
      Serial.println(floor(beratTerukur)/100, 2);
    }

    kirimDataMillis = millis();
  }
  if(!digitalRead(pinTare))
  {
    delay(50);
    if(!digitalRead(pinTare))
    {
      beratBCD[0] = Seg_blank;
      beratBCD[1] = Seg_blank;
      beratBCD[2] = Seg_blank;
      beratBCD[3] = Seg_blank;
      beratBCD[4] = Seg_blank;
      posisiTitik = dotAll;
      scale.power_up();
      delay(10);
      scale.tare();
      scale.power_down();
      while(!digitalRead(pinTare));
    }
  }
  if(!digitalRead(pinHold))
  {
    delay(50);
    if(!digitalRead(pinHold))
    {
      tahanNilai = !tahanNilai;
      while(!digitalRead(pinHold));
    }
  }
}
void timerIsr()
{
  digitalWrite(pin7SegmentCommon[lastScanIndex], CCorCA?LOW:HIGH);
  drive7Segment(beratBCD[index7Segment]);
  if(posisiTitik == dotAll)
  {
    digitalWrite(pinDot, CCorCA?LOW:HIGH);
  }
  else if(posisiTitik == dotBlank)
  {
    digitalWrite(pinDot, CCorCA?HIGH:LOW);
  }
  else
  {
    digitalWrite(pinDot, (index7Segment == posisiTitik)?CCorCA?LOW:HIGH:CCorCA?HIGH:LOW);
  }
  digitalWrite(pin7SegmentCommon[index7Segment], CCorCA?HIGH:LOW);
  lastScanIndex = index7Segment++;
  if(index7Segment > 4)index7Segment = 0;
}
void drive7Segment(byte nilai)
{
  byte nilai7Segment = CCorCA?~angka[nilai]:angka[nilai];
  for(byte i=0;i<sizeof(pin7Segment);i++)
  {
    digitalWrite(pin7Segment[i], nilai7Segment & 0x01);
    nilai7Segment >>= 1;
  }
}
uint32_t Convert_IntToBCD32(uint32_t DecimalValue)
{
    uint32_t returnValue = 0;
    //uint32_t LSB_L = DecimalValue;
 
    while (DecimalValue >= 10000000L)
    {
        DecimalValue -= 10000000L;
        returnValue += 0x10000000;
    }
    while (DecimalValue >= 1000000L)
    {
        DecimalValue -= 1000000L;
        returnValue += 0x01000000;
    }
    while (DecimalValue >= 100000L)
    {
        DecimalValue -= 100000L;
        returnValue += 0x00100000;
    }
    while (DecimalValue >= 10000)
    {
        DecimalValue -= 10000;
        returnValue += 0x00010000;
    }
    while (DecimalValue >= 1000L)
    {
        DecimalValue -= 1000L;
        returnValue += 0x00001000;
    }
    while (DecimalValue >= 100)
    {
        DecimalValue -= 100;
        returnValue += 0x00000100;
    }
    while (DecimalValue >= 10)
    {
        DecimalValue -= 10;
        returnValue += 0x00000010;
    }
    return returnValue + DecimalValue;
}

Library yang digunakan dalam perakitan timbangan arduino:

  1. HX711.zip
  2. TimerOne.zip

Mesin antrian dmd dilengkapi suara dengan arduino

Mesin antrian adalah sistem informasi antara meja layanan dan pengunjung untuk mengatur waktu pelayanan terhadap pengunjung sesuai urutan kedatangan. Sistem ini terdiri atas media, dan tombol panggil, bisa juga ditambahkan dengan tombol tiket (dengan cetak tiket). Media informasi seperti seven segment, running text (dmd), monitor, suara yang diletakkan di ruang tunggu yang terlihat/terdengar di kursi pengunjung yang sedang antri.

Mesin antrian dalam proyek ini memiliki fitur berikut :

  1. Tombol panggil 4 buah dengan fitur cascade yaitu masing-masing tombol dapat ditekan bersamaan tanpa harus menunggu proses panggilan meja operator lain.
  2. Tombol tiket 1 buah dan dilengkapi cetak tiket
  3. Tombol reset untuk mengembalikan ke keadaan awal
  4. Media dot matik P10 sebagai papan informasi.
  5. Suara panggil mp3 berupa nomor antrian dan nomor loket

Skema Mesin antrian arduino :

Komponen yang digunakan dalam membuat mesin antrian menggunakan dmd (dot matrix display) berbasis arduino :

  1. Arduino uno
  2. DMD P10
  3. Printer thermal
  4. DF Player mini mp3, speaker, resistor
  5. Tombol

Sketch / koding sistem antrian arduino :

#define pinTombolPanggil1   A0
#define pinTombolPanggil2   A1
#define pinTombolPanggil3   A2
#define pinTombolPanggil4   A3

#define pinTombolReset      A4
#define pinTombolTiket      A5

#define pinMP3Busy          2

#define belas               12 //belas.mp3
#define puluh               13 //puluh.mp3
#define seratus             14 //seratus.mp3
#define ratus               15 //ratus.mp3
#define seribu              16 //seribu.mp3
#define ribu                17 //ribu.mp3
#define koma                18 //Koma.mp3

#define antrianNomor        101
#define silahkanKeCS        102

#include <SPI.h>
#include <DMD_Semesin.h>
#include <fonts/angka6x14ABCD.h>
#include <DFPlayer_Mini_Mp3.h>
#include "Adafruit_Thermal.h"


byte nomorAntrianDaftar;
byte nomorAntrianPanggil;
byte nomorCSPanggil;

SPIDMD dmd(1, 1);
SoftwareSerial serialPrinter(4, 5);
Adafruit_Thermal printer(&serialPrinter);

struct DataAntrian
{
  uint16_t counterTiket;
  uint16_t counterPanggil;
  uint8_t CS;
  bool dataTombolTekan[4];
};

DataAntrian dataAntrian;
byte pinTombolPanggil[] = {pinTombolPanggil1, pinTombolPanggil2, pinTombolPanggil3, pinTombolPanggil4};
char buffer[20];

bool statusTombolTiket;
byte statusTombolPanggil[4];


void setup() {
  pinMode(pinTombolPanggil1, INPUT_PULLUP);
  pinMode(pinTombolPanggil2, INPUT_PULLUP);
  pinMode(pinTombolPanggil3, INPUT_PULLUP);
  pinMode(pinTombolPanggil4, INPUT_PULLUP);

  pinMode(pinTombolReset, INPUT_PULLUP);
  pinMode(pinTombolTiket, INPUT_PULLUP);

  Serial.begin(9600);

  Serial.println(F("Mesin antrian arduino"));
  Serial.println(F("https://www.project.semesin.com"));

  mp3_set_serial (Serial);
  mp3_set_volume(30);
  Serial.println();

  serialPrinter.begin(9600);
  printer.begin();
  printer.sleep();

  dmd.clearScreen();
  dmd.setBrightness(255);
  dmd.selectFont(angka6x14ABCD);
  dmd.begin();
}

void loop() {

  bacaTombol();

  if (!digitalRead(pinTombolReset))
  {
    delay(100);
    if (!digitalRead(pinTombolReset))
    {
      dataAntrian.counterTiket = 0;
      dataAntrian.counterPanggil = 0;
      dataAntrian.CS = 0;
      dataAntrian.dataTombolTekan[0] = 0;
      dataAntrian.dataTombolTekan[1] = 0;
      dataAntrian.dataTombolTekan[2] = 0;
      dataAntrian.dataTombolTekan[3] = 0;

      dmd.clearScreen();
      Serial.println("Reset");
      while (!digitalRead(pinTombolReset));
    }
  }

  for (byte i = 0; i < sizeof(pinTombolPanggil); i++)
  {
    if (dataAntrian.counterTiket > dataAntrian.counterPanggil)
    {
      if (dataAntrian.dataTombolTekan[i])
      {
        dataAntrian.counterPanggil++;
        dataAntrian.CS = i + 1;

        sprintf(buffer, "%02d>%1d", dataAntrian.counterPanggil, dataAntrian.CS);
        dmd.drawString(2, 1, buffer);

        Serial.print("call=");
        Serial.println(dataAntrian.counterPanggil);
        Serial.print("cs=");
        Serial.println(dataAntrian.CS);

        mp3_play_and_wait(antrianNomor);
        suaraBilangan(dataAntrian.counterPanggil);
        mp3_play_and_wait(silahkanKeCS);
        suaraBilangan(dataAntrian.CS);

        Serial.println();
        dataAntrian.dataTombolTekan[i] = false;
      }
    }
  }
}

void suaraBilangan(uint32_t Bilangan)
{
  if (Bilangan < 100)
  {
    suaraPuluhan(Bilangan);
  }
  else if (Bilangan < 1000)
  {
    suaraRatusan(Bilangan);
  }
  else
  {
    suaraRibuan(Bilangan);
  }
}
void suaraPuluhan(uint8_t Bilangan)
{
  if (Bilangan < 12)
  {
    mp3_play_and_wait(Bilangan);
  }
  else if (Bilangan < 20)
  {
    mp3_play_and_wait(Bilangan - 10);
    mp3_play_and_wait(belas);
  }
  else
  {
    uint8_t puluhan = Bilangan / 10;
    mp3_play_and_wait(puluhan);
    mp3_play_and_wait(puluh);

    puluhan *= 10;
    if (Bilangan - puluhan != 0)
    {
      mp3_play_and_wait((Bilangan - puluhan));
    }
  }
}
void suaraRatusan(uint16_t Bilangan)
{
  uint8_t ratusan = (uint8_t)(Bilangan / 100);
  if (ratusan == 1)
  {
    mp3_play_and_wait(seratus);
  }
  else
  {
    mp3_play_and_wait(ratusan);
    mp3_play_and_wait(ratus);
  }
  if (Bilangan % 100)
  {
    suaraPuluhan(Bilangan - (ratusan * 100));
  }
}
void suaraRibuan(uint32_t Bilangan)
{
  uint16_t ribuan = (uint16_t)(Bilangan / 1000);
  if (ribuan == 1)
  {
    mp3_play_and_wait(seribu);
  }
  else if (ribuan < 100)
  {
    suaraPuluhan(ribuan);
    mp3_play_and_wait(ribu);
  }
  else
  {
    suaraRatusan(ribuan);
    mp3_play_and_wait(ribu);
  }
  if (Bilangan % 1000)
  {
    suaraRatusan(Bilangan - (ribuan * 1000));
  }
}

void mp3_play_and_wait(uint16_t num) {
  mp3_play (num);
  delay(200);
  while (!digitalRead(pinMP3Busy))
  {
    bacaTombol();
  }
}

void bacaTombol()
{
  if (!digitalRead(pinTombolTiket))
  {
    if (!statusTombolTiket)
    {
      delay(100);
      if (!digitalRead(pinTombolTiket))
      {
        dataAntrian.counterTiket++;
        printer.wake();
        printer.setDefault();

        printer.justify('C');
        printer.println("Nomor Antrian");
        printer.doubleHeightOn();
        printer.println(dataAntrian.counterTiket);
        printer.doubleHeightOff();
        printer.println("Terima kasih");
        printer.feed(2);
        printer.sleep();

        Serial.print("ambil tiket : ");
        Serial.println(dataAntrian.counterTiket);

        statusTombolTiket = true;
      }
    }
  }
  else
  {
    statusTombolTiket = false;
  }

  for (byte i = 0; i < sizeof(pinTombolPanggil); i++)
  {
    if (!digitalRead(pinTombolPanggil[i]))
    {
      if (!statusTombolPanggil[i])
      {
        delay(100);
        if (!digitalRead(pinTombolPanggil[i]))
        {
          dataAntrian.dataTombolTekan[i] = true;
          statusTombolPanggil[i] = true;

          Serial.print("TombolPanggil:");
          Serial.println(i);
        }
      }
    }
    else
    {
      statusTombolPanggil[i] = false;
    }
  }
}

library :

suara mp3

  1. mp3 mesin antrian arduino.zip

Tombol cerdas cermat +sesi diskualifikasi menggunakan arduino

Cerdas cermat adalah pertandingan yang mengandalkan kecerdasan serta kecepatan. Untuk memberikan keadilan bagi seluruh group peserta, maka perangkat pendukung harus memiliki kriteria berikut :

  1. waktu scanning
    metode yang sering digunakan adalah interupsi dan scanning tombol, dalam hal penggunaan arduino uno (yang memiliki 2 external interrupt dan 23 pin change interrupt) masing-masing memiliki kelemahan dan kelebihan :

    • metode interruptpenggunaan external interrupt adalah metode yang paling baik, namun arduino uno hanya memiliki 2 external interrupt (hanya untuk 2 group) sehingga kurang efektif. Jika menggunakan 23 jalur external interrupt lebih banyak akan tetapi jenis interupsi ini di arduino uno terpisah dalam 3 kelompok, sehingga, seandainya 2 group cerdas cermat dalam satu kelompok interupsi menekan tombol (dalam waktu  scanning-nya) naka harus diambil salah satu group cerdas cermat saja, dan masalahnya pengambilan keputusan ini akan menjadi masalah keadilan bagi peserta.
    • metode scanning tombol
      metode ini bisa diistilahkan ‘tombol yang tepat di waktu yang tepat’ karena jika tombol cerdas cermat ditekan bersamaan, maka yang akan terpilih adalah tombol yang sedang di scanning. Namun sebetulnya waktu scanning ini sangatlah cepat, dan letak keadilannya ditentukan oleh ‘waktu’
  2.  interlock tombol
    • Ketika group yang paling cepat di sahkan, maka tombol group lain tidak berfungsi.
    • seluruh tombol group cerdas cermat hanya bisa di tekan pada saat yang ditentukan (misalkan setelah pertanyaan selesai dibacakan) jika mendahului waktu tersebut, maka tombolnya tidak berfungsi (diskualifikasi sesi pertanyaan) dengan cara menahan [tombol reset] dan melepas-nya ketika pertanyaan selesai di bacakan

blok diagram cerdas cermat menggunakan arduino:

 

skema mesin cerdas cermat berbasis arduino:

 

koding bel cerdas cermat berbasis arduino:

#define pinGroup1               2
#define pinGroup2               3
#define pinGroup3               4
#define pinGroup4               5

#define pinGroup1Indikator      A0
#define pinGroup2Indikator      A1
#define pinGroup3Indikator      A2
#define pinGroup4Indikator      A3

#define pinReset                8
#define pinBel                  9

#define relayAktif              LOW
#define jumlahGroup             4
#define waktuBel                3000

byte pinGroup[jumlahGroup] = {pinGroup1, pinGroup2, pinGroup3, pinGroup4};
byte pinGroupIndikator[jumlahGroup] = {pinGroup1Indikator, pinGroup2Indikator, pinGroup3Indikator, pinGroup4Indikator};

byte groupAktif;
byte groupScan;
byte tombolAktif;
long millisBel;
bool statusTombol;
bool statusSesi;
bool sesi[jumlahGroup];

// the setup routine runs once when you press reset:
void setup() {
  Serial.begin(9600);
  Serial.println(F("Tombol cerdas cermat berbasis arduino"));
  Serial.println(F("https://www.project.semesin.com"));
  Serial.println();

  for (int i = 0; i < sizeof(pinGroup); i++)
  {
    pinMode(pinGroup[i], INPUT_PULLUP);
    pinMode(pinGroupIndikator[i], OUTPUT);
  }

  pinMode(pinReset, INPUT_PULLUP);

  digitalWrite(pinBel, !relayAktif);
  pinMode(pinBel, OUTPUT);

  memset(sesi, 1, 4);
}

// the loop routine runs over and over again forever:
void loop() {

  groupScan = (groupScan + 1) % jumlahGroup;
  if (!digitalRead(pinGroup[groupScan]))
  {
    if (tombolAktif)
    {
      if (sesi[groupScan])
      {
        groupAktif = groupScan + 1;
        statusTombol = true;
        statusSesi = true;
      }
    }
    else if (!statusSesi)
    {
      if (sesi[groupScan])
      {
        sesi[groupScan] = false;
        Serial.print("Diskualifikasi : ");
        Serial.println(groupScan + 1);
      }
    }
  }

  if (!digitalRead(pinReset))
  {
    delay(50);

    if (!digitalRead(pinReset))
    {
      tombolAktif = false;
      if (groupAktif)
      {
        digitalWrite(pinGroupIndikator[groupAktif - 1], LOW);
        digitalWrite(pinBel, !relayAktif);
        groupAktif = 0;
        Serial.println("Reset");
        statusSesi = false;
        memset(sesi, 1, 4);
      }
    }
  }
  else if (groupAktif)
  {
    if (statusTombol)
    {
      Serial.print("Group : ");
      Serial.println(groupAktif);

      millisBel = millis() + waktuBel;
      digitalWrite(pinBel, relayAktif);

      digitalWrite(pinGroupIndikator[groupScan], HIGH);
      statusTombol = false;
      tombolAktif = false;
    }
  }
  else if (!tombolAktif)
  {
    Serial.println("Sesi mulai");

    tombolAktif = true;
  }

  if (millisBel < millis())
  {
    digitalWrite(pinBel, !relayAktif);
  }
}

 

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.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);

  rtc.begin();

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

  Wire.beginTransmission(0x3F);
  if (Wire.endTransmission())
  {
    lcd = LiquidCrystal_I2C(0x27, 16, 2);
  }
  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 >= 60)
              {
                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:

Pengunci nilai batas (Bandgap interlock) pada arduino

Sistem interlock pada pemograman digunakan untuk mengunci suatu blok program agar dijalankan hanya satu kali. Penguncian dapat dilakukan dengan flag/bendera, jadi sebelum masuk suatu blok program nilai flag penguncinya diuji dan hanya bisa dilewati jika nilainya cocok. pada arduino algoritma flag arduino (pengunci nilai arduino / interlock arduino) biasanya dideklarasikan sebagai boolean/bool yang bernilai true dan false.

Contoh sketch berikut ini menggunakan sensor analog (bisa dikembangkan untuk sensor dengan basis komunikasi) sebagai input. Sedangkan alarm/buzzer berlaku sebagai output. Tombol berfungsi sebagai konfirmasi bahwa alarm telah disetujui.

Komponen yang digunakan :

  1. Arduino uno
  2. Sensor analog (potensio, LM35, water level, flex, dll)
  3. Buzzer
  4. Tombol push on

Skema pengujian sistem kunci arduino:

Sketch / koding contoh penggunaan flag pada arduino:
Fungsi utama:

  1. Alarm hanya hidup jika nilai diluar batas dan belum dikonfirmasi
  2. Alarm mati jika tombol konfirmasi sudah ditekan
  3. Sistem alarm dapat kembali berfungsi jika nilai sudah dalam batas
//Pin
#define pinSensor           A0
#define pinTombolKonfirmasi 2
#define pinAlarm            13

#define batasAtas 600
#define batasBawah 400

bool sistemNormal = true;

void setup() {
  pinMode(pinTombolKonfirmasi, INPUT_PULLUP);
  pinMode(pinAlarm, OUTPUT);

  Serial.begin(9600);
  Serial.println("Alarm pengunci nilai batas (Bandgap interlock) pada arduino");
  Serial.println("https://www.project.semesin.com/");
}

void loop() {
  int nilaiSensor = analogRead(pinSensor);
  Serial.print("Nilai pembacaan sensor : ");
  Serial.println(nilaiSensor);

  if((nilaiSensor <= batasBawah) || (nilaiSensor >= batasAtas))//Pembacaan diluar batas
  {
    if(sistemNormal)//alarm belum dikonfirmasi
    {
      Serial.println("Pembacaan sensor diluar batas.");
      digitalWrite(pinAlarm, HIGH);
      sistemNormal = false;
    }
  }
  else //Pembacaan dalam batas
  {
    sistemNormal = true;
  }

  if(!digitalRead(pinTombolKonfirmasi))
  {
    Serial.println("Alarm dikonfirmasi.");
    digitalWrite(pinAlarm, LOW);
  }

  delay(1000);
}

dalam bentuk lain:

//Pin
#define pinSensor           A0
#define pinTombolKonfirmasi 2
#define pinAlarm            13

#define batasAtas 600
#define batasBawah 400

bool Alarm;
bool telahKonfirmasi;
bool Konfirmasi;

void setup() {
  pinMode(pinTombolKonfirmasi, INPUT_PULLUP);
  pinMode(pinAlarm, OUTPUT);

  Serial.begin(9600);
  Serial.println("Alarm pengunci nilai batas (Bandgap interlock) pada arduino");
  Serial.println("https://www.project.semesin.com/");
}

void loop() {

  int nilaiSensor = analogRead(pinSensor);
  Serial.print("Nilai pembacaan sensor : ");
  Serial.println(nilaiSensor);

  bool sistemNormal = ((nilaiSensor >= batasBawah) && (nilaiSensor <= batasAtas));
  if(!telahKonfirmasi)
  {
    Konfirmasi = !digitalRead(pinTombolKonfirmasi);
  }

  if(sistemNormal && (!Alarm || (Alarm && Konfirmasi)))
  {
    Alarm = false;
    telahKonfirmasi = false;
    Serial.println("Status : Sistem normal");
  }
  else if(sistemNormal && Alarm)
  {
    Serial.println("Status : Sistem normal, belum dikonfirmasi");
  }
  else if(!sistemNormal && Konfirmasi)
  {
    Alarm = false;
    telahKonfirmasi = true;
    Serial.println("Status : Sistem tidak normal, telah dikonfirmasi");
  }
  else if(!sistemNormal && !telahKonfirmasi)
  {
    Alarm = true;
    Serial.println("Status : Sistem tidak normal");
  }
  digitalWrite(pinAlarm, Alarm);

  delay(1000);
}

Pengaturan alarm dengan arduino dan RTC DS1307 melalui 4 tombol

Alarm berfungsi sebagai pengingat atau pemberitahu baik melalui visual dan suara. Biasanya alarm diaktifkan pada waktu-waktu tertentu sesuai kebutuhan, adakalanya dalam satu hari ada beberapa waktu alarm diaktifkan.

Dalam desain ini saya hanya menggunakan satu entri waktu alarm yang bisa diatur dengan 4 (empat) tombol, fungsi masing-masing tombol adalah:

  1. tombol kiri (M) untuk menu, tekan pertama untuk pengaturan jam, kedua untuk menit, ketiga untuk detik dan ke-empat untuk kembali.
  2. tombol kanan (E) untuk exit/langsung kembali jika sudah dalam menu.
  3. tombol atas untuk tambah
  4. tombol bawah untuk kurang

breadboard:

komponen yang digunakan:

  1. Arduino Uno
  2. LCD matrik 16×2
  3. I2C to LCD PCF8574
  4. RTC DS1307
  5. Buzzer
  6. Tombol 4bh

sketch/program:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <EEPROM.h>

//pin
byte tombolUp = 9;
byte tombolDn = 10;
byte tombolMinus = 11;
byte tombolPlus = 8;
byte buzzer = 13;

LiquidCrystal_I2C  lcd(0x3F, 16, 2);
byte detikTerakhir = 60;

int alarmJamAddr = 0;
int alarmMenitAddr = 1;
int alarmDetikAddr = 2;

byte alarmJam;
byte alarmMenit;
byte alarmDetik;

bool alarmStatus = false;
unsigned long millisMulai;
unsigned long millisAlarmMulai;

bool buzzStatus;

uint16_t jedaBuzzer = 1000;
uint16_t waktuAlarm = 10000;//Alarm 10 detik

byte menu = 0;
byte menuLCDPos = 8;
byte temp;

void setup()
{
  Serial.begin(9600);
  Serial.println("Setting alarm menggunakan Arduino dan RTC1307 melalui 4 push button");
  Serial.println("https://www.project.semesin.com");

  pinMode(buzzer, OUTPUT);
  pinMode(tombolUp, INPUT_PULLUP);
  pinMode(tombolDn, INPUT_PULLUP);
  pinMode(tombolMinus, INPUT_PULLUP);
  pinMode(tombolPlus, INPUT_PULLUP);

  Wire.begin();
  Wire.beginTransmission(0x3F);
  if (Wire.endTransmission())
  {
    lcd = LiquidCrystal_I2C(0x27, 16, 2);
  }
  lcd.begin();
  lcd.backlight();
  lcd.setBacklight(HIGH);

  lcd.setCursor (0, 0);
  lcd.print("Waktu:    :  :  ");
  lcd.setCursor(0, 1);
  lcd.print("Alarm:    :  :  ");

  readEEPROMDataWaktu();

  lcd.setCursor(8, 1);
  if (alarmJam < 10)lcd.print('0');
  lcd.print(alarmJam);
  lcd.setCursor(11, 1);
  if (alarmMenit < 10)lcd.print('0');
  lcd.print(alarmMenit);
  lcd.setCursor(14, 1);
  if (alarmDetik < 10)lcd.print('0');
  lcd.print(alarmDetik);
}

void loop()
{
  tmElements_t tm;

  do
  {
    lcd.setCursor(menuLCDPos, 1);
    switch (bacaTombol())
    {
      case '+':
        temp = EEPROM.read(menu - 1);
        if (((temp >= 23) && (menu == 1)) || ((temp >= 59) && (menu > 1)))
          temp = 0;
        else
          temp++;
        EEPROM.write(menu - 1, temp);
        if (temp < 10)lcd.print('0');
        lcd.print(temp);
        break;
      case '-':
        temp = EEPROM.read(menu - 1);
        if ((temp == 0) && (menu == 1))
          temp = 23;
        else if ((temp == 0) && (menu > 1))
          temp = 59;
        else
          temp--;
        EEPROM.write(menu - 1, temp);
        if (temp < 10)lcd.print('0');
        lcd.print(temp);
        break;
      case 'M':
        menu++;
        if (menu == 1)
        {
          menuLCDPos = 8;
          temp = alarmJam;
          lcd.blink();
        }
        else if (menu == 2)
        {
          menuLCDPos = 11;
        }
        else if (menu == 3)
        {
          menuLCDPos = 14;
        }
        if (menu == 4)
        {
          menu = 0;
          lcd.noBlink();
          readEEPROMDataWaktu();
        }
        break;
      case 'E':
        menu = 0;
        lcd.noBlink();
        readEEPROMDataWaktu();
        break;
    }
  }
  while (menu);

  if (alarmStatus)
  {
    if (millisMulai + jedaBuzzer < millis())
    {
      buzzStatus = !buzzStatus;
      digitalWrite(buzzer, buzzStatus);
      millisMulai = millis();
    }
    if (millisAlarmMulai + waktuAlarm < millis())
    {
      alarmStatus = false;
      digitalWrite(buzzer, LOW);
    }
  }

  if (RTC.read(tm)) {
    if (tm.Second != detikTerakhir)
    {
      lcd.setCursor(8, 0);
      if (tm.Hour < 10)lcd.print('0');
      lcd.print(tm.Hour);
      lcd.setCursor(11, 0);
      if (tm.Minute < 10)lcd.print('0');
      lcd.print(tm.Minute);
      lcd.setCursor(14, 0);
      if (tm.Second < 10)lcd.print('0');
      lcd.print(tm.Second);

      if ((alarmJam == tm.Hour) && (alarmMenit == tm.Minute) && (alarmDetik == tm.Second))
      {
        alarmStatus = true;
        millisMulai = millis();
        millisAlarmMulai = millisMulai;
      }

      detikTerakhir = tm.Second;
    }
  }
}

char bacaTombol()
{
  char tombol = ' ';
  if (!digitalRead(tombolUp))
  {
    tombol = '+';
  }
  else if (!digitalRead(tombolDn))
  {
    tombol = '-';
  }
  else if (!digitalRead(tombolMinus))
  {
    tombol = 'M';
  }
  else if (!digitalRead(tombolPlus))
  {
    tombol = 'E';//exit
  }
  while (!digitalRead(tombolUp));
  while (!digitalRead(tombolDn));
  while (!digitalRead(tombolMinus));
  while (!digitalRead(tombolPlus));
  delay(200);

  return tombol;
}

void readEEPROMDataWaktu()
{
  alarmJam = EEPROM.read(alarmJamAddr);
  alarmMenit = EEPROM.read(alarmMenitAddr);
  alarmDetik = EEPROM.read(alarmDetikAddr);
}

 

I2C scanner

apabila ditemui kesulitan dalam mencari alamat I2C dari PCF8574 (modul I2C ke LCD 16×2) gunakan I2C scanner berikut:

#include <Wire.h>
 
void setup()
{
  Wire.begin();
 
  Serial.begin(9600);
  Serial.println("\nI2C Scanner");
}
 
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      
      byte addressFull = address << 1;
      Serial.print("(");
      if (addressFull<16)
        Serial.print("0");
      Serial.print(addressFull,HEX);
      Serial.println(")");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");
 
  delay(5000);
}

alamat tulis I2C yang umum:

  • DS1307 = 0xD0
  • AT24C32 = 0xA0 – oxAE

Library: