By-pass 3 voies

De Kernel Fablab Lannion
Aller à : navigation, rechercher

By-pass 3 voies automatisé et régulation climatique

Sommaire

LE PROJET

Le by-pass est un distributeur à 3 voies et 2 positions inséré dans un système de ventilation pour aiguiller le flux d'air entrant vers l'une des 2 voies sortantes, extérieur ou local à climatiser, en fonction de températures mesurées. Le by-pass est composé d'un Té en acier galvanisé et d'un registre (clapet) orienté par un servomoteur piloté par un micro-contrôleur Arduino Pro Mini.

La régulation climatique est assurée par le micro-contrôleur et 2 sondes de température DS18B20 qui mesurent en permanence la température en entrée du by-pass et la température ambiante dans le local de référence, en l’occurrence une « cave à vins ». Suivant les températures mesurées et la « plage de confort » prévue dans le local, le micro-contrôleur ordonnera au servomoteur de positionner le registre du by-pass pour que l'air entrant soit redirigé vers le local ou vers l'extérieur.

Application à la climatisation d'une cave à vin

Plus particulièrement le but du projet est de climatiser une cave à vins en récupérant l'air frais rejeté par un chauffe-eau thermodynamique qui utilise l’aérothermie pour chauffer l’eau sanitaire d'une maison.

La conservation du vin

Le vin est un produit agricole qui est sensible à la température, particulièrement aux chocs ther­miques, il supporte mal les amplitudes thermiques rapides comme les températures extrêmes. Les températures idéales semblent se situer entre 10 °C et 14 °C « plage de confort ».

Généralement l'endroit dans lequel est implanté la cave à vin ne satisfait pas ces conditions ther­miques ; soit il est situé à l'intérieur de l'immeuble et il se trouve à une température supérieure à la température de conservation du vin ; soit il est à l'extérieur et il subit les conditions thermiques du climat local. Dans tous les cas il convient d'isoler thermiquement l'endroit et de réguler la tempéra­ture.

Le chauffe-eau thermodynamique

Le chauffe-eau thermodynamique utilise l’aérothermie pour chauffer l’eau sanitaire d'une maison. Le chauffe-eau récupère les calories présentes naturellement dans l’air pour transmettre la chaleur à l’eau du ballon et de rejette ce même air refroidi à l 'extérieur. L’air utilisé par le chauffe-eau ther­modynamique peut provenir de différentes sources : l’air ambiant non chauffé, l’air extérieur ou l’air extrait d’une VMC.

Le principe de la climatisation de la cave à vin avec l'air ex­pulsé par le chauffe-eau

L'air expulsé par le chauffe-eau thermodynamique est récupéré pour climatiser la cave à vin. Un cir­cuit de dérivation (by-pass) est intercalé dans le circuit d'air expulsé du chauffe-eau pour aiguiller l'air soit vers l'extérieur soit vers la cave à vin en fonction de sa température et de celle de la cave et de la plage de confort souhaitée.

  • Lorsque la température de la cave à vin est supérieure au seuil haut de la plage de confort et à la température de l'air expulsé par le chauffe-eau , l'air est envoyé vers la cave pour la réfrigérer ;
  • Lorsque la température de la cave à vin est inférieure au seuil bas de la plage de confort et à la température de l'air expulsé, l'air est est envoyé vers la cave pour la réchauffer ;
  • Le by-pass est maintenu dans sa position tant que la température de la cave à vin est dans la plage de confort.

Les températures sont mesurées par les 2 sondes de température DS18B20 avec une précision de 0,06°C puis affichées sur un LCD de 2 lignes à 16 caractères ; 1 ligne pour la température de l'air expulsé du ballon et 1 ligne pour la température ambiante de la cave. Le rafraîchissement des données des sondes de température est paramétrable de 1s à l'infini, paramétré à 15 secondes pour les besoin de ce projet.

Puisque la lecture des températures sur le LCD est ponctuelle et peu fréquente et que l'afficheur LCD est un composant énergivore, il prévu d'afficher la température à la demande pendant une durée au minimum égale à celle du rafraîchissement des données des sondes de température.


En cas d'anomalie du bus 1-Wire qui gère les sondes, l’affichage indique « 88 » ou « 77 » selon la sonde incriminée, si la sonde est absente ou n’est pas détectée ou est en court-circuit.

Le positionnement du registre vers la cave est signalé sur l'afficheur sur la ligne dédiée à la température de la cave.

Pour éviter les battements intempestifs du registre, la durée minimum entre 2 battements est programmable de 1s à l'infini et paramétrée à 5 minutes pour les besoins de ce projet.

LE MATERIEL

Le By-pass : Aiguillage de l'air extérieur/cave

Nous utiliserons une « dérivation en T » en acier galvanisé permettant d'interconnecter trois gaines d'aération de diamètre 125 mm en entrée et en sorties. A l'intersection des branches du Té nous positionnons un clapet qui pivote autour de son axe pour obturer soit la sortie vers l'extérieur soit la sortie vers la cave et ainsi aiguiller l'air sortant vers l'une ou l'autre sortie. Registre.jpg

  • Le clapet est découpé dans une plaque de zinc galvanisé selon un gabarit conçu à l'aide du logiciel FreeCad.
  • La liaison entre le clapet et son axe est réalisé par 2 serre-fils élec­triques (dominos) dégainés et soudés sur le clapet.
  • Pour l'axe nous utiliserons une tige filetée de 4mm guidée et vissée dans les dominos pour assurer la liaison avec le clapet. La liaison entre l'axe et le Té est assurée par des paliers en bronze fritté, auto lubrifiants et trempés à l'huile.

