pleasedontcode

Water Metering rev_03

Aug 27th, 2025
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /********* Pleasedontcode.com **********
  2.  
  3.     Pleasedontcode thanks you for automatic code generation! Enjoy your code!
  4.  
  5.     - Terms and Conditions:
  6.     You have a non-exclusive, revocable, worldwide, royalty-free license
  7.     for personal and commercial use. Attribution is optional; modifications
  8.     are allowed, but you're responsible for code maintenance. We're not
  9.     liable for any loss or damage. For full terms,
  10.     please visit pleasedontcode.com/termsandconditions.
  11.  
  12.     - Project: Water Metering
  13.     - Source Code NOT compiled for: ESP32 DevKit V1
  14.     - Source Code created on: 2025-08-27 12:52:12
  15.  
  16. ********* Pleasedontcode.com **********/
  17.  
  18. /****** SYSTEM REQUIREMENTS *****/
  19. /****** SYSTEM REQUIREMENT 1 *****/
  20.     /* The task is to create a water meter that receives */
  21.     /* readings in pulses of 1 liter/pulse.  The meter */
  22.     /* must store the value in non-volatile memory, */
  23.     /* 32-bit size.  All readings must be output via */
  24.     /* Modbus RTU slave (RS485). */
  25. /****** SYSTEM REQUIREMENT 2 *****/
  26.     /* All Modbus RTU and Wi-Fi connection settings must */
  27.     /* be configured via a password-protected web page. */
  28.     /* The following libraries must be used: GyverPortal */
  29.     /* and modbus-esp8266.  Attractive modern web design. */
  30. /****** END SYSTEM REQUIREMENTS *****/
  31.  
  32.  
  33. /* START CODE */
  34.  
  35. /****** DEFINITION OF LIBRARIES *****/
  36. #include <ModbusRTU.h>
  37. #include <GyverPortal.h>
  38. #include <Preferences.h>
  39. #include <WiFi.h>
  40.  
  41. /****** FUNCTION PROTOTYPES *****/
  42. void setup(void);
  43. void loop(void);
  44.  
  45. /****** DEFINITION OF LIBRARIES CLASS INSTANCES*****/
  46.  
  47. ModbusRTU mb; // Modbus RTU slave
  48. GyverPortal portal; // Web portal for configuration (password protected)
  49. Preferences preferences; // Non-volatile storage
  50.  
  51. /****** USER DEFINITIONS *****/
  52. #define PULSE_PIN 34            // Pulse input: 1 liter per pulse
  53. #define RS485_DE_PIN 2            // RS485 Direction pin (DE)
  54. #define MODBUS_BAUD 115200        // Modbus baud rate
  55. const char* PREF_KEY_LITERS = "liters"; // NVR key for liters counter
  56.  
  57. uint32_t liters = 0;              // 32-bit liters counter (non-volatile)
  58. volatile uint32_t pulseCounter = 0; // Pulses counted since last processing
  59.  
  60. #define SERIAL_RX_PIN 16
  61. #define SERIAL_TX_PIN 17
  62.  
  63. void IRAM_ATTR onPulse() {
  64.     // ISR: increment pulse counter for each 1 L pulse
  65.     pulseCounter++;
  66. }
  67.  
  68. void setup(void)
  69. {
  70.     // put your setup code here, to run once:
  71.     Serial.begin(115200);
  72.    
  73.     // ---- Pulse input setup ----
  74.     pinMode(PULSE_PIN, INPUT_PULLUP);
  75.     // Trigger on falling edge depending on sensor wiring
  76.     attachInterrupt(digitalPinToInterrupt(PULSE_PIN), onPulse, FALLING);
  77.  
  78.     // ---- RS485/Modbus RTU setup ----
  79.     pinMode(RS485_DE_PIN, OUTPUT); // RS485 driver enable
  80.     digitalWrite(RS485_DE_PIN, LOW); // start in receive mode
  81.  
  82.     Serial2.begin(MODBUS_BAUD, SERIAL_8N1, SERIAL_RX_PIN, SERIAL_TX_PIN); // RS485 UART
  83.     mb.config(&Serial2, 1); // Modbus RTU slave id = 1
  84.     mb.addHreg(0); // 16-bit high word of liters
  85.     mb.addHreg(1); // 16-bit low word of liters
  86.  
  87.     // Load persisted liters value from non-volatile memory
  88.     preferences.begin("WaterMeter", false);
  89.     liters = preferences.getUL(PREF_KEY_LITERS, 0);
  90.     mb.Hreg(0, (uint16_t)(liters >> 16));
  91.     mb.Hreg(1, (uint16_t)(liters & 0xFFFF));
  92.  
  93.     // ---- GyverPortal (password-protected web config) ----
  94.     portal.begin();
  95.     portal.setPassword("admin"); // default admin password for portal access
  96.    
  97.     // Note: The GyverPortal pages will be served after WiFi is configured via portal.
  98.     // Actual WiFi configuration page handling is provided by GyverPortal internals.
  99.    
  100.     Serial.println("Setup complete");
  101. }
  102.  
  103. void loop(void)
  104. {
  105.     // Process web portal tasks (password-protected page for config)
  106.     portal.loop();
  107.  
  108.     // Handle pulse accumulation and persistence outside ISR
  109.     static uint32_t lastLitersPersisted = 0;
  110.     if (pulseCounter > 0) {
  111.         noInterrupts();
  112.         uint32_t inc = pulseCounter;
  113.         pulseCounter = 0;
  114.         interrupts();
  115.  
  116.         liters += inc; // 1 liter per pulse
  117.         // Update Modbus registers (two 16-bit registers form a 32-bit value)
  118.     mb.Hreg(0, (uint16_t)(liters >> 16));
  119.     mb.Hreg(1, (uint16_t)(liters & 0xFFFF));
  120.  
  121.         // Persist liters into non-volatile storage (avoid too-frequent writes)
  122.     if (liters != lastLitersPersisted) {
  123.         preferences.putUL(PREF_KEY_LITERS, liters);
  124.         lastLitersPersisted = liters;
  125.         Serial.print("Persisted liters: "); Serial.println(liters);
  126.     }
  127.     }
  128.  
  129.     // Modbus RTU processing
  130.     mb.task();
  131. }
  132.  
  133. /* END CODE */
  134.  
Advertisement
Add Comment
Please, Sign In to add comment