ENC28J60 et DHT11

Un shield ethernet ENC28J60 plus un capteur DHT 11

#include "EtherShield.h"
#include <stdlib.h>
#include <string.h>
#include <DHT.h>

static uint8_t mymac[6] = {
  0x54,0x55,0x58,0x10,0x00,0x23};   
static uint8_t myip[4] = {
  192,168,0,25};
#define MYWWWPORT 80
#define BUFFER_SIZE 550
#define DHTPIN 2                                  // pin n°2 de l'arduino pour connecter le signal du DHT11
#define DHTTYPE DHT11                             // DHT 11 

DHT dht(DHTPIN, DHTTYPE);
static uint8_t buf[BUFFER_SIZE+1];
staticfloat h, t;
int nnn=0 ;
char numstr[6];

EtherShield es=EtherShield();

uint16_t http200ok(void)
{
  return(es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n")));
}

// prepare the webpage by writing the data to the tcp send buffer
uint16_t print_webpage(uint8_t *buf)
{
   uint16_t plen;
   plen=http200ok();
   plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<html><head><title>ENC28J60 Ethernet</title></head><body>"));
   plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("
 Temp&eacute;rature :   "));
   
   
   dtostrf(t,4,1,numstr);
   plen=es.ES_fill_tcp_data(buf,plen,numstr);
   plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("*C"));
   
   plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("
 Humidit&eacute; :   "));
   dtostrf(h,4,1,numstr);
   plen=es.ES_fill_tcp_data(buf,plen,numstr);
   plen=es.ES_fill_tcp_data_p(buf,plen,PSTR(" %"));
 
   
   
   plen=es.ES_fill_tcp_data_p(buf,plen,PSTR(" 
 <a href=.>[mise &agrave; jour]</a> "));  // add a Refresh button
   itoa(nnn,numstr,10);   
   plen=es.ES_fill_tcp_data(buf,plen,numstr);
  
   
   plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</body></html>"));
   nnn++;
  return(plen);
}


void setup(){
  Serial.begin(9600); 
    
  // Initialise SPI interface
  es.ES_enc28j60SpiInit();

  // initialize enc28j60
  es.ES_enc28j60Init(mymac);

  // init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mymac,myip, MYWWWPORT);
  
  dht.begin();
}

void loop(){
  uint16_t plen, dat_p;
  
  while(1) {
    // read packet, handle ping and wait for a tcp packet:
    dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
        /* dat_p will be unequal to zero if there is a valid 
     * http get */
    if(dat_p==0){
      // no http request
      continue;
    }
    // tcp port 80 begin
    
   
    if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
      // head, post and other methods:
      dat_p=http200ok();
      dat_p=es.ES_fill_tcp_data_p(buf,dat_p,PSTR("<h1>200    xxxx  OK</h1>"));
      goto SENDTCP;
    }
    // just one web page in the "root directory" of the web server
    if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0){
      
      dat_p=print_webpage(buf);
      goto SENDTCP;
    }
    else{
      dat_p=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n<h1>401 Unauthorized</h1>"));
      goto SENDTCP;
    }
SENDTCP:
    float h = dht.readHumidity();
    float t = dht.readTemperature();                    //ici
    Serial.println("c");
    es.ES_www_server_reply(buf,dat_p); // send web page data
    // tcp port 80 end
    
  }
  
}

Ai-je bien placé la lecture du capteur ?

Pas sûr, car la création de la page web se fait deux fois pour un seul refresh, preuve avec le Serial.println

Mais surprise si je ne demande que l’une ou l’autre des valeurs, c’est un seul passage.

Je ne sais pas non plus comment gérer les valeurs non conformes

Qui a une solution ?

Bonjour fr,

Je te conseille de tracer les premiers caractère du buffer reçus pour vérifier que t'on navigateur n'émet pas des requêtes supplémentaires.

 // just one web page in the "root directory" of the web server
    if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0){
      --> Ajouter trace ici
      dat_p=print_webpage(buf);
      goto SENDTCP;
    }

J'ai en effet rencontré un problème du même ordre avec un navigateur qu'envoyait de temps en temps un requête supplémentaire de demande d'icone. La fameuse "Favicon" qui s'affiche dans l'onglet.
Aussi pour m'en sortir je filtre les requêtes "GET /favicon.ico" dans mon traitement du GET.

Merci de vouloir m'aider.

Mais c'est trop vague pour mes connaissances sur les échanges entre machines sur le web

Le code que tu nous a fournit est un peu illisible. Ce serait bien de remplacer les goto SENDTCP et continue par des if(){} else{} ou des appels de fonction.
Et puis ce serait bien de séparer ES_enc28j60PacketReceive de ES_packetloop_icmp_tcp afin de récupérer la taille reçue, ça peux toujours servir comme par exemple dans les traces …

Peux-tu dans un premier temps tracer les requêtes reçus par le navigateur et nous les transmettre dans le cas où

fr:
la création de la page web se fait deux fois pour un seul refresh

?

Déclaration d’un emplacement mémoire pour les traces au debut de la fonction loop() :

 char            ChaineTampon_L[30+1];

Déclaration pour récupérer la taille des données reçues :

        uint16_t                tailleDonneesRecues;

Ajouter les traces en remplaçant :

        // read packet, handle ping and wait for a tcp packet:
    dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
        /* dat_p will be unequal to zero if there is a valid 
     * http get */
    if(dat_p==0){
      // no http request
      continue;
    }
    // tcp port 80 begin
    
   
    if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
      // head, post and other methods:
      dat_p=http200ok();
      dat_p=es.ES_fill_tcp_data_p(buf,dat_p,PSTR("<h1>200    xxxx  OK</h1>"));
      goto SENDTCP;
    }