Le clapet est piloté par un servomoteur commandé par un microcontrôleur, un système de tringlerie et de palonniers assure la liaison entre le servomoteur et l'axe du clapet.

Le microcontrôleur PRO MINI 5V pour Arduino : La commande centrale

Le Pro Mini 5V pour Arduino est une carte microcontrôleur basée sur l'ATmega328 qui fonctionne sous 5V avec un résonateur externe à 16 MHz spécialement conçu pour des installations semi-per­manentes. Pour minimiser sa taille et son coût, il n'est pré-équipé ni d'USB ni de broches, il faut donc souder des connec­teurs ou des fils selon les besoins et le Pro Mini doit donc être raccordé à l' environnement de développement via un adaptateur USB ( FTDI Basic carte ou câble) pour télécharger les programmes et alimenter la carte.

Arduino Pro Mini - 1 Euro.JPG
  • ATmega328 à 16 MHz avec résonateur externe
  • Pas de connexion USB
  • Auto-reset
  • Protection d'inversion de polarité
  • Protection contre les surtensions
  • Entrée DC 5V jusqu' à 12V
  • Puissance max : 5V, 150mA
  • 14 Entrées/Sorties numériques ( 0 – 13 )
  • 8 Entrées analogiques ( A0 - A7 )
  • Dimensions : 33mm x 18 mm x 6mm

L'Arduino Pro Mini peut-être alimenté avec un cable FTDI ou une carte FTDI Breakout connectée aux 6 broches de tête, ou directement avec une tension de +5V régulée sur la broche VCC.

Il dispose aussi d'un régulateur de tension sur la carte qui lui permet de recevoir une tension non régulée jusque 12V sur la broche RAW et, dans ce cas, surtout pas sur VCC.

  • RAW. Pour alimenter la carte directement jusque +12V
  • VCC. Pour alimenter la carte avec un courant régulé +3.3V ou +5V
  • GND. Ground pins.

Les 6 broches frontales d'interface

Pro Mini - 6 broches de tête.jpg

Nota : la broche DTR permet la réinitialisation automatique (AutoReset) quand un nouveau scéna­rio est téléchargé sans avoir à appuyer sur le bouton de remise à zéro (Reset).

Les 14 broches numériques

Chacune des 14 broches numériques sur le Pro Mini peut être utilisée comme une entrée ou une sor­tie, en utilisant les instructions pinMode (), digitalWrite (), et digitalRead (fonctions).

Chaque broche peut fournir ou recevoir un maximum de 40 mA et a une résistance de pull-up interne (déconnectée par défaut) de 20-50 kOhms.

En outre, certaines de ces broches ont des fonctions spécialisées :

  • Serial: 0 (RX) and 1 (TX). Ces broches sont utilisées pour recevoir (RX) et émettre des TTL serial data. Ces broches sont connectées aux broches TX0 et RX1 des 6 broches de tête.
  • Interruptions externes : broches 2 et 3 . Ces broches peuvent être configurées de manière à déclencher une interruption sur une valeur LOW, un front montant ou descendant, ou un changement de valeur. Voir la fonction attachInterrupt ( ) pour plus de détails.
  • Sorties analogiques : broches 3 , 5, 6 , 9, 10 , et 11 . Ces broches peuvent fournir des sorties analogiques (PWM) sur 8 bits avec la fonction analogWrite () .
  • SPI : broches 10 ( SS ) , 11 ( MOSI ) , 12 ( MISO ) , 13 ( SCK ) . Ces broches supportent la communication SPI qui, bien que prévue par le matériel sous-jacent, n'est pas actuellement inclus dans le langage Arduino .
  • LED : broche 13 qui est associée à une LED. Lorsque la broche est sur une état HIGH la LED est allumée, lorsque la broche est LOW la LED est éteinte.

Les 8 entrées analogiques

Le Mini Pro dispose aussi de 8 entrées analogiques (A0-A7), chacune fournissant des informations sur 10 bits soit 1024 valeurs différentes . Quatre d'entre elles (A0-A3) sont sur ​​un bord (longueur) de la carte, deux autres (A6 et A7) sur un autre bord (largeur) et deux entrées ( A4 et A5 ) à l'arrière de la carte . Les entrées analogiques mesurent la tension (VCC) à de la terre.

En outre, certaines de ces broches ont des fonctions spécialisées :

  • I2C: A4 (SDA) et A5 (SCL) pour la communication I2C (TWI) en utilisant la bibliothèque Wire library.

Le Reset

La broche RST  lorsqu'elle passe l'état LOW réinitialise le microcontrôleur. C'est généralement uti­lisé pour ajouter un bouton externe de remise à zéro lorsque la carte est bloquée.

DS18B20 : Les sondes de température

Ds18b20.jpg Le DS18B20 est un thermomètre numérique qui fournit sur 9 bits à 12 bits des mesures de tempéra­ture en degrés Celsius avec une fonction d'alarme programmable non volatile des points supérieurs et inférieurs de déclenchement.

Le DS18B20 communique via un bus 1-Wire qui, par définition, ne nécessite qu'une seule ligne de données (et la masse) pour une communication avec microprocesseur de pilotage, en l'occurrence un PRO Mini Arduino.

Sa gamme de température s’étend de –55°C à +125°C, avec une précision de ±0.5°C entre –10°C et +85°C.

Le DS18B20 fonctionne avec une tension comprise entre 3 et 5,5V mais peut aussi s'ali­menter directement à partir de la ligne 'Data' ("tension parasite") ce qui permet son utili­sation sans alimentation externe.

