Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SPI.h>
- #include <Ethernet.h> // Arduino Uno Ethernet Shield "W5100"
- //#include <UIPEthernet.h> // Arduino Nano Ethernet Shield "ENC28j60"
- #include <PubSubClient.h>
- #define vers "Water Meter V1.0"
- #define debug true
- #define dhcp true
- byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xE1};
- //IPAddress ip(192, 168, 1, 200);
- //IPAddress gw(192, 168, 1, 1);
- //IPAddress mask(255, 255, 255, 0);
- // MQTT Network Settings
- const char* mqtt_server = "192.168.1.10";
- const int mqtt_port = 1883;
- const char* mqtt_id = "ardnano_water_meter";
- const char* mqtt_topic_rx = "control/water_meter";
- const char* mqtt_topic_tx = "sensors/water_meter";
- const char* mqtt_topic_lwt = "status/water_meter";
- const char* mqtt_user = "super_secret_username";
- const char* mqtt_pass = "super_secret_password";
- String rx;
- String tx_msg;
- int rxLength = 0;
- byte sensorInterrupt = 0;
- float calibrationFactor = 4.8; // F = 4.8 * Q (L / Min) (for my sensor, FL-808 model, 1" hall effect, 1-60 L/Min)
- volatile byte pulseCount;
- float flowRate;
- float pressure;
- unsigned int flowMilliLitres;
- unsigned long totalMilliLitres;
- unsigned long oldTime;
- EthernetClient client;
- PubSubClient mqttClient(mqtt_server, mqtt_port, client);
- void setup()
- {
- pinMode(2, INPUT); // water flow hall effect pulse
- pinMode(A0, INPUT); // pressure sensor
- digitalWrite(2, HIGH);
- Ethernet.begin(mac); // DHCP
- //Ethernet.begin(mac, ip, gw, mask); // Static IP
- #if debug
- Serial.begin(115200);
- while (!Serial) {
- ;
- }
- #endif
- #if debug
- Serial.print("Version: ");
- Serial.println(vers);
- Serial.print("My IP address: ");
- Serial.println(Ethernet.localIP());
- #endif
- reconnect();
- pulseCount = 0;
- flowRate = 0.0;
- flowMilliLitres = 0.0;
- totalMilliLitres = 0.0;
- oldTime = 0;
- pressure = 0.0;
- attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
- }
- void loop()
- {
- if ((millis() - oldTime) > 1000)
- {
- detachInterrupt(sensorInterrupt);
- if (!mqttClient.loop() && mqttClient.state() != 0) {
- reconnect();
- }
- flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor; // Flow rate in liters per minute
- pressure = analogRead(A0);
- double volts = pressure * (5.0 / 1023.0);
- oldTime = millis();
- flowMilliLitres = (flowRate / 60) * 1000;
- totalMilliLitres += flowMilliLitres;
- tx_msg = "{\"gpm\":";
- tx_msg.concat(int(flowRate) * 0.2641721); // convert liters per minute to gallons per minute
- tx_msg.concat(",\"lpm\":");
- tx_msg.concat(int(flowRate)); // liters per minute
- tx_msg.concat(",\"gal\":");
- tx_msg.concat(totalMilliLitres * 0.0002641721); // convert milliliters to gallons usage
- tx_msg.concat(",\"mil\":");
- tx_msg.concat(totalMilliLitres); // milliliters usage since last reset/clear
- tx_msg.concat(",\"psi\":");
- tx_msg.concat((((pressure - 103) / 819) * 100)); // actual psi reading, calibrate the voltage to match sensor range (my sensor = 0-100 psi, 0.5-4.5v linear scale, 0 psi = 0.5v, 50 psi = 2.5v, 100 psi = 4.5v)
- // 103 = 0.5v on the analog pin, 819 = 4.5v (roughly), scale is 0-1023 (10 bit resolution)
- tx_msg.concat(",\"volts\":");
- tx_msg.concat(volts); // DC voltage of pin A0 (0-5v)
- tx_msg.concat("}");
- tx_msg.trim();
- byte tx_buf[tx_msg.length()+1];
- tx_msg.getBytes(tx_buf, tx_msg.length()+1);
- if(!mqttClient.publish(mqtt_topic_tx, tx_buf, tx_msg.length())) {
- Serial.println("Publish FAILED!");
- delay(500);
- reconnect();
- }
- #if debug
- Serial.print("TX: ");
- Serial.print((char *)tx_buf);
- Serial.print(" [");
- Serial.print(tx_msg.length()+1);
- Serial.println("]");
- #endif
- pulseCount = 0;
- attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
- }
- }
- void pulseCounter()
- {
- pulseCount++;
- }
- // MQTT reconnection function
- void reconnect() {
- while (mqttClient.state() != 0) {
- #if debug
- Serial.println("Attempting MQTT connection...");
- #endif
- //mqttClient.setServer(mqtt_server, mqtt_port);
- mqttClient.setCallback(callback);
- if (mqttClient.connect(mqtt_id, mqtt_user, mqtt_pass, mqtt_topic_lwt, 0, 1, "offline")) {
- mqttClient.subscribe(mqtt_topic_rx);
- //mqttClient.subscribe(mqtt_topic_rx2);
- mqttClient.publish(mqtt_topic_lwt, "online", true);
- }
- else {
- #if debug
- Serial.print("failed, rc= ");
- Serial.println(mqttClient.state());
- Serial.println("try again in 5 seconds");
- #endif
- delay(5000);
- }
- }
- }
- void(* resetFunc) (void) = 0;
- // MQTT received data callback function
- void callback(char* topic, byte* payload, unsigned int length) {
- #if debug
- Serial.print("RX: ");
- #endif
- rx = String((char *)payload);
- rxLength = rx.length();
- for (int i = length; i <= rxLength; i++) {
- rx.setCharAt(i, ' ');
- }
- rx.trim();
- #if debug
- Serial.println(rx);
- //Serial.print(" - ");
- //Serial.println((char *)payload);
- //rx = String((char *)payload);
- //Serial.println(rx);
- //Serial.println();
- #endif
- if(rx == "clear") {
- totalMilliLitres = 0.0;
- #if debug
- Serial.println("CLEAR REQUESTED!"); // an automation publishes to this topic nightly at midnight to reset daily usage
- #endif
- }
- if (rx == "reboot") {
- #if debug
- Serial.println("REBOOT REQUESTED!"); // if the clear command (above) fails, an automation resets the device to force a clear
- #endif
- resetFunc();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement