/*
Projet : Thermostat Intelligent HomeHub
Version : 1.20
Date : 2025-07-13
Auteur : Daniel Talbot Technicien
Description : Application du style graphique au sous-menu Température de nuit
*/
#include <Wire.h>
#include <SPI.h>
#include <RTClib.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_FT6206.h>
#include <EEPROM.h>
#include <DHT.h>
#include <math.h>
#define DHTPIN 11
#define DHTTYPE DHT22
#define TFT_CS 10
#define TFT_DC 9
#define TFT_RST 8
RTC_DS1307 rtc;
DHT dht(DHTPIN, DHTTYPE);
Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST);
Adafruit_FT6206 ctp = Adafruit_FT6206();
enum Mode { MODE_MENU_PRINCIPAL, MODE_REG_TEMP_JOUR, MODE_REG_TEMP_NUIT };
Mode modeActif = MODE_MENU_PRINCIPAL;
struct Reglages {
float tempJour;
float tempNuit;
bool enCelsius;
bool langueFR;
};
Reglages reglages;
float ancienneTempAffichee = -100.0;
void initialiserMateriel();
void afficherMenuPrincipal();
void afficherHorloge();
void afficherTemperature();
void reglerTemperatureJour();
void reglerTemperatureNuit();
void sauvegarderReglages();
void chargerReglages();
void gererTactile();
void gererTactileReglageJour();
void gererTactileReglageNuit();
void afficherValeurTemperatureJour();
void afficherValeurTemperatureNuit();
void setup() {
initialiserMateriel();
chargerReglages();
afficherMenuPrincipal();
}
void loop() {
if (modeActif == MODE_MENU_PRINCIPAL) {
gererTactile();
} else if (modeActif == MODE_REG_TEMP_JOUR) {
gererTactileReglageJour();
} else if (modeActif == MODE_REG_TEMP_NUIT) {
gererTactileReglageNuit();
}
}
void initialiserMateriel() {
rtc.begin();
dht.begin();
tft.begin();
tft.setRotation(1);
tft.fillScreen(ILI9341_BLACK);
if (!ctp.begin()) {
while (1);
}
}
void afficherMenuPrincipal() {
tft.fillScreen(ILI9341_BLACK);
tft.setTextSize(3);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(20, 20);
tft.print("Menu Principal");
tft.setTextSize(2);
tft.setTextColor(ILI9341_CYAN);
tft.setCursor(20, 80); tft.print("1. Heure/Date");
tft.setCursor(20, 120); tft.print("2. Temperature");
tft.setCursor(20, 160); tft.print("3. Reglage Jour");
tft.setCursor(20, 200); tft.print("4. Reglage Nuit");
tft.setCursor(20, 240); tft.print("5. Langue / Unites");
modeActif = MODE_MENU_PRINCIPAL;
}
void afficherHorloge() {
DateTime now = rtc.now();
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(40, 100);
tft.setTextColor(ILI9341_YELLOW);
tft.setTextSize(3);
tft.print(now.hour());
tft.print(" : ");
tft.print(now.minute());
delay(2000);
afficherMenuPrincipal();
}
void afficherTemperature() {
float t = dht.readTemperature(reglages.enCelsius ? false : true);
tft.fillScreen(ILI9341_NAVY);
// Titre stylisé centré
const char* titre = "Temperature ambiante";
tft.setTextSize(2);
tft.setTextColor(ILI9341_CYAN);
int16_t x1, y1;
uint16_t w, h;
tft.getTextBounds(titre, 0, 0, &x1, &y1, &w, &h);
int x = (320 - w) / 2;
tft.setCursor(x, 20);
tft.print(titre);
// Dessin d'une icône simple de thermomètre
tft.fillCircle(50, 140, 10, ILI9341_RED);
tft.fillRoundRect(45, 90, 10, 50, 5, ILI9341_RED);
// Affichage température numérique
char buffer[10];
dtostrf(t, 4, 1, buffer);
tft.setTextSize(5);
tft.setTextColor(ILI9341_WHITE);
tft.getTextBounds(buffer, 0, 0, &x1, &y1, &w, &h);
x = (320 - w) / 2;
tft.setCursor(x, 100);
tft.print(buffer);
tft.print(reglages.enCelsius ? "C" : "F");
// Cadre décoratif autour du texte
uint16_t totalWidth = w + 60;
uint16_t totalHeight = h + 40;
int rectX = x - 20;
int rectY = 100 - 20;
tft.drawRoundRect(rectX, rectY, totalWidth, totalHeight, 10, ILI9341_YELLOW);
delay(2500);
afficherMenuPrincipal();
}
void reglerTemperatureJour() {
ancienneTempAffichee = -100.0;
tft.fillScreen(ILI9341_NAVY);
const char* titre = "Temperature de jour";
tft.setTextSize(2);
tft.setTextColor(ILI9341_YELLOW);
int16_t x1, y1;
uint16_t w, h;
tft.getTextBounds(titre, 0, 0, &x1, &y1, &w, &h);
int x = (320 - w) / 2;
tft.setCursor(x, 20);
tft.print(titre);
tft.fillRoundRect(20, 180, 60, 40, 10, ILI9341_BLUE);
tft.setTextSize(3); tft.setTextColor(ILI9341_WHITE);
tft.setCursor(40, 190); tft.print("-");
tft.fillRoundRect(240, 180, 60, 40, 10, ILI9341_RED);
tft.setCursor(260, 190); tft.print("+");
tft.fillRoundRect(120, 180, 80, 40, 10, ILI9341_GREEN);
tft.setCursor(140, 190); tft.print("OK");
afficherValeurTemperatureJour();
modeActif = MODE_REG_TEMP_JOUR;
}
void afficherValeurTemperatureJour() {
tft.fillRect(0, 90, 320, 60, ILI9341_NAVY);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(5);
char buffer[10];
dtostrf(reglages.tempJour, 4, 1, buffer);
int16_t x1, y1; uint16_t w, h;
tft.getTextBounds(buffer, 0, 0, &x1, &y1, &w, &h);
int x = (320 - w) / 2;
tft.setCursor(x, 100);
tft.print(buffer);
tft.print(reglages.enCelsius ? "C" : "F");
// Cadre décoratif autour du texte
uint16_t totalWidth = w + 60;
uint16_t totalHeight = h + 40;
int rectX = x - 20;
int rectY = 100 - 20;
tft.drawRoundRect(rectX, rectY, totalWidth, totalHeight, 10, ILI9341_YELLOW);
ancienneTempAffichee = reglages.tempJour;
}
void reglerTemperatureNuit() {
ancienneTempAffichee = -100.0;
tft.fillScreen(ILI9341_DARKCYAN);
const char* titre = "Temperature de nuit";
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
int16_t x1, y1;
uint16_t w, h;
tft.getTextBounds(titre, 0, 0, &x1, &y1, &w, &h);
int x = (320 - w) / 2;
tft.setCursor(x, 20);
tft.print(titre);
tft.fillRoundRect(20, 180, 60, 40, 10, ILI9341_BLUE);
tft.setTextSize(3); tft.setTextColor(ILI9341_WHITE);
tft.setCursor(40, 190); tft.print("-");
tft.fillRoundRect(240, 180, 60, 40, 10, ILI9341_RED);
tft.setCursor(260, 190); tft.print("+");
tft.fillRoundRect(120, 180, 80, 40, 10, ILI9341_GREEN);
tft.setCursor(140, 190); tft.print("OK");
afficherValeurTemperatureNuit();
modeActif = MODE_REG_TEMP_NUIT;
}
void afficherValeurTemperatureNuit() {
tft.fillRect(0, 90, 320, 60, ILI9341_DARKCYAN);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(5);
char buffer[10];
dtostrf(reglages.tempNuit, 4, 1, buffer);
int16_t x1, y1; uint16_t w, h;
tft.getTextBounds(buffer, 0, 0, &x1, &y1, &w, &h);
int x = (320 - w) / 2;
tft.setCursor(x, 100);
tft.print(buffer);
tft.print(reglages.enCelsius ? "C" : "F");
// Cadre décoratif autour du texte
uint16_t totalWidth = w + 60;
uint16_t totalHeight = h + 40;
int rectX = x - 20;
int rectY = 100 - 20;
tft.drawRoundRect(rectX, rectY, totalWidth, totalHeight, 10, ILI9341_YELLOW);
ancienneTempAffichee = reglages.tempNuit;
}
void sauvegarderReglages() {
EEPROM.put(0, reglages);
}
void chargerReglages() {
EEPROM.get(0, reglages);
if (isnan(reglages.tempJour) || reglages.tempJour < 5 || reglages.tempJour > 35) {
reglages.tempJour = 21.0;
reglages.tempNuit = 18.0;
reglages.enCelsius = true;
reglages.langueFR = true;
sauvegarderReglages();
}
}
void gererTactile() {
if (!ctp.touched()) return;
TS_Point p = ctp.getPoint();
int tx = p.y;
int ty = 240 - p.x;
if (ty > 80 && ty < 100) { afficherHorloge(); }
else if (ty > 120 && ty < 140) { afficherTemperature(); }
else if (ty > 160 && ty < 180) { reglerTemperatureJour(); }
else if (ty > 200 && ty < 220) { reglerTemperatureNuit(); }
else if (ty > 240 && ty < 260) {
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(20, 100);
tft.setTextColor(ILI9341_RED);
tft.setTextSize(2);
tft.print("Fonction Langue/Unites");
delay(2000);
afficherMenuPrincipal();
}
}
void gererTactileReglageJour() {
if (!ctp.touched()) return;
TS_Point p = ctp.getPoint();
int tx = p.y;
int ty = 240 - p.x;
if (ty > 180 && ty < 220) {
if (tx > 20 && tx < 80) reglages.tempJour -= 0.5;
else if (tx > 240 && tx < 300) reglages.tempJour += 0.5;
else if (tx > 120 && tx < 200) {
sauvegarderReglages();
afficherMenuPrincipal();
return;
}
}
if (ancienneTempAffichee != reglages.tempJour) {
afficherValeurTemperatureJour();
delay(250);
}
}
void gererTactileReglageNuit() {
if (!ctp.touched()) return;
TS_Point p = ctp.getPoint();
int tx = p.y;
int ty = 240 - p.x;
if (ty > 180 && ty < 220) {
if (tx > 20 && tx < 80) reglages.tempNuit -= 0.5;
else if (tx > 240 && tx < 300) reglages.tempNuit += 0.5;
else if (tx > 120 && tx < 200) {
sauvegarderReglages();
afficherMenuPrincipal();
return;
}
}
if (ancienneTempAffichee != reglages.tempNuit) {
afficherValeurTemperatureNuit();
delay(250);
}
}
Temp.
Intérieur