Lire la température ambiante avec votre Raspberry Pi

Salut,

Je vous propose de voir comment mesurer la température ambiante à l’aide d’un Raspberry Pi et d’un petit capteur de température.

Le matériel


Pour mesurer la température, il existe de nombreux petits capteurs électroniques qui se différencient selon quatre caractéristiques principales :

  1. Leur sortie est analogique ou numérique
  2. Leur plage d’utilisation (en particulier dans les températures négatives)
  3. Leur précision et la linéarité de la valeur retournée en fonction de la température réelle
  4. Leur conditionnement

Le principe pour la plupart des capteurs de température est d’avoir une résistance interne dont la valeur varie en fonction de la température. Les capteurs électroniques les plus courant dans les montages en électronique domestique sont:

  • Le TMP36 (j’y reviendrai dans un prochain article sur un capteur de température avec transmission radio)
  • Le LM35
  • Le DS18B20

Ce dernier, le DS18B20 du fabriquant « Dallas », présente l’énorme avantage d’avoir une sortie numérique, ce qui arrange bien nos affaires puisque le Raspberry Pi ne possède pas de ports d’entrée/sortie analogiques. Ce capteur intègre un ADC (Analog to Digital Converter), c’est à dire un convertisseur analogique/numérique, et utilise le bus 1-Wire (lien) pour interagir avec lui et donc lire la température.

Les spécifications de la bête sont là: lien. On voit qu’il s’agit d’un petit composant à trois broches:

  1. Une broche pour la masse (GND)
  2. Une broche pour l’alimentation (VCC)
  3. Une broche pour les données (DQ)

Les instructions de montage indiquent qu’il faut mettre une résistance de tirage entre le circuit de données et l’alimentation. Pour éviter de faire des soudures, ou d’avoir une résistance sur la plaque de prototypage, j’ai opté pour un petit circuit intégrant tout ça:

C’est juste plus facile et ça ne change rien, ni au principe, ni aux fonctions des broches.

Les branchements


Le schéma de branchement que l’on trouve partout sur le net est le suivant:

On voit qu’il est possible d’alimenter le DS18B20 avec le pin 3.3V du RPi. Si vous optez pour le même petit circuit que moi, vous n’aurez pas à mettre la résistance de tirage puisqu’elle est déjà intégrée. Il est important de brancher la broche des données du capteur sur le pin physique 7 du RPi (soit le GPIO 4 comme montré sur le schéma).

La raison est que dans le code du noyau de base de la distribution du RPi, c’est uniquement ce port là qui implémente la communication par bus 1-Wire. Ça peut se changer en modifiant le fichier « /boot/cmdline.txt« , mais cela nécessite un reboot du système. Par exemple, si on voulait utiliser le GPIO 8:

bcm2708.w1_gpio_pin=8

Mais restons simple et gardons le branchement par défaut sur le pin 7 (GPIO 4). Sur la photo ci-dessous, le fil rouge relie la broche « + » à l’alimentation 3.3V, le fil jaune relie la broche « – » à la masse, et le fil orange relie la broche « S » au port GPIO 4 du RPi.

La partie logicielle


Dans un premier temps, il faut charger les modules (l’équivalent des pilotes Windows) qui gèrent le bus 1-Wire sur le port GPIO 4. Taper les deux commandes suivantes :

pi@domopi ~ $ sudo modprobe w1-therm
pi@domopi ~ $ sudo modprobe w1-gpio

On vérifie que les modules sont bien chargés :

pi@domopi ~ $ lsmod
Module                  Size  Used by
w1_gpio                 2751  0
w1_therm                2866  0
wire                   25349  2 w1_gpio,w1_therm
cn                      4780  1 wire

Pour rendre le chargement de ces modules automatique au démarrage du système, il faut rajouter les deux lignes suivantes dans le fichier « /etc/modules » , puis sauvegarder:

w1-therm
w1-gpio

 Si tout s’est bien passé, le système présente désormais un nouveau périphérique sous forme de fichier (sous Unix, tout est fichier). Il faut chercher dans le répertoire « /sys/bus/w1/devices/w1_bus_master1/ » , en particulier dans le sous répertoire commençant par « 28- » qui correspond au nom de la sonde vue sur le bus 1-Wire :

