Arduino


Contrôler la VMC de la maison en fonction de la température et de l'hydrométrie.

Publié le 22/12/2018



L'idée est de pouvoir accéder à chacun des composants du module via internet et d'interroger/interagir sur les composants à distance...



La ventilation peut être coupée/allumée via cette interface.

Un serveur Web héberge le site ci-dessous, qui va venir interroger les capteurs. Le rafraîchissement des données a lieu toutes les 10 secondes ou à chaque changement d'état (allumage/extinction de la ventilation).



Exemple : Visualisation des données des composants du module sur mon smartphone:

Liste des composants nécessaires pour la réalisation du circuit :

  • Arduino UNO 1
  • DTH11-Capteur d'humidité + température1
  • BMP105-Capteur atmosphérique + température1
  • LM117-Convertisseur 3.3v1
  • ESP8266-Module Wifi1
  • Relais1


Schéma du montage électronique :


Pour les amateurs d'impression 3D, j'ai fait quelques templates qui permettent d'imprimer divers boitiers pouvant accueillir les divers composants utilisés dans mes tutoriels.
- Pour un composant PIR, vous trouverez le boitier à imprimer ici.

    Il faut compter environ 4h pour imprimer les composants de ce boitier.


- Pour un relais, vous trouverez le boitier à imprimer ici.
    Il faut compter environ 2h pour imprimer les composants de ce boitier.




L'ensemble des impressions 3D a été réalisé sur une imprimante Creality3D Ender-3 pro avec les réglages standards suivants:

Pour les personnes possédant Fritzing, voici le schéma électronique.


Voici le code à télécharger dans votre Arduino:

#include <SoftwareSerial.h>
#include <SFE_BMP180.h>
#include <Wire.h>


//*****************************************************************************************//
#define build 1
#define revision 1
//*****************************************************************************************//

// ##################################
// Useful Constants 
// ##################################
#define SECS_PER_MIN  (60UL)
#define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY  (SECS_PER_HOUR * 24L)

// ##################################
// Useful Macros for getting elapsed time 
// ##################################
#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN)  
#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN) 
#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR)
#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY) 

// ##################################
// Useful Macros for debugging 
// ##################################
// Comment this line if you need to activate debugging
//#define DEBUG
#ifdef DEBUG
  #define SERIAL_PRINTLN(x)  Serial.println (x)
#else
  #define SERIAL_PRINTLN(x)
#endif
#ifdef DEBUG
  #define SERIAL_PRINT(x)  Serial.print (x)
#else
  #define SERIAL_PRINT(x)
#endif
#ifdef DEBUG
  #define SERIAL_WRITE(x)  Serial.write (x)
#else
  #define SERIAL_WRITE(x)
#endif

// ##################################
// Constantes
// ##################################
#define BUFFER_SIZE 64
#define DELAY_WEBSERVER_DIE 60000
#define ALTITUDE 192.0
#define DELAY_ASK_SENSOR 30000
// ##################################

      
// ##################################
// Broches utilisées par les capteurs
// ##################################
#define DHT11_PIN 5 // Broche "DATA" du DHT11
#define PHOTORESISTANCE_PIN 0; // Broche "DATA" de la photorésistance
#define RESET_ESP8266_PIN 13
#define ALIM_ESP8266_PIN 6

// ##################################
// Mes objets
// ##################################
SoftwareSerial ESP8266(10,11); // defines arduino pin 10 as RX and 11 as TX
HardwareSerial & dbgSerial = Serial; // serial monitor

SFE_BMP180 pressure;
// ##################################

// ##################################
// ID des composants de la sonde
// ##################################
#define SERVER_ID    2
// ##################################

// ##################################
// ID des composants de la sonde
// ##################################
#define INTERRUPTEUR_ID    18
#define HUMIDITE_ID       19
#define TEMPERATURE_ID    20
#define PRESSION_ID       21
#define LUMINOSITE_ID     22
// ##################################



// ##################################
// Variables de stockages des capteurs
// ##################################
boolean _b_ledValue_18  = 0; //off by default
int   _i_valeur1_19     = 0;
int   _i_valeur1_19_last     = 0;
int   _i_valeur2_21     = 0;
int   _i_valeur4_20     = 0;
int   _i_valeur5        = 0;
byte _b_compteurReboot = 0;
// ##################################


// ##################################
// Variables globales
// ##################################
unsigned long _il_tempsDepart = 0;
unsigned long _ii_tempsLastQueryingWebServer = 0;
unsigned int  _ii_counterWebServer=0;
unsigned int  _ii_counterResetESP8266=0;
char buffer[BUFFER_SIZE]; // Don't touch
boolean lb_HomePage = 0;
// ##################################
          
