Projet Lazy Compagny -> Température/Hygrométrie via 433mhz + Site internet

Projet Lazy Compagny -> Température/Hygrométrie via 433mhz + Site internet

26 mars 2019 0 Par Jérôme Ferrari

Salutation, camarades!

Cet hiver, j’ai eu une problématique: “Comment surveiller à distance l’environnement de la Lazy Compagny pendant leur hibernation?”

J’ai donc décomposé le problème en trois:

  • Quelles variables du champs de bataille dois-je mesurer et comment?
  • Comment coder et transmettre l’information au QG?
  • Comment débriefer facilement les informations?

Pour information, tout le code et la liste du matériel sera disponible en fin de post.

Pour information, Les sources sont CC-BY-NC-SAhttps://creativecommons.org/licenses/by-nc-sa/3.0/fr/

PARTIE I : Quelles variables du champs de bataille dois-je mesurer et comment?

Pour l’hibernation des tortues, les deux variables les plus importantes à surveiller sont la température car il ne faut pas qu’elle soit en dessous de 0°C et l’hygrométrie qui doit être aux alentours de 70%.

Pour résoudre cette première problématique, je me suis orienté vers un capteur DHT22 car la plage de température est idéal (-40°C à 125°C pour 0.5°C de précision)

Son utilisation est extrêmement simple car une librairie Arduino est disponible et permet de récupérer facilement les informations et qu’il est plug and play.

Voici le code que j’ai utilisé pour le faire fonctionner

    #include "DHT.h"// DHT22
    #define DHTPIN 3     // Pin de lecture des donnees DHT
    #define DHT5VPIN 2   // Pin pour alimentation DHT
    #define DHTTYPE DHT22   // DHT 22  (AM2302)

    //global vars
    DHT dht(DHTPIN, DHTTYPE);

   void setup() {

    //setup led
    pinMode(13,OUTPUT);

   //setup DHT22
    pinMode(DHT5VPIN, OUTPUT);
    digitalWrite(DHT5VPIN, HIGH);//enable power
    dht.begin();

    //for debugging
    Serial.begin(9600);
    }

    void loop(){

    //read from dht22
    digitalWrite(13,HIGH);
    float h = dht.readHumidity();
    float t = dht.readTemperature();

    //Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t)) {
   Serial.println("Failed to read from DHT sensor!");
   return;
   }

    //some debug info
    Serial.println("Humidity ");
    Serial.println(h);
    Serial.println("Temperature: ");
    Serial.println(t);

    delay(3000);
    }

Voila maintenant que nous sommes capable de mesurer l’environnement des tortues, nous pouvons passer à la transmission de données.

PARTIE II : Comment coder et transmettre l’information au QG?

Pour cela je suis partie sur une solution de transmission sans fil via un module 433Mhz

A gauche le recepteur et à droite le transmetteur

Pour la partie transmission, au premier abord cela est simple car comme pour le capteur DHT22 une librairie arduino existe et le transmitter est plug and play. Cependant, il ne faut pas oublier que le nombre de caractères transmissible par trame est limité, ce qui m’a obligé à tronquer les informations venant de la partie mesure.

Voici le code que j’ai utilisé pour le faire fonctionner

#include // 433MHz tx
#include "DHT.h"// DHT22

#define DHTPIN 3     // Pin de lecture des donnees DHT
#define DHT5VPIN 2   // Pin pour alimentation DHT
#define DHTTYPE DHT22   // DHT 22  (AM2302)

//global vars
DHT dht(DHTPIN, DHTTYPE);
char data[50];
//char *data;
int identifier;
int hnew;
int tnew;
int tmaxnew=000;
int tminnew=900;
int hmaxnew=000;
int hminnew=900;
int tbuff;
int hbuff;
 
