Double watermeter on NodeMCU



  • Objective of this project is to survey abnormal flowrate on the 2 main usage of water : home and garden (I had last year a abnormal bill of about 400m3 ....).

    Existing installation :

    • Raspberry Pi3
    • Domoticz
    • Livebox ADSL
    • Router Synology RT1900ac
    • Oregon sensor temperature
    • OWL CM180

    I use ESP8266 on a NodeMCU dev kit with MySensors 2.2 librarie
    Power is provided by a standart USB supply

    Watermeter : G. GIOANOLA USLF/20 with reed switch cable 2.5m3/h 1 pulse/liter

    • 2 independants counter for each way, count of total volume (m3) and flowrate (l/mn)
    • reset on board by push button for all counter
    • separate soft reset for each way counters from Domoticz
    • save counters on EEPROM every 5h (in case of long time WiFi lost)
    • switch rebounce corrected by small soft
    • send result by WiFi to Domoticz

    Very simple schema :
    0_1546528520487_schema.jpg

    And also box:
    0_1546528562671_box_pcb.jpg

    and sketch :

    //==============================================================
    //                     DOUBLE WATERMETER using WiFi
    //
    // - Count Volume and Flowrate for 2 physical watermeter by reed switch
    // - send values every 1 mn through WiFi
    // - possible hard reset of the 2 counters by switch on board
    // - possible of soft reset for each counter from Domoticz
    // - save values every about each 5h on EEPROM (in case of lost local network)
    // - soft treatement about debouncing reed switch
    //
    // material and soft :
    // - watermeter G. GIOANOLA 2.5 m3/h - 1 pulse / liter 
    // - ESP8266 on NodeMCU dev kit
    // - MySensors 2.20 librarie
    // - Domoticz 3.8153
    // - Raspberry Pi 3
    // - use a static IP in the local network
    //
    // Objectives :
    // Verify leakage and usage for home and garden, send alerte
    //
    // All constant on this sketch are adapted to a max flowrate of 2.5 m3/h
    //
    // Philippe Marsault / France 
    //==============================================================
    //
    // References :
    //
    // MySensors Library
    // https://www.mysensors.org/download/sensor_api_20
    //
    // Article decrivant la transmission EDF Linky Arduino en protocole OWL180
    // http://domotique.web2diz.net/teleinfo-edf-arduino-sans-fil-avec-rfxcom/
    //
    // Présentation de l’ESP8266
    // https://www.ekito.fr/people/presentation-de-l-esp8266/
    //
    // Utilisation de l'EEPROM
    // https://www.carnetdumaker.net/articles/stocker-des-donnees-en-memoire-eeprom-avec-une-carte-arduino-genuino/
    // Sinon voir fonctions "savestate" et "loadstate" de la bibliothèque Mysensors
    // (save et load operent seulement sur 1 byte)
    // https://www.mysensors.org/apidocs-beta/group__MySensorsCoregrp.html#ga07bd2de06f11e34fca1fa77621d164ec
    //
    // NodeMcu v1.0 (ESP8266 12E) store/read a value from EEPROM
    // http://www.esp8266.com/viewtopic.php?p=66197
    //
    // Documentation nodeMCU
    // https://nodemcu.readthedocs.io/en/master/
    // https://tttapa.github.io/ESP8266/Chap01%20-%20ESP8266.html
    //
    // Chargement des caractéristiques de carte NodeMCU ESP12E
    // https://github.com/arduino/Arduino/wiki/Unofficial-list-of-3rd-party-boards-support-urls
    //
    // Building a WiFi Gateway using ESP8266
    // https://www.mysensors.org/build/esp8266_gateway
    // https://projetsdiy.fr/mysensors-version2-decouverte-nouveautes-convertir-sketch/
    //
    // Driver  Windows 10 du CP210x (port USB de la carte NodeMCU) (pour raccordement au PC)
    // https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers
    //
    // Utilisation des PIN avec Interrupt
    // http://www.electronicwings.com/nodemcu/nodemcu-gpio-interrupts-with-arduino-ide
    // Debouncing switch
    // https://www.microcontrollertips.com/debouncing-switches-in-hardware-and-software-faq/
    // http://www.ganssle.com/debouncing-pt2.htm
    //
    // Charger le driver CH340G pour connecter NodeMCU a un PC Win 10
    // Installer l'interface de developpement Arduino IDE sur https://www.arduino.cc
    // Connecter PC et carte Nodemcu avec un cable micro USB (pour smartphone)
    // programmation : appuyer sur la touche FLASH puis sur RESET et relacher FLASH
    // 
    // Utilisation avec Domoticz
    // https://projetsdiy.fr/mysensors-v2-gateway-wifi-esp8266-jeedom-domoticz/#Preparer_le_programme_de_la_Gateway
    // Configurer avec une adresse IP fixe (option recommandée)
    //
    //==============================================================
    //
    // MYSENSORS librarie
    //
    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Henrik EKblad
     * Contribution by a-lurker and Anticimex,
     * Contribution by Norbert Truchsess <norbert.truchsess@t-online.de>
     * Contribution by Ivo Pullens (ESP8266 support)
     *
     * DESCRIPTION
     * The EthernetGateway sends data received from sensors to the WiFi link.
     * The gateway also accepts input on ethernet interface, which is then sent out to the radio network.
     *
     * VERA CONFIGURATION:
     * Enter "ip-number:port" in the ip-field of the Arduino GW device. This will temporarily override any serial configuration for the Vera plugin.
     * E.g. If you want to use the defualt values in this sketch enter: 192.168.178.66:5003
     *
     * LED purposes:
     * - To use the feature, uncomment any of the MY_DEFAULT_xx_LED_PINs in your sketch, only the LEDs that is defined is used.
     * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved
     * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
     * - ERR (red) - fast blink on error during transmission error or recieve crc error
     *
     * See http://www.mysensors.org/build/esp8266_gateway for wiring instructions.
     * nRF24L01+  ESP8266
     * VCC        VCC
     * CE         GPIO4
     * CSN/CS     GPIO15
     * SCK        GPIO14
     * MISO       GPIO12
     * MOSI       GPIO13
     * GND        GND
     *
     * Not all ESP8266 modules have all pins available on their external interface.
     * This code has been tested on an ESP-12 module.
     * The ESP8266 requires a certain pin configuration to download code, and another one to run code:
     * - Connect REST (reset) via 10K pullup resistor to VCC, and via switch to GND ('reset switch')
     * - Connect GPIO15 via 10K pulldown resistor to GND
     * - Connect CH_PD via 10K resistor to VCC
     * - Connect GPIO2 via 10K resistor to VCC
     * - Connect GPIO0 via 10K resistor to VCC, and via switch to GND ('bootload switch')
     *
      * Inclusion mode button:
     * - Connect GPIO5 via switch to GND ('inclusion switch')
     *
     * Hardware SHA204 signing is currently not supported!
     *
     * Make sure to fill in your ssid and WiFi password below for ssid & pass.
     */
    
    // Enable debug prints to serial monitor
    //#define MY_DEBUG
    
    // Use a bit lower baudrate for serial prints on ESP8266 than default in MyConfig.h
    #define MY_BAUD_RATE 9600
    
    // Enables and select radio type (if attached)
    //#define MY_RADIO_NRF24  --> mise en commentaire : pas de module radio
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    #define MY_GATEWAY_ESP8266
    
    #define MY_ESP8266_SSID "XXXXXXXXX"
    #define MY_ESP8266_PASSWORD "YYYYYYYYYYY"
    
    // Enable UDP communication
    //#define MY_USE_UDP  // If using UDP you need to set MY_CONTROLLER_IP_ADDRESS below
    
    // Set the hostname for the WiFi Client. This is the hostname
    // it will pass to the DHCP server if not static.
    #define MY_ESP8266_HOSTNAME "NodeMCU controleur eau"
    
    // Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP)
    #define MY_IP_ADDRESS 192,168,2,51
    
    // If using static ip you can define Gateway and Subnet address as well
    #define MY_IP_GATEWAY_ADDRESS 192,168,2,1
    #define MY_IP_SUBNET_ADDRESS 255,255,255,0
    
    // The port to keep open on node server mode
    #define MY_PORT 5003
    
    // How many clients should be able to connect to this gateway (default 1)
    // 2 counters and 2 switch for reset
    #define MY_GATEWAY_MAX_CLIENTS 4
    
    // Controller ip address. Enables client mode (default is "server" mode).
    // Also enable this if MY_USE_UDP is used and you want sensor data sent somewhere.
    //#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 68
    
    // Enable inclusion mode
    //#define MY_INCLUSION_MODE_FEATURE
    
    // Enable Inclusion mode button on gateway
    //#define MY_INCLUSION_BUTTON_FEATURE
    // Set inclusion mode duration (in seconds)
    //#define MY_INCLUSION_MODE_DURATION 60
    // Digital pin used for inclusion mode button
    //#define MY_INCLUSION_MODE_BUTTON_PIN  3
    
    // Set blinking period for led on the board
    #define MY_DEFAULT_LED_BLINK_PERIOD 100
    
    // Flash leds on rx/tx/err
    // Led pins used if blinking feature is enabled above
    //#define MY_DEFAULT_ERR_LED_PIN 16  // Error led pin
    //#define MY_DEFAULT_RX_LED_PIN  16  // Receive led pin
    //#define MY_DEFAULT_TX_LED_PIN  16  // the PCB, on board LED
    
    //--------------------------------------------------------------
    // Table  PIN / GPIO
    // https://github.com/esp8266/Arduino/issues/584
    //--------------------------------------------------------------
    
    #define D0 16
    #define D1  5 // I2C Bus SCL (clock)
    #define D2  4 // I2C Bus SDA (data)
    #define D3  0
    #define D4  2 // Same as "LED_BUILTIN", but inverted logic
    #define D5 14 // SPI Bus SCK (clock)
    #define D6 12 // SPI Bus MISO 
    #define D7 13 // SPI Bus MOSI
    #define D8 15 // SPI Bus SS (CS)
    #define D9  3 // RX0 (Serial console)
    #define D10 1 // TX0 (Serial console)
    
    //--------------------------------------------------------------
    // Call libraries 
    //--------------------------------------------------------------
    
    #if defined(MY_USE_UDP)
    #include <WiFiUdp.h>
    #endif
    
    #include <ESP8266WiFi.h>
    #include <MySensors.h>
    
    #include <SPI.h>
    #include <SoftwareSerial.h>
    #include <EEPROM.h>
    
    //--------------------------------------------------------------
    // Declare and initialize MySensors variables
    // Volume (m3), flowrate (l/mn) and flowrate (m3/h) for flowmeter 1 and 2
    // Binary used to reset counter A ou B
    //--------------------------------------------------------------
    
    #define CHILD_ID_A  1                        // Id of the compteur A
    #define CHILD_ID_B  2                        // Id of the compteur B
    #define CHILD_ID_AR 3                        // Id of the reset compteur A
    #define CHILD_ID_BR 4                        // Id of the reset compteur B
    MyMessage flowMsg_A(CHILD_ID_A,V_FLOW);     // flowrate (l/mn)
    MyMessage flowMsg_m3_A(CHILD_ID_A,V_VAR1);  // flowrate (m3/h)
    MyMessage volumeMsg_A(CHILD_ID_A,V_VOLUME); // volume (m3)
    MyMessage flowMsg_B(CHILD_ID_B,V_FLOW);     // flowrate (l/mn)
    MyMessage flowMsg_m3_B(CHILD_ID_B,V_VAR2);  // flowrate (m3/h)
    MyMessage volumeMsg_B(CHILD_ID_B,V_VOLUME); // volume (m3)
    MyMessage light_msgA(CHILD_ID_AR, V_STATUS );// Reset watermeter A
    MyMessage light_msgB(CHILD_ID_BR, V_STATUS );// Reset watermeter B
    
    //--------------------------------------------------------------
    // type of variables
    //--------------------------------------------------------------
    
    const long delay_TX_volume = 60000;    // delay (millisecondes) between send to Raspberry (every minutes)
          long ref_time_TX_ms;             // Time reference to compute data transmission delay
    const long delay_EEPROM = 18000000;    // delay (millisecondes) between save on EEPROM (every 5h)
                                           // 100.000 cycles -> 57 years
          long ref_time_EP_ms;             // Time reference to compute EEPROM save
    
    const int eeprom_adr_vol_total = 0;    // adress to write in EEPROM
    
    const int pulses_par_litre_A = 1;      // pulses per liter (depending watermeter caracteristics)
    const int pulses_par_litre_B = 1;      // pulses per liter (depending watermeter caracteristics)
    
    unsigned long vol_litres_total_A;      // Total volume (liter) (4 octets)
    unsigned long vol_litres_total_B;      // Total volume (liter) (4 octets)
    
    // utilisé dans la fonction void comptage ()
    unsigned long pulses_compteur_total_A; // nombre d impulsions (4 octets)
    unsigned long pulses_compteur_total_B; // nombre d impulsions (4 octets)
    unsigned long pulses_compteur_debit_A;
    unsigned long pulses_compteur_debit_B;
    float litres_precis_A; // variable pour les compteurs à + de 1 impulsion par litre
    float litres_precis_B; // variable pour les compteurs à + de 1 impulsion par litre
    float volume_m3_A;     // volume total en m3
    float volume0_m3_A;    // volume total en m3 pour calcul debit
    float volume_m3_B;     // volume total en m3
    float volume0_m3_B;    // volume total en m3 pour calcul debit
    float flowrate_lmn_A;
    float flowrate_lmn_B;
    float flowrate_m3h_A;
    float flowrate_m3h_B;
    float coeff_flowrate;
    
    int val_A;
    int val_B;
    int val_old_A=HIGH;
    int val_old_B=HIGH;
    
    const int PIN_compteur_eau_A = D1;  // broche D1 Input pin number to count water meter pulses 
    const int PIN_compteur_eau_B = D2;  // broche D2 Input pin number to count water meter pulses
    const int PIN_reset          = D5;  // broche D5 Input pin number to reset water meter pulses A & B
    const int PIN_LED_BUILTIN    = D4;  // broche D4 Led on board / inverted logic
    
    void setup() {
    //==============================================================
    // Fonction appelée lors de la mise sous tension de l'Arduino
    //==============================================================
    
      // INPUT is connected only by switch to GND
      pinMode(PIN_compteur_eau_A,INPUT_PULLUP); // use PIN_compteur_eau as INPUT  
      pinMode(PIN_compteur_eau_B,INPUT_PULLUP); // use PIN_compteur_eau as INPUT
      pinMode(PIN_reset,         INPUT_PULLUP); // use PIN_reset        as INPUT
      // OUTPUT is not connected
      pinMode(PIN_LED_BUILTIN, OUTPUT);  // use PIN link to the blue LED as OUTPUT (for blinking)
    
    // Initialize values
      
      Serial.begin(MY_BAUD_RATE);     // Serial port board <-> PC for debug
      
     /* -----------------------------------------------------------------
       Interrupt is NOT used to avoid switch rebounce count
       small code is implemented to limid rebounce counting in the loop
     ----------------------------------------------------------------- */
      
      // Link between PIN, routine and type of signal for software interrupt
      //attachInterrupt(digitalPinToInterrupt(PIN_compteur_eau_A),count_pulses_A, FALLING); 
      //attachInterrupt(digitalPinToInterrupt(PIN_compteur_eau_B),count_pulses_B, FALLING);
      //attachInterrupt(digitalPinToInterrupt(PIN_reset)         ,reset_count_AB, FALLING); 
    
      reset_count_A();
      reset_count_B();
    
      Serial.println();
      Serial.println("== Compteur Eau v1.00 =="); 
      
      // Restore volume values from EEPROM when module restart (power On)
      Serial.println("== EEPROM =="); 
      EEPROM.begin(32); // max size needed for storage
      EEPROM.get(eeprom_adr_vol_total   , vol_litres_total_A     );
      EEPROM.get(eeprom_adr_vol_total+4 , pulses_compteur_total_A);
      EEPROM.get(eeprom_adr_vol_total+8 , vol_litres_total_B     );
      EEPROM.get(eeprom_adr_vol_total+12, pulses_compteur_total_B);
      
      // Display volume to terminal PC (port USB emulation COM) 
      Serial.print("Volume A : ");
      Serial.print(vol_litres_total_A);
      Serial.print(" -- Volume B : ");
      Serial.println(vol_litres_total_B);
    
      // Initialisation des volumes pour calcul du debit en entree de boucle
      litres_precis_A = float(vol_litres_total_A);
      litres_precis_B = float(vol_litres_total_B);
      volume_m3_A = litres_precis_A*0.001;
      volume_m3_B = litres_precis_B*0.001;
      volume0_m3_A = volume_m3_A;
      volume0_m3_B = volume_m3_B;
    
      // Blink led at the end of setup (10 times)
      LED_blink(10);
      
      Serial.println("");
      Serial.println("----- End of Setup -----");  
    }
    
    void presentation()
    {
      /*
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("UV Sensor", "1.2");
      // Register all sensors to gateway (they will be created as child devices)
      present(CHILD_ID_UV, S_UV);
      */
      // Present locally attached sensors here
      
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Water Meter", "1.0");
    
      // Register this device as Waterflow sensor
      present(CHILD_ID_A, S_WATER, "Compteur A");
      present(CHILD_ID_B, S_WATER, "Compteur B");
      present(CHILD_ID_AR,S_DIMMER, "Reset Compteur A");
      present(CHILD_ID_BR,S_DIMMER, "RESET Compteur B");
    
      Serial.println("----- End of presentation -----");  
    }
    
    void receive(const MyMessage &message)
    {
      //When receiving a V_STATUS command, execute reset counter A
    
      if ( message.type == V_STATUS ) {
        Serial.println( "V_STATUS command received..." );
    
        int lstate = message.getInt();
        if (( lstate < 0 ) || ( lstate > 1 )) {
          Serial.println( "V_STATUS data invalid (should be 0/1)" );
          return;
        }
        if ( lstate == 1 && message.sensor == 3) {
          Serial.println( "Reset command received watermeter A" );
          reset_count_A();
          return;
        }
        if ( lstate == 1 && message.sensor == 4) {
          Serial.println( "Reset command received watermeter B" );
          reset_count_B();
          return;
        }
    
      } else {
        Serial.println( "Invalid command received..." );
        return;
      }
    }
    
    void loop() {
    //==============================================================
    // Infinite loop
    //==============================================================
    
     // RESET counter by switch ?
     
      int val=digitalRead(PIN_reset);
      
      if(val==LOW) {
       reset_count_A();
       reset_count_B();
       Print_volume();
       LED_blink(1); // blink LED (and then wait to avoid switch rebounce)
      }
    
      // test for switch A
      int val_A=digitalRead(PIN_compteur_eau_A);
      
      if(val_A==LOW && val_old_A==HIGH ) {
        count_pulses_A(); // increment pulse counter
        delay(200); // wait to avoid rebounce
        val_old_A=LOW;
      } else {
        if(val_A==HIGH ) val_old_A=HIGH;
      }
    
      // test for switch B
      int val_B=digitalRead(PIN_compteur_eau_B);
      
      if(val_B==LOW && val_old_B==HIGH ) {
        count_pulses_B(); // increment pulse counter
        delay(200); // wait to avoid rebounce
        val_old_B=LOW;
      } else {
        if(val_B==HIGH ) val_old_B=HIGH;
      }
        
      // Calculate exact total volume (unit m3) - take in account pulse number for counter with >= 1 pulse/liter
      //calcul du volume exact total en m3 (tient compte du nombre d'impulsions - valable pour compteur a + de 1 pulse par litre)
      litres_precis_A = float(vol_litres_total_A)+ float(1.0/float(pulses_par_litre_A)*float(pulses_compteur_total_A));
      litres_precis_B = float(vol_litres_total_B)+ float(1.0/float(pulses_par_litre_B)*float(pulses_compteur_total_B));
      volume_m3_A = litres_precis_A*0.001;
      volume_m3_B = litres_precis_B*0.001;
     
     /* -----------------------------------------------------------------
      Test time interval for transmission to Raspberry
      millis() -> number of milliseconde since module power ON
                  reset every about 50 days ...
      ref_time_TX_ms -> time reference in the loop
      delay_TX_volume -> delay between transmissions to Raspberry (ms)
     ----------------------------------------------------------------- */
      
      if (millis() - ref_time_TX_ms > delay_TX_volume){
        
      // Compute flowrate as l/mn : volume difference divide by time
      // flowrate = 1000.0*60.0*1000.0*(volume_m3-volume0_m3)/float(millis() - ref_time_TX_ms)
        coeff_flowrate = 60000000.0/float(millis() - ref_time_TX_ms);
        
        flowrate_lmn_A = coeff_flowrate*(volume_m3_A-volume0_m3_A);
        flowrate_lmn_B = coeff_flowrate*(volume_m3_B-volume0_m3_B);
    
      // Equivalent m3/h
        flowrate_m3h_A = flowrate_lmn_A * 0.06 ;
        flowrate_m3h_B = flowrate_lmn_B * 0.06 ;
      
      // update time reference between transmissions
        ref_time_TX_ms = millis(); 
      // update volume reference between transmissions
        volume0_m3_A = volume_m3_A;
        volume0_m3_B = volume_m3_B;
      
      // Display volume values on terminal PC (port USB emulation COM)
        Print_volume();
        
      // Display flowrate values on terminal PC (port USB emulation COM) unit l/mn and m3/h
        Serial.print("Flowrate A (l/mn) : "); // send on serial port in ASCII format
        Serial.print(flowrate_lmn_A,2); // send value on serial port 
        Serial.print(" (l/mn) ou "); 
        Serial.print(flowrate_m3h_A,3); // send value on serial port
        Serial.print(" (m3/h) -- Flowrate B (l/mn) : "); 
        
        Serial.print(flowrate_lmn_B,2); // send value on serial port 
        Serial.print(" (l/mn) ou "); 
        Serial.print(flowrate_m3h_B,3); // send value on serial port
        Serial.println(" (m3/h)"); 
      
      // Send values to gateway with MySensors protocol
        send(volumeMsg_A.set(volume_m3_A, 3));     // Send volume value to gateway - format x.xxx
        send(volumeMsg_B.set(volume_m3_B, 3));     // Send volume value to gateway - format x.xxx
        send(flowMsg_A.set(flowrate_lmn_A, 1));    // Send flowrate value to gateway - format x.x (l/mn)
        send(flowMsg_B.set(flowrate_lmn_B, 1));    // Send flowrate value to gateway - format x.x (l/mn)
        // Values for database
        send(flowMsg_m3_A.set(flowrate_m3h_A, 1)); // Send flowrate value to gateway - format x.x (m3/h) VAR1
        send(flowMsg_m3_B.set(flowrate_m3h_B, 1)); // Send flowrate value to gateway - format x.x (m3/h) VAR2
      // Blink LED to indicate sending to gateway
        LED_blink(1);
      }
    
     /* -----------------------------------------------------------------
        Save volume values on EEPROM
     ----------------------------------------------------------------- */  
      if (millis() - ref_time_EP_ms > delay_EEPROM){
        
      // Message on terminal : save on EEPROM
        Serial.println("");
        Serial.println("-- Sauvegarde sur EEPROM --");
     
      //save current volume and pulses on EEPROM (permanent)
      // in case of loose of power supply or WiFi
      // Write reduce life time of EEPROM (max < 100 000 cycles)
        EEPROM.put(eeprom_adr_vol_total   , vol_litres_total_A     );
        EEPROM.put(eeprom_adr_vol_total+4 , pulses_compteur_total_A);
        EEPROM.put(eeprom_adr_vol_total+8 , vol_litres_total_B     );
        EEPROM.put(eeprom_adr_vol_total+12, pulses_compteur_total_B);
        EEPROM.commit(); // Save changes to the flash (eeprom)
        Serial.println("-- EEPROM.put --- ");
        Print_volume();
      
      // update time reference between transmissions
        ref_time_EP_ms = millis(); 
    
      // Read again EEPROM to verify and print on terminal
        Serial.println("-- Verification ecriture sur EEPROM --");
        EEPROM.get(eeprom_adr_vol_total   , vol_litres_total_A     );
        EEPROM.get(eeprom_adr_vol_total+4 , pulses_compteur_total_A);
        EEPROM.get(eeprom_adr_vol_total+8 , vol_litres_total_B     );
        EEPROM.get(eeprom_adr_vol_total+12, pulses_compteur_total_B);
        Serial.println("-- EEPROM.get --- ");
        Print_volume();
    
      }
    // End of loop
    }
    
    void count_pulses_A(){
    //==============================================================
    // Take in account each pulse in a integer "pulses_compteur_total_A"
    // test if pulse count reach value for 1 liter
    //==============================================================
    
      pulses_compteur_total_A++; // increment pulse counter
      
      if (pulses_compteur_total_A >= pulses_par_litre_A) 
        {
      // 1 L still count then reset pulse counter and increment volume counter
        pulses_compteur_total_A = 0;
        vol_litres_total_A++;
        }
      Serial.print("-- vol_litres_total_A : ");
      Serial.println(vol_litres_total_A);
    }
    
    void count_pulses_B(){
    //==============================================================
    // Take in account each pulse in a integer "pulses_compteur_total_B"
    // test if pulse count reach value for 1 liter
    //==============================================================
    
      pulses_compteur_total_B++; // increment pulse counter
      
      if (pulses_compteur_total_B >= pulses_par_litre_B) 
        {
      // 1 L still count then reset pulse counter and increment volume counter
        pulses_compteur_total_B = 0;
        vol_litres_total_B++;
        }
      Serial.print("-- vol_litres_total_B : ");
      Serial.println(vol_litres_total_B);
    }
    
    void reset_count_AB(){
    //==============================================================
    // Reset counter A & B
    // (not used in this sketch witch switch)
    //==============================================================
    
      reset_count_A();
      reset_count_B();
    }
    
    void reset_count_A(){
    //==============================================================
    // Reset counter B
    // Will be save in EEPROM after delay_EEPROM time
    //==============================================================
    
      pulses_compteur_total_A = 0;
      pulses_compteur_debit_A = 0;
      vol_litres_total_A = 0;
      flowrate_lmn_A = 0;
      volume0_m3_A = 0;
      volume_m3_A = volume0_m3_A;
      ref_time_TX_ms = millis();        // Initialize to current time for transmission
      ref_time_EP_ms = ref_time_TX_ms;  // Initialize to current time for EEPROM save
      Serial.println(" ------ RESET COUNTER A ---- ");
    }
    
    void reset_count_B(){
    //==============================================================
    // Reset counter B
    // Will be save in EEPROM after delay_EEPROM time
    //==============================================================
    
      pulses_compteur_total_B = 0;
      pulses_compteur_debit_B = 0;
      vol_litres_total_B = 0;
      flowrate_lmn_B = 0;
      volume0_m3_B = 0;
      volume_m3_B = volume0_m3_B;
      ref_time_TX_ms = millis();        // Initialize to current time for transmission
      ref_time_EP_ms = ref_time_TX_ms;  // Initialize to current time for EEPROM save
      Serial.println(" ------ RESET COUNTER B ---- ");
    }
    
    void LED_blink(byte N_blink){
    //==============================================================
    // Blink the led N_blink time 
    // MY_DEFAULT_LED_BLINK_PERIOD ms On / MY_DEFAULT_LED_BLINK_PERIOD ms Off
    //==============================================================
      for(byte i = 0; i < N_blink; ++i)    // Loop for N_blink blink
      {
      digitalWrite(PIN_LED_BUILTIN, LOW); // turn the LED on (LOW is the voltage level)
      delay(MY_DEFAULT_LED_BLINK_PERIOD);  // time to wait (millisecond)
      
      digitalWrite(PIN_LED_BUILTIN, HIGH);  // turn the LED off by making the voltage HIGH
      delay(MY_DEFAULT_LED_BLINK_PERIOD);  // time to wait (millisecond)
      }
    }
    
    void Print_volume(){
    //==============================================================
    // Print volumes on serial terminal 
    //==============================================================
        Serial.println("");
        Serial.print("volume total A (L) : ");
        Serial.print(vol_litres_total_A,3);      // format x.xxx
        Serial.print(" -- volume total B (L) : ");
        Serial.println(vol_litres_total_B,3);    // format x.xxx
    }
    


Suggested Topics

51
Online

11.4k
Users

11.1k
Topics

112.6k
Posts