// Code d'erreur de la fonction readDHT11() 
enum 
{
  DHT11_SUCCESS, //!< Pas d'erreur
  DHT11_TIMEOUT_ERROR, //!< Temps d'attente dépassé
  DHT11_CHECKSUM_ERROR //!< Données reçues erronées
};
        
/****************************************************************/
/*                             INIT                             */
/****************************************************************/
void setup()
{
  
  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  // En cas de reboot 
  // Penser à réinitialiser toutes les IO utilisées
  digitalWrite(7, LOW);
  digitalWrite(4, LOW);
  pinMode(RESET_ESP8266_PIN, OUTPUT);
  digitalWrite(RESET_ESP8266_PIN, HIGH);     
  pinMode(ALIM_ESP8266_PIN, OUTPUT);
  digitalWrite(ALIM_ESP8266_PIN, LOW);   
  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  
  Serial.begin(9600);
  delay(10);
  Serial.println();
  Serial.println();
  Serial.println(F("Startup"));

  ESP8266.begin(115200);
  pinMode(7, OUTPUT);
  digitalWrite(7, HIGH);
  delay(1000);
  Serial.println(F("*************************************************************************"));
  Serial.print(F("ESP8266 : Serveur Web "));
  Serial.println(SERVER_ID);
  Serial.println(F("****************************************"));
  Serial.print(F("File:     ")); Serial.println(__FILE__); 
  Serial.print(F("Build:    ")); Serial.print(build);     Serial.print(F(".")); Serial.println(revision);
  Serial.print(F("Compile:  ")); Serial.print(__TIME__);  Serial.print(F(", "));   Serial.println(__DATE__);
  Serial.print(F("Free RAM: ")); Serial.print(freeRam()); Serial.println(F("B\r\n"));
  Serial.println(F("*************************************************************************"));
  
  
  
  Serial.print(F("Pause "));

  for (int i=0;i<30;i++)
  {
    Serial.print(F("."));
    delay(1000);
  }
  Serial.println(F("."));

  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);

  if (pressure.begin())
    Serial.println(F("BMP180 init success"));
  else
  {
    // Oops, something went wrong, this is usually a connection problem,
    // see the comments at the top of this sketch for the proper connections.
  
    Serial.println(F("BMP180 init fail\n\n"));
    return;
  }

  int _i_pression=0, _i_altitude=0, _i_temperature=0;
  readPressure(&_i_pression, &_i_altitude, &_i_temperature);

  Serial.print(F("Pression : "));
  Serial.println((int) _i_pression);
  Serial.print(F("i_altitude: "));
  Serial.println((int) _i_altitude);
  Serial.print(F("Temperature (^C): "));
  Serial.println((int) _i_temperature);

  _i_valeur2_21 = (int) _i_pression;
  _i_valeur4_20 = (int) _i_temperature;
        
  // Lecture de la température et de l'humidité + gestion des erreurs      
  byte _b_DHT11_temperature=0,_b_DHT11_humidity=0;  
  switch (readDHT11(DHT11_PIN, &_b_DHT11_temperature, &_b_DHT11_humidity)) 
  {
    case DHT11_SUCCESS: 
    
        // Affichage de la température et du taux d'humidité 
        Serial.print(F("Humidite (%): "));
        Serial.println((int) _b_DHT11_humidity);
        Serial.print(F("Temperature (^C): "));
        Serial.println((int) _b_DHT11_temperature);
        if (_i_valeur1_19!=0) _i_valeur1_19_last = _i_valeur1_19;    
  
        _i_valeur1_19 = (int) _b_DHT11_humidity;     
  
    break;
      
    case DHT11_TIMEOUT_ERROR: 
          Serial.println(F("Temps d'attente depasse !")); 
          
    break;
    
    case DHT11_CHECKSUM_ERROR: 
          Serial.println(F("Erreur de checksum !")); 
          
    break;
  }  
   
  delay(3000);

  Serial.println(F("Alimente ESP8266")); 
    
  envoieAuESP8266(F("AT+CIOBAUD=9600"));
  recoitDuESP8266(3000, false);

  
  ESP8266.begin(9600);  

  delay(2000);
  initESP8266();
  digitalWrite(4, HIGH); 
  digitalWrite(7, LOW);

  //wdt_enable(WDTO_8S);
  _ii_tempsLastQueryingWebServer = millis();
}
/****************************************************************/
/*                        BOUCLE INFINIE                        */
/****************************************************************/
void loop()
{
  if (millis() - _il_tempsDepart<0)
   {
      _il_tempsDepart = millis();
      _ii_tempsLastQueryingWebServer = millis();
   }
   

  if (millis() - _il_tempsDepart>= DELAY_ASK_SENSOR)
  {
      // Lecture de la température et de l'humidité + gestion des erreurs    
      byte _b_DHT11_temperature=0,_b_DHT11_humidity=0;
      switch (readDHT11(DHT11_PIN, &_b_DHT11_temperature, &_b_DHT11_humidity)) 
      {
        case DHT11_SUCCESS: 
        
            // Affichage de la température et du taux d'humidité 
            
                SERIAL_PRINT(F("Humidite (%): "));
                SERIAL_PRINTLN((int) _b_DHT11_humidity);
                SERIAL_PRINT(F("Temperature (^C): "));
                SERIAL_PRINTLN((int) _b_DHT11_temperature);
                if (_i_valeur1_19!=0) _i_valeur1_19_last = _i_valeur1_19;    
  
                if (_i_valeur1_19_last>0) 
                  _i_valeur1_19 = (int) _b_DHT11_humidity; 
                else
                  _i_valeur1_19 = ((int) _b_DHT11_humidity + _i_valeur1_19_last)/2;  
        break;
          
        case DHT11_TIMEOUT_ERROR: 
              SERIAL_PRINTLN(F("Temps d'attente depasse !")); 
              
        break;
        
        case DHT11_CHECKSUM_ERROR: 
              SERIAL_PRINTLN(F("Erreur de checksum !")); 
              
        break;
      }
    
      int _i_pression=0, _i_altitude=0, _i_temperature=0;

      _b_compteurReboot = 0;

      readPressure(&_i_pression, &_i_altitude, &_i_temperature);
      _i_valeur2_21 = (int) _i_pression;
      _i_valeur4_20 = (int) _i_temperature;
      //_i_valeur5 = (int)analogRead(PHOTORESISTANCE_PIN);      
      SERIAL_PRINT(F("Pression : "));
      SERIAL_PRINTLN((int) _i_pression);
      SERIAL_PRINT(F("i_altitude: "));
      SERIAL_PRINTLN((int) _i_altitude);
      SERIAL_PRINT(F("Temperature (^C): "));
      SERIAL_PRINTLN((int) _i_temperature);
      if (_b_ledValue_18==1)
        SERIAL_PRINTLN(F("Led : On"));
      else
        SERIAL_PRINTLN(F("Led : Off"));
      SERIAL_PRINT(F("Reset : "));
      SERIAL_PRINTLN(_ii_counterResetESP8266);
      SERIAL_PRINT(F("Time remaining = "));
      SERIAL_PRINT(elapsedDays(millis()/1000));
      SERIAL_PRINT(F("d "));
      SERIAL_PRINT(numberOfHours(millis()/1000));
      SERIAL_PRINT(F(":"));
      SERIAL_PRINT(numberOfMinutes(millis()/1000));
      SERIAL_PRINT(F(":"));
      SERIAL_PRINT(numberOfSeconds(millis()/1000));
      _il_tempsDepart = millis();
   }


      
	// the program is alive...for now. 
	//wdt_reset();

	ESP8266.readBytesUntil('\n', buffer, BUFFER_SIZE); //read until newline
       
	// we expect a message like this "+IPD,ch,len:data"
	if(strncmp(buffer, "+IPD,", 5)==0) //check if message starts with +IPD
	{ 
	  int ch; // channel ID
	  int len; //  message length
	  char *pb; // pointer inside the buffer
	  
	  sscanf(buffer+5, "%d,%d", &ch, &len); //extract channel and length
	  if (len > 0) // if message not empty
	  {
		_ii_tempsLastQueryingWebServer = millis();
		 
		// to find the data we must move the cursor after the colon
		pb=buffer;
		while(*pb!=':') pb++; // increase pointer until character is a colon
		pb++; // +1 to move after the colon, not at the colon

		clearESP8266SerialBuffer();

		if (strstr(pb, "GET /?18=1"))
		{
		  SERIAL_PRINTLN(F("********** led ON **********"));
		  _b_ledValue_18=1;
		  homepage(ch);
		  digitalWrite(7, HIGH);
		}
		else
		{
		  if (strstr(pb, "GET /?18=0"))
		  {
			SERIAL_PRINTLN(F("********** led OFF **********"));
			_b_ledValue_18=0;
			homepage(ch);
			digitalWrite(7, LOW);
		  }
		  else
		  {
			if (strstr(pb, "GET /?ALLSENSORS=1"))
			{
			  SERIAL_PRINTLN(F("********** All sensors **********"));
			  homepage(ch);
			}
			else
			{
			  if (strstr(pb, "GET /?RESET=1"))
			  {
				SERIAL_PRINTLN(F("********** RESET **********"));
				
				RebootESP8266();
			  }
			  else
			  if (strstr(pb, "GET /?INFO=1"))
			  {
				SERIAL_PRINTLN(F("********** INFORMATION **********"));
				homepageInfo(ch);
			  }
			}
		  }
		}
	  }
	}

	clearBuffer();   
}

