Outils pour utilisateurs

Outils du site


raspberry_pi:ds18b20_temperature_numerique

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
raspberry_pi:ds18b20_temperature_numerique [06/10/2016 16:58]
sky99
raspberry_pi:ds18b20_temperature_numerique [06/10/2016 17:12] (Version actuelle)
sky99
Ligne 1: Ligne 1:
 +====== DS18B20 – Mesurer la température avec une sonde numérique ======
 +
 Pour mesurer la température,​ il est possible d’utiliser divers capteurs, tels que le [[raspberry_pi:​tmp36_temperature|TMP36]],​ le DHT11/DH22, ou encore le DS18B20. C’est à cette dernière sonde que nous nous intéresserons aujourd’hui. Il s’agit d’une sonde numérique (pas besoin de convertisseur analogique-numérique tel que le [[raspberry_pi:​mcp3008_lecture_analogique|MCP3008]]) qui est assez précise (±0.5°C sur la plage -10°C – 85°C), raisonnablement facile à utiliser, et consommant peu. Par rapport à une sonde analogique, c’est un peu plus complexe, puisqu’il faut utiliser le protocole dallas 1-wire, mais nous verrons qu’il y a déjà les outils nécessaires pour exploiter tout cela. Pour mesurer la température,​ il est possible d’utiliser divers capteurs, tels que le [[raspberry_pi:​tmp36_temperature|TMP36]],​ le DHT11/DH22, ou encore le DS18B20. C’est à cette dernière sonde que nous nous intéresserons aujourd’hui. Il s’agit d’une sonde numérique (pas besoin de convertisseur analogique-numérique tel que le [[raspberry_pi:​mcp3008_lecture_analogique|MCP3008]]) qui est assez précise (±0.5°C sur la plage -10°C – 85°C), raisonnablement facile à utiliser, et consommant peu. Par rapport à une sonde analogique, c’est un peu plus complexe, puisqu’il faut utiliser le protocole dallas 1-wire, mais nous verrons qu’il y a déjà les outils nécessaires pour exploiter tout cela.
  
