Enregistrement sur SD qui s'arrête - C++ - Programmation
Marsh Posté le 31-08-2021 à 11:08:41
Sans absolument aucun code ou autre information, ça vas être difficile d'aider, aucune log d'erreur, avez vous cherché au niveau d'un éventuelle fuite de mémoire qui rendrait l'écriture impossible ?
Je ne suis absolument pas spécialiste du domaine mais je suis presque sur que le manque d'info va rendre l'aide à partir d'un forum difficile...
Marsh Posté le 31-08-2021 à 17:28:10
+1 pour mechkurt. C'est un projet scolaire ou universitaire (quoique à cette période de l'année?)? Débugger est une compétence essentielle en programmation! Vu que c'est juste l'enregistrement qui déconne je regarderais de près le code qui s'en occupe (les différentes couches driver SPI - filesystem - ...) et je rajouterais des tests et des printf pour voir. Laisser tourner le truc pendant une heure branché sur un PC ne devrait pas trop poser de problèmes, 1h c'est pas énorme. Ensuite, une fois le problème plus isolé, on pourra eventuellement utiliser d'autres appareils, notamment un analyseur logique sur le bus SPI (je suppose) entre µC et carte SD voir un scope pour vérifier l'intégrité des signaux.
Ah et je suppose que vous avez déjà testés une autre carte SD?
PS: à déplacer dans la cat' Electronique?
Marsh Posté le 31-08-2021 à 22:11:50
Bonsoir,
Fournir le code de la station, aucun soucis, mais merci de m'indiquer la démarche (simple).
Ce n'est ni un projet scolaire ou universitaire. Juste une étude entre la météo et les précipitations et le temps de percolation et de réponse d'un lac situé à 80 mètre sous terre. Des sondes situées dans ce lac nous donnerons les variations de pression (donc de niveau) ainsi que les températures. le tout est horodaté. Je suis spéléo.
Oui, plusieurs cartes formatées en 32 ont été essayées.
L'enregistrement est bon avec les bonnes données dans les bonnes colonnes, mais l'enregistrement coupe bêtement...
Quelque soit les configurations ou modifications actuelles, une coupure d'enregistrement se produit environ une heure après le début d'enregistrement, même en le laissant tourner 24 h....avec ou sans le solaire. Le maxi a été 1h30, mais coupure sans raison... c'est plus souvent une heure.
Si vous pensez qu'il est préférable de déplacer le sujet, pas de problèmes
Marsh Posté le 31-08-2021 à 22:49:26
Vu la quantité de code le plus simple c'est probablement d'en faire une archive .zip et de la mettre sur un service de partage de fichiers, p.ex. https://www.cjoint.com/ ou un truc "Cloud" (évitons Google par contre). Après ça nous apportera probablement pas grand chose, à moins qu'il y ait une erreur grossière qui saute à l'oeil directement... Le mieux c'est encore de débugger sur le matériel réel.
Je suppose que ce n'est pas un problème de batterie qui se vide après 1h? Les cartes SD peuvent demander des pics d'intensité assez importantes en écriture, il y a du découplage etc? Eventuellement faire une photo du truc?
Marsh Posté le 01-09-2021 à 07:53:57
Voilà ci dessous le code entier.
Je ne pense pas que cela soit un problème d'alimentation car pour les essais l'alimentation est celle du bureau par usb. Avec le panneau solaire, c'est sur le jack d'alimentation. Le résultat est identique.
Pour les essais également le compteur était de 5, toutes les 2 minutes et demie (et non 30 comme actuellement soit le quart d'heure) Il y avait donc plus d'enregistrements sur la carte au lieu de 4 maintenant, mais coupure après 1 heure.
Merci
#include <PCF85063TP.h>
#include <Wire.h>
//Baromètre Humidité et Température //
#include <HP20x_dev.h>
#include <Arduino.h>
/*#include "Wire.h"*/
#include <KalmanFilter.h>
/*#include "PCF85063TP.h"*/
#include <DFRobot_SHT3x.h>
#include <SD.h>
#include <SPI.h>
PCD85063TP clock;//define a object of PCD85063TP class
//DFRobot_SHT3x sht3x(&Wire,/*address=*/0x45,/*RST=*/4);
DFRobot_SHT3x sht3x;
unsigned char ret = 0;
File monFichier;
/*
* Variables statiques
*/
#define PLUVIOMETRE 1 //pin D3, interruption n°1
#define VALEUR_PLUVIOMETRE 0.2794 //valeur en mm d'eau à chaque bascule d'auget
#define GIROUETTE A1 //port analogique A1
#define ANEMOMETRE 0 //pin D2, interruption n°0
#define PI 3.1415
#define RAYON 0.07 //rayon en mètre de l'anémomètre en mètre
unsigned long previousMillis = 0;
unsigned long previousMillis2 = 0;
unsigned long delaiAnemometre = 3000L; //3 secondes
unsigned long delaiProgramme = 60000L; //60 sec
float vitesseVent(0); //vent moyen cumulé sur 1 min
float gust(0); //vent max cumulé sur 1 min
int nbAnemo = 0; //nb d'occurence de mesure Anemo
int nbGir = 0; //nb d'occurence de mesure Girouette
float pluvio1min(0); //pluie sur 1 min
float gir(0); //direction moyenne de la girouette sur 1 min (en degrés)
/*
* Variables globales
*/
volatile unsigned int countPluviometre = 0; //variable pour l'interruption du pluviometre pour compter les impulsions
volatile unsigned int countAnemometre = 0; //variable pour l'interruption de l'anémomètre pour compter les impulsions
char direct[] = "";
String Azimut, Lejour;
int LAnnee = 2021, Ljour, Lmois, Lheure, Lminute, Lseconde, compteur = 0;
float TempB, TempC, TempF, Humid, PressA, Vent, MoyenB, MoyenC, MoyenF, MoyenH, MoyenP, MoyenV, VentMax(0);
/*
* Fonction d'interruption du pluviomètre qui incrémente un compteur à chaque impulsion
*/
void interruptPluviometre()
{
countPluviometre++;
}
/*
* Fonction d'interruption de l'anémomètre qui incrémente un compteur à chaque impulsion
*/
void interruptAnemometre(){
countAnemometre++;
}
void setup()
{
Serial.begin(9600); // série de démarrage pour la sortie
/* Mise sous tension, délai de 150 ms, jusqu’à ce que la tension soit stable */
delay(150);
/* Reset HP20x_dev */
HP20x.begin();
delay(100);
//Initialize the chip
while (sht3x.begin() != 0)
{
Serial.println("Échec de l’initialisation de la puce, vérifier la connexion du fil" );
delay(3000);
Serial.begin(9600);
clock.begin();
clock.stopClock();
clock.fillByYMD(2021,8,17);//Année,Mois,Jour
clock.fillByHMS(7,5,00);//15:28 30"
clock.fillDayOfWeek(TUE);//Saturday
clock.setTime();//write time to the RTC chip
clock.startClock();
//clock.setcalibration(1, 32767.2); // Réglage du décalage par fréquence d’horloge
uint8_t ret = clock.calibratBySeconds(0, -0.000041);
Serial.print("offset value: " );
Serial.print("0x" );
Serial.println(ret, HEX);
}
/**
* readSerialNumber Lire le numéro de série de la puce.
* Renvoie le numéro de série à 32 chiffres.
*/
Serial.print("Numéro de série de la puce : " );
Serial.println(sht3x.readSerialNumber());
if(!sht3x.softReset())
{
Serial.println("Échec de l’initialisation de la puce...." );
}
Serial.print("Initialisation de la carte SD..." );
pinMode(10, OUTPUT);
if (!SD.begin(4))
{
Serial.println("échec d’initialisation!" );
return;
}
monFichier = SD.open("Combe.txt", FILE_WRITE);
if (monFichier)
{
Serial.print("\nÉcriture dans Grande Combe.txt..." );
monFichier.println("Date;Heure;Temp_BaroC;Temp_C;Temp_F;Humidite%;Pression;Vent max m/s;Vent moyen m/s;Azimut vent;Direction vent;Vent dominant;Pluie mm;" ); // titres colonnes sur sd mod avec sonde
Serial.println("" );
monFichier.close();
}
Serial.println("initialisation effectuée." );
Serial.println("------------------Lecture en mode de mesure unique-----------------------" );
pinMode(PLUVIOMETRE, INPUT_PULLUP);
attachInterrupt(PLUVIOMETRE,interruptPluviometre,RISING) ;
pinMode(ANEMOMETRE, INPUT_PULLUP);
attachInterrupt(ANEMOMETRE,interruptAnemometre,RISING) ;
}
/*
* Fonction qui converti en angle la valeur analogique renvoyée par l'arduino (valeurs fixes)
* RETURN : angle en degré
*/
float getGirouetteAngle(int value)
{
float angle = 0;
if (value > 280 && value < 290)
{angle = 180; Azimut = "Sud";} // Sud
if (value > 240 && value < 250)
{angle = 202.5; Azimut = "SSO";} // SSO
if (value > 628 && value < 636)
{angle = 225; Azimut = "SO";} // SO
if (value > 598 && value < 606)
{angle = 247.5; Azimut = "OSO";} // OSO
if (value > 940 && value < 950)
{angle = 270; Azimut = "Ouest";} // Ouest
if (value > 824 && value < 832)
{angle = 292.5; Azimut = "ONO";}// ONO
if (value > 884 && value < 892)
{angle = 315; Azimut = "NO";} // NO
if (value > 700 && value < 710)
{angle = 337.5; Azimut = "NNO";} // NNO
if (value > 784 && value < 792)
{angle = 0; Azimut = "Nord";} // Nord
if (value > 402 && value < 412)
{angle = 22.5; Azimut = "NNE";} // NNE
if (value > 458 && value < 468)
{angle = 45; Azimut = "NE";} // NE
if (value > 78 && value < 85)
{angle = 67.5; Azimut = "ENE";} // ENE
if (value > 88 && value < 98)
{angle = 90; Azimut = "Est";} // Est
if (value > 60 && value < 70)
{angle = 112.5; Azimut = "ESE";} // ESE
if (value > 180 && value < 190)
{angle = 135; Azimut = "SE";} // SE
if (value > 122 && value < 132)
{angle = 157.5; Azimut = "SSE";}// SSE
return angle;
}
void printTime()
{
clock.getTime();
Lheure = clock.hour;
Serial.print("\n " );Serial.print(Lheure);
Serial.print(":" );
Lminute = clock.minute;
Serial.print(Lminute);
Serial.print(":" );
Lseconde = clock.second;
Serial.print(Lseconde);
Serial.print(" " );
Serial.print(" " );
switch (clock.dayOfWeek)
{
case MON:
Lejour = "Lundi";
break;
case TUE:
Lejour = "Mardi";
break;
case WED:
Lejour = "Mercredi";
break;
case THU:
Lejour = "Jeudi";
break;
case FRI:
Lejour = "Vendredi";
break;
case SAT:
Lejour = "Samedi";
break;
case SUN:
Lejour = "Dimanche";
break;
}
Serial.print(Lejour);
Serial.print(" " );
Ljour = clock.dayOfMonth;
Serial.print(Ljour);
Serial.print("/" );
Lmois = clock.month;
Serial.print(Lmois);
Serial.print("/" );
if (Lmois == 12 and Ljour == 31)
LAnnee ++;
Serial.print(LAnnee);
}
void loop()
{
printTime();
delay(30000);
monFichier = SD.open("Combe.txt", FILE_WRITE);
if (monFichier)
Serial.println("\n Données en cours :" );
compteur++;
TempB = HP20x.ReadTemperature() / 100.0;
TempC = sht3x.getTemperatureC();
TempF = sht3x.getTemperatureF();
Humid = sht3x.getHumidityRH();
PressA = HP20x.ReadPressure() / 100.0;
vitesseVent = (PI * RAYON * 2 * countAnemometre)/3*3.6; //3 = durée de prise de mesure (3sec) m/s
if(vitesseVent > VentMax)
VentMax = vitesseVent;
MoyenB += TempB;
MoyenC += TempC;
MoyenF += TempF;
MoyenH += Humid;
MoyenP += PressA;
MoyenV += vitesseVent;
Serial.print("\n Compteur : " ); Serial.print(compteur);
Serial.print("\n T° Baromètre C° : " );Serial.print(TempB);
Serial.print("\n Température en Celsius : " ); Serial.print(TempC);
Serial.print("\n Température en Farhenheit : " ); Serial.print(TempF);
Serial.print("\n Humidite Relative(%RH) : " ); Serial.print(Humid);
Serial.print("\n Pression actuelle en hPa : " ); Serial.print(PressA);
unsigned long currentMillis = millis(); // read time passed
//Récupération des infos de l'anémomètre et girouette toutes les 3 sec
//Enregistrement cumulé des valeurs
if (currentMillis - previousMillis > delaiAnemometre)
{
previousMillis = millis();
nbAnemo++;
countAnemometre = 0;
int gdir = analogRead(GIROUETTE);
gir = getGirouetteAngle(gdir);
nbGir++;
Serial.print("\n Vent actuel en m/s : " );Serial.println(vitesseVent);
Serial.print(" Vitesse vent cumulée : " );Serial.println(MoyenV);
Serial.print(" N bascules du Pluviomètre : " );Serial.println(countPluviometre);
Serial.print(" Direction vent actuel : " );Serial.print(gir); Serial.print("° " ); Serial.println(Azimut);
pluvio1min += countPluviometre*VALEUR_PLUVIOMETRE;
countPluviometre = 0;
Serial.print(" Pluviométrie en mm : " );Serial.println(pluvio1min);
}
if (compteur == 30)
{
MoyenB = MoyenB / compteur;
MoyenC = MoyenC / compteur;
MoyenF = MoyenF / compteur;
MoyenH = MoyenH / compteur;
MoyenP = MoyenP / compteur;
MoyenV = MoyenV / compteur;
Serial.print("\n Écriture dans Grande Combe.txt..." );
Serial.print("\n température moyenne : " ); Serial.print(MoyenB);
Serial.print("\n température moyenne C° : " ); Serial.print(MoyenC);
Serial.print("\n température moyenne F : " ); Serial.print(MoyenF);
Serial.print("\n Humidité moyenne : " ); Serial.print(MoyenH);
Serial.print("\n Pression moyenne : " ); Serial.print(MoyenP);
Serial.print("\n Vent moyen en m/s : " ); Serial.print(MoyenV);
Serial.print("\n Vent Max en m/s : " ); Serial.print(VentMax);
Serial.print("\n Pluviométrie en mm : " );Serial.println(pluvio1min);
String DateNomJour = String(Lejour);
String DateNumJour = String(Ljour);
String DateMois = String(Lmois);
String DateHeure = String(Lheure);
String DateMinute = String(Lminute);
String DateSeconde = String(Lseconde);
String TempBaro = String(MoyenB);
String TemperatureC = String(MoyenC);
String TemperatureF = String(MoyenF);
String Humidite = String(MoyenH);
String Pression = String(MoyenP);
String VMoyen = String(MoyenV);
String VMax = String(VentMax);
String Pluviometrie = String(pluvio1min);
String Girouette = String(gir);
DateNomJour += " " + DateNumJour + "/" + DateMois + "/" + LAnnee;
DateHeure += ":" + DateMinute + ":" + DateSeconde;
String Combe = DateNomJour + ";" + DateHeure + ";" + TempBaro + ";" + TemperatureC + ";" + TemperatureF + ";" + Humidite + ";" + Pression + ";" + VMax + ";" + VMoyen + ";" + Azimut + ";" + gir + ";" + " " + ";" + Pluviometrie ;
monFichier = SD.open("Combe.txt", FILE_WRITE); //Maximum 8 caractères avant le .txt
if (monFichier)
{
monFichier.println(Combe);
Serial.println("\n terminée." );
monFichier.close();
/* }
/* else
{
Serial.println("erreur d’ouverture de Grande Combe.txt" ); */
}
delay(5000);
MoyenB = 0;
MoyenC = 0;
MoyenF = 0;
MoyenH = 0;
MoyenP = 0;
MoyenV = 0;
VentMax = 0;
pluvio1min = 0;
compteur = 0;
}
// On enregistre la donnée
}
Marsh Posté le 01-09-2021 à 10:12:49
Salut,
Je n'y connais pas grand chose en Arduino, mais, concernant cette partie :
Code :
|
1/ Je ne comprends pas trop ce "if (monFichier)" sans rien derrière.
2/ Pour moi tu ne referme jamais ce "open" et tu refais ensuite des open/close plus bas dans le code.
3/ Pourquoi d'ailleurs ce "SD.open" alors que tu n'écris a priori rien dans le fichier avant de le ré-ouvrir plus tard.
Code :
|
J'ai également du mal à comprendre pourquoi tu as commenté le "else". La syntaxe du commentaire semble également erronée.
Ce n'est probablement pas indispensable mais j'aurais pour ma part tendance à segmenter les données dans plusieurs fichiers plutôt que de les écrire dans un seul ... Un par jour, par semaine, par mois ... à voir selon les données et la façon de les exploiter derrière.
Plus globalement le code me semble assez "approximatif" : il manque par exemple pour moi plusieurs "else" et/ou de tests de retour de fonction avec les remontés d'erreurs qui vont avec.
A+
Marsh Posté le 01-09-2021 à 17:16:57
Bon, après un bref regard je suis d'accord avec eusebius, le code n'est pas top. Ne le prend pas mal surtout, j'ai bien conscience que tu n'es (probablement) pas dév.
Quelque exemples pour illustrer ce que je dis:
-du code mis en commentaire de partout
-mélange de char[] et de String
-les "variables statiques" sont des directives préprocesseur (et des variables globales il y en a aussi dans le tas)
-Serial.beginn appellé possiblement x fois dans une boucle
-Je pense une mauvaise compréhension de comment fonctionnent les chaînes de caractères
-utilisation d'interruption sur des signaux possiblement "bruités" (->debounce)
-…
J'ai aussi pensé à autre chose, il consomme combien de RAM ton code? Je ne sais pas si Serial.println utilise la FLASH ou recopie tout dans la RAM. Il faudrait vérifier, le logiciel Arduino devrait l'afficher après la compilation.
Si j'ai le temps je vais essayer de nettoyer un peu tout ça ce soir, mais comme je n'ai pas le hardware je ne peux pas tester donc exercice difficile...
edit: eusebius:
Citation : 1/ Je ne comprends pas trop ce "if (monFichier)" sans rien derrière. |
Je ne pense pas que ce soit ça ta difficulté, mais au pif: if(bidule) est équivalent à if(bidule!=0).
Marsh Posté le 01-09-2021 à 18:32:08
Bon, je peux pas tout faire mais voici une version un peu meilleure de la fonction setup(). En gros plein de texte sur l'interface série pour savoir ce qui se passe, vérifier les valeurs returnées par les appels de fonctions. Attention, en cas d'échec le µC va s'arrêter (tourner en boucle infinie while(1); ), il faut éteindre et rallumer pour une nouvelle tentative (après avoir vérifié les connections etc). Pour l'initialisation du SHT3x j'ai mis une boucle do {} while(); pour essayer 10 fois avant d'abandonner, mais c'est plus pour montrer cette technique, ça devrait fonctionner du premier coup. Attention aussi aux "nombres magiques", autrement dit des constantes qui traînent sans aucune explication. Il vaut mieux utiliser des #define, surtout si la même valeur est utilisée à plusieurs endroits différents (car sinon gare au changement à un endroit mais pas à l'autre...). Le fichier sur la carte SD je l'ouvre une fois et je le laisse ouvert, il faudra prévoir un bouton poussoir ou autre pour dire à l'Arduino de fermer le fichier et d'"éjecter" la carte SD pour pouvoir l'éteindre et récupérer la carte avec les infos.
Bref, c'est un début. Je te conseille de reprendre tout le code petit par petit et essayer de nettoyer en suivant ces quelque conseils. Des conseils tu peux aussi en trouver d'autres sur internet et puis dans la cat' Électronique il y a un loooong sujet dédié Arduino.
Code :
|
Marsh Posté le 01-09-2021 à 23:22:40
Bonsoir,
Merci de vos réflexions. Je suis plus à l'aise avec beaucoup de vide sous les pieds et la biologie souterraine qu'avec la programmation.
C'est vrai que certaine fonctions ont été mises en commentaires pour "essayer" d'améliorer sans toutefois perde la ligne au cas ou!. Par exemple, plutôt que d'ouvrir et fermer la carte SD, l'idée était de la laisser ouverte....pas concluant!.
Pour l'horloge, c'est la bibliothèque et exemple du module d'origine. Il fonctionne très bien et l'horloge est réglée à une minute de décalage, ce qui n'est pas grave du tout car le décalage est constant et sur le temps, pas d'importance.
Merci pour ces premières idées.
Marsh Posté le 02-09-2021 à 15:59:07
fpaude a écrit : Je suis plus à l'aise avec beaucoup de vide sous les pieds et la biologie souterraine qu'avec la programmation. |
Oui, j'en doute pas. Malheureusement perso je ne connais pas bien le monde Arduino et puis sans le matériel difficile voire impossible d'améliorer / de débugger le code.
Une autre idée quand même: Tu pourrais virer tout les capteurs et ne garder que l'enregistrement (d'une valeur qui s'incrémente tout le temps, genre millis() )voir si ça fonctionne ou pas. Il faut essayer de créer un code le plus court possible qui présente le bug pour pouvoir débugger plus facilement. Si le code "minimaliste" fonctionne on pourra rajouter capteur par capteur en prenant soin de tester après chaque grosse modification.
Marsh Posté le 02-09-2021 à 22:54:00
Bonsoir,
J'ai téléversé les lignes de code proposée, Résultat: l'horloge est totalement déréglée et se réinitialise à chaque démarrage (mais ce n'est pas à priori trop grave actuellement), le libellé de chaque colonne dans l'enregistrement SD a disparu, toutes les données restent bonnes, mais coupure de l'enregistrement au bout d'une heure.
Nous allons essayer de désactiver toutes les mesures sauf une en gardant l'heure.
A suivre donc. Merci
Marsh Posté le 03-09-2021 à 12:45:32
Pour la fonction getGirouetteAngle, j'ai l'impression que tout le monde a pompé sur https://www.sla99.fr/2019/09/12/pro [...] urs-meteo/ or sa méthode me semble plus que douteuse :
Manifestement il a positionné sa girouette aux 16 angles qu'il voulait repérer, il a pris les mesures du capteur, il a tapé une fourchette de 10 (9 en fait au vu de son code, et en fait parfois moins) autour de ce qu'il a mesuré et basta.
Citation : Pour la girouette, c’est un peu plus compliqué. Il faut associer un tableau de valeur à la valeur analogique retournée, puis définir l’angle associé. Concrètement, le nord (N) = 0°, le nord-nord-est = 22,5°, etc … Il faut donc mesurer à la main les 16 valeurs analogiques et faire une fonction de correspondance. |
Mais ça, ça laisse plein de trous dans la raquette, pour lesquels il va renvoyer 0, alors que ça n'a aucune raison d'être la bonne valeur.
En supposant que la capteur envoie une mesure localement continue par morceaux ce que laisse supposer sa remarque
Citation : les valeurs bougent de 1 ou 2 |
Je vois que capteur n'a pas l'air de varier de manière simple : si je prends les valeurs d'orientation successives on a (en prenant la valeur moyenne de la fonction pour déterminer l'angle :
E : 93
ESE : 65
SE : 184.5
SSE : 127
S : 285
SSO : 245
SO : 632
OSO : 602
O : 945
ONO : 828
C'est pas du tout linéaire, donc un vrai ré-étalonnage s'impose, en particulier pour voir a quel moment on a des sautes de plage de valeurs.
Il y a peut être un mix de valeurs de plusieurs capteurs pour une valeur finale composite, repérable dans le pattern des bits de l'entier retourné par le capteur.
(Et penser a faire un étalonnage en faisant tourner dans un sens, et dans l'autre).
Ah en fait c'est tout con, le capteur n'envoie que 16 valeurs d'après la page d'un revendeur :
Citation : Faite tourner la girouette pour repérer les 16 valeurs de tensions différentes relatives à ses différentes positions. |
Dans ce cas la, sa méthode va marcher. Mais j'éviterais de renvoyer 0 si on lit une valeur pas prévue, je renverrais plutôt -1, pour détecter ce cas de figure dans le code appelant et agir en fonction.
Seulement 16 valeurs c'est un poil riquiqui comme plage de valeurs pour le capteur, je ne m'y attendais pas. Mais manifestement, au vu d'un rapide googlage, c'est le standard des capteurs bas de gamme valant dans les 15 €, manifestement c'est avec une techno à aimants.
A+,
Marsh Posté le 03-09-2021 à 16:43:58
Le code que j'avais posté c'était plus un exemple de comment organiser/écrire ça plus proprement, pas un truc à copier 1:1. Comme je disais, sans avoir le hardware impossible de t'aider.
Par contre je voudrais insister sur un point: Si tu laisses le fichier ouvert il faut impérativement prévoir un mécanisme pour le fermer avant de mettre le système hors tension pour retirer la carte, sinon tu vas perdre des données (->buffer etc).
Marsh Posté le 03-09-2021 à 23:18:00
Bonsoir, et merci de toutes vos idées d'améliorations.
Pour le moment, tout le programme écrit semble fonctionner correctement. Chaque sonde ou module a été testé seul avant d'être associé avec un autre pour former le tout. Nous sommes tout a fait conscient qu'il peut-être simplifié ou améliorer, mais nous avons laissé tourner l'ensemble pendant 24 h. les données s'affichent et sont cohérentes dans la fenêtre Sérial. une mesure toutes les 30 secondes, moyennes ou cumuls... tous les quart d'heures.
C'est l'enregistrement qui pose problème.
L'idée de n'utiliser qu'un seul capteur était une bonne idée pour voir le résultat. Le choix a été fait au hasard avec la Pression et Température. Toutes les lignes qui n'étaient pas en relation avec le baromètre et sa température associé ont été désactivée.
L'horloge a été conservée en l'état. La pile est neuve et a été changée.
Résultat: bons enregistrements avec moyennes, mais coupure après 1 heure. A noter toutefois qu'après la coupure, l'affichage du Sérial est différent avec des sauts de lignes en moins, cela reste lisible, mais plus condensé.
L'idée est davantage tournée vers un problème matériel que de programmation, ou un peu des deux!!!
Le choix des connections Grove a été fait pour limiter les faux contacts et la solidité de l'ensemble.
Dernier point, si le téléversement est à nouveau réalisé, tout repart correctement en enregistrement pour se couper 1 h après. La carte a été formaté spécialement (Fat32)et ne sert qu'aux enregistrements.
Marsh Posté le 04-09-2021 à 00:26:15
fpaude a écrit : Bonsoir, |
> le libellé de chaque colonne dans l'enregistrement SD a disparu
C'est normal : RdC n'a pas fait un monFichier.close(); après la ligne 80, donc le premier SD.open de la première execution de loop() va écraser la ligne de libellé avec sa première écriture.
J'ai regardé le code que tu as posté initialement, il est assez compréhensible, et a première vue, la seule chose que je vois qui me choque, c'est ceci :
void loop()
{
printTime();
delay(30000);
monFichier = SD.open("Combe.txt", FILE_WRITE);
if (monFichier) {
Serial.println("\n Données en cours :" );
}
...
tu fais un monFichier = SD.open, tu écris pas dans le fichier, tu ne fermes pas le fichier, et tu le rouvres ensuite. (eusebius te signalait justement ce point)
Il se peut que chaque fois que tu ouvres ton fichier sans le refermer, tu consomme un descripteur de fichier, et que tu les épuises au bout d'un certain temps, puisque c'est fait une fois par appel à loop donc deux fois par minute. Et si tu n'as plus de descripteur de fichier disponible, tu ne peux plus écrire dans le fichier, ce qui collerait bien avec le comportement décrit, surtout que si ça coupe au bout de 1h, ça correspondrait a 120 appels a loop, ce qui est pas loin de 128, un chiffre d'informaticien, qui pourrait bien être le nb total de descripteurs disponibles dans ton système.
A mon avis, tu devrais juste faire ici
void loop()
{
printTime();
delay(30000);
Serial.println("\n Données en cours :" );
et laisser le reste du code initialement posté tel quel (dans un premier temps, car il est améliorable, mais déjà, ça laisserait voir si c'est la source du problème).
EDIT : Ah si, il y a une autre erreur :
Combe = DateNomJour + ";" + DateHeure + ";" + TempBaro + ";" + TemperatureC + ";" + TemperatureF + ";" + Humidite + ";"
+ Pression + ";" + VMax + ";" + VMoyen + ";" + Azimut + ";" + gir + ";" + " " + ";" + Pluviometrie ;
ça devrait être
Combe = DateNomJour + ";" + DateHeure + ";" + TempBaro + ";" + TemperatureC + ";" + TemperatureF + ";" + Humidite + ";"
+ Pression + ";" + VMax + ";" + VMoyen + ";" + Azimut + ";" + Girouette + ";" + " " + ";" + Pluviometrie ;
et une autre :
if (Lmois == 12 and Ljour == 31) {
LAnnee++;
}
ce qui fait que le 21 décembre, tu vas incrémenter l'année toute les 30s...
A+,
Marsh Posté le 04-09-2021 à 00:38:01
gilou a écrit : |
En effet, j'étais parti sur l'idée d'ouvrir le fichier dans setup() et de le laisser ouvert tout le temps jusqu'à un appui sur un bouton poussoir pour signaler au µC "c'est terminé, ferme le fichier". Sauf que je n'ai pas posté de code complet et en mélangeant ma version de setup avec le reste, bref...
Je plussoie ton analyse concernant les descripteurs de fichiers (ou alors un problème de mémoire vive si il y a du malloc caché quelque part au fin-fond de la lib'?).
Marsh Posté le 04-09-2021 à 02:56:04
Bon, j'ai reformaté le code pour le rendre plus lisible, et ai corrigé les erreurs signalées.
J'ai pas d'environnement pour le tester.
A mes fautes de frappes près, ça devrait être meilleur
Code :
|
A+,
Marsh Posté le 04-09-2021 à 08:21:11
Merci, c'est effectivement plus clair.
Après essai, voici les corrections et questions en relation:
A la ligne 37 et 38, j'ai enlevé l'espace avant le L
A la ligne 260, cela ne passe pas tel quel. J'ai donc remplacé les deux Smois par Lmois. C'est accepté dans la compilation. A quoi sert le ! avant le = Lmois ?
J'ai fait un copier-coller. J'ai 423 ligne dans le copier et dans le coller, seulement 386. A priori, toutes les lignes vides ne sont pas prises en compte.
Lors de l'affichage Sérial, tous les caractères accentués sont remplacer par un ? inversé, alors que les textes n'ont pas changés par rapport aux versions précédentes par exemple : T° Baromètre C° devient Tʔ Baromʔtre Cʔ
Pour le moment cela tourne bien, je vais le laissé toute la journée. Je vais au forum des assos pour recruter de jeunes spéléos en devenir!!!
Marsh Posté le 04-09-2021 à 08:48:11
Complément d'information, le pluviomètre compte bien la hauteur d'eau, mais le nombre de bascules d'auget reste à zéro dans le Sérial
Marsh Posté le 04-09-2021 à 11:25:09
fpaude a écrit : Merci, c'est effectivement plus clair. |
Si, les textes ont probablement changé d'encodage suite a mon édition sous emacs (ou a leur passage via un formateur en ligne), ça explique les ? en sortie.
Si ça se trouve, ils ont été tranformés en isolatin
> A la ligne 37 et 38, j'ai enlevé l'espace avant le L
C'est ce foutu formateur en ligne qui l'a mis (j'utilise un formateur, car le forum n'a pas les mêmes idées sur l'indentation que mon emacs)
Pour la ligne 260, si si, c'est tout a fait du bon C, != signifie pas égal, différent, c'est le contraire de ==
Bon, j'ai simplifié le code, et en plus j'ai vu que j'avais oublié de taper la ligne qui fait la sauvegarde et qui est essentielle au bon fonctionnement de l'algo
Bon, en te remettant tout dans le bon encodage (manifestement, la console ou tu affiches ton texte est en isolatin-1) ça donne ceci :
Code :
|
En y réfléchissant, c'est probablement le copier-coller depuis le forum qui fait le souk. Copies le dans un fichier texte que tu auras au préalable créé avec l'encodage ANSI dans le bloc-note et ça sera OK, je viens de vérifier.
A+,
Marsh Posté le 04-09-2021 à 15:51:58
Dernier point :
Le début de setup devrait ressembler a ceci :
Code :
|
avec ce que tu as actuellement qui suit le test while (!sht3x.begin()) { , tu réinitalises la RTC a chaque tentative d'initialisation du capteur d'humidité, et il n'y a a priori aucune raison
Au fait, il y a une raison d'utiliser les deux capteurs de température ?
A+,
Marsh Posté le 05-09-2021 à 09:08:39
Bonjour,
Voici les dernières nouvelles:
Sans savoir comment et pourquoi, les caractères accentués sont revenus.
La compilation ne passe toujours pas avec les deux Smois, mais accepte les Lmois.
L'ensemble a tourné hier toute le journée, arrêt pour lire les résultats, relance toute la nuit et lecture ce matin.
Les capteurs Pression et Humidité ont chacun également la température. Il y a une très légère différence environ 2/10 de degrés sur les moyennes, pourtant ils sont côte à côte. enregistrer les deux, c'est juste parce qu'ils sont là. Le baromètre a uniquement la température en Celsius, l'Humidité en Celsius et Fahrenheit. l'humidité est automatiquement donnée en % RH.
Tout cela va dans le bon sens, et encore un grand merci. Nous allons pouvoir envisager la mise en place dans la garrigue de la station, et les sondes destinées à aller sous terre à -80 mètres dans un lac (sondes autonomes et prévues pour cela)
Marsh Posté le 05-09-2021 à 11:17:37
C'est ma faute pour les Smois, je viens de le voir.
Remplacer la déclaration
int SMois = 0;
par
int Smois = 0;
avec un m minuscule
et idem dans les utilisations, et ça ira.
Ce qui donne :
Code :
|
Il reste quelques trucs dont je ne suis pas sur :
En tout cas, content de voir que mon diagnostic était le bon (maximum de descripteur de fichiers ouverts atteint).
A+,
Marsh Posté le 08-09-2021 à 22:34:43
Bonsoir,
L'ensemble du code a été compilé sans soucis et mis en marche devant la clim (dans l'Aude, il fait chaud!) puis débranché et mis en place avec le panneau solaire sur le toit. Tout cela a été réalisé depuis lundi minuit jusqu'à aujourd'hui 22 h avec deux arrêt pour vérifier.
Tout semble correct dans les mesures.
Je ne pense pas que le "KalmanFilter.h" soit inutile car c'est lui qui convertit les angles de la girouette (valeur des résistances internes.)
Pour l'horloge, j'ai réussi à la régler à 30 secondes près, mais en utilisant le croquis du fournisseur. Les lignes de codes actuelles restent inopérantes sans raisons. A supprimer ou modifier?
L'Aude étant dès ce soir en alerte inondation, l'ensemble a été remis en place pour valider au mieux cet épisode Cévenol.
Je vous tiens au courant des dernières mesures, et d'ores et déjà un grand merci pour vos solutions.
Si vos pas vous approchent de l'Aude, c'est avec plaisir que je vous ferais découvrir la Spéléologie. ))
Marsh Posté le 08-09-2021 à 23:56:45
> Si vos pas vous approchent de l'Aude, c'est avec plaisir que je vous ferais découvrir la Spéléologie.
Merci pour l'invitation , mais ce n'est plus de mon age (j'ai passé la 60-aine, et ma condition physique n'est plus suffisante).
> Je ne pense pas que le "KalmanFilter.h" soit inutile car c'est lui qui convertit les angles de la girouette (valeur des résistances internes.)
A aucun moment n'est instancié de filtre, donc ce qui est dans KalmanFilter.h n'est pas utilisé.
Pour un exemple d'utilisation, voir ici : https://github.com/Seeed-Studio/Gro [...] x_demo.ino
Il y a instanciation du filtre :
KalmanFilter t_filter; //temperature filter
Puis une utilisation dudit filtre sur la mesure renvoyée par le capteur
long Temper = HP20x.ReadTemperature();
Serial.println("Temper:" );
float t = Temper / 100.0;
Serial.print(t);
Serial.println("C.\n" );
Serial.println("Filter:" );
Serial.print(t_filter.Filter(t));
Serial.println("C.\n" );
Cela est inexistant dans le code posté ici.
A+,
Marsh Posté le 31-08-2021 à 08:59:59
Bonjour,
Sur une base Méga 2560, et uniquement en Grove, nous avons fait une station météo.
Il y a un anémomètre, girouette, anémomètre, pression et température, humidité et température. A cela a été ajouté une horloge et un enregistrement sur carte SD.
Les mesures s'effectuent toutes les 30 secondes et suivant les capteurs, la moyenne, le cumul, le maxi, etc est enregistré sur SD tous les quarts d'heure (ce qui représente 13 colonnes exploitables sous Excell)
Tout fonctionne très bien, sauf que, environ une heure après le début des enregistrements, cela s'arrête sans raison apparente. A l'écran, les mesures continuent normalement, c'est juste l'enregistrement sur SD qui présente un problème.
Cette station météo étant destinée à être mis en place dans un lieu difficile d'accès et sans réseau, elle sera alimentée par panneau solaire.
Merci à vous de nous proposer des idées de solutions.
Bonne journée.