Ds18b20 avec cable.jpg Pour les besoin du projet nous optons pour la version étanche du DS18B20 avec un câble de raccordement de 1m, imperméable et anti-corrosion, spéciale­ment conçu pour une utilisation dans des milieux liquides. 1 sonde pour la température de sortie du ballon thermodynamique et 1 sonde pour la température de la cave.

Le 1-Wire Bus System

le 1-Wire bus system[1]utilise un seul bus master pour contrôler un ou plusieurs slave devices. Le DS18B20 est toujours un slave. Quand il y a seulement un slave sur le bus, il est nommé single-drop sinon multidrop.

Le bus 1-Wire nécessite une résistance de pull-up externe d'environ 5kΩ pour bien stabiliser l'état de repos. Si pour une raison quelconque une transaction doit être suspendue, le bus DOIT être laissé dans l'état d'attente si l'opération est à reprendre. Un temps infini de reprise est possible dans la me­sure où le bus 1-Wire est dans l'état « haut » d'attente ; si le bus est maintenu « bas » pendant plus de 480μs, tous les composants sur le bus seront réinitialisés.

Les branchements entre la sonde et le PRO Mini

Le DS18B20 communique sur un bus 1-Wire nécessitant seulement 1 fil (plus la masse) ; Plusieurs capteurs peuvant être utilisés simultanément sur le même bus grâce à un système d'adressage de chaque capteur qui possède une adresse unique (64 bits ROM soit 8 octets)

  • VCC - Tension d'alimentation (fil rouge)
  • DQ - Données (fil jaune)
  • GND - Masse d'alimentation (fil vert)

On branche :

  • les bornes 1 (GND) sur le GND de l’arduino,
  • les bornes 2 (DQ) sur la broche 2 de l’Arduino
  • et les bornes 3 (VCC) sur l’alimentation 5V
  • Entre les broches 2 et 3 , on rajoute une résistance de 4700 Ohms.


Lecture de la température avec le PRO Mini

Le code est basé sur une bibliothèque C++ disponible pour les utilisateurs Arduino: OneWire.h qui gère plusieurs types de capteurs dont le DS18B20.

La fonctionnalité de base de la DS18B20 est son capteur de température numérique . La résolution de la sonde de température est de 9, 10 , 11 , ou 12 bits configurable par l'utilisateur, correspondant respectivement à des incréments de 0,5 °C , 0.25 °C , 0.125 °C , et de 0,0625 °C . La résolution par défaut au démarrage est de 12 bits ( 0,0625 °C ).

Au repos le DS18B20 est dans un état à faible puissance. Pour initialiser une mesure de tempéra­ture, le maître (PRO Mini) doit émettre une commande Convert T. Si le DS18B20 est alimenté par une alimentation externe , le maître peut émettre les commande read time slots après la commande T Convert et le DS18B20 va répondre en transmettant 0 tant que la conversion de la température est en cours et 1 lorsque la conversion est effectuée . Si le DS18B20 est alimenté avec une tension pa­rasite, cette technique de notification ne peut pas être utilisé car le bus doit être suralimenté pendant la conversion de la température.

Le DS18B20 contient un scratchpad qui est une sorte de mémoire tampon sécurisée ou l’on peut venir lire et/ou écrire.

La température est une valeur à virgule stockée sur 2 octets sous la forme d’un flottant avec un ex­posant, une mantisse et un signe :

  • le premier octet du scratchpad correspond aux bits de pois faible (LSB),
  • le deuxième octet aux bits de poids fort (MSB).

Pour avoir la température en degré Celsius il faut appliquer la formule : température= ((MSB << 8) + LSB) * 0.0625

DS18B20 - Scratchpad.jpg

Afficheur LCD 16 x 2 Lignes : Affichage des températures

LCD 16x2.jpg
  • Contrôleur HD44780 standard
  • Tension d'alimentation: 5V
  • 2 lignes de 16 caractères
  • 4 trous pour vis M2
  • dimensions : 8.0 cm x 3.5 cm x 1.1 cm
  • Bibliothèque LiquidCrystal.h

Les 16 bornes

Borne
Symbole
Type
Fonction
1
Vss
Alim
Masse 0V
2
Vdd
Alim
Alimentation générale 5V
3
V0
Alim
Alimentation du panneau LCD (Contraste des caractères)

V0 = VDD → Caractères invisibles ; V0 = 0 → Contraste maximum

4
RS
Entrée
RS = 0 et R/W = 1

→ Sélection du drapeau BUSY et du compteur d’adresse

5
R/W
Entrée
R/W = 0 → Mode écriture

R/W = 1 → Mode lecture

6
E
Entrée
Enable : entrée de validation

RS et R/W sont lues front montant, et le bus de données sur front descendant.

7
D0
E/S
Bus de données, bit n°0 (LSB) non utilisé en mode 4 bits
8
D1
E/S
Bus de données, bit n°1 (LSB) non utilisé en mode 4 bits
9
D2
E/S
Bus de données, bit n°2 (LSB) non utilisé en mode 4 bits
10
D3
E/S
Bus de données, bit n°3 (LSB) non utilisé en mode 4 bits
11
D4
E/S
Bus de données, bit n°4 (LSB)
12
D5
E/S
Bus de données, bit n°5 (LSB)
13
D6
E/S
Bus de données, bit n°6 (LSB)
14
D7
E/S
Bus de données, bit n°7 (LSB)
15
A
Alim
Anode du système de rétro-éclairage

(à alimenter en 5V à travers une résistance de 50 à 100Ω pour limiter le courant à 100mA)

16
K
Alim
Cathode du système de rétro-éclairage (masse)

Les branchements entre le module d'affichage et le Pro Mini