void clearBuffer(void) 
{
	for (int i =0;i<BUFFER_SIZE;i++ ) 
	{
		buffer[i]=0;
	}
}

/*************************************************************
* FUNCTION : void clearESP8266SerialBuffer();(void)
* PURPOSE : read any remaining characters in espSerial buffer
*************************************************************/
void clearESP8266SerialBuffer()
{
  SERIAL_PRINTLN("Flush Serial ESP8266=");
  int li_i = 0;
  while ( ESP8266.available() && li_i<36000) // while there are characters available
  {
      char a = ESP8266.read();
      SERIAL_WRITE(a);
      
      if (li_i++>=36000)
        SERIAL_PRINTLN("Force End flushing");
  }
  SERIAL_PRINTLN("==============================");
}

/****************************************************************/
/*                Fonction qui initialise l'ESP8266             */
/****************************************************************/
void initESP8266()
{  
  SERIAL_PRINTLN(F("**********************************************************"));  
  SERIAL_PRINTLN(F("**************** DEBUT DE L'INITIALISATION ***************")); 
  SERIAL_PRINTLN(F("**********************************************************")); 
  SERIAL_PRINTLN(F("")); 
  SERIAL_PRINTLN(F("https://github.com/espressif/ESP8266_AT/wiki/AT_Description")); 
  SERIAL_PRINTLN(F("")); 
  /*Serial.println(F("************************ AT+RST **************************"));  
  envoieAuESP8266("AT+RST"); 
  recoitDuESP8266(5000, false);*/
  SERIAL_PRINTLN(F("************************** AT ****************************"));  
  envoieAuESP8266(F("AT")); 
  if (!recoitDuESP8266(3000, true))
  {
    SERIAL_PRINTLN(F("--> Erreur initialisation. Reboot ...")); 
    return;
  }
  SERIAL_PRINTLN(F("************************** AT+GMR ****************************"));  
  envoieAuESP8266(F("AT+GMR")); 
  if (!recoitDuESP8266(5000, true))
  {
    SERIAL_PRINTLN(F("--> Erreur initialisation. Reboot ...")); 
    return;
  }
  //SERIAL_PRINTLN(F("********************* AT+CWMODE=3 ************************")); 
  //envoieAuESP8266(F("AT+CWMODE=3")); 
  SERIAL_PRINTLN(F("********************* AT+CWMODE=1 ************************")); 
  envoieAuESP8266(F("AT+CWMODE=1")); 
  if (!recoitDuESP8266(5000, true))
  {
    SERIAL_PRINTLN(F("--> Erreur initialisation. Reboot ...")); 
    return;
  }
  SERIAL_PRINTLN(F("********************** AT+CWLAP **************************")); 
  envoieAuESP8266(F("AT+CWLAP")); 
  if (!recoitDuESP8266(15000, true))
  {
    SERIAL_PRINTLN(F("--> Erreur initialisation. Reboot ...")); 
    return;
  }
  SERIAL_PRINTLN(F("************** AT+CWJAP=\"Livebox-17F6\" *****************")); 
  envoieAuESP8266("AT+CWJAP=\"MyBOX SSID\",\"My BOX Key\""); 
  if (!recoitDuESP8266(15000, true))
  {
    SERIAL_PRINTLN(F("--> Erreur initialisation. Reboot ...")); 
    return;
  }
  SERIAL_PRINTLN(F("*********************** AT+CIFSR **************************")); 
  envoieAuESP8266(F("AT+CIFSR")); 
  if (!recoitDuESP8266(3000, true))
  {
    SERIAL_PRINTLN(F("--> Erreur initialisation. Reboot ...")); 
    return;
  }
  SERIAL_PRINTLN(F("********************* AT+CIPMUX=1 *************************")); 
  envoieAuESP8266(F("AT+CIPMUX=1"));   
  if (!recoitDuESP8266(3000, true))
  {
    SERIAL_PRINTLN(F("--> Erreur initialisation. Reboot ...")); 
    return;
  }
  SERIAL_PRINTLN(F("*********************** AT+CIPSTA **************************")); 
  envoieAuESP8266(F("AT+CIPSTA=\"192.168.1.241\"")); 
  if (!recoitDuESP8266(3000, true))
  {
    SERIAL_PRINTLN(F("--> Erreur initialisation. Reboot ...")); 
    return;
  }
  SERIAL_PRINTLN(F("******************* AT+CIPSERVER=1,80 *********************")); 
  envoieAuESP8266(F("AT+CIPSERVER=1,80")); 
  if (!recoitDuESP8266(5000, true))
  {
    SERIAL_PRINTLN(F("--> Erreur initialisation. Reboot ...")); 
    return;
  }
  SERIAL_PRINTLN(F("**********************************************************")); 
  SERIAL_PRINTLN(F("***************** INITIALISATION TERMINEE ****************")); 
  SERIAL_PRINTLN(F("**********************************************************")); 
  SERIAL_PRINTLN(F(""));
}

