/*
Project: Digital Clock with Alarm & PIR Sensor
Author: LAGSILVA
Hardware: Arduino UNO / PIR Sensor / LED Display with TM1637 / Buzzer
Date: 19.Mar.2018
Revision: 1.1
License: CC BY-NC-ND 4.0
(Attribution-NonCommercial-NoDerivatives 4.0 International)
-----------------------------------------------------------------------
Notes:
1. Display Time, Temperature, Humidity & Dew Point
2. Special Features: PIR sensor & time of Alarm recorded in RTC
-----------------------------------------------------------------------
*/
#include <TM1637Display.h> // Library of Display TM1637 (I2C)
#include <Bounce2.h> // Library to read Encoder key
#include <TimerOne.h> // Library of Timer1
//#include <Time.h> // Time Library
#include <DS1307RTC.h> // Library of Real Time Clock (RTC)
#include <Wire.h> // Library of Wire to support DS1307RTC (Real-Time Clock) - Pins to Arduino UNO: A4 (SDA), A5 (SCL)
#include <DHT.h> // Library of Temperature and Humidity sensor
#define DHTPIN 11 //Sensor DHT11 conected to the pin 11 on Arduino
// Definition of what DHT sensor type you are using
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE); // Define the name DHT for the sensor of Temperature and Humidity
#define DS1307_I2C_ADDRESS 0x68 // This is the I2C address (RTC)
int hora, minuto, hh, mm, temp, umid, tpo, dezHora, uniHora, horaAlarme, minutoAlarme;
byte statusPIR, statusAlarme, statusTempo, statusGatilho;
#define DIO 2 // Arduino Conection on Pin #2 = DIO of Display Module TM1637
#define CLK 3 // Arduino Conection on Pin #3 = CLK of Display Module TM1637
//Encoder variables
byte encoderPinSW = 4; // Encoder variable - SW
byte encoderPinB = 5; // Encoder variable - DT
byte encoderPinA = 6; // Encoder variable - CLK
int PIR = 7; // Pin #7 connected to PIR (Presence Infra Red sensor)
int BUZ = 8; // Pin #8 connected to buzzer (Alarm)
int chk; // Variable to read the sensor DHT11
//dht11 DHT; // Define the name DHT for the sensor of Temperature and Humidity
//#define DHT11_PIN 11 // Sensor DHT11 conected to the Pin #11 on Arduino
byte encoderPos = 0;
byte encoderPinALast = LOW;
byte n = LOW;
byte linSW = 0;
Bounce SW = Bounce(); // Definition of Bounce object for the switch (SW) of Encoder
// Begin of display
TM1637Display display(CLK, DIO);
// Segments map of display
//
// A
// ---
// F | | B
// -G-
// E | | C
// ---
// D
//
// Definition of special characters to be used with the display
const uint8_t Grau[] = {
SEG_A | SEG_B | SEG_F | SEG_G , //
};
const uint8_t UR[] = {
SEG_C | SEG_D | SEG_E | SEG_G , // %
};
const uint8_t Celsius[] = {
SEG_A | SEG_D | SEG_E | SEG_F , // C
};
const uint8_t Fahrenheit[] = {
SEG_A | SEG_E | SEG_F | SEG_G , // F
};
const uint8_t letraA[] = {
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
};
const uint8_t letraL[] = {
SEG_D | SEG_E | SEG_F , // L
};
const uint8_t letraT[] = {
SEG_D | SEG_E | SEG_F | SEG_G, // t
};
const uint8_t letraI[] = {
SEG_E, // i
};
const uint8_t letraS[] = {
SEG_A | SEG_C | SEG_D | SEG_F | SEG_G, // S
};
const uint8_t letraO[] = {
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // O
};
const uint8_t letraE[] = {
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // E
};
const uint8_t letraN[] = {
SEG_C | SEG_E | SEG_G, // n
};
const uint8_t letraF[] = {
SEG_A | SEG_E | SEG_F | SEG_G , // F
};
// Definition of numbers to be shown with colon in the display
uint8_t dataWithColon[] = {
0b10111111, // 0
0b10000110, // 1
0b11011011, // 2
0b11001111, // 3
0b11100110, // 4
0b11101101, // 5
0b11111101, // 6
0b10000111, // 7
0b11111111, // 8
0b11101111, // 9
0b00000000, // 10
};
void setup() {
dht.begin();
setSyncProvider(RTC.get); // Update the time with data of RTC (Real Time Clock)
setSyncInterval(300); // Set the number of seconds between re-sync
display.setBrightness (0x0a); // (0x0f) is the max brightness
pinMode(PIR, INPUT); // Define pin of PIR as input
pinMode(BUZ, OUTPUT); // Define pin of Buzzer as output
pinMode (encoderPinA, INPUT);
pinMode (encoderPinB, INPUT);
pinMode (encoderPinSW, INPUT_PULLUP);
// After setting up the button, setup the Bounce instance :
SW.attach(encoderPinSW);
SW.interval(100);
//TimerOne initialization
Timer1.initialize(1000); // Set Timer1 for 1000 microseconds
Timer1.attachInterrupt(lerEncoder); // Timer1 reads the Encoder
//setTime(16, 20, 00, 26, 03, 2016); // Set the time and calendar manually
//RTC.set(now()); // Update the RTC with current time
// Read data of Alarm recorded in RTC
Wire.beginTransmission(DS1307_I2C_ADDRESS); // Open I2C line in write mode
Wire.write((byte)0x08); // Set the register pointer to (0x08)
Wire.endTransmission(); // End Write Transmission
Wire.requestFrom(DS1307_I2C_ADDRESS, 3); // In this case read only 3 bytes
horaAlarme = Wire.read(); // Read the hour of Alarm stored at RTC
minutoAlarme = Wire.read(); // Read the minute of Alarm stored at RTC
statusAlarme = Wire.read(); // Read the status of Alarm stored at RTC
// Initial values of variables
hh = 23;
mm = 59;
statusGatilho = LOW;
statusTempo = LOW;
}
void buzzer() { // Routine for Alarm/Buzzer
display.showNumberDec(dezHora, true, 1, 0);
display.setSegments(dataWithColon + uniHora, 1, 1);
display.showNumberDec(minuto, true, 2, 2);
tone(BUZ, 880, 300);
delay(300);
tone(BUZ, 523, 200);
delay(200);
display.setSegments(dataWithColon + 10, 1, 0); // Clear digit #1
display.setSegments(dataWithColon + 10, 1, 1); // Clear digit #2
display.setSegments(dataWithColon + 10, 1, 2); // Clear digit #3
display.setSegments(dataWithColon + 10, 1, 3); // Clear digit #4
delay(100);
}
void lerEncoder() { //Encoder reading
// Update the Bounce instance :
SW.update();
//Check the Encoder key status
if (SW.fell()) {
linSW++;
if (linSW <= 6) {
statusPIR = LOW;
display.setSegments(letraS, 1, 0); // Show the symbol of word S
display.setSegments(letraE, 1, 1); // Show the symbol of word E
display.setSegments(letraT, 1, 2); // Show the symbol of word T
display.setSegments(dataWithColon + 10, 1, 3); // Clear digit #4
delay(500);
}
else {
linSW = 0;
statusPIR = HIGH;
}
}
switch (linSW) {
case 1: //Set the Hours of Alarm
n = digitalRead(encoderPinA);
if ((encoderPinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoderPinB) == LOW) {
encoderPos++;
horaAlarme++;
} else {
encoderPos--;
horaAlarme--;
}
encoderPinALast = n;
horaAlarme = constrain(horaAlarme, 0, 23);
display.showNumberDec(horaAlarme, true, 2, 0);
display.setSegments(letraA, 1, 2); // Show the symbol of word A
display.setSegments(letraL, 1, 3); // Show the symbol of word L
}
case 2: //Set the Minutes of Alarm
n = digitalRead(encoderPinA);
if ((encoderPinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoderPinB) == LOW) {
encoderPos++;
minutoAlarme++;
} else {
encoderPos--;
minutoAlarme--;
}
encoderPinALast = n;
minutoAlarme = constrain(minutoAlarme, 0, 59);
display.setSegments(letraA, 1, 0); // Show the symbol of word A
display.setSegments(letraL, 1, 1); // Show the symbol of word L
display.showNumberDec(minutoAlarme, true, 2, 2);
}
case 3: //Set status of Alarm (On-Off)
n = digitalRead(encoderPinA);
if ((encoderPinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoderPinB) == LOW) {
encoderPos++;
statusAlarme = HIGH;
} else {
encoderPos--;
statusAlarme = LOW;
}
encoderPinALast = n;
if (statusAlarme == LOW) {
display.setSegments(letraO, 1, 0); // Show the symbol of word O
display.setSegments(letraF, 1, 1); // Show the symbol of word F
display.setSegments(letraF, 1, 2); // Show the symbol of word F
display.setSegments(dataWithColon + 10, 1, 3); // Clear digit #4
}
if (statusAlarme == HIGH) {
//display.showNumberDec(1111, true, 4, 0);
display.setSegments(letraO, 1, 0); // Show the symbol of word O
display.setSegments(letraN, 1, 1); // Show the symbol of word N
display.setSegments(dataWithColon + 10, 1, 2); // Clear digit #3
display.setSegments(dataWithColon + 10, 1, 3); // Clear digit #4
}
statusGatilho = HIGH;
}
case 4: //Set the Hour of Time
n = digitalRead(encoderPinA);
if ((encoderPinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoderPinB) == LOW) {
encoderPos++;
hh++;
} else {
encoderPos--;
hh--;
}
encoderPinALast = n;
hh = constrain(hh, 0, 23);
display.showNumberDec(hh, true, 2, 0);
display.setSegments(letraT, 1, 2); // Show the symbol of word T
display.setSegments(letraI, 1, 3); // Show the symbol of word I
}
case 5: //Set the Minutes of Time
n = digitalRead(encoderPinA);
if ((encoderPinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoderPinB) == LOW) {
encoderPos++;
mm++;
} else {
encoderPos--;
mm--;
}
encoderPinALast = n;
mm = constrain(mm, 0, 59);
display.setSegments(letraT, 1, 0);
display.setSegments(letraI, 1, 1); // Show the symbol of word T
display.showNumberDec(mm, true, 2, 2); // Show the symbol of word I
}
case 6: //Set Time Adjustment
n = digitalRead(encoderPinA);
if ((encoderPinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoderPinB) == LOW) {
encoderPos++;
statusTempo = HIGH;
} else {
encoderPos--;
statusTempo = LOW;
}
encoderPinALast = n;
if (statusTempo == LOW) {
display.setSegments(letraO, 1, 0); // Show the symbol of word O
display.setSegments(letraF, 1, 1); // Show the symbol of word F
display.setSegments(letraF, 1, 2); // Show the symbol of word F
display.setSegments(dataWithColon + 10, 1, 3); // Clear digit #4
}
if (statusTempo == HIGH) {
//display.showNumberDec(1111, true, 4, 0);
display.setSegments(letraO, 1, 0); // Show the symbol of word O
display.setSegments(letraN, 1, 1); // Show the symbol of word N
display.setSegments(dataWithColon + 10, 1, 2); // Clear digit #3
display.setSegments(dataWithColon + 10, 1, 3); // Clear digit #4
}
}
encoderPinALast = n;
}
}
void loop() {
//Clear all digits of display
display.setSegments(dataWithColon + 10, 1, 0); // Clear digit #1
display.setSegments(dataWithColon + 10, 1, 1); // Clear digit #2
display.setSegments(dataWithColon + 10, 1, 2); // Clear digit #3
display.setSegments(dataWithColon + 10, 1, 3); // Clear digit #4
do { // Keep the display off and check the sensor PIR and the time of Alarm
if (linSW == 0) {
statusPIR = digitalRead(PIR);
}
hora = hour();
minuto = minute();
if (hora == horaAlarme && minuto == minutoAlarme && statusAlarme == HIGH) {
buzzer();
}
} while (statusPIR == LOW);
hora = hour();
minuto = minute();
if (hora == horaAlarme && minuto == minutoAlarme && statusAlarme == HIGH) {
buzzer();
}
//Set Time (adjustment of Hours and Minutes)
if (linSW == 0 && statusTempo == HIGH) {
setTime(hh, mm, 00, day(), month(), year());
RTC.set(now());
setSyncProvider(RTC.get);
statusTempo = LOW;
}
// Write data of Alarm into RTC
if (linSW == 0 && statusGatilho == HIGH) {
Wire.beginTransmission(DS1307_I2C_ADDRESS); // Open I2C line in write mode
Wire.write((byte)0x08); // Set the register pointer to (0x08)
Wire.write(horaAlarme); // Record at RTC memory the Hour of Alarm
Wire.write(minutoAlarme); // Record at RTC memory the Minute of Alarm
Wire.write(statusAlarme); // Record at RTC memory the Status of Alarm
Wire.endTransmission(); // End Write Transmission
statusGatilho == LOW;
}
if (linSW == 0) {
//Display Hour and Minutes
dezHora = hora / 10;
uniHora = hora % 10;
display.showNumberDec(dezHora, true, 1, 0);
display.setSegments(dataWithColon + uniHora, 1, 1);
display.showNumberDec(minuto, true, 2, 2);
delay(2000);
}
if (linSW == 0) {
temp = dht.readTemperature(false); // Read temperature in Celsius degrees (C)
//Optional Temperature in Fahrenheit (F). Remove the comments ("//") of following statement to use it.
//temp = dht.readTemperature(true); //Reading of Temperature in Fahrenheit degree (F)
//Display Temperature (C or F)
display.showNumberDec(temp, true, 2, 0); // Show Temperature in 2 digits begenning at Display #0 (first from left to right)
display.setSegments(Grau, 1, 2); // Show the symbol of degree ()
display.setSegments(Celsius, 1, 3); // Celsius symbol
//display.setSegments(Fahrenheit, 1, 3); // Optional Fahrenheit symbol. Remove the comments ("//") of following statement to use it.
delay(2000);
}
if (linSW == 0) {
umid = dht.readHumidity(); // Read Humidity (%)
//Display Relative Humidity (%)
display.showNumberDec(umid, true, 2, 0);
display.setSegments(Grau, 1, 2);
display.setSegments(UR, 1, 3);
delay(2000);
}
if (linSW == 0) {
tpo = temp - (100 - umid) / 5; // Dew Point calculation (aproximated)
//Optional calculation of Temperature in Fahrenheit degrees (F). Remove the comments ("//") of following statement before use it.
//tpo = (tpo * 18) / 10 + 32;
//Display Dew Point (C or F)
display.showNumberDec(tpo, true, 2, 0);
display.setSegments(UR, 1, 2);
display.setSegments(UR, 1, 3);
delay(2000);
}
}