/**
Horloge1
pour 02- LILYGO TTGO T5 + 2.13" E-Paper Screen (250 x 122 px)
OK compilé avec type de carte = "ESP32 Dev Module"
**/
#define version "3.3"
#include <stdint.h>
#include <GxEPD.h> // note: cette lib inclue la lib "Adafruit_GFX.h" dans laquelle se trouvent les fonctions de base
#include "SPI.h"
#include <Wire.h>
#include "uRTCLib.h"
#include "DHT.h"
uRTCLib rtc(0x68);
//! There are three versions of the 2.13 screen
//#include <GxGDE0213B1/GxGDE0213B1.h> // 2.13" b/w
//#include <GxGDEH0213B72/GxGDEH0213B72.h> // 2.13" b/w new panel
#include <GxGDEH0213B73/GxGDEH0213B73.h> // 2.13" b/w newer panel
#include "chiffres/60_75/chiffres60_75.c"
// FreeFonts from Adafruit_GFX
#include <Fonts/FreeMonoBold9pt7b.h>
#include <Fonts/FreeMonoBold12pt7b.h>
#include <Fonts/FreeMonoBold18pt7b.h>
#include <Fonts/FreeMonoBold24pt7b.h>
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>
#define SPI_MOSI 23
#define SPI_MISO -1
#define SPI_CLK 18
#define ELINK_SS 5
#define ELINK_BUSY 4
#define ELINK_RESET 16
#define ELINK_DC 17
#define SDCARD_SS 13
#define SDCARD_CLK 14
#define SDCARD_MOSI 15
#define SDCARD_MISO 2
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
#define DHTPIN 19 // Digital pin connected to the DHT sensor
//#define bouton1 39
//#define led1 12 //const int led1 = 12;
const int led1 = 12;
const int bouton1 = 39;
bool led1_etat = LOW;
bool bouton1_etat; // état bouton1
const uint32_t partial_update_period_s = 1;
const uint32_t full_update_period_s = 6 * 60 * 60;
uint32_t start_time;
uint32_t next_time;
uint32_t previous_time;
uint32_t previous_full_update;
uint32_t memoM1 = 0;
uint32_t memoM2 = 0;
uint32_t currentMillis=0;
const uint32_t tempo1 = 2000; // 2000 ms = 2s
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 2 /* Time ESP32 will go to sleep (secondes) */
uint8_t annee;
uint8_t mois;
uint8_t jour;
uint8_t jour_de_la_semaine;
uint8_t heure=0;
uint8_t minute=0;
uint8_t memo_minute=0;
uint8_t seconde=0;
GxIO_Class io(SPI, ELINK_SS, ELINK_DC, ELINK_RESET);
GxEPD_Class display(io, ELINK_RESET, ELINK_BUSY);
SPIClass sdSPI(VSPI);
const char *skuNum = "SKU:H239";
int startX = 40, startY = 10;
DHT dht(DHTPIN, DHTTYPE);
void Set_Time()
{
// appelée par appui sur le bouton (en bord de carte) après avoir correctement paramétré ces données.
uint8_t second = 3;
uint8_t minute = 39;
uint8_t hour = 5;
uint8_t dayOfWeek = 4; // toutefois le jour de la semaine sera recalculé plus bas, en temps réel
uint8_t dayOfMonth = 20;
uint8_t month = 1;
uint8_t year = 21; // 2021
// ensuite je re-commente la ligne ci-dessous pour éviter de reprogrammer l'heure en appuyant sur le bouton par inadvertance...
// rtc.set(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
}
void setup()
{
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
delay (2000);
pinMode(bouton1, INPUT);
pinMode(led1, OUTPUT);
//Serial.begin(115200);
//Serial.println("//Serial OK");
#ifdef ARDUINO_ARCH_ESP8266
URTCLIB_WIRE.begin(0, 2); // D3 and D4 on ESP8266
#else
URTCLIB_WIRE.begin();
#endif
start_time = next_time = previous_time = previous_full_update = millis();
display.init();
display.setRotation(1);
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
display.setFont(&FreeMonoBold12pt7b);
display.setCursor(0, 0);
//esp_sleep_enable_ext0_wakeup((gpio_num_t)BUTTON_PIN, LOW);
display.fillScreen(GxEPD_WHITE);
// display.eraseDisplay();
display.update();
dht.begin();
}
void print_big_chiffre(uint8_t nb, uint16_t x0 ,uint16_t y0) //avec bitmaps perso
{
uint16_t w0=60;
uint16_t h0=75;
switch (nb)
{
case 0: {display.drawBitmap(chiffre0, x0, y0, w0, h0, GxEPD_BLACK); } break;
case 1: {display.drawBitmap(chiffre1, x0, y0, w0, h0, GxEPD_BLACK); } break;
case 2: {display.drawBitmap(chiffre2, x0, y0, w0, h0, GxEPD_BLACK); } break;
case 3: {display.drawBitmap(chiffre3, x0, y0, w0, h0, GxEPD_BLACK); } break;
case 4: {display.drawBitmap(chiffre4, x0, y0, w0, h0, GxEPD_BLACK); } break;
case 5: {display.drawBitmap(chiffre5, x0, y0, w0, h0, GxEPD_BLACK); } break;
case 6: {display.drawBitmap(chiffre6, x0, y0, w0, h0, GxEPD_BLACK); } break;
case 7: {display.drawBitmap(chiffre7, x0, y0, w0, h0, GxEPD_BLACK); } break;
case 8: {display.drawBitmap(chiffre8, x0, y0, w0, h0, GxEPD_BLACK); } break;
case 9: {display.drawBitmap(chiffre9, x0, y0, w0, h0, GxEPD_BLACK); } break;
}
}
void affiche_heure()
{
uint16_t box1_x = 0;
uint16_t box1_y = 5;
uint16_t box1_w = 245;
uint16_t box1_h = 85;
uint16_t cursor_y = box1_y;
display.fillRect(box1_x, box1_y, box1_w, box1_h, GxEPD_WHITE);
display.setCursor(box1_x, cursor_y);
uint8_t x0= box1_x;
uint8_t heures_unites;
uint8_t heures_dizaines;
heures_unites = heure %10;
heures_dizaines = heure /10;
print_big_chiffre(heures_dizaines, x0, cursor_y);
print_big_chiffre(heures_unites, x0+56, cursor_y);
x0+=133;
uint8_t minutes_unites ;
uint8_t minutes_dizaines;
minutes_unites = minute %10;
minutes_dizaines = minute /10;
print_big_chiffre(minutes_dizaines, x0, cursor_y);
print_big_chiffre(minutes_unites, x0+56, cursor_y);
display.setCursor(106, 70);
display.setTextSize(3);
display.println(":");
display.updateWindow(box1_x, box1_y, box1_w, box1_h, true);
}
void calcul_jour_de_la_semaine()
{
// d'après l'Algorithme de Mike Keith
uint16_t d, m, y, z, jds;
d=jour;
m=mois;
y=annee;
if (m>=3)
{
jds = ( ((23*m)/9) + d + 4 + y + (y/4) - (y/100) + (y/400) - 2 ) % 7;
}
else
{
z = y-1;
jds = ( ((23*m)/9) + d + 4 + y + (z/4) - (z/100) + (z/400) ) % 7;
}
jour_de_la_semaine = jds;
}
uint8_t decToBcd( int val )
{
return (uint8_t) ((val / 10 * 16) + (val % 10));
}
String conv_time(uint8_t t)
{
String r;
r=String(t);
if (t<10) {r="0"+r;}
return r;
}
void affiche_date()
{
uint16_t box2_x = 0;
uint16_t box2_y = 121-20;
uint16_t box2_w = 175;
uint16_t box2_h = 20;
display.fillRect(box2_x, box2_y, box2_w, box2_h, GxEPD_WHITE);
String date;
calcul_jour_de_la_semaine();
switch (jour_de_la_semaine)
{
case 0: { date+="DIM ";} break;
case 1: { date+="LUN ";} break;
case 2: { date+="MAR ";} break;
case 3: { date+="MER ";} break;
case 4: { date+="JEU ";} break;;
case 5: { date+="VEN ";} break;
case 6: { date+="SAM ";} break;
}
date += String(conv_time(jour))+" ";
switch (mois)
{
case 1: {date+="JAN"; } break;
case 2: {date+="FEV"; } break;
case 3: {date+="MARS";} break;
case 4: {date+="AVR"; } break;
case 5: {date+="MAI"; } break;
case 6: {date+="JUIN";} break;
case 7: {date+="JUIL";} break;
case 8: {date+="AOUT";} break;
case 9: {date+="SEPT";} break;
case 10: {date+="OCT"; } break;
case 11: {date+="NOV"; } break;
case 12: {date+="DEC"; } break;
}
date += " 20"+String(annee);
//date;
uint16_t x0=290, y0=75;
display.setTextColor(GxEPD_BLACK);
display.setFont(&FreeMonoBold9pt7b);
display.setTextSize(1);
display.setCursor(0, display.height() -2);
display.print(date);
display.updateWindow(box2_x, box2_y, box2_w, box2_h, true);
currentMillis = millis();
if (currentMillis > 2000) memoM1= currentMillis - 2000; // pour afficher +rapidement au départ
}
void affiche_temperature(double T)
{
uint16_t y0 = 122; // position verticale du bord supérieur de la box
uint16_t dy = 34; // dimension verticale de la box
uint16_t box3_x = 180; // position horizontale du bord gauche de la box
uint16_t box3_y = y0-dy;
uint16_t box3_w = 65; // largeur de la box
uint16_t box3_h = dy;
display.fillRect(box3_x, box3_y, box3_w, box3_h, GxEPD_WHITE); // efface la surface de la box (en RAM de l'afficheur)
display.setTextColor(GxEPD_BLACK);
display.setFont(&FreeMonoBold12pt7b);
display.setTextSize(1,2);
display.setCursor(box3_x, y0-4);
display.print(T,1);
display.setFont(&FreeMonoBold9pt7b);
display.setTextSize(1);
display.setCursor(box3_x +30, display.height() -20);
display.print("o"); // le signe 'degré' (° Celsius en l'occurence) , absent de la police de caractères
// display.drawRect(box3_x, box3_y, box3_w, box3_h, GxEPD_BLACK); // pour test visuel de la position et taille de la box
display.updateWindow(box3_x, box3_y, box3_w, box3_h, true); // affichage physique sur l'e-paper
}
void affichages()
{
affiche_heure();
affiche_date();
float H1 = dht.readHumidity();
double T1 = dht.readTemperature(); // °C par defaut
//Serial.print(F("Temperature: ")); ////Serial.println(T1);
affiche_temperature(T1);
}
void loop()
{
bouton1_etat = digitalRead(bouton1);
if (bouton1_etat == 0)
{
Set_Time();
for(int n=0; n<20; n++)
{
digitalWrite(led1, HIGH);
delay(20);
digitalWrite(led1, LOW);
delay(20);
}
}
currentMillis = millis();
if(currentMillis - memoM1 >= tempo1)
{
memoM1 = currentMillis;
// B = digitalRead(BUTTON_PIN);
digitalWrite(led1, HIGH); // allume la led (ajoutée) (pour un bref petit flash) -> test visuel du fonctionnement
rtc.refresh();
annee=rtc.year();
mois=rtc.month();
jour=rtc.day();
jour_de_la_semaine=rtc.dayOfWeek();
heure = rtc.hour();
memo_minute = minute;
minute = rtc.minute();
seconde = rtc.second();
digitalWrite(led1, LOW); // éteint la led ajoutée
if(minute != memo_minute)
{
affichages();
}
}
esp_light_sleep_start();
}