void software_Reset() 
{
  // Restarts program from beginning but does not reset the peripherals and registers
  asm volatile ("  jmp 0");  
}

void RebootESP8266()
{
  // Reboot ESP8266
  
  // Reset de l'ESP8266
  SERIAL_PRINTLN();
  SERIAL_PRINTLN(F("ALIM ESP8266"));
  SERIAL_PRINTLN();
  SERIAL_PRINTLN(F("->ALIM OFF"));
  digitalWrite(ALIM_ESP8266_PIN, LOW);
  delay(2000);
  SERIAL_PRINTLN(F("->ALIM ON"));
  digitalWrite(ALIM_ESP8266_PIN, HIGH);

  
  SERIAL_PRINTLN();
  SERIAL_PRINTLN(F("RESET ESP8266"));
  SERIAL_PRINTLN();
  SERIAL_PRINTLN(F("->PIN RESET ESP8266 LOW"));
  digitalWrite(RESET_ESP8266_PIN, LOW);
  delay(200);
  digitalWrite(RESET_ESP8266_PIN, HIGH);
  recoitDuESP8266(5000, false);
  
  // On relance
  if (_b_compteurReboot == 5)
  {
      SERIAL_PRINTLN();
      SERIAL_PRINTLN(F("RESET ARDUINO"));
      SERIAL_PRINTLN();
      software_Reset();  
  }
  _b_compteurReboot++;
}


