Bilan de la nuit : aucun enregistrement sur la carte sd. Lorsque je l'ai remise dans le lecteur la pompe s'est enclenchée. Sauriez vous me dire d'où vient le soucis ?
Tu as inséré la SD alors que l'ARDUINO était sous tension ?
Non avant par contre je l'ai retiré sous tension
J'imagine que la fonction SD.begin() est appelée dans le setup() ?
La fonction setup() est appelée une seule fois au démarrage de la carte.
Lors de l'appel à SD.begin() si la SD n'est pas présente, cet appel échoue.
Ensuite, inutile d'essayer d'écrire ou de lire.
Tu imagines la suite ou pas ?
Oui la fonction sd.begin est présente y a t'il une erreur dans mes boucles de if ?
Si sd.begin() est appelée dans setup(), il faut redémarrer la carte après insertion de la SD, ou éteindre la carte, insérer la SD, et démarrer.
un projet qui fonctionne, avec datalogger sur carte SD, facilement adaptable à un simple chauffage solaire en supprimant une bonne partie du code, car basé sur des machines à états distinctes pour chaque fonction : Thermalduino, régulation de chauffage open source - Français - Arduino Forum
C'est ce que j'ai fait hbachetti, min code te paraît correct.
Merci bricofoy mais tout semble fonctionner il me reste juste ce point à régler car la fonction écrire sur la carte avec delay marche...mais met tout en pause
ça serait bien que tu postes ton code complet
pour trouver le soucis ça aiderait
// --- 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 <http://www.gnu.org/licenses/>.
//
/*
******************************************************************************************************************************************************
**
** Utilisation des broches
**
** Analogiques
** 3 : => Solar Relai pompe de circulation
**
** Digitales
** 3 : => bus OneWire
**
******************************************************************************************************************************************************
*/
/*
******************************************************************************************************************************************************
**
** Début du code
** . Includes
** . Defines
** . Variables globales
** . Objets
**
******************************************************************************************************************************************************
*/
#include <avr/wdt.h> // Pour le WatchDog
#include <OneWire.h> // Pour les capteurs de température
#include <SD.h>
#include <SPI.h>
#include <DS3231.h>
File myFile;
DS3231 rtc(SDA,SCL);
int pinCS = 10; // Pin 10 on Arduino Uno
/*
** 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 = A3; // 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, 0x39, 0x69, 0xFF, 0x09, 0x00, 0x00, 0xE2 }, // Température à l'intérieur des panneaux solaires
{ 0x28, 0xED, 0xD8, 0xFF, 0x09, 0x00, 0x00, 0x78 }, // Température Piscine
};
// 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
// État d'activation de la tempo
int tempoActive = 0;
// Temps à l'activation de la tempo
unsigned long tempoDepart = 0;
/*
******************************************************************************************************************************************************
**
** setup ==> Fonction obligatoire d'initialisation
**
******************************************************************************************************************************************************
*/
void setup() {
Serial.begin(115200);
// 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;
pinMode(pinCS, OUTPUT);
// SD Card Initialization
if (SD.begin())
{
Serial.println("SD card is ready to use.");
} else
{
Serial.println("SD card initialization failed");
return;
}
rtc.begin();
}
Il en manque un bon morceau là il me semble...
2eme et dernière partie du programme
/*
******************************************************************************************************************************************************
**
** 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[1]);
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);
// Si état pompe est off cad 4,
if ( etat = 4 ) {
// Alors on active la temporisation
tempoActive = 1;
tempoDepart = millis();
}
// Si la temporisation est active,
if ( tempoActive ) {
// Et si il s'est écoulé 1h=3600s,
if ( ( millis() - tempoDepart ) >= 3600000 ) {
// Alors on ecrit sur la carte sd
myFile = SD.open("test.txt", FILE_WRITE);
if (myFile) {
myFile.print(rtc.getDateStr());
myFile.print(";");
myFile.print(rtc.getTimeStr());
myFile.print(";");
myFile.print("Ts:");
myFile.print(tempPanel);
myFile.print(";");
myFile.print("Tp:");
myFile.print(tempBottom);
myFile.print(";");
myFile.print("Pompe:");
myFile.print(etat);
myFile.close(); // close the file
}
// if the file didn't open, print an error:
else {
Serial.println("error opening test.txt");
delay(3000);
}
// Et on désactive la temporisation pour ne pas afficher ce message une seconde fois
tempoActive = 0;
}
}
// Si état pompe est on cad 6,
if ( etat = 6 ) {
// Alors on active la temporisation
tempoActive = 1;
tempoDepart = millis();
}
// Si la temporisation est active,
if ( tempoActive ) {
// Et si il s'est écoulé 2min,
if ( ( millis() - tempoDepart ) >= 120000 ) {
// Alors on ecrit sur la carte sd
myFile = SD.open("test.txt", FILE_WRITE);
if (myFile) {
myFile.print(rtc.getDateStr());
myFile.print(";");
myFile.print(rtc.getTimeStr());
myFile.print(";");
myFile.print("Ts:");
myFile.print(tempPanel);
myFile.print(";");
myFile.print("Tp:");
myFile.print(tempBottom);
myFile.print(";");
myFile.print("Pompe:");
myFile.print(etat);
myFile.close(); // close the file
}
// if the file didn't open, print an error:
else {
Serial.println("error opening test.txt");
delay(3000);
}
// Et on désactive la temporisation pour ne pas afficher ce message une seconde fois
tempoActive = 0;
}
}
}
/*
******************************************************************************************************************************************************
**
** 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);
}
Avant que je ne fasse la fonction "millis" tout fonctionnait mais écrivait les données toutes les 1/2 seconde sur la carte. Désormais rien ne s'écrit et la pompe ne démarre plus. Le programme doit rester coincé je pense...
Bonsoir,
la ligne ''if ( etat = 6 )'' (et celles dans ce style) ne font pas ce que tu penses. Il faut écrire ''if(etat==6)'' pour faire une comparaison .
Top merci supercc, je modifie dès demain matin et je vous tiens au jus...
Bon ben non ça ne marche pas. Il doit y avoir un soucis avec mes boucles conditionnelles car rien ne s'écrit sur la carte et la pompe ne s'enclenche pas, même en passant le sèche cheveux sur la sonde de température pour simuler le soleil. Si vous voyez les erreurs... Merki d'avance
Un bon réflexe : place des Serial.println dans ton code là où tu soupçonnes qu'il peut y avoir des problèmes.
Par exemple affiche les températures.
En mettant les 2 boucles en début de loop voici le résultat sur la carte sd : 01.01.2000;19:08:34;Ts:36.69;Tp:17.50;Pompe:5
Dès le démarrage la pompe s'est enclenchée. J'ai arrêté au bout de 20 min et seulement 1 enregistrement sur la carte. Je vais regarder avec le moniteur série mais le soucis est qu'il faut que j'installe sur un pc portable car là obligé de tout débranché. Si vous avez une idée de ce qui bloque dans mon programme...
A la place des if (etat==4); puis je mettre if(relayOff); ou if(relayOff 255); et dans le cas if (etat==5); mettre if(relayOn); ou if(relayOn 0); ?
PS : et pas état==6 comme je me suis trompé dans le programme
Tu écrases le fichier à chaque ouverture.
Si tu veux ajouter une ligne dans le fichier il faut l'ouvrir en append :
myFile = SD.open("test.txt", O_RDWR | O_APPEND);
Une simplification (pas urgent ni vital) :
// ***** code existant *****
// dans setup() :
pinMode(pinRelayPump, OUTPUT); // utilise A3 comme sortie digitale
// ensuite dans stopPump() et startPump()
// tu utilises A3 comme sortie PWM (ça fonctionne mais il y a plus simple)
analogWrite(pinRelayPump, relayOff);
analogWrite(pinRelayPump, relayOn);
// ***** code corrigé *****
// utilise A3 comme sortie digitale
digitalWrite(pinRelayPump, LOW);
digitalWrite(pinRelayPump, HIGH);