// --- Programme Arduino ---
// Copyright finizi - Créé le 14/07/2012
// www.DomoEnergyTICs.com
// Code sous licence GNU GPL :
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//
/*
******************************************************************************************************************************************************
**
** Utilisation des broches
**
** Analogiques
** 4 : => Solar Relai pompe de circulation
**
** Digitales
** 3 : => bus OneWire
**
******************************************************************************************************************************************************
*/
/*
******************************************************************************************************************************************************
**
** Début du code
** . Includes
** . Defines
** . Variables globales
** . Objets
**
******************************************************************************************************************************************************
*/
#include // Pour le WatchDog
#include // Pour les capteurs de température
/*
** Déclaration des constantes et des paramètres
*/
#define paramLongSun 600000 // en millisecondes : Durée de fonctionnement à partir de laquelle on considère que le fonctionnement est établi depuis longtemps (600000 = 10 minutes)
#define paramDeltaTempStart 8.0 // en degrés : Ecart de température nécessaire pour la mise en route de la pompe
#define paramDeltaTempStop 4.0 // en degrés : Ecart de température minimum pour le fonctionnement de la pompe
#define etatInconnu 0 // L'état est inconnu. C'est la valeur par défaut. C'est donc l'état au démarrage
#define etatArret 4 // Le circuit est plein, prêt à fonctionner. La pompe est à l'arrêt
#define etatSoleil 5 // La pompe fonctionne et le soleil chauffe les panneaux
#define etatLongSoleil 6 // La pompe fonctionne et le soleil chauffe les panneaux depuis plus de paramLongSoleil
#define etatManuOff 8 // Toute l'installation est mise à l'arrêt
#define etatManuPump 9 // La pompe de circulation est en marche forcée
#define onewireModeLecture 0xBE // Code pour initier la lecture des capteurs OneWire
#define onewireModeMesure 0x44 // Code pour déclencher la lecture des capteurs OneWire
#define onewireNb 2 // Nombre de capteurs OneWire gérés
const int pinOneWire = 3; // Broche utilisée pour lire les températures disponibles via des composant One-Wire DS18B20
const int pinRelayPump = A4; // Commande du relai de pompe de circulation
#define relayOn 0
#define relayOff 255
/*
** Déclaration des variables et initialisations
*/
int etat = etatInconnu;
int lastEtat = etatInconnu;
float tempPanel = -99.9;
float tempBottom = -99.0;
// Adresses matérielles des capteurs One-Wire <== Là, il faut mettre les adresses des capteurs réellement utilisés
static byte onewireSensorSerial[onewireNb][8] = {
{ 0x28, 0x55, 0x63, 0x02, 0x04, 0x00, 0x00, 0x06 }, // Température à l'intérieur des panneaux solaires
{ 0x28, 0x55, 0x75, 0x02, 0x04, 0x00, 0x00, 0x40 }, // Bas du ballon d'eau chaude
};
// Chaines d'état à afficher (certaines seront utilisées plus tard)
const String etatsText[10] = {
"Inconnu", // #define etatInconnu 0
"Vide", // #define etatVide 1
"Remplissage", // #define etatRemplissage 2
"Vidange", // #define etatVidange 3
"Arret", // #define etatArret 4
"Soleil", // #define etatSoleil 5
"SoleilLong", // #define etatLongSoleil 6
"ClosingValve", // #define etatClosingValve 7
"ManuOff", // #define etatManuOff 8
"ManuPompe" // #define etatManuPump 9
};
const float temperatureMini = -40.0; // Température en dessous de la quelle elle n'est pas prise en compte
const unsigned long temperatureReadInterval = 10L * 1000L; // Temps entre 2 lectures de température
unsigned long pumpStartTime = 0; // Temps écoulé, en millisecondes, depuis le démarrage de la pompe de circulation
unsigned long temperatureTime = 0; // Temps écoulé, en millisecondes, depuis la dernière lecture des températures
/*
** Création des objets
*/
OneWire oneWire(pinOneWire); // On défini la broche utilisée pour OneWire
/*
******************************************************************************************************************************************************
**
** setup ==> Fonction obligatoire d'initialisation
**
******************************************************************************************************************************************************
*/
void setup() {
// Initialisation du WatchDog. Se déclenche au bout de 8 secondes d'inactivité
wdt_enable(WDTO_8S);
// Initialiser les broches pour que le relai soit inactif au démarrage
analogWrite(pinRelayPump, relayOff);
// Initialiser les autres broches comme broche de commande
pinMode(pinRelayPump, OUTPUT);
// Ouvrir tous les relais (ne plus rien alimenter)
stopPump();
// Effectue une première mesure pour alimenter les capteurs de température
for (int i = 0; i <= onewireNb; i++) {
onewireMesureTemp(onewireSensorSerial[i]);
}
delay(2000);
for (int i = 0; i <= onewireNb; i++){
onewireMesureTemp(onewireSensorSerial[i]);
}
delay(1000);
etat = etatInconnu;
lastEtat = etatInconnu;
}
/*
******************************************************************************************************************************************************
**
** loop ==> Fonction obligatoire. Boucle infinie de fonctionnement
**
******************************************************************************************************************************************************
*/
void loop() {
// Reset du watchDog : C'est reparti pour 8 secondes
wdt_reset();
/*************************************************************
**
** Lecture de tous les capteurs
*/
boolean temperatureRead = 0;
if ( (temperatureTime == 0) || ( (millis() - temperatureTime > temperatureReadInterval) && (millis() >= temperatureTime) ) ) {
temperatureTime = millis();
/// Lecture des températures
tempPanel = onewireMesureTemp(onewireSensorSerial[0]);
tempBottom = onewireMesureTemp(onewireSensorSerial[4]);
temperatureRead = true;
}
/*************************************************************
**
** Actions à mener en fonction des mesures effectuées et de l'état en cours
*/
switch(etat) {
case etatManuOff: // ==> L'installation a été mise à l'arrêt manuellement
// Ne rien faire et laisser ainsi
break;
case etatManuPump: // ==> La pompe est en marche forcée (mise en marche manuelle)
// Ne rien faire et laisser ainsi
break;
case etatArret: // ==> la pompe est à l'arrêt
// Vérifier si les condition de mise en route sont remplies
if (tempPanel >= tempBottom + paramDeltaTempStart) {
startPump();
}
break;
case etatSoleil: // ==> La pome de circulation est en route de façon NON prolongée
// Vérifier si la pompe doit être arrêtée
if (tempPanel <= tempBottom + paramDeltaTempStop) {
stopPump();
etat = etatArret;
}
// Vérifier si le régime de croisière est atteint
if ( (millis() - pumpStartTime > paramLongSun) && (millis() >= pumpStartTime) ) {
pumpStartTime = 0;
etat = etatLongSoleil;
}
break;
case etatLongSoleil: // ==> La pome de circulation est en route de façon prolongée et est donc en régime de croisière
// Vérifier si l'écart de température entre les panneaux et le bas du ballon d'eau chaude est suffisante
if (tempPanel <= tempBottom + paramDeltaTempStop) {
stopPump();
etat = etatArret;
}
break;
case etatInconnu: // ==> Survient normalement au démarrage
stopPump();
etat = etatArret;
break;
}
// Enregistrer l'état pour la boucle suivante
lastEtat = etat;
// Attendre un peu avant de boucler (une demi seconde)
delay(500);
}
/*
******************************************************************************************************************************************************
**
** Fonctions diverses
**
******************************************************************************************************************************************************
*/
/*
** Fonction pour arrêter la pompe de circulation. L'installation devient alors à l'arrêt
*/
void stopPump() {
analogWrite(pinRelayPump, relayOff);
pumpStartTime = 0;
etat = etatArret;
}
/*
** Fonction pour démarrer la pompe de circulation. L'installation devient alors en fonctionnement
*/
boolean startPump() {
analogWrite(pinRelayPump, relayOn);
pumpStartTime = millis();
etat = etatSoleil;
return(true);
}
/*
** Fonction pour lire une température sur le capteur dont l'adresse est en paramètre
*/
float onewireMesureTemp(byte addr[8]) {
byte data[12]; // Tableau de 12 octets pour lecture des 9 registres de RAM et des 3 registres d'EEPROM du capteur One Wire
int tempet = 0; // variable pour resultat brute de la mesure
float tempetf = 0.0; // variable pour resultat à virgule de la mesure
oneWire.reset();
oneWire.select(addr);
oneWire.write(onewireModeMesure, 1); //
oneWire.reset();
oneWire.select(addr);
oneWire.write(onewireModeLecture); // Récupération des valeurs de la RAM du capteur
// Lire les 9 octets de la RAM (appelé Scratchpad)
for ( int i = 0; i < 9; i++) { // 9 octets de RAM stockés dans 9 octets
data[i] = oneWire.read(); // lecture de l'octet de rang i stocké dans tableau data
}
tempetf = ((data[1] << 8) | data[0]) * 0.0625;
return (tempetf);
}