pi@domopi ~ $ ls -la /sys/bus/w1/devices/w1_bus_master1/
total 0
drwxr-xr-x 4 root root    0 Jan 27 14:16 .
drwxr-xr-x 9 root root    0 Jan 27 12:45 ..
drwxr-xr-x 3 root root    0 Jan 27 14:16 28-0000053b95d8
lrwxrwxrwx 1 root root    0 Apr  5 19:46 driver -> ../../bus/w1/drivers/w1_master_driver
drwxr-xr-x 2 root root    0 Jan 27 14:16 power
lrwxrwxrwx 1 root root    0 Apr  5 19:46 subsystem -> ../../bus/w1
-rw-r--r-- 1 root root 4096 Apr  5 19:46 uevent
-rw-rw-r-- 1 root root 4096 Apr  5 19:46 w1_master_add
-r--r--r-- 1 root root 4096 Apr  5 19:46 w1_master_attempts
-r--r--r-- 1 root root 4096 Apr  5 19:46 w1_master_max_slave_count
-r--r--r-- 1 root root 4096 Apr  5 19:46 w1_master_name
-r--r--r-- 1 root root 4096 Apr  5 19:46 w1_master_pointer
-rw-rw-r-- 1 root root 4096 Apr  5 19:46 w1_master_pullup
-rw-rw-r-- 1 root root 4096 Apr  5 19:46 w1_master_remove
-rw-rw-r-- 1 root root 4096 Apr  5 19:46 w1_master_search
-r--r--r-- 1 root root 4096 Apr  5 19:46 w1_master_slave_count
-r--r--r-- 1 root root 4096 Apr  5 19:46 w1_master_slaves
-r--r--r-- 1 root root 4096 Apr  5 19:46 w1_master_timeout

Sous ce répertoire, on trouve le fichier qui nous intéresse, nommé « w1_slave » :

pi@domopi ~ $ ls -la /sys/bus/w1/devices/w1_bus_master1/28-0000053b95d8/
total 0
drwxr-xr-x 3 root root    0 Jan 27 14:16 .
drwxr-xr-x 4 root root    0 Jan 27 14:16 ..
lrwxrwxrwx 1 root root    0 Apr  5 19:59 driver -> ../../../bus/w1/drivers/w1_slave_driver
-r--r--r-- 1 root root 4096 Apr  5 19:59 id
-r--r--r-- 1 root root 4096 Apr  5 19:59 name
drwxr-xr-x 2 root root    0 Jan 27 14:16 power
lrwxrwxrwx 1 root root    0 Apr  5 19:59 subsystem -> ../../../bus/w1
-rw-r--r-- 1 root root 4096 Apr  5 19:59 uevent
-r--r--r-- 1 root root 4096 Jan 27 14:16 w1_slave

Si l’on affiche le contenu de ce fichier, le pilote 1-Wire va interroger la capteur en direct et retourner une valeur si c’est possible à l’instant demandé :

pi@domopi ~ $ cat /sys/bus/w1/devices/w1_bus_master1/28-0000053b95d8/w1_slave
7d 01 4b 46 7f ff 03 10 24 : crc=24 YES
7d 01 4b 46 7f ff 03 10 24 t=23812

 On voit ici que le checksum (CRC) est correct, et que la valeur de température est de 23,812°C. Il nous reste à créer un petit script qui va:

  1. Chercher automatiquement le bon fichier
  2. Tenter une lecture de la température, jusqu’à ce qu’une valeur soit retournée
  3. Formater correctement la sortie

Voici le petit script que j’ai écrit (comme d’habitude, écrit et commenté en anglais, sorry…) :

#!/bin/bash

# Root Directory for the Wire1 (w1) devices
ROOTDIR="/sys/bus/w1/devices/w1_bus_master1/"

# Searching for the directory starting with "28" corresponding to the device unique address
# Warning: this code only works if you have one device only. Change the code otherwise...
DEVICE=$(find $ROOTDIR -name "28*")

while true; do
	read UNUSED CRC TEMP <<<$(cat $DEVICE/w1_slave | awk -F "=" '/crc/ {print $2} /t/ {OFMT = "%.1f"; print $2/1000}')
	
	# If the CRC is "YES", we can print out the temperature
	if [[ $CRC == "YES" ]]; then
		echo $TEMP
		break
	# Otherwise, wait 500ms and try again
	else
		sleep 0.5
	fi
done

 Ce qui donne le résultat suivant, après avoir donné les droits d’exécution au script :

 Lire la température par le réseau


Comme je l’ai déjà montré pour les prises électriques radio commandées, dans le cadre de mon installation, j’ai besoin de pouvoir interroger le DomoPi depuis mon RPi frontal, via le réseau.

Rien de plus simple, depuis que je vous ai montré et détaillé comment faire communiquer les deux RPi via le réseau, il suffit de mettre à jour le script qui reçoit les commandes pour traiter les requêtes de lecture de la température.