char tch;
char hch;
void setup() {

//setup led
pinMode(13,OUTPUT);

//setup virtualwire
vw_set_ptt_inverted(true); //
vw_set_tx_pin(12);
vw_setup(4000);// Vitesse de transmission des donnees Kbps

//setup DHT22
pinMode(DHT5VPIN, OUTPUT);
digitalWrite(DHT5VPIN, HIGH);//enable power
dht.begin();

//for debugging
Serial.begin(9600);
Serial.println("This is the transmitter!");
identifier = 0;
}

void loop(){

    //read from dht22
    digitalWrite(13,HIGH);
    float h = dht.readHumidity();
    float t = dht.readTemperature();

    //Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t)) {
   Serial.println("Failed to read from DHT sensor!");
   return;
   }

    //some debug info
    Serial.println("Humidity ");
    Serial.println(h);
    Serial.println("Temperature: ");
    Serial.println(t);

    //format data string
    
    h = h*10;
    t= t+40;
    t = t*10;
    hnew= h;
    tnew =t;
   if (tnew>tmaxnew){tmaxnew=tnew;}
   if (tnewhmaxnew){hmaxnew=hnew;}
   if (hnew=2000) for the next reading
    identifier++;
    delay(3000);
}    

Pour la partie réception, la récupération d’information est plutôt simple car la librairie arduino utilisée gère aussi bien la transmission que la réception de données.

Voici le code pour le récepteur (to do commenter mon code)

#include 

char temperature[3];
char temperaturemax[3];
char temperaturemin[3];
char humidity[3];
char humiditymax[3];
char humiditymin[3];
int t;
int tmax;
int tmin;
int h;
int hmax;
int hmin;
float tf;
float tfmin;
float tfmax;
float hf;
float hfmax;
float hfmin;


void setup()
{
  //setup virtualwire
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_set_rx_pin(12);
  vw_setup(4000);  // Bits per sec

  //setup led
  pinMode(13, OUTPUT);

  //setup serial for debugging
  Serial.begin(9600);
  Serial.println("Receiver test");

  // Start the receiver PLL
  vw_rx_start();
}
void loop()
{

  //read and print!
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  if (vw_get_message(buf, &buflen)) // Non-blocking
  {
    Serial.println((char*)buf);
    //Serial.println(buflen);

    char dummy[VW_MAX_MESSAGE_LEN];

    temperature[0] = (int)(char*)buf[1];
    temperature[1] = (int)(char*)buf[2];
    temperature[2] = (int)(char*)buf[3];

    temperaturemax[0] = (int)(char*)buf[5];
    temperaturemax[1] = (int)(char*)buf[6];
    temperaturemax[2] = (int)(char*)buf[7];

    temperaturemin[0] = (int)(char*)buf[9];
    temperaturemin[1] = (int)(char*)buf[10];
    temperaturemin[2] = (int)(char*)buf[11];

    humidity[0] = (int)(char*)buf[13];
    humidity[1] = (int)(char*)buf[14];
    humidity[2] = (int)(char*)buf[15];

    humiditymax[0] = (int)(char*)buf[17];
    humiditymax[1] = (int)(char*)buf[18];
    humiditymax[2] = (int)(char*)buf[19];

    humiditymin[0] = (int)(char*)buf[21];
    humiditymin[1] = (int)(char*)buf[22];
    humiditymin[2] = (int)(char*)buf[23];

    t = (int(temperature[0]) - 48) * 100 + (int(temperature[1]) - 48) * 10 + (int(temperature[2]) - 48);
    tf = t;
    tf = tf / 10;
    tf = tf - 40;
    tmax = (int(temperaturemax[0]) - 48) * 100 + (int(temperaturemax[1]) - 48) * 10 + (int(temperaturemax[2]) - 48);
    tfmax = tmax;
    tfmax = tfmax / 10;
    tfmax = tfmax - 40;
    tmin = (int(temperaturemin[0]) - 48) * 100 + (int(temperaturemin[1]) - 48) * 10 + (int(temperaturemin[2]) - 48);
    tfmin = tmin;
    tfmin = tfmin / 10;
    tfmin = tfmin - 40;

    h = (int(humidity[0]) - 48) * 100 + (int(humidity[1]) - 48) * 10 + (int(humidity[2]) - 48);
    hf = h;
    hf = hf / 10;
    hmax = (int(humiditymax[0]) - 48) * 100 + (int(humiditymax[1]) - 48) * 10 + (int(humiditymax[2]) - 48);
    hfmax = hmax;
    hfmax = hfmax / 10;
    hmin = (int(humiditymin[0]) - 48) * 100 + (int(humiditymin[1]) - 48) * 10 + (int(humiditymin[2]) - 48);
    hfmin = hmin;
    hfmin = hfmin / 10;
    Serial.print("TActuel:");
    Serial.print(tf);
    Serial.print(", TMin:");
    Serial.print(tfmin);
    Serial.print(", TMax:");
    Serial.println(tfmax);
    Serial.print("HActuel:");
    Serial.print(hf);
    Serial.print(", HMin:");
    Serial.print(hfmin);
    Serial.print(", HMax:");
    Serial.println(hfmax);
  }
}    