/****************************************************************/
/*        Fonction qui envoie une commande à l'ESP8266          */
/****************************************************************/
void envoieAuESP8266(String commande)
{  
  SERIAL_PRINTLN(commande);
  ESP8266.println(commande); 
}
/****************************************************************/
/*Fonction qui lit et affiche les messages envoyés par l'ESP8266*/
/****************************************************************/
bool recoitDuESP8266(const int timeout, bool mustControl)
{
  bool found = false;
  long int time = millis();
  char c_Old=' ';
  
  while( (time+timeout) > millis() && !found)
  {
    while(ESP8266.available())
    {
      char c = ESP8266.read(); 
      SERIAL_PRINT(c);
      
      if (!found)
      {        
        if (c_Old=='O' && c=='K')
        {
          // contains
          SERIAL_PRINTLN(" -> Valide");
          found = true;
          //break;
        }
  
        c_Old = c;
      }
    }    
  }

  if (!mustControl) found = true;
  
  return found;
}




/**************************************************************
* FUNCTION : void homepage(int id)
* PURPOSE : send a web page and close connection
***************************************************************/
void homepage(int id)
{
    String Header;
    int li_lenContent = 0;
    
    Header =  F("HTTP/1.1 200 OK\r\n");            //bog standard stuff - should provide alternative headers
    Header += F("Content-Type: text/html\r\n");
    Header += F("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache\r\n");
    Header += F("Connection: close\r\n");  
    //Header += F("Refresh: 30\r\n");  
    
    if (_ii_counterWebServer>=65535)
      _ii_counterWebServer=0;
    
    _ii_counterWebServer++;
    
    li_lenContent = sendHTMLResponse(id, false);
    
    Header += F("Content-Length: ");  //ESP likes to know the length
    Header += (int)(li_lenContent);  //length determined here
    Header += F("\r\n\r\n");    //blank line
    
    SERIAL_PRINTLN(F("************ Prepare data **************"));
    
    ESP8266.print(F("AT+CIPSEND="));    //send the web page
    ESP8266.print(id);
    ESP8266.print(F(","));
    ESP8266.println(Header.length()+li_lenContent);
    delay(10);
    if (ESP8266.find(">")) 
    {  
      //prompt from ESP8266 indicating ready
      SERIAL_PRINTLN(F("************ send Header **************"));
      ESP8266.print(Header);  //out it goes!!
      SERIAL_PRINTLN(F("************ send Content **************"));
      sendHTMLResponse(id, true);
      delay(10);
    }
    
    ESP8266.print(F("AT+CIPCLOSE="));
    ESP8266.print(id);
    ESP8266.print(F("\r\n"));
    SERIAL_PRINTLN(F("************ Close connexion **************"));
    
    clearESP8266SerialBuffer();    
}