// ->Arduino broches : 5,6,7,8,11,12 pour AFFICHEUR
// afficheur Broche 1 -> GND// afficheur Broche 2 -> +5V
// afficheur Broche 3 -> Pont(R10*R2) 
// afficheur Broche 4 -> Arduino 12
// afficheur Broche 5 -> GND 
// afficheur Broche 6 -> Arduino 11
// afficheur Broche 7 inutilisée
// afficheur Broche 8 inutilisée
// afficheur Broche 9 inutilisée
// afficheur Broche 10 inutilisée
// afficheur Broche 11 -> Arduino 8
// afficheur Broche 12 -> Arduino 7
// afficheur Broche 13 -> Arduino 6
// afficheur Broche 14 -> Arduino 5
// afficheur Broche 15 -> +5V
// afficheur Broche 16 -> GND
// Pont(R10*R2) : +5V <- R10=10kHoms -> * <- R2=2.2kHoms -> GND</nowiki>

Gestion de l'affichage par interruption (interrupt0)

L'affichage est initialisé par une interruption (interrupt0) déclenchée sur mise à l'état LOW de la borne 2 de l'Arduino et l'affichage durera au minimum un temps de cycle de rafraîchissement des données des sondes de température et au maximum 2 temps de cycles.

// ->Arduino broche : 2 pour la gestion de Interrupt0
// const unsigned int Interrupt0_broche= 2 ;  // ->(Bouton poussoir -> GND)
                                              // ->(R10=10 kOhms->+5V)

Servomoteur Métal Gear MG995 : Actionneur du clapet

Le servomoteur Métal Gear MG995 est un actionneur simple positionnant un "bras" d'un angle va­riant de 0 à 180°. Il est piloté par le microcontrôleurs Pro Mini (Arduino) et actionne le clapet du registre via un système de tringlerie et palonnier.

Servomoteur Métal Gear MG995.gif
  • Dimension : 40.6 x 19.8 x 37.8 mm
  • Poids : 70g
  • Couple max à 4.8V : 13kg/cm
  • Couple max à 6.0V : 15kg/cm
  • Vitesse de fonctionnement à vide (4.8V) : 0.17sec/ 60°
  • Vitesse de fonctionnement à vide (6.0V) : 0.13sec/ 60°
  • Tension de fonctionnement : 4.8 - 7.2 Volts
  • Température de fonctionnement : de 0 à +55°C

Les branchements entre le servomoteur et le Pro Mini

Une des grandes caractéristiques de l'Arduino est qu'il dispose d'une biblio­thèque de logiciel qui permet de contrôler un ou deux servomoteurs connectés aux broches 9 et 10.

On branche :

  • le câble brun (gnd) sur le Ground de l’arduino,
  • le câble rouge (+5V) sur l’alimentation 5V de l'Arduino(VCC)
  • le câble orange (signal) sur le port 9 (ou 10) de l’Arduino
// -> Arduino broche  : 9 pour SERVO
const unsigned int Servo_broche = 	 9 ;    	// SERVO : cable "Signal"