Maintenant que nous savons mesurer, transmettre les informations, il faut pouvoir les lire sur n’importe quel écran.

PARTIE 3: Comment débriefer facilement les informations?

Pour cela, je suis parti sur une solution où un Arduino s’occupe de faire le serveur. J’ai donc rajouté un module ENC28J60 sur mon Arduino Mega

J’avoue que j’ai bien galéré car c’est un domaine qui m’était jusque là totalement inconnu. Le plus difficile a été d’interfacer correctement le serveur Arduino avec le reste de mon réseau.

Ii faut aussi penser aux Pins utilisées car pour les Mega, il vaut mieux utiliser la Pin 53

Je ne préfère pas rentrer pour l’instant dans le détail car trop de souvenirs douloureux sont encore présent donc…

Voici le code complet pour le site internet

#include 
#include 
#define STATIC 0  // set to 1 to disable DHCP (adjust myip/gwip values below)

static word homePage();
// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
static byte myip[] = { 192, 168, 51, 177 };
static byte gwip[] = { 192, 168, 51, 1 };
byte Ethernet::buffer[500];
BufferFiller bfill;

// Initialisation des variables
char temperature[3];
char temperaturemax[3];
char temperaturemin[3];
char humidity[3];
char humiditymax[3];
char humiditymin[3];
int t;
int tmax;
int tmin;
int h;
int hmax;
int hmin;
static int tf;
int tfmin;
int tfmax;
static int hf;
int hfmax;
int hfmin;


void setup()
{

  //setup virtualwire
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_set_rx_pin(12);
  vw_setup(4000);  // Bits per sec

  //setup led
  pinMode(13, OUTPUT);

  //setup serial for debugging
  //Serial.println("Receiver test");

  // Start the receiver PLL
  vw_rx_start();
  Serial.begin(9600);
  if (ether.begin(sizeof Ethernet::buffer, mymac, 53) == 0)
    Serial.println( "Failed to access Ethernet controller");

#if STATIC
  ether.staticSetup(myip, gwip);
#else
  if (!ether.dhcpSetup())
    Serial.println("DHCP failed");
#endif
  //ether.staticSetup(myip, gwip); 
}