par

    /* Lit un packet recu du buffer ethernet */
    tailleDonneesRecues=es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf);
    /* Récupère la position des données reçues */
    dat_p=es.ES_packetloop_icmp_tcp(buf,tailleDonneesRecues);
        /* dat_p will be unequal to zero if there is a valid  * http get */
         /* Reste à faire --> Remplacer le code si dessous par du code plus propre avec if(){} else{} */
   if(dat_p==0){
      // no http request
      continue;
    }
    // tcp port 80 begin
    
   
if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
      /* Vérifie que la trame rçu ne dépasse pas le tampon des traces */
      if(tailleDonneesRecues>30)
      {
            /* Seuls les 30 premiers caractères de la trame sont copiés */
            strncpy (ChaineTampon_L, (char *)&(buf[dat_p]), 30); 
      }
      else
      {
           /* Tous les caractères de la trame sont copiés */
           strncpy (ChaineTampon_L, (char *)&(buf[dat_p]), tailleDonneesRecues); 
      }
      /* Ajout du caractère de fin de chaine */
      ChaineTampon_L[tailleDonneesRecues]=0;
 
           /* envoi les traces sur le port série */
           Serial.print("Taille: ");
            Serial.println(tailleDonneesRecues);
            Serial.print("Reçu: ");
            Serial.println(ChaineTampon_L);

      // head, post and other methods:
      dat_p=http200ok();
      dat_p=es.ES_fill_tcp_data_p(buf,dat_p,PSTR("<h1>200    xxxx  OK</h1>"));
      goto SENDTCP;
    }

N’ayant pas compilé le code que je t’ai fourni, je te laisse corriger la syntaxe si besoin…

Philomenale

Intéressant, je dois pouvoir m'en resservir un jour.

Pour l'instant j'ai résolu le pb en mettant les mesures juste avant "continue, avec un compteur pour ne le faire que de temps en temps, et là j'ai pu placer le test NAN, mais j'avais encore des 0° qui sortaient avec des 0%, je les ai supprimés en testant le 0%

Ca tourne, maintenant il va me falloir faire afficher sur ma page web les courbes.

Mes connaissances en php sont très limitées, comme j'ai déjà sur le PC un pt programme qui tourne en Python, je pense que je vais y mettre un bout de plus pour le faire.

Y a moyen de passer sur une page web les valeurs, de la lire avec Python puis de tager ces points sur une image;

La prochaine fois que je m’achète un ajout ethernet pour Arduino, je prendrais un ENC28J60 LAN Ethernet Network Module Shield For Arduino MCU AVR 51 LPC bien moins cher;