By-pass 3 voies
By-pass 3 voies automatisé et régulation climatique
LE PROJET
Présentation générale
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.
Le contexte
La conservation du vin
Le vin est un produit agricole qui est sensible à la température, particulièrement aux chocs thermiques, 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 thermiques ; 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érature.
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 thermodynamique 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 expulsé par le chauffe-eau
L'air expulsé par le chauffe-eau thermodynamique est récupéré pour climatiser la cave à vin. Un circuit 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.
- 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 électriques (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 ArduinoLa 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-permanentes. Pour minimiser sa taille et son coût, il n'est pré-équipé ni d'USB ni de broches, il faut donc souder des connecteurs 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.
Description
L'alimentation
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 y a aussi 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 Entrées/Sorties (I/O)
Les 6 broches frontales d'interface
Nota : la broche DTR permet la réinitialisation automatique (AutoReset) quand un nouveau scénario 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 sortie, 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.
Reset
La broche RST lorsqu'elle passe l'état LOW réinitialise le microcontrôleur. C'est généralement utilisé pour ajouter un bouton externe de remise à zéro lorsque la carte est bloquée.
DS18B20 Les sondes de température
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'alimenter directement à partir de la ligne 'Data' ("tension parasite") ce qui permet son utilisation sans alimentation externe.
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.
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 mesure 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.
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érature, 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 parasite, 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 exposant, une mantisse et un signe : le premier octet du scratchpad correspond aux bits de pois faible (LSB) et le deuxième octet aux bits de poids fort (MSB). Pour avoir la température en degré Celsius il faut appliquer la formule suivante : température = ((MSB << 8) + LSB) * 0.0625
Description du Scratchpad
Afficheur LCD 16 x 2 Lignes Affichage des températures
Spécifications
- [[Image:]]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
Fonction | |||
Masse 0V | |||
Alimentation générale 5V | |||
Alimentation du panneau LCD (Contraste des caractères)
V0 = VDD → Caractères invisibles ; V0 = 0 → Contraste maximum | |||
RS = 0 et R/W = 1 → Sélection du drapeau BUSY et du compteur d’adresse | |||
R/W = 0 → Mode écriture
R/W = 1 → Mode lecture | |||
Enable : entrée de validation
RS et R/W sont lues front montant, et le bus de données sur front descendant. | |||
Bus de données, bit n°0 (LSB)
non utilisé en mode 4 bits | |||
Bus de données, bit n°0 (LSB)
non utilisé en mode 4 bits | |||
Bus de données, bit n°0 (LSB)
non utilisé en mode 4 bits | |||
Bus de données, bit n°0 (LSB)
non utilisé en mode 4 bits | |||
Bus de données, bit n°0 (LSB) | |||
Bus de données, bit n°5 | |||
Bus de données, bit n°6 | |||
Bus de données, bit n°7 (MSB) | |||
Anode du système de rétro-éclairage (à alimenter en 5V à travers une résistance de 50 à 100Ω pour limiter le courant à 100mA) | |||
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.
[[Image:]]
// ->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 variant 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.
- 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 bibliothèque de logiciel qui permet de contrôler un ou deux servomoteurs connectés aux broches 9 et 10.
[[Image:]]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
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) |
Les 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" |
Constantes et variables globales
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 byte Bdegre[8] = // pour création du symbole ° (degré) { // déclaration d’un tableau de 8 octetsB00111, // définition de chaque octet au format binaireB00101, // 1 pour pixel affiché – 0 pour pixel éteintB00111, // 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 unsigned long Horloge_T_save = 0 ;// Sauvegarde de l'horloge des sondes de température const int Tempo_T = 15000 ; // 15 s mini entre 2 lectures de température |
Gestion du servomoteur
// ->Pour la gestion du servomoteurServo 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
- 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
- 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) ***
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 températures=88) 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 -------------------------*
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
//
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
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
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
FTDI Basic Breakout 5V USB to TTL 6-Pin ModuleL'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éveloppement par une carte FTDI Basic Breakout 5V USB to TTL 6-Pin Module.
[[Image:]]Il s'agit de la version la plus récente 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éinitialisation 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 couleur 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.
[[Image:]]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 soudant un nouveau cavalier vers la broche 3,3 V.