A nouveau, je vous propose ici le script déjà présenté pour la partie prises électriques, complété par la partie lecture de la température :

#!/bin/bash
# Author: Arno0x0x
# Description:
#	This script executes some domotic orders based on the command passed as argument.
#	The network wrapper is Xinetd on port 6868/tcp (domoservices)
# Dependencies:
#	This script depends on two binaries to send RF433 commands to remote controled outlets
#	1. chacon_send : Used to control "Chacon - D-IO" outlets.
#					 Usage: chacon_send <wiringPI pin> <controler code> <outlet code> <on|off>
#					 Ex:	chacon_send 0 12325261 1 on					 
#	2. phenix_send : Used to control "PHENIX type" outlets. WiringPi pin used is forced to 0 at compile time.
#					 Usage: phenix_send <wiringPI pin> <controler code> <outlet code> <1|0>
#					 Ex:	phenix_send 0 10110 1 1

#-----------------------------------------------------------------------
# Initialize main variables
# ligth1 = salle a manger | light2 = salon
# heater1 = salon | heater2 = entree
#-----------------------------------------------------------------------
export LANG=en_GB.UTF-8
_rootDir="/home/pi/Domotique"
_domoServicesLogFile="${_rootDir}/domoservices.log"
_light1_ON="sudo ${_rootDir}/phenix_send 0 10110 1 1"
_light1_OFF="sudo ${_rootDir}/phenix_send 0 10110 1 0"
_light2_ON="sudo ${_rootDir}/phenix_send 0 10110 2 1"
_light2_OFF="sudo ${_rootDir}/phenix_send 0 10110 2 0"
_heater1_ON="sudo ${_rootDir}/chacon_send 0 12325261 1 on"
_heater1_OFF="sudo ${_rootDir}/chacon_send 0 12325261 1 off"
_heater2_ON="sudo ${_rootDir}/chacon_send 0 12325261 2 on"
_heater2_OFF="sudo ${_rootDir}/chacon_send 0 12325261 2 off"
_readTemperature="${_rootDir}/readTemperature.sh"

#-----------------------------------------------------------------------
# Read the command passed on stdin
read _command

case ${_command} in
   light1ON)
		${_light1_ON}
		[[ $? -eq 0 ]] || echo "[ERROR]" >> ${_domoServicesLogFile}
		;;
   light1OFF) 
		${_light1_OFF}
		[[ $? -eq 0 ]] || echo "[ERROR]" >> ${_domoServicesLogFile}
		;;
   light2ON)
		${_light2_ON}
		[[ $? -eq 0 ]] || echo "[ERROR]" >> ${_domoServicesLogFile}
		;;
   light2OFF) 
		${_light2_OFF}
		[[ $? -eq 0 ]] || echo "[ERROR]" >> ${_domoServicesLogFile}
		;;
   heater1ON)
		${_heater1_ON}
		[[ $? -eq 0 ]] || echo "[ERROR]" >> ${_domoServicesLogFile}
		;;
   heater1OFF)
		${_heater1_OFF}
		[[ $? -eq 0 ]] || echo "[ERROR]" >> ${_domoServicesLogFile}
		;;
   heater2ON)
		${_heater2_ON}
		[[ $? -eq 0 ]] || echo "[ERROR]" >> ${_domoServicesLogFile}
		;;
   heater2OFF)
		${_heater2_OFF}
		[[ $? -eq 0 ]] || echo "[ERROR]"  >> ${_domoServicesLogFile}
		;;
   readTemperature)
		echo $($_readTemperature)
		[[ $? -eq 0 ]] || echo "[ERROR]"  >> ${_domoServicesLogFile}
		;;
   *) echo "[ERROR] UNKNOWN COMMAND"
	  ;;
esac

C’en est fini pour la lecture de température, en tous cas en local. J’ai un projet en préparation de lecture de température à distance, mais ça fera l’objet d’un autre article.

Je vous montrerai très bientôt comment faire un petite page web de présentation des premiers services domotiques : prises commandées sans fil et lecture de température.

A bientôt !

Vous aimez cet article ? Faites le savoir avec quelques bitcoins !

Publicités

3 réflexions sur “Lire la température ambiante avec votre Raspberry Pi

  1. gsmurf7 10 avril 2015 / 19 h 43 min

    Très intéressant ton article, crois-tu qu’il soit possible de relevé la température sur plusieurs sondes « locales » directement branchées sur le RPI ?

    J'aime

    • arno0x0x 11 avril 2015 / 8 h 44 min

      Oui, il est possible de mettre plus de nœuds sur un bus 1-Wire, donc à priori plusieurs sondes « locales » en 1-Wire.

      J'aime

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s