Académique Documents
Professionnel Documents
Culture Documents
Henri MEURDESOIF
Gestionnaire de parc informatique
ICARE UMS 2877 - Polytech'Lille
Avenue Paul Langevin
59650 Villeneuve d'Ascq
Dans les pages qui suivent je vais vous décrire les étapes de ce projet en suivant simplement les
étapes de son évolution.
Sommaire
01. Pourquoi ce besoin ?................................................................................................................................4
02. Comment contrôler la température?.........................................................................................................4
03. Avec quel matériels ?...............................................................................................................................5
04. Je résume..................................................................................................................................................7
05. Du matériel, mais quelle quantité ?..........................................................................................................7
06. À quel prix ?...........................................................................................................................................11
07. Mais comment cela fonctionne ?...........................................................................................................12
08. Premier montage test : DS18B20 (température)....................................................................................13
09. Second montage test : DHT22 (humidité).............................................................................................16
10. La programmation..................................................................................................................................18
11. Quelques graphiques..............................................................................................................................22
12. La fabrication.........................................................................................................................................25
13. Dernier test avec une mise en œuvre localement...................................................................................27
14. Mise en œuvre en salle...........................................................................................................................28
15. Une interface Web ?...............................................................................................................................29
16. Je résume les difficultés.........................................................................................................................32
17. Conclusion et évolution.........................................................................................................................32
Annexe 1 : 18B20_read_adresses................................................................................................................34
Annexe 2 : DHT...........................................................................................................................................35
Annexe 3 : 18B20PAR_DHT22_115200bauds............................................................................................35
Annexe 4 : probe.py.....................................................................................................................................38
Annexe 5 : probe_average.py.......................................................................................................................39
Annexe 6 : probe18B20P_munin.py............................................................................................................41
Annexe 7 : probeDHT22_munin.py.............................................................................................................42
Annexe 8 : index.php...................................................................................................................................44
Annexe 9 : cold.php.....................................................................................................................................45
Notre matériel est hébergé au Centre de Ressources Informatiques de l'Université de Lille Sciences
et Technologies. En 2014 nous nous sommes retrouvés confrontés à un problème de structure : le faux-
plancher était limité à 600 kg/m2 alors qu'une armoire informatique pouvait accueillir 1 200 kg/m2 en
baies de disques.
De ce fait, nous avons fait les travaux nécessaires dans une nouvelle salle et nous y sommes
installés. Nous en avons profité pour entrer dans le plan de « développement durable » du CRI en mettant
en place un corridor froid.
Oui, mais… C'est là que les choses se compliquent un peu, car arrivent les questions :
- Où ? Quand ? Comment ? Etc.
- Ai-je bien fait de faire une armoire avec uniquement des baies de disques, une autre armoire
avec des serveurs, ainsi qu'une autre avec l'équipement réseau ?
- Que se passera t-il quand je vais ajouter ou retirer du matériel ? Quel impact cela aura t-il sur les
flux de température ?
• Le thermomètre à mercure : Ils sont interdits à la vente depuis le 1er mars 1999 non pas à cause
de leur inefficacité, mais à cause de la dangerosité pour la santé du mercure qu'ils déversent dans
nos habitations quand ils se cassent accidentellement et aussi grâce à la mise sur le marché de
thermomètres électroniques de toutes sortes pouvant les remplacer efficacement. Cette mesure
réduit aussi les sources d'agents polluants de l'environnement.
1 Source : fr.wikipedia.org/wiki/Sens_(physiologie)#Thermoception
2 Image : store.glennz.com/collections/animals/products/less-formal
• Le thermomètre enregistreur USB : Il n''enregistre qu'une zone pendant un laps de temps assez
court.
• Et relever la température via le matériel en place tels que les serveurs, baies, switchs, etc ? Oui
c'est possible, mais selon le constructeur cela s'avère plus ou moins facile. Et centraliser toutes les
informations via un seul protocole demande d'y consacrer un peu de temps, à trouver la bonne
MIB (Management Information Base, terme informatique désignant une base de données utilisées
pour la gestion des réseaux, manipulable par des protocoles tels que SNMP (Simple Network
Management Protocol)) et à l'exploiter.
De plus :
• Comment connaître la température là où il n'y a pas de machine (partie du corridor encore
inoccupée) ?
• Pourquoi ne pas contrôler aussi la température dans le faux-plafond et le
faux-plancher ?
• Comment relever et enregistrer plusieurs zones à un prix intéressant et
pouvoir consulter le tout à distance ?
On peut donc l'utiliser comme un serveur pour faire les relevés, les mémoriser, les consulter, etc.
Dans un premier temps ce fût le choix du Raspberry que j'ai retenu en modèle B Rev 2, car (à l'époque,
fin 2014) ce modèle était le plus courant, disponible et pas cher.
De plus, le premier n’est pas directement utilisable sur le Raspberry Pi car il délivre une tension/un
courant (donc analogique) et nécessite la mise en œuvre d’une carte de mesure avec convertisseur
analogique => digital (ADC ou CAN).
Dans les seconds, une famille est particulièrement adaptée au Raspberry Pi, c’est la série de 1-wire,
ou capteurs utilisants un seul fil (nous verrons qu’il en faut tout de même trois en comptant
l'alimentation). Le Raspberry Pi (en fait Linux) quant à lui embarque le pilote capable de gérer cette
famille de composants.
Dans mes différentes lectures (magazines, sites web, forums…) les plus souvent cités sont les
capteurs de températures Dallas 18B20.
- DS18B20 : Il faut relier la patte de masse (Terre, ground, GND) à gauche et celle
de tension d'alimentation (Power Supply Voltage/VDD) à droite soit du côté du
circuit, soit du côté de la sonde. La patte centrale étant celle des données (Data
In/Out, DQ).
6 www.mon-club-elec.fr/pmwiki_mon_club_elec/pmwiki.php?n=MAIN.ArduinoExpertCapteursComplexesDS18B20Test
7 datasheets.maximintegrated.com/en/ds/DS18B20-PAR.pdf
8 www.maximintegrated.com/en/app-notes/index.mvp/id/203
9 www.sparkfun.com/datasheets/Sensors/Temperature/DHT22.pdf
Et : Une platine de test, quelques résistances (4,7 kΩ et moins selon la longueur des câbles).
04. Je résume
◦ Les enregistrer
◦ Les consulter à distance
Mes salles ? Oui depuis le début je dis « ma salle », mais vu qu'en plus de la salle machines, nous
avons une seconde pièce où est implantée notre librairie de sauvegarde. Et que cette pièce est dépourvue
de ventilation, pourquoi ne pas aussi y contrôler la température … ?
8 dans le faux-plafond
8 dans le faux-plancher
• Arduino UNO : 1
Pour faire quelque chose de propre, qui n'est pas censé évoluer et économiser du câble j'ai préféré
prendre un peu de temps et mesurer.
3,0m
1,0m
4,5m
0,5m
0,5m
0,5m d
ans l'amoir
e
11 2,5 12 2,5 13
2,5
14 2,5 15 2,5 16
4m
1,0
1,0
1,0
5m
10
31-2 25-2 19-2
10m
1,2 1,2 1,2
32 26 20
1,0
1,0
1,0
Plafond : 30m (10+20) Plancher : 25m (5+20)
H1-4 H2-4 33-2 23-2 2,5 21-2
1 2,5 2,5 2 9 2,5 2,5 10
1,2 1,2 1,2
34 24 22
2,5
2,5
2,5
1,0
1,0
49 43 37
1,2 1,2 1,2
48-2 42-2 36-2
1,0
1,0
1,0
51 41 39
1,2 1,2 1,2
50-2 40-2 2,5 38-2
Soit environ le coût de 6 sondes toutes faites (sans PDU ou système multi-capteurs pour les
brancher). Cela semble acceptable.
À ce stade, j'avoue être passé à côté d'une information : Le Raspberry ne sait pas dialoguer avec
un capteur DS18B20-PAR… Comme je les avais déjà commandés et reçus… Je me suis tourné vers la
solution Arduino Uno, modèle de base qui devrait être suffisant à mon projet.
Note : On peut trouver tout cela moins chers sur des sites de ventes bien connus…
11 www.conrad.fr/ce/fr/product/1188439/Borne-de-polarite-WAGO-221-412-Nombre-de-poles-2-transparent-orange-100-pcs
Le maître initialise le bus en forçant un zéro pendant plus de 480 µs. Les esclaves lui répondent en
mettant eux aussi leur sortie à zéro pendant un certain temps, indiquant ainsi leur présence.
Le maître déclenche une lecture dite ROM et l’esclave renvoie son identifiant unique, gravé lors
de la fabrication. Chaque identifiant a une longueur de 48 bits (8 octets) encadré par un octet indiquant le
type de matériel (ici le type est : sonde de température = 28H) et un octet de CRC qui permet au maître
de vérifier qu’il a correctement reçu les informations d’identification du composant. Les 48 bits
permettent d’individualiser à peu près 280 000 milliards de composants…
Dans le mode parasite, l’esclave est connecté en reliant ses broches d’alimentation ensemble et en
les reliant à la masse. Il n’y a plus besoin dans ce cas que de deux fils pour assurer la liaison avec les
esclaves connectés au bus 1-wire.
Lorsque le bus est au niveau 1, un condensateur interne au composant esclave est chargé, et c’est
lui qui assurera l’alimentation du composant pendant que le niveau du bus sera bas.
Le DS18B20 a une gamme de mesure qui s’étend de -55 °C à +125 °C. Il transmet sa mesure
directement en degrés Celsius, codée sur 16 bits. Sa précision est de ±0,5 °C entre -10 °C et +85 °C.
Un tour sur Internet et chez les vendeurs asiatiques montre que ce composant est disponible sous
forme de boîtier TO92 (cela ressemble à un transistor, mais ce n’est pas un transistor !) ou de sonde
étanche, montée, avec les fils de sortie.
12 www.framboise314.fr/mesure-de-temperature-1-wire-ds18b20-avec-le-raspberry-pi/
8.1. : Je n'entrerai pas dans le détail de l'utilisation d'un Arduino, une simple recherche sur un
moteur de recherche vous donnera toutes les informations nécessaires. Mais en bref il suffit
- de télécharger le logiciel « Arduino » (1.6.7 au moment du projet)
www.arduino.cc/en/Main/Software
- de l'installer
- de brancher la carte via câble USB sur votre machine
ATTENTION :
• À la première ligne : j'insère une librairie (disponible sur le site Arduino) qu'il vous
faudra télécharger auparavant pour que le programme puisse l'utiliser.
• À la seconde ligne de bien mettre le numéro de la PIN de l'Arduino :
SENSOR_PIN 2 (sur mon précédent schéma elle est aussi sur la PIN 2)
8.7. : Et pour les identifier visuellement : je les numérote via un coup de feutre argenté et un feutre
pointe fine (oui il faut écrire très petit...).
Je change de sonde, j'appuie sur le bouton RESET sur la carte Arduino, l'adresse de la nouvelle
sonde apparaît dans le moniteur série, je copie/colle l'adresse et je répète l'opération encore soixante
fois… Cela me donne ce fichier :
DeviceAddress Probe01 = { 0x28, 0x1C, 0xB5, 0xA0, 0x06, 0x00, 0x00, 0xDD };
DeviceAddress Probe02 = { 0x28, 0x1D, 0xC3, 0xA0, 0x06, 0x00, 0x00, 0x1B };
DeviceAddress Probe03 = { 0x28, 0xAF, 0xD6, 0xA0, 0x06, 0x00, 0x00, 0xDC };
…
DeviceAddress Probe62 = { 0x28, 0xFC, 0xD3, 0xA0, 0x06, 0x00, 0x00, 0x79 };
Ce qui me donne :
Probe01 = 281CB5A0060000DD
Probe02 = 281DC3A00600001B
Probe03 = 28AFD6A0060000DC
…
Probe62 = 28FCD3A006000079
9.1. : Montage
Une DHT22 n'a pas de numéro d'identification, ce qui n'est pas trop grave puisque j'en mets une
par zone et que chacune est reliée sur une entrée de l'Arduino, donc selon l'entrée/PIN interrogée on sait
quelle sonde/zone répond.
Changement de sonde, RESET pour les trois autres sondes : OK elles fonctionnent.
• Les deux premiers programmes ne gèrent qu'une sonde à la fois. Je vais devoir maintenant en
gérer « N »…
• Et avoir les résultats non plus via le moniteur série de l'Arduino, mais via un serveur > USB >
Arduino.
Pour ce dernier point (faire les relevés et dialoguer avec l'Arduino), je vais utiliser Python côté
serveur et une communication série côté Arduino.
Attention :
Et comme souvent, il faut faire attention à certaines lignes. Ici se sont les lignes :
• ONE_WIRE_BUS 2 qui définit sur quelle port de l'Arduino sont connectées les DS18B20.
• La note pas de « ; » après une commande « défine » est une note personnel, car (peut être
comme vous) je découvre le langage Arduino.
Cela induit que la première sonde DHT sera sur le port 3, la seconde sur le 4, la troisième
sur le 5 et la quatrième et dernière sera sur le port 6.
• Serial.begin(115200) : donne la vitesse de transmission du port série, par défaut 9600 (j'en
reparlerai un peu plus loin dans la section Version 2).
J'avoue qu'à la base, je ne suis pas programmeur. Ce projet fut pour moi l'occasion de m'initier à
Python (et de découvrir autre chose que Bash, Sed et Awk).
Mais pourquoi Python ? Simplement parce qu'il est fortement utilisé au sein de mon laboratoire et
que je pouvais avoir de l'aide localement par le biais de mes collègues. On le dit un langage facile, ce que
je confirme ;-)
Donc pour faire les relevés et dialoguer avec l'Arduino, je vais utiliser Python côté serveur pour
établir une communication de type série avec l'Arduino via le port USB.
Pour cela il faut installer la librairie pyserial, en tant que root (administrateur sous Linux), cela
donne les commandes suivantes :
$ yum install python-pip
$ pip install –upgrade pip
$ pip install pyserial
$ yum install numpy
Le programme probe.py est en Annexe 4, toujours pour que vous puissiez le copier/coller et
l'utiliser sans à avoir à le retaper.
$ ./probe.py
IL NE RENVOIE RIEN A L ECRAN ! Pour contrôler il faut regarder dans le fichier qu'il a créé :
$ cat /tmp/probe
14/01/16 05:35:29 61
14/01/16 05:35:29 2870CCA0060000FD 28.00
...
14/01/16 05:35:59 28DFCAA006000019 25.50
14/01/16 05:36:30 Probe1 45.00 16.60
14/01/16 05:36:31 Probe2 18.60 33.10
14/01/16 05:36:32 Probe3 No good boss.
14/01/16 05:36:33 Probe4 29.90 25.30
$ ./probe.py debug
Au passage on peut noter que le programme dure 10:09:07 -> 10:11:17 = 2mn10s
Je reviendrai sur ce point par la suite…
Une fois le programme dans l'Arduino celui-ci tourne en boucle dès qu'il est alimenté, donc rien
d'autre à faire.
Pour le programme en python, je vais simplement l'ajouter dans la table Cron, pour un lancement
toutes les trois minutes vu que le programme dure 2mn10s. Pour cela :
$ crontab -e
MAILTO=""
# NE PAS ENVOYER DE MAIL A CHAQUE CRON
# TOUTES LES 3 MINUTES interrogation des sondes de températures/humidités et enregistrement dans /tmp/probe
*/3 * * * * /usr/bin/python /root/arduino/programmes/probe.py
et
$ ll /tmp/
-rw-r--r-- 1 root root 2671 14 janv. 10:32 probe
… attendre 3 minutes ...
$ ll /tmp/
-rw-r--r-- 1 root root 2671 14 janv. 10:35 probe
Lire manuellement les 66 valeurs de températures et avoir directement une idée de la moyenne est
illusoire, encore plus si on veut le faire par zone (faux-plancher et faux-plafond, corridor chaud et froid,
librairie), donc je vais automatiser cela par un autre programme et en profiter pour avoir aussi les écarts
types par zone et préparer cela en vue de l'afficher dans une page Web.
Pour cela rappelez-vous que j'ai, par exemple pour une rangée d'armoires, mis 9 sondes dans le
corridor froid et 9 dans le corridor chaud.
31 25 19
32 26 20
33 23 21
34 24 22
Puis je calcule la moyenne pour chaque zone, ainsi que son écart type.
J'enregistre le tout dans un fichier et je l'encapsule de balises php, car les résultats me serviront par
la suite dans des pages web.
Idem, automatisations via une mise en cron et un lancement toutes les trois minutes
# TOUTES LES 3 MINUTES calcul de la moyenne des sondes et préparation du fichier php dans /tmp/probe_calcul
*/3 * * * * /usr/bin/python /root/arduino/programmes/probe_average.py
Voilà maintenant j'ai des sondes et je les relève régulièrement. Mais visuellement, pour suivre
tout cela, ce n'est pas terrible de lire des fichiers textes. Comme une image vaut mieux qu'un long
discours, un graphique vaut mieux que plein de chiffres !
Personnellement, ayant déjà Munin en place et étant lancé dans mes programmes en Python, je
combine les deux.
Encore une fois merci à mon moteur de recherche pour trouver des réponses à mes questions et
merci à ces personnes qui partagent leurs astuces sur le net… Ma source d'inspiration fut donc :
http://munin-monitoring.org/wiki/HowToWritePlugins
Pas grand-chose à dire dessus, chacun trouve les valeurs d'un type de sonde et fait le nécessaire
pour que Munin puisse les exploiter.
$ ./probeDHT22_munin.py
temperature.value 16.6
humidity.value 45.0
Je ne vais pas expliquer chaque étape, car tout se trouve dans la documentation de Munin.
$ cp probeDHT22_munin.py /usr/share/munin/plugins/DHT22_1
$ ln -s /usr/share/munin/plugins/DHT22_1 /etc/munin/plugins/DHT22_1
if __name__ == "__main__":
if len(sys.argv) == 2:
print_munin_config(sys.argv[1],"X")
else:
timestamp, humidity, temperature = get_temperature_from_sensor("X") # Probe Number
print_temperature_for_munin(humidity,temperature)
$ vi /etc/munin/plugin-conf.d/dht
[DHT22_1]
user root
[DHT22_2]
user root
[DHT22_3]
user root
[DHT22_4]
user root
Par contre je ne vais pas copier à la main 61 fichiers, donc une petite ligne de commande pour le
faire à ma place :
$ for i in {1..9}; do cp probe18B20P_munin.py /usr/share/munin/plugins/18B20P_0$i ; /bin/sed -i "s/\"01\"/\"0$i\"/g"
/usr/share/munin/plugins/18B20P_0$i ; done
$ for i in {1..9}; do echo "[18B20P_0$i]" >> /etc/munin/plugins/18b20p ; echo "user root" >> /etc/munin/plugins/18b20p ;
echo "" >> /etc/munin/plugins/18b20p ; done
$ for i in {10..62}; do echo "[18B20P_$i]" >> /etc/munin/plugins/18b20p ; echo "user root" >> /etc/munin/plugins/18b20p ;
echo "" >> /etc/munin/plugins/18b20p ; done
Je sais, on peut simplifier un peu ces lignes de codes, mais j'aime bien faire une première passe sur
quelques fichiers, ici 9 et continuer si tout s'est bien déroulé… Chacun ses petites habitudes...
12. La fabrication
Le fait de réunir les fil par paire réduit les risques en cas de coupure d'un fil et réduit de moitié la
résistance, comme elle sera importante vu les longueurs de câbles, c'est intéressant.
Côté Arduino :
noir = GND ? = data DHT22 bleu = data DS18 rouge = Vcc 5V
Arduino RJ45
Maintenant je sors :
• le mètre ruban, la pince et je coupe mes longueurs de câbles en pensant à les repérer
• Je coupe aussi mes gaines thermorétractables
• la pince à dénuder ou le cutter, attention au doigts…
• le fer à souder…
Mince ! Comme je l'avais lu sur internet et vous le disais au chapitre « 7 : Comment cela
fonctionne » Le bus 1-wire est relié au Vcc par une résistance de tirage de 4,7 kΩ. En fonction de la
longueur des fils de liaison, il sera parfois nécessaire d’ajuster sa valeur.
Mais les informations sur le sujet son rares, je n'ai trouvé que sur :
http://www.framboise314.fr/mesure-de-temperature-1-wire-ds18b20-avec-le-raspberry-pi/
Où l'on site du 200m, 10 capteurs et 1,5 kΩ de résistances
13
Longueur : l = 156 m
156 m
R=1,7×10−8 Ωm ≈2,65Ω
1,0×10−6 m2
OK… mais j'en fais quoi ? J'avoue que n'étant pas du domaine, il faudrait que je creuse un peu
plus pour savoir si je dois simplement déduire 2,65Ω des « habituels » 4,7 kΩ des exemples et de ce fait
mettre une résistance de 4,6 kΩ ?
En pratique : Je n'avais qu'une résistance de 4,7 kΩ et une autre de 470 Ω à ma disposition. J'ai
essayé celle de 470 Ω avec mes 156m de câbles et cela à fonctionné.
14 webetab.ac-bordeaux.fr/Pedagogie/Physique/Physico/Electro/e07fil.htm
Voilà, tout est en place. Maintenant comment vais-je visualiser toutes mes sondes sans regarder X
graphiques ? En résumant le tout par une petite page Web qui me conduira si besoin aux graphiques.
• Une image en fond, servant de point de référence, autrement dit les mes zones de textes se
baseront sur cette image pour se positionner d'après le point en HAUT a GAUCHE de l'image
qui a la référence 0px : 0px.
• Inclure un petit librairie15 javascript pour afficher proprement l'heure (au lieu de faire une
grosse programmation à la main…)
<script type="text/javascript" src="date.js"></script>
<script>
(function ()
{
document.write(new Date().toString("hh:mm tt"));
})();
</script>
• Et placer les liens menant vers les pages des zones : froide, chaude, plancher/plafond et
librairie.
Le résultat :
15 www.datejs.com/
Les avis divergent, certaines personnes aiment la représentation 3D, d'autres préfèrent un tableau
(2D), personnellement pour voir de suite s'il fait chaud en bas à droite par rapport à en haut à gauche ou
comme nous avons eu le cas : avoir une température dans la moitié du faux-plancher et une autre dans
l'autre moitié, mais une moitié étant le faux-plancher coupé en diagonale, car une climatisation tournait
plus que l'autre… Rien ne vaut, pour moi, une représentation 3D…
• Les exemples de programmes trouvés sur internet sont souvent mono-capteur, ou avec 2 ou 3
capteurs mais, dans ce cas, utilisés manuellement et unitairement en multipliant les lignes de
codes. Mais jamais mis dans une boucle pour, comme ici, en gérer des dizaines.
• Les câbles que j'ai bien fait de faire sur mesure, car cela diminue la longueur totale, donc la
résistance.
• Justement en parlant de la résistance, tous les exemples du net étant basés sur un branchement via
une platine de test, donc une longueur de câble nulle, ils donnent la valeur de 4,7 kΩ, hors plus on
met de câbles, plus il faut baisser la résistance. Mais de combien ? Je ne connais pas assez ce
domaine pour répondre à cette question.
• Les difficultés d'assemblage à cause des connecteurs Wago (malgré des sections de fils
doublées et étamées.).
• Environ le coût de 2 lots de 3 sondes toutes faites (sans les à cotés : PDU ou système multi-capteurs
pour les brancher).
• Un peu de temps.
J'ai mis en place une solution à une échelle plus grande, sans trop de difficulté.
Maintenant je ne dis pas qu'elle ne peut pas être améliorée, puisqu'au contraire j'y pense en :
• Mettre le tout dans un « joli » boiter16 1U rackable permettant au passage d'y mettre une
alimentation pour alimenter séparément l'Arduino et les sondes, une possibilité de faire des
connectiques en façade via prises jack ou RJ45...
16 www.selectronic.fr/coffret-rack-19-en-plastique-1u-noir.html
Connections: DS18B20 Pinout (Left to Right, pins down, flat side toward you)
- Left = Ground
- Center = Signal (Pin 2): (with 3.3K to 4.7K resistor to +5 or 3.3 )
- Right = +5 or +3.3 V
This sketch looks for 1-wire devices and prints their addresses (serial number)
to the Serial Monitor in a format that is useful in Arduino sketches.
Based on example at: http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html
TELEVERSER LE PROGRAMME
MONITOR SERIE
PUIS CHANGER DE SONDE ET RESET SUR ARDUINO
LA NOUVELLE ADRESSE APPARAIT DANS LE MONITOR
*/
void setup() {
// pinMode(fan, OUTPUT);
Serial.begin(9600);
dht.begin();
}
void loop() {
// Wait a few seconds between measurements.
delay(2000);
// 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;
}
Serial.print("Humidity: ");
Serial.print(h);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(t);
Serial.println(" *C ");
Annexe 3 : 18B20PAR_DHT22_115200bauds
/* ICARE : Multiple DS18B20 Temperature Sensors
and Multiple DHT 22 (AM2302) humidity/temperature sensors
DS18B20 Pinout (Left to Right, pins down, flat side toward you)
- Left = Ground
- Center = Signal (Pin 2): (with 3.3K to 4.7K resistor to +5 or 3.3 )
- Right = +5 or +3.3 V
DS18B20-PAR for Parasite-Power Pinout (Left to Right, pins down, flat side toward you)
- Left = Ground
- Center = Signal (Pin 2): (with 3.3K to 4.7K resistor to +5 or 3.3 )
- Right = No Connect
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address
// The First DHT22 is plugged into port 3 on the Arduino (can be changed)
// supposed second in port 4, third in port 5...
int FisrtDHT = 3;
dht = (DHT*)malloc(nSensors*sizeof(DHT));
for (int i=0; i<nSensors; i++)
{
// assumes first sensor is pin 3 and
// each subsequent sensor is plugged into the next pin down
dht[i] = DHT(i+FisrtDHT, DHT22);
dht[i].begin();
}
void loop(void)
{
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
sensors.requestTemperatures(); // Send the command to get temperatures
if (Serial.available())
{
message = Serial.read()-'0'; // on soustrait le caractère 0, qui vaut 48 en ASCII
Annexe 4 : probe.py
#!/usr/bin/env python
def get_temperature(DEBUG):
if DEBUG == "debug" :
print ser
print "-> sleep10 : start : " + time.strftime('%d/%m/%y %H:%M:%S',time.localtime())
if DEBUG == "debug" :
print "-> sleep10 : end : " + time.strftime('%d/%m/%y %H:%M:%S',time.localtime())
try:
ser.flush() # serial : erasing buffer information
if DEBUG == "debug" :
print "-> 1 : start : " + time.strftime('%d/%m/%y %H:%M:%S',time.localtime())
if DEBUG == "debug" :
print "-> end : " + time.strftime('%d/%m/%y %H:%M:%S',time.localtime())
print "-> 2 : start : " + time.strftime('%d/%m/%y %H:%M:%S',time.localtime())
if DEBUG == "debug" :
print "-> end : " + time.strftime('%d/%m/%y %H:%M:%S',time.localtime())
print "-> 3 : start : " + time.strftime('%d/%m/%y %H:%M:%S',time.localtime())
if DEBUG == "debug" :
print "-> end : " + time.strftime('%d/%m/%y %H:%M:%S',time.localtime())
except Exception,e:
if DEBUG == "debug" :
print e
else:
pass
finally:
ser.flush()
ser.close()
if DEBUG == "debug" :
print "-"*80
print read_nb_18B
print read_val_18B
print read_val_DHT
print "-"*80
if __name__ == "__main__":
if len(sys.argv) == 2:
get_temperature(sys.argv[1])
else:
get_temperature("no")
Annexe 5 : probe_average.py
#!/usr/bin/env python
## Prode 18B20
if onwhat == "floor": # floor for probe01 to probe08 and humidity 1
a = range(1,9)
else:
a = "None"
# find the correspondence between the number of the probe and its id
# |-Path of the file containing the correspondence between the number of the probe and its ID
with open("/home/root/arduino/18B20_adresses_DEC") as fichier:
for ligne in fichier:
m = probe.match(ligne.strip())
if m is not None:
if ii == m.group("probe_id"):
DS18B20_ID = m.group("probe_macadd")
tableau = np.array(malist).astype(np.float)
moyenne = "%.1f" % np.mean(tableau)
ecartype = "%.1f" % np.std(tableau)
with open("/tmp/probe_calcul", "a") as fichier:
fichier.write("$"+onwhat+"_moyenne = "+moyenne+"; \n")
fichier.write("$"+onwhat+"_ecartype = "+ecartype+"; \n")
if onwhat == "start":
with open("/tmp/probe_calcul", "w") as fichier:
fichier.write("<?php \n")
if onwhat == "stop":
with open("/tmp/probe_calcul", "a") as fichier:
fichier.write("?> \n")
if __name__ == "__main__":
get_temperature("start","None")
get_temperature("floor","1") # on what + humidity probe number
get_temperature("ceiling","2")
get_temperature("library","4")
get_temperature("cold","None")
get_temperature("hotpeer","None")
get_temperature("hotodd","3")
get_temperature("stop","None")
Annexe 6 : probe18B20P_munin.py
#!/usr/bin/env python
def get_temperature_from_sensor(PN):
# find the correspondence between the number of the probe and its id
# |-Path of the file containing the correspondence between the number of the probe and its ID
with open("/home/root/arduino/18B20_adresses_DEC") as fichier:
for ligne in fichier:
m = probe.match(ligne.strip())
if m is not None:
if PN == m.group("probe_id"):
DS18B20_ID = m.group("probe_macadd")
def print_munin_config(action,PN):
if action == "autoconf":
print "yes"
return
if action == "suggest":
print "temperature"
return
if action != "config":
return
def print_temperature_for_munin(temperature):
print 'temperature.value %0.1f' % float(temperature)
if __name__ == "__main__":
if len(sys.argv) == 2:
print_munin_config(sys.argv[1],"01")
else:
timestamp, temperature = get_temperature_from_sensor("01") # Probe Number
print_temperature_for_munin(temperature)
Annexe 7 : probeDHT22_munin.py
#!/usr/bin/env python
def get_temperature_from_sensor(PN):
def print_munin_config(action,PN):
if action == "autoconf":
print "yes"
return
if action == "suggest":
print "humidity temperature"
return
if action != "config":
return
def print_temperature_for_munin(humidity,temperature):
print 'temperature.value %0.1f' % float(temperature)
print 'humidity.value %0.1f' % float(humidity)
if __name__ == "__main__":
if len(sys.argv) == 2:
print_munin_config(sys.argv[1],"1")
else:
timestamp, humidity, temperature = get_temperature_from_sensor("1") # Probe Number
print_temperature_for_munin(humidity,temperature)
.salle {
position:relative;
}
/* librairie de sauvegarde */
.library {
position:absolute;
color:blue;
top:255px;
left:30px;
}
/* plancher */
.floor {
position:absolute;
color:blue;
top:485px;
left:685px;
}
/* plafond */
.ceiling {
position:absolute;
color:blue;
top:438px;
left:685px;
}
/* corridor froid */
.cold {
position:absolute;
color:blue;
top:260px;
left:385px;
}
<body style="width:824px;height595px">
<script>
(function ()
{
document.write(new Date().toString("hh:mm tt"));
})();
</script>
<br/><br/>Cliquez sur la zone dont vous voulez afficher les températures: Corridors chauds, froid, serveurs, librairie, plancher ou
plafond<br/><br/>
<div class="salle">
<img src="images/salle_html.jpg" border="0" alt="Salle machines ICARE" usemap="#zones" />
<map name="zones">
<area shape="rect" coords="90,65,165,250" href="lib.php" alt="Temperatures de la librairie" />
<area shape="rect" coords="250,25,660,110" href="hot.php" alt="Temperatures du coridor chaud pair" />
<area shape="rect" coords="250,200,660,295" href="cold.php" alt="Temperatures du coridor froid" />
<area shape="rect" coords="250,385,660,475" href="hot.php" alt="Temperatures du coridor chaud impair" />
<area shape="rect" coords="665,410,790,455" href="pla.php" alt="Temperatures du plafond" />
<area shape="rect" coords="665,455,790,500" href="pla.php" alt="Temperatures du plancher" />
<area shape="rect" coords="250,110,660,200" href="serveurs.html" alt="Temperatures des serveurs" />
<area shape="rect" coords="250,295,660,385" href="serveurs.html" alt="Temperatures des serveurs" />
</map>
<div class="library"><b>T° moyenne : <?php echo $library_moyenne ?>°C<br>Ecart type : <?php echo $library_ecartype ?></b></div>
<div class="hotpeer"><b><?php echo $hotpeer_moyenne ?>°C, <?php echo $hotpeer_ecartype ?></b></div>
<div class="cold"><b><?php echo $cold_moyenne ?>°C, <?php echo $cold_ecartype ?></b></div>
<div class="hotodd"><b><?php echo $hotodd_moyenne ?>°C, <?php echo $hotodd_ecartype ?></b></div>
<div class="ceiling"><b><?php echo $ceiling_moyenne ?>°C, <?php echo $ceiling_ecartype ?></b></div>
<div class="floor"><b><?php echo $floor_moyenne ?>°C, <?php echo $floor_ecartype ?></b></div>
</body>
</html>
Annexe 9 : cold.php
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="refresh" content="180;url=http://adm-pub.icare.univ-lille1.fr/temperatures/cold.php" />
<link rel="icon" type="image/png" href="icons/temp4.png" />
<title>Temeperatures du corridor froid</title>
.salle {
position:relative;
}
/* pair */
.div_18 { position:absolute;color:blue;top:206px;left:510px; }
.div_20 { position:absolute;color:blue;top:260px;left:510px; }
.div_22 { position:absolute;color:blue;top:310px;left:510px; }
.div_28 { position:absolute;color:blue;top:110px;left:400px; }
.div_26 { position:absolute;color:blue;top:160px;left:400px; }
.div_24 { position:absolute;color:blue;top:220px;left:400px; }
.div_30 { position:absolute;color:blue;top:10px;left:310px; }
.div_32 { position:absolute;color:blue;top:65px;left:310px; }
.div_34 { position:absolute;color:blue;top:120px;left:310px; }
/* impair */
.div_35 { position:absolute;color:#99CCFF;top:206px;left:370px; }
<body style="width:824px;height595px">
<script>
(function ()
{
document.write(new Date().toString("hh:mm tt"));
})();
</script>
<div class="salle">
<img src="images/corridor2.jpg" border="0" alt="corridor"/>
<div class="div_18"><b><a href="/munin/localhost/localhost/18B20P_18.html">18:</a> <?php echo $P18?>°C</b></div>
<div class="div_20"><b><a href="/munin/localhost/localhost/18B20P_20.html">20:</a> <?php echo $P20?>°C</b></div>
<div class="div_22"><b><a href="/munin/localhost/localhost/18B20P_22.html">22:</a> <?php echo $P22?>°C</b></div>
<div class="div_24"><b><a href="/munin/localhost/localhost/18B20P_24.html">24:</a> <?php echo $P24?>°C</b></div>
<div class="div_26"><b><a href="/munin/localhost/localhost/18B20P_26.html">26:</a> <?php echo $P26?>°C</b></div>
<div class="div_28"><b><a href="/munin/localhost/localhost/18B20P_28.html">28:</a> <?php echo $P28?>°C</b></div>
<div class="div_30"><b><a href="/munin/localhost/localhost/18B20P_30.html">30:</a> <?php echo $P30?>°C</b></div>
<div class="div_32"><b><a href="/munin/localhost/localhost/18B20P_32.html">32:</a> <?php echo $P32?>°C</b></div>
<div class="div_34"><b><a href="/munin/localhost/localhost/18B20P_34.html">34:</a> <?php echo $P34?>°C</b></div>
<p></p>
</td>
<td VALIGN = Top Align = Left>
Sonde de température DS18B20P : <br/>
- Température: -55 ~ 125 °C<br/>
- Précision: +/- 0,5 °C
</td>
</tr>
</table>
</body>
</html>