-===== DS18B20 Raspberry pi : le câblage =====+===== DS18B20 ​sur un Raspberry pi : le câblage =====
 Si nous regardons la sonde de près, elle est en forme de demi cylindre, avec un côté plat, portant des inscriptions,​ comme on peut le voir sur la photo suivante : Si nous regardons la sonde de près, elle est en forme de demi cylindre, avec un côté plat, portant des inscriptions,​ comme on peut le voir sur la photo suivante :
 {{http://​nagashur.com/​blog/​wp-content/​uploads/​2015/​08/​DS18B20_pinout_4747_800px.jpg | Brochage du DS18B20}} {{http://​nagashur.com/​blog/​wp-content/​uploads/​2015/​08/​DS18B20_pinout_4747_800px.jpg | Brochage du DS18B20}}
Ligne 73: Ligne 75:
 Comme nous l'​avons déjà vu brièvement,​ il est possible de récupérer uniquement la température dans une variable. Nous devrons alors diviser l'​ensemble par 1000 pour pouvoir avoir une température en  degrés Celsius. Cependant, le problème est que l'​interpréteur bash ne gère pas les nombres à virgule, mais uniquement les entiers. Il existe diverses solutions, et [[http://​stackoverflow.com/​questions/​12722095/​how-can-i-get-a-float-division-in-bash|vous pourrez en apprendre davantage en suivant ce lien]]. Pour faire simple, une solution serait d'​utiliser bc, mais ce n'est pas installé par défaut sur le raspberry pi. Une autre solution qui fonctionne sans ajouter de paquets est d'​utiliser awk. Comme nous l'​avons déjà vu brièvement,​ il est possible de récupérer uniquement la température dans une variable. Nous devrons alors diviser l'​ensemble par 1000 pour pouvoir avoir une température en  degrés Celsius. Cependant, le problème est que l'​interpréteur bash ne gère pas les nombres à virgule, mais uniquement les entiers. Il existe diverses solutions, et [[http://​stackoverflow.com/​questions/​12722095/​how-can-i-get-a-float-division-in-bash|vous pourrez en apprendre davantage en suivant ce lien]]. Pour faire simple, une solution serait d'​utiliser bc, mais ce n'est pas installé par défaut sur le raspberry pi. Une autre solution qui fonctionne sans ajouter de paquets est d'​utiliser awk.
  
 +==== Script bash ====
 +
 +Ainsi, on obtient un petit script **readTemp1.sh** basique :
 +
 +<file bash readTemp1.sh>​
 +
 +#!/bin/bash
 +temp01=`cat /​sys/​bus/​w1/​devices/​28-000006799670/​w1_slave | tail -n 1 | cut -f10 -d " " | cut -f 2 -d "​="​`
 +temp02=$(awk "BEGIN {printf \"​%.3f\",​${temp01}/​1000}"​)
 +echo $temp02
 +
 +</​file>​
 +
 +Enregistrez donc ceci dans un fichier **readTemp1.sh**,​ puis faites ajoutez les droits d'​exécution :
 +
 +<code bash>
 +chmod u+x readTemp1.sh
 +</​code>​
 +
 +Vous pouvez alors exécuter le script en faisant ​ **sudo ./​readTemp1.sh** . Il est également possible de ne pas ajouter les droits en exécution, et se contenter de faire **sudo sh ./​readTemp1.sh**.
 +
 +Dans tous les cas, on obtient un affichage en degrés Celsius avec les décimales (trois, mais on peut réduire en changeant le **%.3f** en **%.2f** dans le script pour avoir deux décimales par exemple).
 +
 +Cette approche basique fonctionne, et permet d'​obtenir la température. Mais idéalement,​ il faudrait vérifier sur la première ligne si l'on a bien un **YES**.
 +
 +C'est ce que nous ferons maintenant :
 +
 +<file bash readTemp2.sh>​
 +#!/bin/bash
 +probe_addr='​28-000006799670'​
 +res=`cat /​sys/​bus/​w1/​devices/​$probe_addr/​w1_slave | head -n 1 | grep YES | wc -l`
 +if [ $res -eq 1 ]
 +then
 +temp01=`cat /​sys/​bus/​w1/​devices/​$probe_addr/​w1_slave | tail -n 1 | cut -f10 -d " " | cut -f 2 -d "​="​`
 +temp02=$(awk "BEGIN {printf \"​%.2f\",​${temp01}/​1000}"​)
 +echo $temp02
 +fi
 +</​file>​
 +
 +Dans ce contexte, le script teste si on a bien YES sur la ligne 1, et si c'est le cas, récupère la température et l'​affiche. Dans le cas contraire, il n'​affiche rien.
 +
 +On peut ajouter un elif dans le script si on veut afficher un message d'​erreur.
 +
 +==== Script python ====
 +
 +Pour ce script, je ne vais pas réinventer la roue, et on va utiliser un script inspiré du [[https://​learn.adafruit.com/​adafruits-raspberry-pi-lesson-11-ds18b20-temperature-sensing/​software|code d'​exemple d'​Adafruit]] :
 +<file python readTemp1.py>​
 +#​!/​usr/​bin/​env python
 +import os
 +import glob
 +import time
 +import sys
 +
 +os.system('​modprobe w1-gpio'​)
 +os.system('​modprobe w1-therm'​)
 +
 +base_dir = '/​sys/​bus/​w1/​devices/'​
 +device_folder = glob.glob(base_dir + '​28*'​)[0]
 +device_file = device_folder + '/​w1_slave'​
 +
 +def read_temp_raw():​
 + f = open(device_file,​ '​r'​)
 + lines = f.readlines()
 + ​f.close()
 + ​return lines
 +
 +def read_temp():​
 + lines = read_temp_raw()
 + while lines[0].strip()[-3:​] != '​YES':​
 + ​time.sleep(0.2)
 + lines = read_temp_raw()
 + ​equals_pos = lines[1].find('​t='​)
 + if equals_pos != -1:
 + ​temp_string = lines[1][equals_pos+2:​]
 + ​temp_c = float(temp_string) / 1000.0
 + ​temp_f = temp_c * 9.0 / 5.0 + 32.0
 + ​return temp_c, temp_f
 +
 +try:
 + while True:
 + ​print(read_temp()[0])
 + ​time.sleep(0.3)
 +except KeyboardInterrupt:​
 + ​sys.exit(0)
 +</​file>​
 +
 +J'ai modifié leur code pour ajouter un [[https://​fr.wikipedia.org/​wiki/​Shebang|shebang]] au début, l'​ajout de [[http://​stackoverflow.com/​questions/​15318208/​capture-control-c-in-python|la gestion d'une exception pour capturer le CTRL+C]], qui permet de quitter le script, sans afficher de messages d'​erreur,​ et enfin le fait de n'​afficher que la température en  Celsius. Si vous voulez des degrés Fahrenheit, il suffira de modifier la ligne 34 pour remplacer le 0 en 1 entre les crochets, et pour afficher les deux il suffit d'​enlever les crochets et le nombre.
 +
 +Ce script affiche la température toutes les demi-secondes,​ et tourne en boucle pour ne se terminer que si l'on fait CTRL+C. En outre, il affichera la température de la première sonde DS18B20 trouvée, et donc ne sera pas adapté à l'​affichage de plusieurs températures. On peut le modifier pour afficher une sonde bien précise qui n'est pas forcément la première, et également pour qu'il affiche la température une fois avant de quitter (pouvant ainsi être utilisé pour d'​autres scripts) :
 +
 +<file python readTemp2.py>​
 +#​!/​usr/​bin/​env python
 +import os
 +import glob
 +import time
 +import sys
 +
 +os.system('​modprobe w1-gpio'​)
 +os.system('​modprobe w1-therm'​)
 +
 +base_dir = '/​sys/​bus/​w1/​devices/'​
 +probe_addr='​28-000006799670/'​ #remplacer ici par l'​adresse de la sonde
 +device_folder = glob.glob(base_dir + probe_addr)[0]
 +device_file = device_folder + '/​w1_slave'​
 +
 +def read_temp_raw():​
 + f = open(device_file,​ '​r'​)
 + lines = f.readlines()
 + ​f.close()
 + ​return lines
 +
 +def read_temp():​
 + lines = read_temp_raw()
 + while lines[0].strip()[-3:​] != '​YES':​
 + ​time.sleep(0.2)
 + lines = read_temp_raw()
 + ​equals_pos = lines[1].find('​t='​)
 + if equals_pos != -1:
 + ​temp_string = lines[1][equals_pos+2:​]
 + ​temp_c = float(temp_string) / 1000.0
 + ​temp_f = temp_c * 9.0 / 5.0 + 32.0
 + ​return temp_c, temp_f
 +
 +print(read_temp()[0])
 +</​file>​
 +
 +A noter qu'on peut également se débarrasser des deux lignes 7 et 8 si l'on a chargé les modules au démarrage.
 +===== Autres ressources =====
  
  
  
 +S'il vous faut d'​autres ressources, en voici quelques unes :
  
 +  * [[https://​learn.adafruit.com/​adafruits-raspberry-pi-lesson-11-ds18b20-temperature-sensing/​hardware|Le tutoriel d'​Adafruit]],​ en Anglais, qui m'a servi de base;
 +  * [[http://​www.manuel-esteban.com/​raspi-capteur-de-temperature-ds18b20/​|Le tutoriel de Yaug's corner]], (en Français) qui fournit encore quelques liens;
 +  * [[http://​www.framboise314.fr/​mesure-de-temperature-1-wire-ds18b20-avec-le-raspberry-pi/​|Le tutoriel de framboise314]],​ toujours en Français, extrêmement complet, avec notamment des explications sur le bus 1-wire, et le mode parasite, et qui complète très bien cet article ou je me suis davantage concentré sur le code que sur le principe électronique général du capteur.
  
  
raspberry_pi/ds18b20_temperature_numerique.1475765895.txt.gz · Dernière modification: 06/10/2016 16:58 par sky99