Comment faire une mise à zéro journalière de mes relevés pluviométriques

Bonjour,
Ci-dessous mon code qui fonctionne très bien. Avec du recul, je désire concernant uniquement la pluviométrie que cette dernière fasse une remise à zéro journalière de mes relevés.

J’utilise :
-SIM900
-UNO REV3
-DHT22
-Pluviomètre

Comment solutionner ma demande.
Merci.

Laure

#include <SoftwareSerial.h>
#include <DHT.h>
#include <EEPROM.h>

struct __attribute__ ((packed)) _paramS {
  unsigned long  nombreDeGodets;
} lesParametres;

const uint32_t motClef = 0xDEADBEEF;
const uint16_t adresseMotClef = 0x00;
const uint16_t adresseDesParametres = adresseMotClef + sizeof(motClef);

const byte pinResetEEPROM = 3; // pin 3 --> bouton --> GND

const byte pinDHT = 5;
const byte pinCapteurPluie = 2; // connectez la pin 2 à la pin de signal du capteur de pluie, avec résistance de pullup externe

const double hauteurPourUnGodet = 0.2794; // mm d'hauteur d'eau
const unsigned long antiRebondGodet = 20; // en ms
volatile unsigned long nombreDeGodets = 0;

const unsigned long periodeEnvoi = 30000ul; // émission toutes les 10m inutes (600s en ms)
unsigned long dernierEnvoi = -periodeEnvoi;

SoftwareSerial SIM800L(7, 8);               //Serial SIM800L pin
DHT dhtSensor(pinDHT, DHT22);

#define Write_API_key "**************"  //Thingspeak Write API Key
const char * apn = "orange";
const char * url = "GET https://api.thingspeak.com/update?api_key=" Write_API_key;


void etablirValeursParDefaut(bool forceReset = false)
{
  uint32_t lectureMotClef;
  EEPROM.get(adresseMotClef, lectureMotClef);
  if (forceReset || lectureMotClef != motClef) {
    // la mémoire n'avait pas encore été initialisée ou on veut forcer le reset
    lesParametres.nombreDeGodets = 0;
    EEPROM.put(adresseDesParametres, lesParametres);
    EEPROM.put(adresseMotClef, motClef);
  } else {
    // la mémoire a déjà été initialisée, on peut charger les paramètres
    EEPROM.get(adresseDesParametres, lesParametres);
  }
}


void ShowSerialData() {
  while (SIM800L.available() != 0) Serial.write(SIM800L.read());
}

void SetupModule() {
  ShowSerialData();

  SIM800L.println(F("AT"));           delay(200);
  ShowSerialData();

  SIM800L.println(F("AT+CPIN?"));     delay(1000);
  SIM800L.println(F("AT+CREG?"));     delay(1000);
  SIM800L.println(F("AT+CGATT?"));    delay(1000);
  ShowSerialData();

  SIM800L.println(F("AT+CIPSHUT"));   delay(1000);
  SIM800L.println(F("AT+CIPSTATUS")); delay(2000);
  SIM800L.println(F("AT+CIPMUX=0"));  delay(2000);
  ShowSerialData();

  //setting the APN,
  SIM800L.print(F("AT+CSTT=\""));
  SIM800L.print(apn);
  SIM800L.println(F("\""));            delay(1000);
  ShowSerialData();

  SIM800L.println(F("AT+CIICR"));     delay(2000);
  ShowSerialData();

  //get local IP adress
  SIM800L.println(F("AT+CIFSR"));     delay(2000);
  ShowSerialData();

  SIM800L.println(F("AT+CIPSPRT=0")); delay(2000);
  ShowSerialData();
}

void godetPlein() {
  static unsigned long dernierGodet = -antiRebondGodet;
  unsigned long maintenant = millis();
  if (maintenant - dernierGodet >= antiRebondGodet) {
    nombreDeGodets++;
    dernierGodet = maintenant;
  }
}

