Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /********* Pleasedontcode.com **********
- Pleasedontcode thanks you for automatic code generation! Enjoy your code!
- - Terms and Conditions:
- You have a non-exclusive, revocable, worldwide, royalty-free license
- for personal and commercial use. Attribution is optional; modifications
- are allowed, but you're responsible for code maintenance. We're not
- liable for any loss or damage. For full terms,
- please visit pleasedontcode.com/termsandconditions.
- - Project: Water Metering
- - Source Code NOT compiled for: ESP32 DevKit V1
- - Source Code created on: 2025-08-27 12:52:12
- ********* Pleasedontcode.com **********/
- /****** SYSTEM REQUIREMENTS *****/
- /****** SYSTEM REQUIREMENT 1 *****/
- /* The task is to create a water meter that receives */
- /* readings in pulses of 1 liter/pulse. The meter */
- /* must store the value in non-volatile memory, */
- /* 32-bit size. All readings must be output via */
- /* Modbus RTU slave (RS485). */
- /****** SYSTEM REQUIREMENT 2 *****/
- /* All Modbus RTU and Wi-Fi connection settings must */
- /* be configured via a password-protected web page. */
- /* The following libraries must be used: GyverPortal */
- /* and modbus-esp8266. Attractive modern web design. */
- /****** END SYSTEM REQUIREMENTS *****/
- /* START CODE */
- /****** DEFINITION OF LIBRARIES *****/
- #include <ModbusRTU.h>
- #include <GyverPortal.h>
- #include <Preferences.h>
- #include <WiFi.h>
- /****** FUNCTION PROTOTYPES *****/
- void setup(void);
- void loop(void);
- /****** DEFINITION OF LIBRARIES CLASS INSTANCES*****/
- ModbusRTU mb; // Modbus RTU slave
- GyverPortal portal; // Web portal for configuration (password protected)
- Preferences preferences; // Non-volatile storage
- /****** USER DEFINITIONS *****/
- #define PULSE_PIN 34 // Pulse input: 1 liter per pulse
- #define RS485_DE_PIN 2 // RS485 Direction pin (DE)
- #define MODBUS_BAUD 115200 // Modbus baud rate
- const char* PREF_KEY_LITERS = "liters"; // NVR key for liters counter
- uint32_t liters = 0; // 32-bit liters counter (non-volatile)
- volatile uint32_t pulseCounter = 0; // Pulses counted since last processing
- #define SERIAL_RX_PIN 16
- #define SERIAL_TX_PIN 17
- void IRAM_ATTR onPulse() {
- // ISR: increment pulse counter for each 1 L pulse
- pulseCounter++;
- }
- void setup(void)
- {
- // put your setup code here, to run once:
- Serial.begin(115200);
- // ---- Pulse input setup ----
- pinMode(PULSE_PIN, INPUT_PULLUP);
- // Trigger on falling edge depending on sensor wiring
- attachInterrupt(digitalPinToInterrupt(PULSE_PIN), onPulse, FALLING);
- // ---- RS485/Modbus RTU setup ----
- pinMode(RS485_DE_PIN, OUTPUT); // RS485 driver enable
- digitalWrite(RS485_DE_PIN, LOW); // start in receive mode
- Serial2.begin(MODBUS_BAUD, SERIAL_8N1, SERIAL_RX_PIN, SERIAL_TX_PIN); // RS485 UART
- mb.config(&Serial2, 1); // Modbus RTU slave id = 1
- mb.addHreg(0); // 16-bit high word of liters
- mb.addHreg(1); // 16-bit low word of liters
- // Load persisted liters value from non-volatile memory
- preferences.begin("WaterMeter", false);
- liters = preferences.getUL(PREF_KEY_LITERS, 0);
- mb.Hreg(0, (uint16_t)(liters >> 16));
- mb.Hreg(1, (uint16_t)(liters & 0xFFFF));
- // ---- GyverPortal (password-protected web config) ----
- portal.begin();
- portal.setPassword("admin"); // default admin password for portal access
- // Note: The GyverPortal pages will be served after WiFi is configured via portal.
- // Actual WiFi configuration page handling is provided by GyverPortal internals.
- Serial.println("Setup complete");
- }
- void loop(void)
- {
- // Process web portal tasks (password-protected page for config)
- portal.loop();
- // Handle pulse accumulation and persistence outside ISR
- static uint32_t lastLitersPersisted = 0;
- if (pulseCounter > 0) {
- noInterrupts();
- uint32_t inc = pulseCounter;
- pulseCounter = 0;
- interrupts();
- liters += inc; // 1 liter per pulse
- // Update Modbus registers (two 16-bit registers form a 32-bit value)
- mb.Hreg(0, (uint16_t)(liters >> 16));
- mb.Hreg(1, (uint16_t)(liters & 0xFFFF));
- // Persist liters into non-volatile storage (avoid too-frequent writes)
- if (liters != lastLitersPersisted) {
- preferences.putUL(PREF_KEY_LITERS, liters);
- lastLitersPersisted = liters;
- Serial.print("Persisted liters: "); Serial.println(liters);
- }
- }
- // Modbus RTU processing
- mb.task();
- }
- /* END CODE */
Advertisement
Add Comment
Please, Sign In to add comment