![]() |
Gestion d'un volet plus ou moins lourd |
avril 2020 |
Bon OK c'est du déjà vu ! Mais si l'on ajoute un suivi de la durée d'ensoleillement avec un beau petit graphique c'est plus tentant !
Remarque préliminaire : Si vous désirez simplement commander un volet qui possède déjà un moteur et des fils de commande, cet article ne concerne pas ce type de cas
. Pour le cas d'un volet déjà équipé il vous suffit d'utiliser une carte HW-622 (Esp-8266 1 relai) de Yunshan décrite dans un autre article du site et pour quelques
euros vous aurez un système que vous pourrez commander à distance, tout est déjà disponible sur la carte et il ne reste que du très très facile pour obtenir un résultat.
Ici nous allons nous intéresser à un volet qui ne possède aucune électronique , ni moteur, ni commande...
Que le volet ou la porte soit petite ou trés grosse cela ne changera rien ou pas grand-chose, nous allons voir deux cas avec des moteurs bien différents...
Un petit cahier des charges :
- Ouverture du rideau dès l'arrivée d'un seuil de luminosité bien précis mais réglable.
- Fermeture du rideau dès que le niveau de luminosité déterminé n'est plus atteint.
- Mémorisation des heures d'ouverture et de fermeture (auto. heures soleil) et envoi du delta à un serveur Mosquitto.
- Possibilité d'ouvertures et de fermetures forcées sans modification de la mémorisation et de l'envoie des vrais horaires à Mosquitto.
- Protection de l'état actuel du moteur dans l'eeprom pour éviter des détériorations du rideau.
- Utilisation d'une horloge RTC précise et sauvegardée pour des calculs précis.
- Affichage sur un petit écran de l'horaire d'ouverture ou de fermeture automatique.
- Réglage du mouvement moteur nécessaire à l'ouverture et à la fermeture.
- Paramétrage complet par l'utilisateur par menus (réseau, moteur, seuil de luminosité).
// Pins de racordement au moteur
int mot_1 = D5; // Gpio 14
int mot_2 = D6; // Gpio 12
int mot_3 = D7; // Gpio 13
int mot_4 = D8; // Gpio 15
// Détermine l'ordre d'alimentation des bobines du moteur en avance et en arriere
const byte t_av[] = {0b00001000,0b00001100,0b00000100,0b00000110,0b00000010,0b00000011,0b00000001,0b00001001};
const byte t_arr[] = {0b00000001,0b00000011,0b00000010,0b00000110,0b00000100,0b00001100,0b00001000,0b00001001};
// Avance équivalent d'un pas
void av_1_tour(){
for (uint8_t pas = 0; pas < 8; pas++){
digitalWrite(mot_1, bitRead(t_av[pas],3));
digitalWrite(mot_2, bitRead(t_av[pas],2));
digitalWrite(mot_3, bitRead(t_av[pas],1));
digitalWrite(mot_4, bitRead(t_av[pas],0));
delay(v_vit);
}
}
// Arriere équivalent d'un pas
void arr_1_tour(){
for (uint8_t pas = 0; pas < 8; pas++){
digitalWrite(mot_1, bitRead(t_arr[pas],3));
digitalWrite(mot_2, bitRead(t_arr[pas],2));
digitalWrite(mot_3, bitRead(t_arr[pas],1));
digitalWrite(mot_4, bitRead(t_arr[pas],0));
delay(v_vit);
}
}
// Coupe l'alim sur le moteur
void stop_moteur(){
digitalWrite(mot_1, LOW);
digitalWrite(mot_2, LOW);
digitalWrite(mot_3, LOW);
digitalWrite(mot_4, LOW);
}
// Pins de racordement au moteur
int mot_avance = D5;
int mot_sens = D6;
// Ferme ou ouvre le rideau v_com = O Ouvre F Ferme
void action_rideau(char v_com){
uint16_t x = 0;
if (v_com == 'F') digitalWrite(mot_sens, HIGH); else digitalWrite(mot_sens, LOW);
analogWrite(mot_avance,200);
while( x < v_nbtour ){
delay(v_vit);
x++;
}
analogWrite(mot_avance,0);
}
Reste à voir le paramétrage de la carte driver :
- Intensité maximum que la carte laissera passer au moteur : SW1 à SW3 + le petit S1 permet un réglage entre 0.3A jusqu'à 3A (perso 1A).
digitalRead(this->PinDT)
this->li_rot_dt()
// retourne etat du signal DT
bool sai_oled::li_rot_dt(){
uint8_t lect_octet;
Wire.requestFrom(adr_i2c_4585, 1);
lect_octet = Wire.read();
Wire.endTransmission();
return bitRead(lect_octet, this->PinDT);
}
Attention pour la librairie de l'écran Oled "SSD1306Wire.h", c'est celle-ci
qu'il faut télécharger sur le site "github", elle est différente de celle qui est disponible dans l'environnement "Arduino".
On la reconnait au "w" de Wire qui doit dans notre cas être une majuscule. (Merci à Guy, pour cette précision qui peut éviter pas mal de galère !).
Merci également à tous les contributeurs(46) de ce petit package qui contient plusieurs librairies. Vous devez charger le zip complet comme montré sur
l'image ci-contre.
Le programme n'est qu'un premier jet ! il n'integre pas la sécurité du controle de l'intensité sur le moteur, alors attention
pour l'instant il ne faut faire que des tests et ne surtout pas laisser un doigt dans le volet !!!
---------------- A UTILISER AVEC PRUDENCE ! ----------------
Le code de base qui doit vous permettre de démarrer pour vos propres projets...
// gest_volet.ino
// Ouverture / Fermeture auto du rideau, d'un volet ou d'une porte
// en fonction de la lumiere
// config pour un Wemos 8266 D1 mini
// version avec une carte driver T6560 et un moteur NEMA17
// castoo.fr
// novembre 2020
// V1.6
#include "ESP8266WiFi.h"
#include "PubSubClient.h"
#include "Wire.h"
#include "SSD1306Wire.h"
#include "sai_oled_i2c.h"
#include "menu_oled_i2c.h"
#include "ESP_EEPROM.h"
#include "RTClib.h"
// Mettre en commentaire cette ligne après débugage
//#define debug_anemo
// Pins de racordement au moteur
int mot_avance = D5;
int mot_sens = D6;
// Pins de racordement I2C (OLED et RTC)
int i2c_sda = D2;
int i2c_scl = D1;
// Pins de racordement de l'encodeur rotatif sur l'extention I2C (economie de gpio voir explication sur site castoo.fr)
int encod_dt = 1; // P1 => broche 5 de l'adaptateur I2C LCD
int encod_clk = 2; // P2 => broche 6 de l'adaptateur I2C LCD
int encod_sw = 0; // P0 => broche 4 de l'adaptateur I2C LCD
// Adresse I2C du 4585 par défaut il est (en principe) à 0x3F si ce n'est pas le cas
// il faut modifier dans les deux class le #define adr_i2c_4585 0x3F
// Création instance objet écran OLED
SSD1306Wire display(0x3c, i2c_sda, i2c_scl); // I2C sur un esp8266 donc D2 > SDA & D1 > SCL
// init menu oled (clk, dt, sw et nom de l'objet LCD)
menu_oled mes_menus_oled(encod_clk, encod_dt, encod_sw, display);
// init saisie (clk, dt, sw et nom de l'objet LCD)
sai_oled mon_sai_oled(encod_clk, encod_dt, encod_sw, display);
// Création instance objet RTC
RTC_DS3231 RTC; // Instance du module RTC de type DS3231 sur I2C
WiFiClient espClient; // déclaration Objet wifi
PubSubClient client(espClient); // déclaration objet mosquitto
int photo_resist = A0; // Modele GL 5528 avec résistance de rappel de 10k à la masse
int v_lumiere = 0; // Valeur lue de la photo-résistance
const String s_jour[] = {"Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"};
bool force_ouvert = false; // Positionné à true si bouton utilisé pour ouverture
bool force_ferme = false; // Positionné à true si bouton utilisé pour fermeture
int d_soleil; // Calcul durée ensoleillement de la journée minute
char msg_envoye[50]; // Message MQTT
DateTime h_actuel; // heure actuelle
int d_actuel; // date actuelle
int v_dsoir; // date derniere mesure nuit
int v_dmatin; // date derniere mesure matin
bool v_nuit = false; // indicateur jour / nuit
// gestion de l'eeprom
struct s_memo_rom {
DateTime matin; // Heure ouverture avec soleil
DateTime soir; // Heure fermeture fin soleil
bool rid_ouvert; // Derniere modification de l'état du rideau auto ou manuelle
char wifi_ssid[50]; // Box hebergement "Broker" serveur mqtt
char wifi_passe[25]; // passe serveur
char ip_mqtt[15]; // IP mosquitto le port 1883 est en dur dans le code
char login_mqtt[25]; // Login mosquitto
char passe_mqtt[25]; // Passe mosquitto
int nbpas1tour; // temps du signal SCK+ pour faire un tour (specifique au moteur et au réglage de pas (1/8 1/2...))
int nb_tour_ouvre; // Nb de tour pour ouverture
int nb_tour_ferme; // Nb de tour pour fermeture
int seuil_lum; // Valeur du seuil de luminosité (suivant type de photo-résistance)
} memo_rom, v_ram;
int adr_deb_memo_rom = 0;
// Choix selectionné dans menu
int A_menu;
const int nb_ch_menuA = 6;
const String ch_menuA[] = {"Ouverture / Fermeture", "Param nb tour moteur", "Param date heure", "Param Réseaux", "Param seuil lumiere", "Retour"};
String _ch_menuA = * ch_menuA;
int B_menu;
const int nb_ch_menuB = 2;
const String ch_menuB[] = {"Vérif. Date Heure", "Retour"}; // A completer prochaine version...
String _ch_menuB = * ch_menuB;
int C_menu;
const int nb_ch_menuC = 6;
const String ch_menuC[] = {"Temps par tour", "Nb tour ouvre", "Test ouvre", "Nb tour ferme", "Test ferme", "Retour"};
String _ch_menuC = * ch_menuC;
int D_menu;
const int nb_ch_menuD = 6;
const String ch_menuD[] = {"Login Wifi", "Adresse IP mosquitto", "Login mosquitto", "Passe mosquitto", "Aff. param Wifi", "Retour"};
String _ch_menuD = * ch_menuD;
String ch_result;
// Initialise des valeurs standard pour le LCD
void prep_aff_LCD(uint8_t typ_pol) {
display.clear();
if(typ_pol == 16) display.setFont(ArialMT_Plain_16);
else if(typ_pol == 24) display.setFont(ArialMT_Plain_16);
else display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
}
// Ferme ou ouvre le rideau v_com = O Ouvre F Ferme
void action_rideau(char v_com){
#ifdef debug_anemo
Serial.println("Entree dans action_rideau : " + v_com);
#endif
uint16_t x = 0;
prep_aff_LCD(16);
if (v_com == 'F'){
digitalWrite(mot_sens, HIGH);
display.drawString(20, 20, "Fermeture");
display.drawString(20, 40, "en cours");
}else{
digitalWrite(mot_sens, LOW);
display.drawString(20, 20, "Ouverture");
display.drawString(20, 40, " en cours");
}
display.display();
analogWrite(mot_avance,200);
while( x < v_ram.nb_tour_ouvre ){
delay(v_ram.nbpas1tour);
x++;
}
analogWrite(mot_avance,0);
}
// ------------------- Cnx au serveur Raspberry Mosquitto ------------------
void setup_wifi() {
#ifdef debug_anemo
Serial.println("Entree dans setup_wifi");
#endif
delay(10);
WiFi.begin(v_ram.wifi_ssid, v_ram.wifi_passe);
prep_aff_LCD(10);
display.drawString(10, 30, "Recherche wifi :");
display.display();
while (WiFi.status() != WL_CONNECTED) {
prep_aff_LCD(10);
display.drawString(30, 30, " WIFI ");
display.display();
delay(450);
prep_aff_LCD(10);
display.drawString(30, 30, "<<<<...>>>>");
display.display();
delay(50);
if(!mes_menus_oled.li_rot_sw()){
prep_aff_LCD(10);
display.drawString(10, 10, "Erreur cnx wifi");
display.drawString(10, 20, "Memo nouveau SSID");
display.drawString(10, 30, "Relancer wifi M/A");
display.display();
delay(300);
while(mes_menus_oled.li_rot_sw()){delay(10);}
return;
}
}
prep_aff_LCD(16);
display.drawString(25, 30, "Wifi OK");
display.display();
delay(500);
randomSeed(micros());
}
// ----------------------------- Cnx à mosquitto ------------------------
void reconnect() {
#ifdef debug_anemo
Serial.println("Entree dans reconnect");
#endif
while (!client.connected()) {
prep_aff_LCD(10);
display.drawString(10, 30, "Recherche mosquitto :");
display.display();
String clientId = "ESP8266Ensoleillement-"; // Creatation d'un ID aléatoire (identification ESP sur mosquitto)
clientId += String(random(0xffff), HEX);
if (!client.connect(clientId.c_str(), v_ram.login_mqtt, v_ram.passe_mqtt)) {
prep_aff_LCD(10);
display.drawString(20, 30, " MQTT ");
display.display();
delay(4000);
prep_aff_LCD(10);
display.drawString(20, 30, "<<<<...>>>>");
display.display();
delay(1000);
}
if(!mes_menus_oled.li_rot_sw()){
prep_aff_LCD(10);
display.drawString(10, 10, "Erreur cnx MQTT");
display.drawString(10, 20, "Memo nouveau param");
display.drawString(10, 30, "Relancer wifi M/A");
display.display();
delay(300);
while(mes_menus_oled.li_rot_sw()){delay(10);}
return;
}
}
prep_aff_LCD(16);
display.drawString(10, 30, "Mosquitto OK");
display.display();
delay(500);
}
// Converti la date en string
String affiche_date(DateTime datetime){
String jour = "";
jour = s_jour[datetime.dayOfTheWeek()] + " " + String(datetime.day())+ "/" + String(datetime.month())+ "/" + String(datetime.year(),DEC);
return jour;
}
// Converti l'heure en string
String affiche_heure(DateTime datetime){
String heure = "";
heure = String(datetime.hour())+ ":" + String(datetime.minute())+ ":" + String(datetime.second());
return heure;
}
// Affiche compte-rendu enregistrement eeprom param wifi
void aff_param_wifi(){
delay(200);
prep_aff_LCD(10);
display.drawString(0, 0, "Parametre Wifi");
display.drawString(0, 10, "ssid: " + String(v_ram.wifi_ssid));
display.drawString(0, 20, "pass: " + String(v_ram.wifi_passe));
display.drawString(0, 30, "ip : " + String(v_ram.ip_mqtt));
display.drawString(0, 40, "logMqtt : ");
display.drawString(40, 40, String(v_ram.login_mqtt));
display.drawString(0, 50, "pasMqtt : " + String(v_ram.passe_mqtt));
display.display();
delay(300);
while(mes_menus_oled.li_rot_sw()){delay(10);}
}
// Affiche compte-rendu enregistrement eeprom
void aff_eeprom(bool lect = true, bool memo_ok = false){
delay(200);
prep_aff_LCD(10);
if(lect) display.drawString(20, 0, "Lecture EEPROM"); else display.drawString(20, 0, "Ecriture EEPROM");
display.drawString(0, 10, "Matin : " + affiche_heure(v_ram.matin));
display.drawString(0, 20, affiche_date(v_ram.matin));
display.drawString(0, 30, "Soir : " + affiche_heure(v_ram.soir));
display.drawString(0, 40, affiche_date(v_ram.soir));
display.drawString(0, 50, "Rideau : ");
if(v_ram.rid_ouvert) display.drawString(35, 50, "Ouvert");
else display.drawString(35, 50, "Fermé");
display.display();
delay(1000);
}
// Lecture eeprom
void lecture_eeprom(){
EEPROM.begin(sizeof(s_memo_rom));
prep_aff_LCD(16);
display.drawString(15, 30, "Lecture eeprom");
display.display();
delay(300);
EEPROM.get(adr_deb_memo_rom, memo_rom);
delay(300);
// Si les dates mémorisées sont > à la date du jour il y a un problème !
//if(memo_rom.matin > RTC.now()) v_ram.matin = RTC.now(); else v_ram.matin = memo_rom.matin;
v_ram.matin = memo_rom.matin;
//if(memo_rom.soir > RTC.now()) v_ram.soir = RTC.now(); else v_ram.soir = memo_rom.soir;
v_ram.soir = memo_rom.soir;
v_ram.rid_ouvert = memo_rom.rid_ouvert;
v_ram.nbpas1tour = memo_rom.nbpas1tour;
v_ram.nb_tour_ouvre = memo_rom.nb_tour_ouvre; // v_ram.nb_tour_ouvre = memo_rom.nb_tour_ferme; A mettre en oeuvre si necessaire
v_ram.seuil_lum = memo_rom.seuil_lum;
strcpy(v_ram.wifi_ssid, memo_rom.wifi_ssid);
strcpy(v_ram.wifi_passe, memo_rom.wifi_passe);
strcpy(v_ram.ip_mqtt, memo_rom.ip_mqtt);
strcpy(v_ram.login_mqtt, memo_rom.login_mqtt);
strcpy(v_ram.passe_mqtt,memo_rom.passe_mqtt);
EEPROM.end();
delay(300);
aff_eeprom();
}
// Ecriture eeprom
void ecriture_eeprom(){
EEPROM.begin(sizeof(s_memo_rom));
prep_aff_LCD(16);
display.drawString(15, 30, "Ecriture eeprom");
display.display();
delay(300);
memo_rom.matin = v_ram.matin;
memo_rom.soir = v_ram.soir;
memo_rom.rid_ouvert = v_ram.rid_ouvert;
memo_rom.nbpas1tour = v_ram.nbpas1tour;
memo_rom.nb_tour_ouvre = v_ram.nb_tour_ouvre;
memo_rom.nb_tour_ferme = v_ram.nb_tour_ouvre;
memo_rom.seuil_lum = v_ram.seuil_lum;
strcpy(memo_rom.wifi_ssid, v_ram.wifi_ssid);
strcpy(memo_rom.wifi_passe,v_ram.wifi_passe);
strcpy(memo_rom.ip_mqtt,v_ram.ip_mqtt);
strcpy(memo_rom.login_mqtt, v_ram.login_mqtt);
strcpy(memo_rom.passe_mqtt, v_ram.passe_mqtt);
EEPROM.put(adr_deb_memo_rom, memo_rom);
delay(300);
bool ok = EEPROM.commit();
delay(300);
aff_eeprom(false, ok); // Parametre pas utilisé dans ce code
EEPROM.end();
delay(300);
}
// Saisie du temps necessaire au moteur pour faire 1 tour
void saisie_temps_1_tour_moteur(){
prep_aff_LCD(10);
display.drawString(10, 10, "Saisir le temps");
display.drawString(10, 20, "nécéssaire au moteur");
display.drawString(10, 30, "pour faire un tour");
display.drawString(10, 40, "Défaut : 1600");
display.display();
while(mes_menus_oled.li_rot_sw()){delay(10);}
mon_sai_oled.init(); // Initialisation ecran OLED pour saisie
String temps_tour = mon_sai_oled.aff_menu_Alpha(); // On lance la saisie
if(temps_tour.length() > 2){
v_ram.nbpas1tour = temps_tour.toInt();
ecriture_eeprom();
}else{
prep_aff_LCD(16);
display.drawString(20, 20, "Valeur");
display.drawString(10, 40, "non valide");
display.display();
delay(300);
while(mes_menus_oled.li_rot_sw()){delay(10);}
}
}
// Saisie du nombre de tour moteur (ouverture/fermeture) (des choix différents ouv/ferm seront dev. si necessaire)
void saisie_nb_tour_moteur(){
prep_aff_LCD(10);
display.drawString(10, 10, "Saisir le nombre");
display.drawString(10, 20, "de tour moteur");
display.drawString(10, 30, "pour ouverture");
display.drawString(10, 40, " et fermeture");
display.drawString(10, 50, " Défaut : 5");
display.display();
while(mes_menus_oled.li_rot_sw()){delay(10);}
mon_sai_oled.init(); // Initialisation ecran OLED pour saisie
String nb_tour = mon_sai_oled.aff_menu_Alpha(); // On lance la saisie
if(nb_tour.toInt() > 0 && nb_tour.toInt() < 10){ // Limitation à 10 tours a augmenter pour besoins spécifiques
v_ram.nb_tour_ouvre = nb_tour.toInt();
ecriture_eeprom();
}else{
prep_aff_LCD(16);
display.drawString(20, 20, "Valeur");
display.drawString(10, 40, "non valide");
display.display();
delay(300);
while(mes_menus_oled.li_rot_sw()){delay(10);}
}
}
// Ferme ou ouvre le rideau pour test nb_tour v_com = O Ouvre F Ferme
void test_rideau(char v_com, uint8_t t_nb_tour){
uint16_t x = 0;
prep_aff_LCD(16);
if (v_com == 'F'){
digitalWrite(mot_sens, HIGH);
display.drawString(20, 0, "Fermeture");
}else{
digitalWrite(mot_sens, LOW);
display.drawString(20, 0, "Ouverture");
}
display.drawString(10, 20, String(t_nb_tour) + " 1/8 pas");
display.drawString(0, 40, "Bouton STOP !");
display.display();
analogWrite(mot_avance,200);
while( x < t_nb_tour ){
for(int y = 0; y < 10; y++){
if(!mes_menus_oled.li_rot_sw()){
analogWrite(mot_avance,0);
return;
}
delay(v_ram.nbpas1tour / 10);
}
x++;
}
analogWrite(mot_avance,0);
}
// Saisie du seuil de luminosité (détermine la quantité de soleil pour ouvrir ou fermer en automatique)
void saisie_seuil_lumiere(){
prep_aff_LCD(10);
display.drawString(10, 0, "Saisir le seuil");
display.drawString(10, 10, "de luminosite");
display.drawString(10, 20, "ouverture/fermeture");
display.drawString(10, 30, "Défaut : 300");
display.drawString(10, 40, "Actuel : " + String(v_ram.seuil_lum));
display.display();
while(mes_menus_oled.li_rot_sw()){delay(10);}
mon_sai_oled.init(); // Initialisation ecran OLED pour saisie
String seuil_luminosite = mon_sai_oled.aff_menu_Alpha(); // On lance la saisie
if(seuil_luminosite.toInt() > 0){
v_ram.seuil_lum = seuil_luminosite.toInt();
ecriture_eeprom();
}else{
prep_aff_LCD(16);
display.drawString(20, 20, "Valeur");
display.drawString(10, 40, "non valide");
display.display();
delay(300);
while(mes_menus_oled.li_rot_sw()){delay(10);}
}
}
// Découverte des réseaux wifi accessibles
void decouverte_wifi() {
String ssid_wifi[9];
delay(100);
WiFi.disconnect(true);
delay(100);
prep_aff_LCD(10);
display.drawString(2, 0, "RAZ wifi en cours...");
display.drawString(2, 10, ">>> Patience ... <<<");
display.drawString(8, 30, "Attention !");
display.drawString(0, 40, "Max 5 réseaux affichés");
display.display();
delay(200);
int n = 0;
for(int nb_rel = 1; nb_rel < 6; nb_rel++){
n = WiFi.scanNetworks();
if( n == -1 ){
display.drawString(0, 50, "Tentative trouver réseau : " + nb_rel);
display.display();
}else{
break;
}
if(nb_rel > 1) delay(400);
}
if( n == -1 ){
prep_aff_LCD(10);
display.drawString(0, 20, "Aucun réseau Wifi en vue !");
display.drawString(0, 40, "Relancez la recherche...");
display.display();
while(mes_menus_oled.li_rot_sw()){delay(10);}
}else{
if(n > 5) n = 5;
for (uint8_t i = 0; i < n+1; ++i) {
if(WiFi.SSID(i).length() >= 25)
ssid_wifi[i] = WiFi.SSID(i).substring(0, 24);
else
ssid_wifi[i] = WiFi.SSID(i);
delay(20);
}
prep_aff_LCD(10);
int W_menu = 0;
W_menu = mes_menus_oled.init(n, *ssid_wifi);
ssid_wifi[W_menu+1].toCharArray(v_ram.wifi_ssid, ssid_wifi[W_menu+1].length()+1);
if(v_ram.wifi_ssid != ""){
prep_aff_LCD(10);
display.drawString(2, 10, "Saisir le mot de passe");
display.drawString(2, 20, "du reseau :");
display.drawString(2, 30, v_ram.wifi_ssid);
display.display();
delay(500);
while(mes_menus_oled.li_rot_sw()){delay(10);}
mon_sai_oled.init();
ch_result = mon_sai_oled.aff_menu_Alpha();
prep_aff_LCD(10);
if(ch_result.length() > 2){
ch_result.toCharArray(v_ram.wifi_passe, ch_result.length()+1);
ecriture_eeprom();
}else{
display.drawString(2, 0, "Mot de passe non valide");
display.drawString(2, 20, "Le passe est init à NULL");
display.display();
v_ram.wifi_passe[0] = '\0';
while(mes_menus_oled.li_rot_sw()){delay(10);}
}
prep_aff_LCD(10);
}
}
}
void setup(){
#ifdef debug_anemo
Serial.begin(115200);
Serial.println("Entrée setup");
#endif
// Ini pin moteur en sortie
pinMode(mot_avance, OUTPUT);
pinMode(mot_sens, OUTPUT);
display.init(); // Ini de l'écran Oled
display.flipScreenVertically();
prep_aff_LCD(10);
lecture_eeprom(); // Récup des parametres dans l'eeprom
//while(mes_menus_oled.li_rot_sw()){delay(10);} // Attente visualisation param dates, seuil...
aff_param_wifi(); // Affache param wifi
//while(mes_menus_oled.li_rot_sw()){delay(10);} // Attente visualisation param connexions (wifi et MQTT)
setup_wifi(); // cnx wifi
delay(500);
client.setServer(v_ram.ip_mqtt, 1883); // cnx mosquitto
delay(2000);
Wire.begin(); // Init I2C
mon_sai_oled.init(); // Initialisation ecran pour saisie OLED
mon_sai_oled.sortie_deb(false); // Invalide sortie balayage aprés chaque saisie (+ rapide mais perso, j'aime pas !) à tester à true...
RTC.begin();
// Initialise la date et le jour au moment de la compilation
// La ligne qui suit sert à définir la date et l'heure afin de régler le module,
// pour les redémarrages suivants, il ne faut PAS la décommenter, sinon à chaque démarrage
// le module se réinitialisera à la date et heure de compilation ce qui n'est pas vraiment grave !
// RTC.adjust(DateTime(__DATE__, __TIME__));
//
}
// Boucle principale
void loop(){
v_lumiere = analogRead(photo_resist);
d_soleil = 0; // Calcul durée ensoleillement de la journée minute
msg_envoye[50]; // Message MQTT
h_actuel = RTC.now(); // heure actuelle
d_actuel = h_actuel.unixtime() / 86400; // date actuelle
v_dsoir = v_ram.soir.unixtime() / 86400; // date derniere mesure nuit
v_dmatin = v_ram.matin.unixtime() / 86400; // date derniere mesure matin
#ifdef debug_anemo
Serial.println("Entree loop" );
Serial.println("Val unix date actuelle : " + String(d_actuel));
Serial.println("Val unix date Ram Matin : " + String(v_dmatin) );
Serial.println("Val unix date Ram Soir : " + String(v_dsoir) );
Serial.println(" ROM Matin : " + affiche_date(v_ram.matin) + " " + affiche_heure(v_ram.matin));
Serial.println(" ROM Soir : " + affiche_date(v_ram.soir) + " " + affiche_heure(v_ram.soir));
Serial.print("Rideau : "); if(v_ram.rid_ouvert) Serial.println("Ouvert"); else Serial.println("Fermé");
Serial.println("Seuil de luminosité : " + String(v_ram.seuil_lum));
Serial.println("Luminosité mesurée : " + String(v_lumiere));
Serial.println("Nombre de pas moteur pour un tour : " + String(v_ram.nbpas1tour));
Serial.println("Nombre de tour moteur Ouv/Ferm : " + String(v_ram.nb_tour_ouvre));
Serial.println("Wifi ssid: " + String(v_ram.wifi_ssid));
Serial.println("Wifi passe: " + String(v_ram.wifi_passe));
Serial.println("MQTT ip : " + String(v_ram.ip_mqtt));
Serial.println("MQTT login : " + String(v_ram.login_mqtt));
Serial.println("MQTT passe : " + String(v_ram.passe_mqtt));
#endif
// Commande par le système en automatique suivant le seuil lumineux
// Passage mode nuit
if((v_lumiere < v_ram.seuil_lum) && (!v_nuit)){
v_nuit = true;
if(v_ram.rid_ouvert){ // Si c'est la nuit que le rideau est ouvert
action_rideau('F');
v_ram.rid_ouvert = false;
force_ouvert = false;
force_ferme = false;
}
delay(1000);
// Meme si le rideau etait déjà fermé en forcé on envoi quand même l'info d'ensoleillement
v_ram.soir = h_actuel;
ecriture_eeprom();
delay(1000);
// Envoie vers Mosquitto de la durée d'ensoleillement
d_soleil = (v_ram.soir.unixtime() - v_ram.matin.unixtime())/60;
// cnx une seule fois par jour alors vérif toujours ok
if (WiFi.status() != WL_CONNECTED) {
setup_wifi(); // cnx wifi
delay(500);
client.setServer(v_ram.ip_mqtt, 1883); // cnx mosquitto
delay(2000);
}
if (!client.connected()) { reconnect(); }
client.loop();
snprintf (msg_envoye, 50, "Ensoleillement %d minutes", d_soleil);
client.publish("Soleil", msg_envoye);
// Passage mode jour
}else if((v_lumiere >= v_ram.seuil_lum) && (v_dmatin < d_actuel)){
v_nuit = false;
if(!v_ram.rid_ouvert){ // Si c'est le jour et que le rideau est fermé
action_rideau('O');
v_ram.rid_ouvert = true;
force_ouvert = false;
force_ferme = false;
}
delay(1000);
v_ram.matin = h_actuel;
ecriture_eeprom();
}
if(v_lumiere < v_ram.seuil_lum && force_ferme) force_ferme = false;
if(v_lumiere >= v_ram.seuil_lum && force_ouvert) force_ouvert = false;
// Commande à partir du menu de paramètre
if(!mes_menus_oled.li_rot_sw()){
delay(300);
A_menu = 0;
A_menu = mes_menus_oled.init(nb_ch_menuA, _ch_menuA);
delay(300);
switch (A_menu){
// Menu général
case 0:
// Marche forcée
if (v_ram.rid_ouvert){
action_rideau('F');
v_ram.rid_ouvert = false;
force_ferme = true;
force_ouvert = false;
}else{
action_rideau('O');
v_ram.rid_ouvert = true;
force_ouvert = true;
force_ferme = false;
}
ecriture_eeprom();
break;
case 1:
// Menu gestion du moteur
delay(300);
C_menu = 0;
C_menu = mes_menus_oled.init(nb_ch_menuC, _ch_menuC);
delay(300);
switch (C_menu){
case 0:
// Saisie du temps necessaire au moteur pour faire 1 tour
saisie_temps_1_tour_moteur();
break;
case 1:
// Saisie du nombre de tour pour ouvrir
saisie_nb_tour_moteur();
break;
case 2:
// test d'ouverture
test_rideau('O', v_ram.nb_tour_ouvre);
break;
case 3:
// Saisie du nombre de tour pour fermer
saisie_nb_tour_moteur();
break;
case 4:
// test de fermeture
test_rideau('F', v_ram.nb_tour_ouvre);
break;
}
break;
case 2:
// Gestion date heure
// A venir...
delay(300);
B_menu = 0;
B_menu = mes_menus_oled.init(nb_ch_menuB, _ch_menuB);
delay(300);
switch (B_menu){
case 0:
// Vérification date et heure actuel dans l'esp
prep_aff_LCD(16);
display.drawString(0, 0, "Dat./Heur. actuel.");
display.drawString(0, 25, "le " + affiche_date(RTC.now()));
display.drawString(25, 45, "il est " + affiche_heure(RTC.now()));
display.display();
while(mes_menus_oled.li_rot_sw()){delay(10);}
break;
}
break;
case 3:
// Gestion réseaux
delay(300);
D_menu = 0;
D_menu = mes_menus_oled.init(nb_ch_menuD, _ch_menuD);
delay(300);
switch (D_menu){
case 0:
// Saisie du ssid Wifi et son mot de passe
decouverte_wifi();
break;
case 1:
// Saisie de l'adresse IP mosquitto
mon_sai_oled.init();
ch_result = mon_sai_oled.aff_menu_Alpha();
if(ch_result.length() > 2){
ch_result.toCharArray(v_ram.ip_mqtt, ch_result.length()+1);
ecriture_eeprom();
}
break;
case 2:
// Saisie du Login mosquitto
mon_sai_oled.init();
ch_result = mon_sai_oled.aff_menu_Alpha();
if(ch_result.length() > 2){
ch_result.toCharArray(v_ram.login_mqtt, ch_result.length()+1);
ecriture_eeprom();
}
break;
case 3:
// Saisie du Passe mosquitto
mon_sai_oled.init();
ch_result = mon_sai_oled.aff_menu_Alpha();
if(ch_result.length() > 2){
ch_result.toCharArray(v_ram.passe_mqtt, ch_result.length()+1);
ecriture_eeprom();
}
break;
case 4:
// Affichage parametre
aff_param_wifi();
}
break;
case 4:
// Saisie du seuil de luminosité (détermine la quantité de soleil pour ouvrir ou fermer en automatique)
saisie_seuil_lumiere();
break;
}
delay(300);
}//else stop_moteur(); // ici mettre commande enable moteur pour stopper alim
prep_aff_LCD(16);
if(v_lumiere >= v_ram.seuil_lum){
display.drawString(10, 0, "Mode Jour");
display.drawString(0, 25, "le " + affiche_date(v_ram.matin));
display.drawString(30, 45, "à " + affiche_heure(v_ram.matin));
}else{
display.drawString(10, 0, "Mode nuit");
display.drawString(0, 25, "le " + affiche_date(v_ram.soir));
display.drawString(30, 45, "à " + affiche_heure(v_ram.soir));
}
display.display();
delay(10);
}