void lectureCapteurs(float &h, float &t, float &p) {
  h = dhtSensor.readHumidity();
  t = dhtSensor.readTemperature();
  noInterrupts();
  lesParametres.nombreDeGodets = nombreDeGodets;
  interrupts();
  // on sauvegarde le nouveau bnombre de godets si nécessaire
  EEPROM.put(adresseDesParametres, lesParametres);

  p = lesParametres.nombreDeGodets * hauteurPourUnGodet;

  Serial.println();
  Serial.print(F("Température = "));  Serial.print(t);    Serial.print(F(" °C"));
  Serial.write('\t');
  Serial.print(F("Humidité = "));     Serial.print(h);    Serial.print(F(" %"));
  Serial.write('\t');
  Serial.print(F("Pluie = "));        Serial.print(p, 4); Serial.println(F(" mm"));
}

void setup() {
  pinMode(pinResetEEPROM, INPUT_PULLUP);
  pinMode(pinCapteurPluie, INPUT); // pullup externe de 10kΩ
  Serial.begin(115200);
  SIM800L.begin(9600);
  dhtSensor.begin();

  etablirValeursParDefaut(digitalRead(pinResetEEPROM) == LOW); // on fait un reset du compteur si le bouton est appuyé
  nombreDeGodets = lesParametres.nombreDeGodets;

  Serial.println("SIM800L GPRS Test");
  delay(2000);
  SetupModule();

  attachInterrupt(digitalPinToInterrupt(pinCapteurPluie), godetPlein, FALLING);
}

void loop() {
  unsigned long maintenant = millis();

  if (maintenant - dernierEnvoi >= periodeEnvoi) { // est-ce le moment d'émettre ?
    dernierEnvoi = maintenant;                     // on se souvient du moment

    // émission
    SIM800L.println(F("AT+CIPSTART=\"TCP\",\"api.thingspeak.com\",\"80\""));
    delay(3000);
    ShowSerialData();
    Serial.println();

    SIM800L.println(F("AT+CIPSEND"));
    delay(2000);
    ShowSerialData();

    float humidite;
    float temperature;
    float hauteurPluie;
    lectureCapteurs(humidite, temperature, hauteurPluie);

    // on construit la requête GET
    String requete = url;
    requete += "&field1=";
    requete += String(temperature);
    requete +=  "&field2=";
    requete += String(humidite);
    requete += "&field3=";
    requete += String(hauteurPluie, 4); // 4 chiffres après la virgule

    Serial.print(F("Envoi de : ")); Serial.println(requete);

    SIM800L.println(requete);
    SIM800L.println((char)26); delay(4000);
    Serial.println();
    ShowSerialData();

    SIM800L.println("AT + CIPSHUT");  delay(500);   // on termine la session
    ShowSerialData();
  }
}

Tu veux une fois pas jour remettre ta variable "nombreDeGodets" à zéro ?

Comme tu sauvegarde tes relevés sur thinkpeak, n'est-il pas possible de gérer les auteurs cumulé sur le Dashboard avec une granularité configurable?
Dans ce cas tu pourrais remettre à zéro ta variable à chaque envois?

Sinon, il doit être possible de récupérer l'heure via ton module GPRS périodiquement, pour compenser la dérive du µC et faire ton reset à l'heure fixe.
Il faudrait regarder du coté de cette librairie pour la gestion de l'heure

Merci pour ta réponse.
"Tu veux une fois pas jour remettre ta variable "nombreDeGodets" à zéro ?" : oui

Concernant thinkpeak il faudrait que je regarde, toutefois je ne sais pas si cela se fait automatiquement.

Sinon ce bout de code ne ferait-il pas l'affaire ? Faut-il mettre obligatoirement une librairie ?

Laure

  }
 
  if(now.hour()== 0) {
    dailyRain = 0.0;                                      // pluie quotidienne claire à minuit
    dailyRain_till_LastHour = 0.0;                        // nous ne voulons pas de pluie négative à 01h00
 
    }

Pour avoir "now" il faut que tu fasse une inclusion d'un fichier d'en-tête d'une librairie.
Je ne crois pas que cela fasse directement partie du framework Arduino.

Mais le problème principal, c'est que l'heure va dériver petit à petit(voir pas si petit à petit :slight_smile: ) et être remis à zéro à chaque "reset" de ton µC

Au sujet de l'inclusion, il s'agit de ça ?
#include "RTClib.h"

Merci.
Laure

Oui, lorsque tu utilises la directive "#include" cela inclus dans ton code les en-tête d'une librairie de fonction ou d'objet.
Mais en interne l'IDE ajoute aussi le code de la librairie.
Dans le cas que tu cite tu utilise une librairie RTClib.

