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.
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
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.
J’ai demandé à Madame de m’imprimer en 3D un support pour rail DIN, vous pourrez trouver le modèle pour arduino uno ici.
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)
C’est alors très facile de récupérer les valeurs et d’alimenter n’importe quel serveur domotique !
Bon bricolage.
Bonjour
quelle est la longueur maxi de fil entre une sonde de température DS18b20 et l’arduino?
Cordialement
Bressy Frederic
Je suis déjà monté à 20m sans problème, mais il faut bien avoir une alimentation externe pour le 5V.
Bonjour,
merci pour ce tuto, j’ai récupéré ton code pour connaître la température de l’air et la température de l’eau de ma piscine.
Par contre, je souhaite envoyer ça sur mon serveur de domotique sous jeedom et là ben je ne sais pas faire. Bon c’est vrai, je ne suis pas un spécialiste mais si tu pouvais m’aiguiller, merci, oldneef
Bonjour,
en fait pour envoyer à jeedom, il faut créer un device virtuel. Une fois créé, il suffit d’appeler l’url qui s’affiche dans jeedom avec les bons paramètres dont ce que tu veux envoyer (temperature, etc …)
L’url est sous cette forme : https://<URL_JEEDOM>/core/api/jeeApi.php?plugin=virtual&apikey=<MON_API>&type=virtual&id=#cmd_id#&value=#value#
#cmd_id# est l’id du device virtuel
#value# est la valeur à envoyer
Ca devrait t’aider à démarrer