Serveur de température 1wire avec un Arduino

Pour gérer mes sondes de températures 1wire (DS18b20) en un point unique et de manière propre, j’ai créé un serveur à base d’Arduino qui créé une page json avec la température de toutes les sondes raccordées. Explications.

Introduction

Afin de faire un projet propre, j’ai utilisé 3 cartes différentes :

  • 1 arduino Uno
  • 1 carte Ethernet W5100 pour Arduino
  • 1 carte prototype DFrobot

Ces cartes sont empilées les unes sur les autres afin de faire un bloc unique qui sera voué à aller dans un tableau électrique, sur un rail din (le support DIN sera imprimé en 3D.

Une fois les cartes empilées, nous disposerons des ports 2-3-5-6-7-8-9, les autres ports sont utilisées pour le RJ45 (liaison SPI sur 10 à 13) et carte SD (pin 4). Cela nous fera alors 7 ports utilisables pour connecter nos sondes DS18b20.

Avec la carte proto, on a l’avantage d’avoir des lignes de 5V et de GND, ce qui permet de câbler les résistances de manière très propre.

productphoto

Cablage sonde DS18b20

Une sonde DS18B20 dispo de 3 pin, qui doivent être câblées comme suit :

  • gauche : GND
  • milieu : à l’arduino et au +5V via une résistance de 4,7 kohms
  • droite : +5V
source : http://bildr.org/2011/07/ds18b20-arduino/

Les sondes DS18b20 peuvent se mettent en parallèle sur un bus de données et communiquer via 1 port unique. Mais pour récolter les valeurs de manière précise, cela signifie de connaitre les id de tous les id de chaque sonde et de les mettre en dur dans le code.

J’ai donc pris le parti de dire : 1 port arduino = 1 sonde. Cela permet de gérer le résultat sans aucun problème. La carte prototype sert donc à ramener toutes les résistances de 4,7 kohms et les leds d’affichage que je voulais faire apparaitre très facilement. Le câblage est facilité et le résultat propre et net !

Assemblage

Plutôt qu’un long discours, je vous met une série de photo.

Les 3 cartes assemblées
Vue d’en haut

J’ai demandé à Madame de m’imprimer en 3D un support pour rail DIN, vous pourrez trouver le modèle pour arduino uno ici.

support rail din pour l’arduino imprimé en 3D
Arduino monté sur support rail din
Arduino dans tableau electrique

L’arduino sera alimenté via un transfo 12V 1A, ce qui sera largement suffisant. Vu qu’il est en tableau électrique, c’est un moyen propre et facile d’alimentation.

Le code source

Il faut d’abord commencer par inclure les fichiers entête nécessaires (voir l’article sur la station météo pour ajouter des librairies dans Arduino)

#include <Ethernet.h>
#include <DallasTemperature.h>
#include <OneWire.h>

Ensuite, il faut assigner une adresse mac à votre carte Arduino. Cela permettra ensuite de faire une réservation DHCP sur votre box/routeur pour retrouver facilement votre Arduino. On déclare ensuite un serveur Ethernet sur le port 80

//Gestion web server
byte mac[6] = { 0xBE, 0xEF, 0x00, 0xFD, 0xC7, 0x93 };
char macstr[18];
EthernetServer server(80);

Je déclare ensuite mes 4 LEDS pour pouvoir les utiliser ensuite. Les 4 LEDS sont branchées sur les 4 ports analogiques, je garde les pin digitales pour les sondes DS18b20.

const int LED_NETWORK = A0;
const int LED_CONNECTION = A1;
const int LED_ERROR_ACTIVITY = A2;
const int LED_OK_ACTIVITY = A3;
int pin[4]={A0,A1,A2,A3};

Viens ensuite la fonction setup où l’on va initier la mac address, démarrer le serveur web et allumer les leds correspondantes si le serveur est bien démarré avec une IP.

void setup()
{
  Serial.begin(9600);
  
  pinMode(LED_CONNECTION, OUTPUT);
  pinMode(LED_NETWORK, OUTPUT);
  pinMode(LED_ERROR_ACTIVITY, OUTPUT);
  pinMode(LED_OK_ACTIVITY, OUTPUT);

  snprintf(macstr, 18, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  Serial.print("DHCP : ");
  Serial.println(macstr);
  
  if(!Ethernet.begin(mac)){
    Serial.println("Network failed");
  }
  else{ 
    //Initialisation        
    server.begin();    
    Serial.println(Ethernet.localIP());
    Serial.println(Ethernet.gatewayIP());
    
    digitalWrite(LED_CONNECTION, LOW);    
    digitalWrite(LED_NETWORK, HIGH);    
    digitalWrite(LED_ERROR_ACTIVITY, LOW);    
    digitalWrite(LED_OK_ACTIVITY, LOW);
    delay(1000);
    
  }
}

Viens ensuite la boucle qui est commentée pas à pas. Elle va générer une page formattée en json avec le résultat des 7 sondes DS18b20.

void loop()
{  
  //on déclare le serveur web disponible
  EthernetClient client = server.available();
  //Si un client appelle la page
  if (client) {
    boolean currentLineIsBlank = true;
    //Tant que le client est connecté
    while (client.connected()) {
      if (client.available()) {
        //Allumage led connexion page web
       digitalWrite(LED_CONNECTION, HIGH);                 
       char c = client.read();
       if (c == '\n' && currentLineIsBlank) {  
          //création du code HTML pour générer un JSON
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: application/json");
          client.println("Access-Control-Allow-Origin: *");
          client.println();
          client.print("[{");
            //boucle pour parcourir les ports 2 à 9 sur l'arduino
            for(int i=2;i<10;i++){
              //initialisation 1wire
              OneWire oneWire(i);
              DallasTemperature sensors(&oneWire);
              //on démarre la capture de données du capteur
              sensors.begin();
              sensors.requestTemperatures(); // Send the command to get temperatures
              //on prépare le code json
              client.print("\"TempOneWire");
              client.print(i);
              client.print("\":");
              //si on a -127, c'est que rien n'est connecté
              if(sensors.getTempCByIndex(0) ==-127){
                client.print("\"N/A\"");
                //on affiche la led rouge 300ms
                digitalWrite(LED_ERROR_BME, HIGH); 
                delay(300);
                digitalWrite(LED_ERROR_BME, LOW);
              }
              else{
                //recupération de la température
                client.print(sensors.getTempCByIndex(0));
                //on affiche la led verte 300ms
                digitalWrite(LED_OK_BME, HIGH); 
                delay(300);
                digitalWrite(LED_OK_BME, LOW);
              }
              client.print(",");             
            }
            //vu que l'on est dans une boucle et qu'il faut terminer le json sans virgule, on rajoute une info fixe : ici l'adresse ip
            client.print("\"IP\":");
            client.print("\"");
            client.print(Ethernet.localIP());
            client.print("\"");
            client.print("}]");
            delay(1000);
            //Extinction led connexion page web
            digitalWrite(LED_CONNECTION, LOW); 
            break;          
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          currentLineIsBlank = false;
        }         
      }
    }
    delay(1);
    client.stop();   
  }
} 

Astuce : Vous pouvez retrouver les sources du projet ici sur mon espace Bitbucket.

Résultat

Voici le résultat visuel lorsque l’on appelle la page (dans mon cas, http://192.168.1.5)

Données JSON fournies par l’Arduino

C’est alors très facile de récupérer les valeurs et d’alimenter n’importe quel serveur domotique !

Bon bricolage.

6 Comments

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.