Mais comme indiqué le problème principal n'est pas là :slight_smile:

Comment solutionner ce problème.

Laure

Bonjour

Ci-dessous mon code qui fonctionne très bien. Avec du recul, je désire concernant uniquement la pluviométrie que cette dernière fasse une remise à zéro journalière de mes relevés.

De passage rapide sur le forum je fais un remarque qui ne va pas très loin. faute de temps disponible

Il est possible de constuire chez/par ThingSpeak, à partir de la série temporelle horodatée brute issue du pluviomètre + un bout de code Matlab, une nouvelle série temporelle représentant les cumuls sur les intervalles de temps souhaités don par exemple une remise à zéro à minuit

je n'ai pas la solution sous le coude, l'aide en ligne ThingSpeak/Matlab est très bien faite, avec de nombreux exemples.

Bonjour al1fch,
Je vais regarder ça (si je trouve).
Merci.

Laure

un moteur de recherche avec 'Matlab ThingSpeak rainmeter' donne des résultats comme celui-ci

https://fr.mathworks.com/matlabcentral/answers/415548-calculate-daily-rainfall-from-continuously-increasing-value

Merci,
Je zieute ça de suite.

Laure

J'ai trouvé des codes. Toutefois, je ne sais ou les insérer pour faire des essais.

Laure

J'ai trouvé des codes. Toutefois, je ne sais ou les insérer pour faire des essais.

-tu ouvres la page web de ton 'Channel'
-cliques sur MATLAB VISUALIZATION ,
-fais une sélection parmi les options proposées : custom pour une page blanche, ou un des modèles de code
-cliques sur CREATE
-une fenêtre d'édition de code MATLAB s'ouvre
-une fois édité fais SAVE ou SAVE AND RUN

A chaque arrivée de donées brutes issue de ton pluviomètre le script MATLAB sera exécuté pour mettre à jour le graphe avec cumul, ça peut être présenté ou pas sous forme d'histogramme
(la syntaxe du code MATLAB n'est pas des plus limpides...)

Je te réitère mes remerciements et ta patience. Je ferai des essais demain.
Bonne soirée.

Laure

Comme je te l'ai indiqué en récupérant l'heure de ton module GPRS, si cela est possible.
Ou en utilise un RTC comme le DS3231

Merci, je vais regarder ça également.
Bonne soirée.

Laure

J'ai essayé avec ce code :

RainMatrix = importdata('data.txt');
% Identifies the first and last year of the series
yr =  RainMatrix(:,3); % years 
yr1 = yr(1); yr_end = yr(end); 
Raincum = NaN(yr_end-yr1+1,7); % placeholder 
k=0; 
for i=yr1:yr_end % scan each year 
    k=k+1; 
    idx = find(yr == i); 
    yri = yr(idx); r  = RainMatrix(idx,4); nr = length(r); 
    length(yri); % check should be 365 or 366 for full years 
    Raincum(k,1) = max(r); 
    for j=2:7 
        rv = r(1:nr - mod(nr,j)); 
        r2 = reshape(rv,j,length(rv)/j);
        r2 = sum(r2); 
        Raincum(k,j) = max(r2); 
    end 
end 
%% 
yrs = [yr1:yr_end]'; 
plot(yrs,Raincum)
legend('1','2','3','4','5','6','7')

j'ai des messages d'erreurs suivants :

Error using importdata
Unable to open file.

Error in Custom (no starter code) 14 (line 1)
RainMatrix = importdata('data.txt');

Je pense que je passe à coté de quelque chose ? Peut-être pas le bon code ?

Laure

comme indiqué dans le code et le message d'erreur cet exemple de code MATLAB travaille sur des données contenue dans un fichier (data.txt) lors qu'il faut travailler sur des données reçues par ThingSpeak dans dans un des champs (Fields) de ton canal (Channel)

Désolè je t'ai sans doute mis sur une piste sur laquelle je ne peux, actuellement, pas vraiment t'accompagner, sans avoir de doute sur la faisabilité

Pas grave "al1fch",
Il faut que je trouve un autre moyen via un code Arduino.

Merci.

Laure

Ou que tu cherche un peu plus de ce coté là.
MATLAB ou Thingpeak n'ont pas un forum dédié?