Nota : comme le servomoteur consomme beaucoup il est possible de l'alimenter directement à partir d'une alimentation externe (et non la broche +5 V de l'Arduino) ; Dans ce cas la Terre (GND) doit-être la même que celle de l'Arduino.

La liaison entre le servomoteur et le clapet du registre

À développer.


Schéma du câblage à l'Aduino

Registre 3.1.dia.jpg

LOGICIELS

Les logiciels sont développés à partir de l'environnement de développement (IDE) de l'Arduino : programmation, compilation et téléchargement des esquisses (sketches). le langage et les bibliothèques utilisés sont ceux fournis avec 'IDE, le langage est basé sur les langages C/C++ .

Pendant la phase de développement le micro-contrôleur est connecté et alimenté via une carte [#FTDI Basic Breakout 5V USB to TTL 6-Pin Module L'interface avec l'environnement de développement|outline FTDI Basic Breakout ]et un cable USB.

L'environnement de test est limité en fonctionnalités, pour les tester le logiciel le plus simple est l'utilisation du Terminal Série (fenêtre séparée) qui permet d'afficher des messages texte reçus de l' Arduino et d'envoyer des caractères vers l'Arduino. Ceci implique la programmation de points de trace pour afficher ou modifier des variables ; pour contrôler ou modifier le déroulement du programme. Une bonne maîtrise de l'environnement Serial est souhaitable, au minimun les commandes Serial.print() et Serial.read().

Pour les besoins du projet il est créé une variable globale Debug_trace, valorisée à true pendant la phase de test.

// ***** AFFICHAGE SUR UN MONITEUR SERIE (un PC par exemple) : Ctrl+Maj+M
boolean Debug_trace = true ; // pour afficher la signature des sondes sur le PC (entre autre) 
                             // pour afficher les températures lues et les consignes au servo

Exemple 1 d'utilisation pour vérifier la signature des sondes DS18B20

 if (Debug_trace)     // Pour debug en cas de changement de sonde
 {
     Serial.print("/ 1-Wire -> "); Serial.print(addr[0], HEX);
     Serial.print(" ; Sonde ")   ; Serial.print(addr[1], HEX);
 }

Exemple 2 d'utilisation pour afficher les températures et la position du servomoteur

 if ( Debug_trace )
 {
     Serial.println();Serial.print("H="); Serial.print(Horloge);
     Serial.print(" / Pos1="); Serial.print(Servo_position_courante); 
     Serial.print(" / Ballon = "); Serial.print(T_SondeB);
     if ( T_SondeB  T_SondeC ) Serial.print(" > "); else Serial.print(" < ");
     Serial.print("Cave = "); Serial.print(T_SondeC);
 }

Les bibliothèques utilisées

// ***** BIBLIOTHEQUES
#include <Servo.h>         // Pour le servomoteur
#include <OneWire.h>       // Pour les sondes de température 
#include <LiquidCrystal.h> // Pour l'afficheur LCD (Liquid Crystal Device)

Constantes et variables globales

Le brochage

// *** BROCHAGE DE LA CARTE
// ->Arduino broches numériques inutilisées : 4
// ->Arduino broche : 0 et 1 sont utilisées pour les échanges Série RX et TX
// ->Arduino broche : 2 pour la gestion de Interrupt0 pour affichage sur LCD
//const unsigned int Interrupt0_broche=  2 ; // ->(Bouton poussoir -> GND)
                                             // ->(R10=10 kOhms->+5V) 
// ->Arduino broche : 3 pour le Bus 1-Wire des SONDES TEMPERATURE 
   const unsigned int OneWire_broche = 3 ;   // SONDES TEMPERATURE : Bus 1-Wire  
                                             // raccorder une R4=4700Homs entre OneWire_broche et +5V 
// ->Arduinobroches : 5,6,7,8,10,11,12pour AFFICHEUR 
// const unsigned int LCD_VSS          // afficheur Broche 1 -> bouton poussoir -> GND 
// const unsigned int LCD_VDD          // afficheur Broche 2 -> +5V
// const unsigned int LCD_V0           // afficheur Broche 3 -> Pont(R10*R2)  
   const unsigned int LCD_rs=12 ;      // afficheur Broche 4 -> Arduino 12
// const unsigned int LCD_rw           // afficheur Broche 5 -> bouton poussoir -> GND  
   const unsigned int LCD_enable=11 ;  // afficheur Broche 6 -> Arduino 11
// const unsigned int LCD_d0           // afficheur Broche 7 inutilisée
// const unsigned int LCD_d1           // afficheur Broche 8 inutilisée
// const unsigned int LCD_d2           // afficheur Broche 9 inutilisée
// const unsigned int LCD_d3           // afficheur Broche 10 inutilisée  
   const unsigned int LCD_d4= 8 ;      // afficheur Broche 11 -> Arduino 8 
   const unsigned int LCD_d5= 7 ;      // afficheur Broche 12 -> Arduino 7 
   const unsigned int LCD_d6= 6 ;      // afficheur Broche 13 -> Arduino 6 
   const unsigned int LCD_d7= 5 ;      // afficheur Broche 14 -> Arduino 5
   const unsigned int LCD_backA=10 ;   // afficheur Broche 15 -> R220=220 Ohms -> Arduino
// const unsigned int LCD_backK        // afficheur Broche 16 -> bouton poussoir -> GND 
// Pont(R10*R2) : +5V <- R10=10kHoms -> * <- R2=2.2kHoms -> GND
// ->Arduino broche : 9 pour SERVO 
   const unsigned int Servo_broche = 9 ; // SERVO : cable "Signal"

Gestion de l'horloge

// ->Pour la gestion de l'horloge
   unsigned long Horloge = 0 ; // Lecture de l'horloge interne en ms

Gestion de l'afficheur

// ->Pour la gestion de l'afficheur
 LiquidCrystal lcd( LCD_rs, LCD_enable, LCD_d4, LCD_d5, LCD_d6, LCD_d7);
 boolean Affichage = false ;// Affichage demandé

Gestion du Bus 1-Wire et des sondes de température

// ->Pour la gestion du Bus 1-Wire et des sondes de température
OneWire ds(OneWire_broche) ; // Création de l'objet OneWire
#define DS18B20 0x28 // Signature 1-Wire des sondes DS18B20 : addr[0]
#define SondeB  0x9C // Signature 1-Wire de la sonde Ballon : addr[1]
#define SondeC  0xD7 // Signature 1-Wire dela sonde Cave    : addr[1]
// nota bene : Ne pas oublier de modifier la signatures 1-Wire au changement de la sonde 
// Debug_trace=true => lecture signatures des sondes connectées au Bus 1-Wire

Gestion des températures

// ->Pour la gestion des températures
float T_ideale_maxi = 15; // température idéale de la cave entre 12 et 15 degrés
float T_ideale_mini = 12; // température idéale de la cave entre 12 et 15 degrés
float T_SondeB ;          // température air du ballon
float T_SondeC ;          // température air de la cave
unsigned long Horloge_T_save = 0 ;     // Sauvegarde de l'horloge des sondes de température
const     int Tempo_T        = 5000 ;  // 5 s mini entre 2 lectures de température
byte Bdegre[8] =          // pour création du symbole ° (degré)
       {                  // déclaration d’un tableau de 8 octets
               B00111,    // définition de chaque octet au format binaire
               B00101,    // 1 pour pixel affiché – 0 pour pixel éteint
               B00111,    // les 3 bits de poids forts ne sont pas écrits car inutiles
               B00000,
               B00000,
               B00000,
               B00000,
       };
byte degre = 0;// symbole ° (degré) : voir création dans le setup

Gestion du servomoteur

// ->Pour la gestion du servomoteur
Servo myservo; // creation de l'objet servomoteur
const int Servo_position_Exterieur = 30 ;  // Position air pulsé vers l'extérieur 
const int Servo_position_Cave      = 100 ; // Position air pulsé vers la cave
      int Servo_position_consigne ;        // consigne au servo : soit Cave soit Extérieur
      int Servo_position_courante;         // Position courante du servo
const int Servo_rotation_pas   = 5 ;       // Pas de rotation du servo en degrés
const int Servo_rotation_tempo = 100 ;     // tempo entre 2 incréments de rotation du servo

unsigned long Horloge_Servo_save =0 ;      // Sauvegarde de l'horloge du servomoteur
unsigned long Tempo_Servo = 300000 ;       // 5 mn mini entre 2 changements de position pour éviter les bagots 

Initialisation de la carte

/*-------------INITIALISATION DE LA CARTE ----------------*/
void setup() 
{ 
  Horloge = millis(); // valeur de l'horloge interne 
  Servo_position_consigne = Servo_position_Exterieur ; // par defaut -> Extérieur
  // ->Initialisation de l'affichage
  pinMode(LCD_backA, OUTPUT); 
  digitalWrite(LCD_backA, HIGH);  // Arrière plan éclairé au max
  attachInterrupt(0, Affichage_demande, LOW ); // Affichage quand bouton poussoir actionné
  lcd.createChar(degre, Bdegre); // création du caractère personnalisé degré °
  lcd.begin(16,2);  // initialise l'affichage à 16 caractères x 2 lignes
  lcd.clear();  // efface l'écran pour commencer
  lcd.setCursor(0,0); // positionne le curseur ligne 0, caractère 0
  lcd.print("REGISTRE V1.1"); // affiche la version du programme
  lcd.setCursor(0,1); // positionne le curseur ligne 1, caractère 0
  lcd.print("Pml");
  for (int i=4; i <= 16; i++){ lcd.print("."); delay(300); } 
  lcd.clear();  
  if ( Debug_trace) 
  {
    Serial.begin(9600); // pour affichage sur moniteur série
    Serial.print("Tempo entre 2 consignes au servomoteur : ");Serial.print( Tempo_Servo/1000 ) ;Serial.println(" secondes"); 
    Serial.print("Tempo entre 2 lectures et affichages des temperatures : ");Serial.print( Tempo_T/1000) ;Serial.println(" secondes");
    Serial.print("Temperature ideale mini = " ); Serial.println( T_ideale_mini ) ;
    Serial.print("Temperature ideale maxi = " ); Serial.println( T_ideale_maxi) ; 
  }
  // ->initialisation des sondes de température
  Horloge_T_save = Horloge ; 
  Lecture_Temperature();    // Gestion des sondes et lecture des températures
  Affichage_Temperature();  // ->initialisation du servo moteur
  Horloge_Servo_save = Horloge 
  myservo.attach(Servo_broche); // attache l'objet myservo à la broche 
  if ( Consigne_position_nouvelle() ) Rotation_Servo();}
}

Le programme principal et Gestion des temporisations

A chaque boucle du programme 2 temporisations sont testées pour gérer les cycles

  1. de lecture des températures et des traitements qui en découlent :
    • mise à jour de l'afficheur et éventuellement affichage des températures
    • calcul d'une nouvelle consigne à donner au servomoteur
  2. de positionnement du registre en cas de nouvelle consigne au servomoteur
/*-----------PROGRAMME PRINCIPAL ******************* PROGRAMME PRINCIPAL---------------*
/ void loop() 
{ 
  Horloge = millis(); // valeur de l'horloge interne pour ce tour

  // ****** TRAITEMENT DES SONDES ET TEMPERATURES 
  if ( Chrono(Horloge_T_save) > Tempo_T ) 
  { 
    Lecture_Temperature(); // Gestion des sondes et lecture des températures 
    Affichage_Temperature(); // au minimum rafraichir  
    Horloge_T_save = Horloge ; // pour le prochain tour 

    // ****** TRAITEMENT DU SERVOMOTEUR 
    if (Consigne_position_nouvelle() ) // faut-il changer de position ? 
    { // oui, peut-être 
      if ( Chrono(Horloge_Servo_save) > Tempo_Servo )  
      { // oui, certainement 
        Rotation_Servo(); 
        Horloge_Servo_save = Horloge ; // pour le prochain tour 
      }  
    }  
  }
} // fin PROGRAMME PRINCIPAL 
*** GESTION DES TEMPORISATIONS (fonction) ***
  • En entrée :
    • une référence à une horloge sauvegardée ! passage par référence
    • l'horloge courante fournie par une variable globale
  • en sortie :
    • le chronomètre mis à jour
unsigned long Chrono(unsigned long& Horloge_avant)
{ 
  unsigned long Chrono = Horloge - Horloge_avant ;
  if ( Chrono < 0 ) 
  { // !! L'horloge a fait un tour de compteur 
    // ce qui arrive approximativement tous les 50 jours 
    Horloge_avant = Horloge ; // c'est pas génial mais c'est très simple ;-)  
    Chrono = 0 ; 
  } 
 return (Chrono) ;
} 

Gestion des sondes de température DS18B20 et lecture des temperatures

  • En entrée : rien
  • En sortie :
    • T_SondeB : variable globale pour la température du ballon
    • T_SondeC : variable globale pour la température de la cave
void Lecture_Temperature()
{ 
  byte data[12] ; // data : Données lues depuis le scratchpad : température dans les octets 0 et 1  
  byte addr[8] ;  // addr : adresse du module 1-Wire détecté 
                  // signature Signature 1-Wire du type de sonde dans octet 0 
                  // signature de la sonde dans octet 1 
  float T_Celsius = 99 ; // température lue en degrés Celsius : erreur=99 
  float Tb = 88.88 ; // température de la sonde air ballon : erreur de lecture = 88.88 
  float Tc = 77.77 ; // température de la sonde air cave : erreur de lecture = 77.77
  // pour debug en cas de changement de sonde par exemple 
  if ( Debug_trace ) { Serial.println(); Serial.print( "Signatures : "); }  
  ds.reset(); // reset du bus 1-Wire 
  // tant qu'il y a une sonde sur le Bus 1-Wire (si bus pas trouvé, alors les 2 températures en erreur) 
  while (ds.search(addr))  
  { 
    if (OneWire::crc8(addr, 7) != addr[7]) // Vérifier que l'adresse a été correctement reçue 
    { // le message est corrompu  
      if ( Debug_trace ) Serial.println("Message corrompu : CRC non valid!"); 
      goto finSonde;  
    }  
    if (addr[0] != DS18B20) // Vérifier qu'il s'agit bien d'un DS18B20
    { // Ce n'est pas une sonde DS18B20 
      if ( Debug_trace ) 
      {  
        Serial.println(); Serial.print("addr[0] = "); Serial.print(addr[0], HEX); Serial.print(" n'est pas une sonde DS18B20"); 
        goto finSonde;  
      } 
    }   
    ds.reset(); // On reset le bus 1-Wire 
    ds.select(addr); // On sélectionne le DS18B20  
    ds.write(0x44, 1); // On lance une prise de mesure de température 
    delay(800); // Et on attend la fin de la mesure  
    ds.reset(); // On reset le bus 1-Wire 
    ds.select(addr); // On sélectionne le DS18B20 
    ds.write(0xBE); // On envoie une demande de lecture du scratchpad
    // On lit le scratchpad Et on stock les 9 octets reçus       
    for (byte i = 0; i < 9; i++) data[i] = ds.read(); 
    // Calcul de la température en degré Celsius
    T_Celsius = ((data[1] << 8) | data[0]) * 0.0625; 
    if (Debug_trace) 
    { // Pour debug en cas de changement de sonde
      Serial.print("/ 1-Wire -> "); Serial.print(addr[0], HEX);
      Serial.print(" ; Sonde "); Serial.print(addr[1], HEX); 
    }  
    switch (addr[1]) 
    { 
      case SondeB: { Tb = T_Celsius; break; } 
      case SondeC: { Tc = T_Celsius; break; } 
    }  
    
    finSonde: ; 
  } // tant qu'il y a une sonde sur le Bus 1-Wire 
  T_SondeB = Tb ;
  T_SondeC = Tc ;
 } // fin Lecture_Temperature

Affichage des températures

A chaque ligne du LCD correspond une sonde, la température en entrée du registre ( celle du ballon ) sur la ligne 1 et sur la ligne 2 la température de la zone à climatisée (la cave). En plus sur la ligne 2 l'indicateur « -> » est affiché lorsque le registre est positionné vers la zone à climatiser.

Les données à afficher sont préparées à chaque cycle de traitement des températures mais ne sont affichées que sur demande via l'interruption Interrupt0 qui est activée lorsque la borne 2 de l'Arduino est à l'état LOW, ce qui arrive en actionnant un bouton poussoir qui mettra la borne à la terre (GND).

Affichage

/*-------------------------- AFFICHAGE DES TEMPERATURES -------------------------*
  • en entrée :
    • T_SondeB : variable globale pour la température du ballon
    • T_SondeC : variable globale pour la température de la cave
  • en sortie : rien
void Affichage_Temperature()
{
  lcd.setCursor(0, 0); 
  lcd.print("Ballon = ") ; lcd.print( T_SondeB) ; lcd.write(degre);lcd.print("C") ;
  lcd.setCursor(0, 1); 
  if ( Servo_position_consigne == Servo_position_Cave ) 
  { lcd.print("->Cave = "); } // info sur LCD : registre en position Cave
  else { lcd.print(" Cave = "); }
  lcd.print( T_SondeC) ; lcd.write(degre); lcd.print("C") ;
  if (Affichage)
  { 
    digitalWrite(LCD_backA, HIGH); // Arrière plan éclairé au max
    lcd.display();// Affichage 
  }
  else
  {
    digitalWrite(LCD_backA, LOW); // Arrière plan éclairé au min
    lcd.noDisplay();// Pas d'affichage}Affichage = false ;
  }

Interruption de demande d'affichage

//
  • en entrée : attachInterrupt(0, Affichage_demande, LOW);
  • en sortie : le boolean Affichage = true
void Affichage_demande(){Affichage = true ;digitalWrite(LCD_backA, HIGH); // Arrière plan éclairé au maxlcd.display();// Affichage }

Le pilotage du servomoteur

Test des températures -> Consigne de rotation du servo

  • en entrée :
    • Servo_position_consigne : variable globale
    • Servo_position_courante : variable globale
  • en sortie :
    • true si nouvelle consigne, false sinon
    • Servo_position_consigne : variable globale
    • Servo_position_courante : variable globale
boolean Consigne_position_nouvelle()
{
 boolean consigne = false ; // par défaut il n'y a pas de nouvelle consigne
 Servo_position_courante = myservo.read() ; // se prémunir du cas où une consigne n'aurait pas été exécutée correctement
 if ( Debug_trace ) 
 {
   Serial.println();Serial.print("H=");Serial.print(Horloge);
   Serial.print(" / Pos1="); Serial.print(Servo_position_courante); 
   Serial.print(" / Ballon = ");Serial.print(T_SondeB);
   if ( T_SondeB > T_SondeC ) 	Serial.print(" > "); else Serial.print(" < ");
   Serial.print("Cave = ");	Serial.print(T_SondeC);
 }
 
 if ( T_SondeC > T_ideale_maxi )
 { // cave trop chaude
   if (T_SondeB < T_SondeC)
   { // refroidir la cave avec l'air provenant du ballon
     if (Debug_trace) { Serial.print(" Refroidir cave  "); }
     Servo_position_consigne = Servo_position_Cave ;
   }
   else
   { // pulser l'air vers l'extérieur
     if (Debug_trace) { Serial.print(" Pulser vers Ext1 "); }
     Servo_position_consigne = Servo_position_Exterieur ;			
   }
 } 
 else if ( T_SondeC < T_ideale_mini ) 
 { // cave trop froide
   if (T_SondeB > T_SondeC)
   { // réchauffer la cave avec l'air provenant du ballon
     if (Debug_trace) { Serial.print(" Rechauffer cave ");}   
     Servo_position_consigne = Servo_position_Cave ;
   }
   else
   { // pulser l'air vers l'extérieur
     if (Debug_trace) { Serial.print(" Pulser vers Ext2 "); }
     Servo_position_consigne = Servo_position_Exterieur ;			
   }
 } 
 if (Debug_trace)
 {
   Serial.print(" / Pos2="); Serial.print(Servo_position_courante);
   switch ( Servo_position_courante )
   {
     case Servo_position_Exterieur: { Serial.print(" Ext "); break; }
     case Servo_position_Cave:      { Serial.print(" Cave"); break; }
     default: { Serial.print(" ??? "); }
   }
   Serial.print("-> Basculer vers ");
   switch ( Servo_position_consigne )
   {
     case Servo_position_Exterieur: { Serial.print(" Ext "); break; }
     case Servo_position_Cave:      { Serial.print(" Cave"); break; }
     default: { Serial.print(" ERREUR2");}
   }
   if ( Servo_position_courante == Servo_position_consigne )   
   { Serial.print("-> Ne rien faire ") ; }
 }
 // si la température de la cave est correcte il faut conserver l'ancienne consigne 
 if ( Servo_position_courante == Servo_position_consigne )   
      consigne = false ;
 else consigne = true ;
 return(consigne);
}

Rotation du servomoteur

Une des grandes caractéristiques de l'Arduino est qu'il dispose d'une bibliothèque de logiciel Servo.h qui permet de contrôler un ou deux servomoteurs connectés à la broche 9 ou 10 en utilisant une seule ligne de code.

EXECUTER LA CONSIGNE DE ROTATION DU SERVOMOTEUR
  • en entrée :
    • Servo_position_consigne : variable globale
    • Servo_position_courante : variable globale
  • en sortie : rien
void Rotation_Servo()
{  
  if (Debug_trace) 
  { 	
    Serial.println(); Serial.print("-> Rotation de la position = "); Serial.print(Servo_position_courante);
    Serial.print(" a la consigne = "); Serial.print(Servo_position_consigne);
    switch ( Servo_position_consigne )
    {
      case Servo_position_Exterieur: { Serial.print(" Ext "); break; }
      case Servo_position_Cave:      { Serial.print(" Cave"); break; }
      default:                       { Serial.print( " ERREUR1 ");}
    }
    Serial.println("!!!!");
  }
  if ( Servo_position_consigne == Servo_position_Cave )
  { // ammener le servo à la position Cave
    Servo_position_courante += Servo_rotation_pas ;
    while ( Servo_position_courante < Servo_position_Cave )
    {
      myservo.write(Servo_position_courante); // repositionner le servo
      delay(Servo_rotation_tempo);            // pas trop vite :)
      Servo_position_courante += Servo_rotation_pas ;
    }
  }
  else
  { // ammener le servo à la position Extérieur
    Servo_position_courante -= Servo_rotation_pas ;
    while ( Servo_position_courante > Servo_position_Exterieur )
    {
      myservo.write(Servo_position_courante); // repositionner le servo
      delay(Servo_rotation_tempo);            // pas trop vite :)
      Servo_position_courante -= Servo_rotation_pas ;
    } 
  }
 
  myservo.write(Servo_position_consigne); // repositionner exactement le servo
 
  lcd.setCursor(0, 1);
  if ( Servo_position_consigne == Servo_position_Cave ) 
  { lcd.print("->Cave = "); } // info sur LCD : registre en position Cave
  else
  { lcd.print("  Cave = ") ; }
}

Annexes

L'interface avec l'environnement de développement

Puisque le Pro Mini ne dispose pas d'une interface USB il sera raccordé à l' environnement de déve­loppement par une carte FTDI Basic Breakout 5V USB to TTL 6-Pin Module.

FTDI.gif

Il s'agit d'une version du FTDI Basic qui utilise un SMD à 6 broches qui permet aux câbles FTDI (USB) de travailler avec les Arduino à 5V, et également être utilisé pour toutes les Serial applications. La différence majeure est qu'il apporte la broche DTR par opposition à la RTS du câble standard FTDI, Cette broche DTR permet la réini­tialisation automatique (AutoReset) des Arduino quand un scénario est téléchargé sans avoir à appuyer sur le bouton de remise à zéro (Reset).

Les broches nommées BLK et GRN correspondent aux fils de cou­leur sur le câble FTDI, noir pour GND et vert pour CTS ; Elles sont utilisées pour aligner la carte FTDI basic Breakout avec la cible.

Cette carte dispose de LED associée aux bornes TX et RX ce qui la rend plus facile à utiliser qu'un câble standard FTDI ; cela permet de visualiser le Serial trafic sur les LED afin de vérifier le fonctionnement de la carte.

Un cavalier sur le dos de la carte qui permet de la configurer pour 3,3 V ou 5 V (puissance de sortie et niveau IO). Par défaut la carte fonctionne à 5V mais il est possible de la configurer à 3,3V en coupant le cavalier par défaut et en sou­dant un nouveau cavalier vers la broche 3,3 V.