static word homePage() {
  //ReadDHT11();

  bfill = ether.tcpOffset();
  bfill.emit_p(PSTR(
                 "HTTP/1.0 200 OKrn"
                 "Content-Type: text/htmlrn"
                 "Pragma: no-cachern"
                 "rn"
                 ""
                 "Tortues server"
                 "

Temperature actuel: $D C
Temperature Maximale: $D C
Temperature Minimale: $D C
Humidite actuel: $D %
Humidite Maximale: $D %
Humidite Minimale: $D %

"), tf, tfmax, tfmin, hf, hfmax, hfmin); return bfill.position(); } void loop() { digitalWrite(13, HIGH); //read and print! uint8_t buf[VW_MAX_MESSAGE_LEN]; uint8_t buflen = VW_MAX_MESSAGE_LEN; if (vw_get_message(buf, &buflen)) // Non-blocking { //Serial.println((char*)buf); //Serial.println(buflen); char dummy[VW_MAX_MESSAGE_LEN]; temperature[0] = (int)(char*)buf[1]; temperature[1] = (int)(char*)buf[2]; temperature[2] = (int)(char*)buf[3]; temperaturemax[0] = (int)(char*)buf[5]; temperaturemax[1] = (int)(char*)buf[6]; temperaturemax[2] = (int)(char*)buf[7]; temperaturemin[0] = (int)(char*)buf[9]; temperaturemin[1] = (int)(char*)buf[10]; temperaturemin[2] = (int)(char*)buf[11]; humidity[0] = (int)(char*)buf[13]; humidity[1] = (int)(char*)buf[14]; humidity[2] = (int)(char*)buf[15]; humiditymax[0] = (int)(char*)buf[17]; humiditymax[1] = (int)(char*)buf[18]; humiditymax[2] = (int)(char*)buf[19]; humiditymin[0] = (int)(char*)buf[21]; humiditymin[1] = (int)(char*)buf[22]; humiditymin[2] = (int)(char*)buf[23]; t = (int(temperature[0]) - 48) * 100 + (int(temperature[1]) - 48) * 10 + (int(temperature[2]) - 48); tf = t; tf = tf / 10; tf = tf - 40; tmax = (int(temperaturemax[0]) - 48) * 100 + (int(temperaturemax[1]) - 48) * 10 + (int(temperaturemax[2]) - 48); tfmax = tmax; tfmax = tfmax / 10; tfmax = tfmax - 40; tmin = (int(temperaturemin[0]) - 48) * 100 + (int(temperaturemin[1]) - 48) * 10 + (int(temperaturemin[2]) - 48); tfmin = tmin; tfmin = tfmin / 10; tfmin = tfmin - 40; h = (int(humidity[0]) - 48) * 100 + (int(humidity[1]) - 48) * 10 + (int(humidity[2]) - 48); hf = h; hf = hf / 10; hmax = (int(humiditymax[0]) - 48) * 100 + (int(humiditymax[1]) - 48) * 10 + (int(humiditymax[2]) - 48); hfmax = hmax; hfmax = hfmax / 10; hmin = (int(humiditymin[0]) - 48) * 100 + (int(humiditymin[1]) - 48) * 10 + (int(humiditymin[2]) - 48); hfmin = hmin; hfmin = hfmin / 10; //Serial.println(int(temperature[0])-48); //Serial.println(int(temperature[1])-48); //Serial.println(int(temperature[2])-48); //Serial.println(int(temperature[3])-48); //Serial.print("TActuel:"); Serial.print(tf); //Serial.print(", TMin:"); //Serial.print(tfmin); //Serial.print(", TMax:"); //Serial.println(tfmax); //Serial.print("HActuel:"); //Serial.print(hf); //Serial.print(", HMin:"); //Serial.print(hfmin); //Serial.print(", HMax:"); //Serial.println(hfmax); digitalWrite(13, LOW); } word len = ether.packetReceive(); word pos = ether.packetLoop(len); if (pos) // check if valid tcp data is received { ether.httpServerReply(homePage()); // send web page data Serial.print("Echo"); } }

Ce qui donne après plusieurs heures de batailles et de souffrances.

site_mini

C’est ainsi que la Lazy Compagny pu commencer son hibernation en toute sérénité!

Ressources:

Matériel utilisé

  • Capteur DHT22
  • Arduino nano
  • Arduino mega 2560
  • Kit transmission/réception 433mhz
  • Module ENC28J60

Code