int sendHTMLResponse(int id, boolean lb_vrai)
{
  int li_lenContent = 0;
  
  String Content;
  
  // ########################
  // Capteur de pression
  // ########################
  Content = PRESSION_ID;
  Content += F("=");
  Content += String(_i_valeur2_21);
  li_lenContent += Content.length();
  if (lb_vrai)
  {
    ESP8266.print(Content);
    SERIAL_PRINTLN(Content);
  }
  
  // ########################
  // Capteur de temperature
  // ########################
  Content = F(";");
  Content += TEMPERATURE_ID;
  Content += F("=");
  Content += String(_i_valeur4_20);
  li_lenContent += Content.length();
  if (lb_vrai)
  {
    ESP8266.print(Content);
    SERIAL_PRINTLN(Content);
  } 

  // ########################
  // Interrupteur
  // ########################
  Content = F(";");
  Content += INTERRUPTEUR_ID;
  if(_b_ledValue_18 == 0) 
    Content += F("=0");
  else
    Content += F("=1");
  li_lenContent += Content.length();
  if (lb_vrai)
  {
    ESP8266.print(Content);
    SERIAL_PRINTLN(Content);
  }

  // ########################
  // Capteur d'humidité
  // ########################
  Content = F(";");
  Content += HUMIDITE_ID;
  Content += F("=");
  Content += String(_i_valeur1_19);
  li_lenContent += Content.length();
  if (lb_vrai)
  {
    ESP8266.print(Content);
    SERIAL_PRINTLN(Content);
  }  

  // ########################
  // Compteur
  // ########################
  Content = F(";0=");
  Content += String(_ii_counterWebServer);
  li_lenContent += Content.length();
  if (lb_vrai)
  {
    ESP8266.print(Content);
    SERIAL_PRINTLN(Content);
  }  

  return li_lenContent;
}

/**************************************************************
* FUNCTION : void homepage(int id)
* PURPOSE : send a web page and close connection
***************************************************************/
void homepageInfo(int id)
{
    String Header;
    int li_lenContent = 0;
    
    Header =  F("HTTP/1.1 200 OK\r\n");            //bog standard stuff - should provide alternative headers
    Header += F("Content-Type: text/html\r\n");
    Header += F("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache\r\n");
    Header += F("Connection: close\r\n");  
    //Header += F("Refresh: 30\r\n");  
    
    if (_ii_counterWebServer>=65535)
      _ii_counterWebServer = 0;
      
    _ii_counterWebServer++;
    
    li_lenContent = sendHTMLInfoResponse(id, false);
    
    Header += F("Content-Length: ");  //ESP likes to know the length
    Header += (int)(li_lenContent);  //length determined here
    Header += F("\r\n\r\n");    //blank line
    
    SERIAL_PRINTLN(F("************ Prepare data **************"));
    
    ESP8266.print(F("AT+CIPSEND="));    //send the web page
    ESP8266.print(id);
    ESP8266.print(F(","));
    ESP8266.println(Header.length()+li_lenContent);
    delay(10);
    if (ESP8266.find(">")) 
    {  
      //prompt from ESP8266 indicating ready
      SERIAL_PRINTLN(F("************ send Header **************"));
      ESP8266.print(Header);  //out it goes!!
      SERIAL_PRINTLN(F("************ send Content **************"));
      sendHTMLInfoResponse(id, true);
      delay(10);
    }
    
    ESP8266.print(F("AT+CIPCLOSE="));
    ESP8266.print(id);
    ESP8266.print(F("\r\n"));
    SERIAL_PRINTLN(F("************ Close connexion **************"));
    
    clearESP8266SerialBuffer();    
}


int sendHTMLInfoResponse(int id, boolean lb_vrai)
{
  int li_lenContent = 0;
  
  String Content;
  Content = F("<title> Server ");
  Content += SERVER_ID;
  Content += F(" </title>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  
  Content = F("<HTML><body bgcolor=\"#99ff99\" alink=\"#EE0000\" link=\"#0000EE\" text=\"#000000\"vlink=\"#551A8B\">");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F("<H1>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F("ESP8266 Web Server Info Page, Reloads = ");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = String(_ii_counterWebServer);
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);

  Content = F("<BR><BR>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F("</H1>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F("<H2>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F("Number of reset(s) = ");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = String(_ii_counterResetESP8266);
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
 
  Content = F("<br>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F("Time remaining = ");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);

  Content = String(elapsedDays(millis()/1000));
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
 
  Content = F("d ");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = String(numberOfHours(millis()/1000));
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
 
  Content = F(":");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = String(numberOfMinutes(millis()/1000));
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
 
  Content = F(":");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = String(numberOfSeconds(millis()/1000));
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
     
  Content = F("<br>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F("This is channel ");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = String(id);
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F(" of 0-4 available channels");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);

  Content = F("<BR><BR></H2>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F("<H3>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F("Pressure [");
  Content += PRESSION_ID;
  Content += F("]=");
  Content += String(_i_valeur2_21);
  Content += F(" Pa<BR>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);



  Content = F("Temperature [");
  Content += TEMPERATURE_ID;
  Content += F("]=");
  Content += String((float)_i_valeur4_20/100, 2);
  Content += F(" &deg;c<BR>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);

  Content = F("Humidite [");
  Content += HUMIDITE_ID;
  Content += F("]=");
  Content += String(_i_valeur1_19);
  Content += F(" %<BR>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);

  Content = F("Relais [");
  Content += INTERRUPTEUR_ID;
  Content += F("]=");
  if(_b_ledValue_18 == 0) 
    Content += F("OFF");
  else
    Content += F("ON");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);

  Content = F("<br><br><br>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F("<i><a href=\"mailto:ludovic_gauthier@yahoo.fr?subject=ESP8266%20Webserver\">Ludovic GAUTHIER 2016</a></i><br>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);
  
  Content = F("</H3></BODY></HTML>");
  li_lenContent += Content.length();
  if (lb_vrai) ESP8266.print(Content);

  return li_lenContent;
}


/**
 * Lit la température et le taux d'humidité capté par un capteur DHT11
 *
 * @param pin Broche sur laquelle est câblé le capteur
 * @param temperature Pointeur vers la variable stockant la température
 * @param humidity Pointeur vers la variable stockant le taux d'humidité
 * @return DHT11_SUCCESS si aucune erreur, DHT11_TIMEOUT_ERROR en cas de timeout, ou DHT11_CHECKSUM_ERROR en cas d'erreur de checksum
 */
byte readDHT11(byte pin, byte* temperature, byte* humidity) 
{
 
  // data[] -> buffer contenant les données du cpateur
  // counter -> compteur permettant de savoir quel bit est reçu (bitwise)
  // index -> compteur permettant de savoir quel octet est reçu (bitwise)
  // timeout -> compteur pour le timeout
  //
  byte data[5] = { 0 }, counter = 7, index = 0;
  unsigned int timeout;

  // Conversion du numéro de broche Arduino en ports/masque binaire "bas niveau" 
  // Utiliser les registres du microcontrôleur est bien plus rapide que digitalWrite()
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *ddr = portModeRegister(port);   // Registre MODE (INPUT / OUTPUT)
  volatile uint8_t *out = portOutputRegister(port);   // Registre OUT (écriture)
  volatile uint8_t *in = portInputRegister(port);   // Registre IN (lecture)
 
  // Réveil du capteur 
  *ddr |= bit;      // OUTPUT
  *out &= ~bit;       // LOW
  delay(18);        // Temps d'attente à LOW causant le réveil du capteur
  *out |= bit;      // HIGH
  delayMicroseconds(40);
  *ddr &= ~bit;       // INPUT
 
  // Attente de la réponse du capteur 
  timeout = 0;
  while(!(*in & bit)) 
    // Attente d'un état LOW 
    if (++timeout == 10000)
    {
      SERIAL_PRINTLN("Time out 1 !");
      return DHT11_TIMEOUT_ERROR;
    }
  timeout = 0;
  while(*in & bit) 
    // Attente d'un état HIGH 
    if (++timeout == 10000)
    {
      SERIAL_PRINTLN("Time out 2 !");
      return DHT11_TIMEOUT_ERROR;
    }
    
 
  // Lecture des données du capteur (40 bits)
  for (byte i = 0; i < 40; ++i) 
  {

  // Attente d'un état LOW 
  timeout = 0;
  while(!(*in & bit))
  {
    //delayMicroseconds(10);
    if (++timeout == 10000)
      {
      SERIAL_PRINTLN("Time out 3 !");
      return DHT11_TIMEOUT_ERROR;
      }
  }
  
  // Mise en mémoire du temps courant
  unsigned long t = micros();

  // Attente d'un état HIGH 
  timeout = 0;
  while(*in & bit)
  {
    //delayMicroseconds(10);
    if (++timeout == 10000)
    {
      SERIAL_PRINTLN("Time out 4 !");
        return DHT11_TIMEOUT_ERROR;
    }
  }
  
  // Si le delta Temps est supérieur à 40µS c'est un "1", sinon c'est un "0" 
  // Le tableau data[] est initialisé à "0" par défaut
  if ((micros() - t) > 40)
    data[index] |= (1 << counter); // "1"
    

  // Si le compteur de bits atteint zéro
  if (counter-- == 0) 
  {
    // On passe à l'octet suivant
    counter = 7; 
    ++index;
    //break; 
  }
  
  }
 
  // Format des données :
  // [0] = humidité en %
  // [1] = zéro
  // [2] = température en degrés Celsius
  // [3] = zéro
  // [4] = checksum (humidité + température)
  //
  *humidity = data[0]; 
  *temperature = data[2]; 

  // Vérifie la checksum 
  if (data[4] != (data[0] + data[2]))
    return DHT11_CHECKSUM_ERROR;  // Erreur de checksum 
  else
    return DHT11_SUCCESS;       // Pas d'erreur 
}

void readPressure(int* _i_pression, int* _i_altitude, int* _i_temperature)
{
  char status;
  double T,P,p0,a;

  // Loop here getting pressure readings every 10 seconds.

  // If you want sea-level-compensated pressure, as used in weather reports,
  // you will need to know the altitude at which your measurements are taken.
  // We're using a constant called ALTITUDE in this sketch:
  

    SERIAL_PRINTLN();
    SERIAL_PRINT("provided altitude: ");
    #ifdef DEBUG
      Serial.print(ALTITUDE,0);
    #endif      
    SERIAL_PRINT(" meters, ");
    #ifdef DEBUG
      Serial.print(ALTITUDE*3.28084,0);
    #endif
    SERIAL_PRINTLN(" feet");

  
  // If you want to measure altitude, and not pressure, you will instead need
  // to provide a known baseline pressure. This is shown at the end of the sketch.

  // You must first get a temperature measurement to perform a pressure reading.
  
  // Start a temperature measurement:
  // If request is successful, the number of ms to wait is returned.
  // If request is unsuccessful, 0 is returned.

  status = pressure.startTemperature();
  if (status != 0)
  {
    // Wait for the measurement to complete:
    delay(status);

    // Retrieve the completed temperature measurement:
    // Note that the measurement is stored in the variable T.
    // Function returns 1 if successful, 0 if failure.

    status = pressure.getTemperature(T);
    if (status != 0)
    {
      // Print out the measurement:
      SERIAL_PRINT("temperature: ");
      #ifdef DEBUG
        Serial.print(T,2);
      #endif
      
      *_i_temperature = (int)(T*100);
      
      SERIAL_PRINT(" deg C, ");
      #ifdef DEBUG
        Serial.print((9.0/5.0)*T+32.0,2);
      #endif
      SERIAL_PRINTLN(" deg F");
      
      // Start a pressure measurement:
      // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
      // If request is successful, the number of ms to wait is returned.
      // If request is unsuccessful, 0 is returned.

      status = pressure.startPressure(3);
      if (status != 0)
      {
        // Wait for the measurement to complete:
        delay(status);

        // Retrieve the completed pressure measurement:
        // Note that the measurement is stored in the variable P.
        // Note also that the function requires the previous temperature measurement (T).
        // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
        // Function returns 1 if successful, 0 if failure.

        status = pressure.getPressure(P,T);
        if (status != 0)
        {
          // Print out the measurement:
          SERIAL_PRINT("absolute pressure: ");
          #ifdef DEBUG
            Serial.print(P,2);
          #endif
          
          *_i_pression = (int)P;
          
          SERIAL_PRINT(" mb, ");
          #ifdef DEBUG
            Serial.print(p0*0.0295333727,2);
          #endif
          SERIAL_PRINTLN(" inHg");
          
          // The pressure sensor returns abolute pressure, which varies with altitude.
          // To remove the effects of altitude, use the sealevel function and your current altitude.
          // This number is commonly used in weather reports.
          // Parameters: P = absolute pressure in mb, ALTITUDE = current altitude in m.
          // Result: p0 = sea-level compensated pressure in mb

          p0 = pressure.sealevel(P,ALTITUDE); // we're at 1655 meters (Boulder, CO)
          
          SERIAL_PRINT("relative (sea-level) pressure: ");
          #ifdef DEBUG
            Serial.print(p0,2);
          #endif
          
          *_i_pression = (int)p0;
          
          SERIAL_PRINT(" mb, ");
          #ifdef DEBUG
            Serial.print(p0*0.0295333727,2);
          #endif
          SERIAL_PRINTLN(" inHg");
          
          // On the other hand, if you want to determine your altitude from the pressure reading,
          // use the altitude function along with a baseline pressure (sea-level or other).
          // Parameters: P = absolute pressure in mb, p0 = baseline pressure in mb.
          // Result: a = altitude in m.

          a = pressure.altitude(P,p0);
          
          SERIAL_PRINT("computed altitude: ");
          #ifdef DEBUG
            Serial.print(a,0);
          #endif
          
          *_i_altitude = (int)a;
          
          SERIAL_PRINT(" meters, ");
          #ifdef DEBUG
            Serial.print(a*3.28084,0);
          #endif
          SERIAL_PRINTLN(" feet");
        }
        else SERIAL_PRINTLN("error retrieving pressure measurement\n");
      }
      else SERIAL_PRINTLN("error starting pressure measurement\n");
    }
    else SERIAL_PRINTLN("error retrieving temperature measurement\n");
  }
  else SERIAL_PRINTLN("error starting temperature measurement\n");
}

// ********************************************************************************** //
//                              OPERATION ROUTINES
// ********************************************************************************** //
// FREERAM: Returns the number of bytes currently free in RAM  
int freeRam(void) 
{
  extern int  __bss_end, *__brkval; 
  int free_memory; 
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end); 
  } 
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval); 
  }
  return free_memory; 
}
Nombre de vue(s): 4368

Forum


Vos avis/remarques...


Veuillez vous connecter pour laisser vos commentaires...