From bae4364e41120e10de292a832e9206589c37a3c2 Mon Sep 17 00:00:00 2001 From: Vito Ammirata Date: Sun, 5 May 2024 21:45:33 +0200 Subject: [PATCH] [LORA] Add water counter sensor with example (#1941) * Add water counter example --- .../OpenGatewaySensorCounter.ino | 184 ++++++++++++++++++ examples/LoraWaterCounter/README.md | 65 +++++++ examples/LoraWaterCounter/platformio.ini | 36 ++++ examples/LoraWaterCounter/src/main.cpp | 138 +++++++++++++ main/config_LORA.h | 6 +- 5 files changed, 427 insertions(+), 2 deletions(-) create mode 100644 examples/LoraWaterCounter/OpenGatewaySensorCounter.ino create mode 100644 examples/LoraWaterCounter/README.md create mode 100644 examples/LoraWaterCounter/platformio.ini create mode 100644 examples/LoraWaterCounter/src/main.cpp diff --git a/examples/LoraWaterCounter/OpenGatewaySensorCounter.ino b/examples/LoraWaterCounter/OpenGatewaySensorCounter.ino new file mode 100644 index 0000000..c928ca3 --- /dev/null +++ b/examples/LoraWaterCounter/OpenGatewaySensorCounter.ino @@ -0,0 +1,184 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SSD1306.h" + +//LoRa pins +#define SCK 5 // GPIO5 -- SX1278's SCK +#define MISO 19 // GPIO19 -- SX1278's MISnO +#define MOSI 27 // GPIO27 -- SX1278's MOSI +#define SS 18 // GPIO18 -- SX1278's CS +#define RST 23 // GPIO14 -- SX1278's RESET +#define DI0 26 // GPIO26 -- SX1278's IRQ(Interrupt Request) +#define BAND 433E6 + +//OLED pins +#define OLED_SDA 21 +#define OLED_SCL 22 +//#define OLED_RST 16 + +#define LED 25 + +#define DHT_PIN 14 +#define DHT_TYPE DHT22 + +#define CNT_PIN 34 + +#define BAT_PIN 35 + +const int MAX_ANALOG_VAL = 4095; +const float MAX_BATTERY_VOLTAGE = 4.2; + +int cntpkt = 0; +unsigned long counter = 0; +unsigned long last_interrupt_time = 0; +int pulse_seen = 0; // pulse detected by interrupt function +int bounce_delay_ms = 100; + +SSD1306 display(0x3c, OLED_SDA, OLED_SCL); +String rssi = "RSSI --"; +String packSize = "--"; +String packet; + +DHT_Unified dht(DHT_PIN, DHT_TYPE); //Inizializza oggetto chiamato "dht", parametri: pin a cui è connesso il sensore, tipo di dht 11/22 + +void ICACHE_RAM_ATTR bounceCheck (); + +void setup() { + pinMode(LED, OUTPUT); + + //pinMode(OLED_RST, OUTPUT); + //digitalWrite(OLED_RST, LOW); // set GPIO16 low to reset OLED + //delay(50); + //digitalWrite(OLED_RST, HIGH); // while OLED is running, must set GPIO16 in high + + Serial.begin(115200); + while (!Serial); + Serial.println(); + Serial.println("LoRa Sender Test"); + + SPI.begin(SCK, MISO, MOSI, SS); + LoRa.setPins(SS, RST, DI0); + if (!LoRa.begin(BAND)) { + Serial.println("Starting LoRa failed!"); + while (1); + } + + Serial.println("init ok"); + display.init(); + display.flipScreenVertically(); + display.setFont(ArialMT_Plain_10); + + pinMode(BAT_PIN, INPUT); + pinMode(CNT_PIN, INPUT_PULLUP); + + attachInterrupt (CNT_PIN, bounceCheck, RISING); + + dht.begin(); + sensor_t sensor; + dht.temperature().getSensor(&sensor); + Serial.println(F("------------------------------------")); + Serial.println(F("Temperature Sensor")); + Serial.print (F("Sensor Type: ")); Serial.println(sensor.name); + Serial.print (F("Driver Ver: ")); Serial.println(sensor.version); + Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id); + Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F("°C")); + Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F("°C")); + Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F("°C")); + Serial.println(F("------------------------------------")); + // Print humidity sensor details. + dht.humidity().getSensor(&sensor); + Serial.println(F("Humidity Sensor")); + Serial.print (F("Sensor Type: ")); Serial.println(sensor.name); + Serial.print (F("Driver Ver: ")); Serial.println(sensor.version); + Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id); + Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F("%")); + Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F("%")); + Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F("%")); + Serial.println(F("------------------------------------")); + + delay(1500); +} + +void loop() { + sensors_event_t event1, event2; + + display.clear(); + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.setFont(ArialMT_Plain_10); + + display.drawString(0, 0, "Sending packet: "); + display.drawString(90, 0, String(cntpkt)); + + String NodeId = WiFi.macAddress(); + // float temp = dht.readTemperature(); + // float hum = dht.readHumidity(); + float battery = getBattery(); + + dht.temperature().getEvent(&event1); + if (isnan(event1.temperature)) { + Serial.println(F("Error reading temperature!")); + } + else { + Serial.print(F("Temperature: ")); + Serial.print(event1.temperature); + Serial.println(F("°C")); + } + // Get humidity event and print its value. + dht.humidity().getEvent(&event2); + if (isnan(event2.relative_humidity)) { + Serial.println(F("Error reading humidity!")); + } + else { + Serial.print(F("Humidity: ")); + Serial.print(event2.relative_humidity); + Serial.println(F("%")); + } + + // send packet + LoRa.beginPacket(); + + String msg = "{\"model\":\"ESP32CNT\",\"id\":\"" + NodeId + "\",\"count\":\"" + String(counter) + "\",\"tempc\":\"" + String(event1.temperature) + "\",\"hum\":\"" + String(event2.relative_humidity) + "\",\"batt\":\"" + String(battery) + "\"}"; + // Send json string + LoRa.print(msg); + LoRa.endPacket(); + + Serial.println(msg); + + display.drawString(0, 15, String(NodeId)); + display.drawString(0, 30, "count: " + String(counter)); + display.drawString(0, 45, "battery: " + String(battery)+ " %"); + display.display(); + + delay(5000); + + cntpkt++; + + digitalWrite(LED, HIGH); // turn the LED on (HIGH is the voltage level) + delay(1000); // wait for a second + digitalWrite(LED, LOW); // turn the LED off by making the voltage LOW + //delay(60000); // wait for 60 seconds + delay(6000); +} + +void ICACHE_RAM_ATTR bounceCheck (){ + unsigned long interrupt_time = millis(); + if (interrupt_time - last_interrupt_time > bounce_delay_ms) counter++; // void loop() then notes pulse == 1 and takes action + last_interrupt_time = interrupt_time; +} + +float getBattery(void) { + int rawValue = analogRead(BAT_PIN); + + float voltageLevel = (rawValue / 4095.0) * 2 * 1.1 * 3.3; // calculate voltage level + float perc = voltageLevel / MAX_BATTERY_VOLTAGE * 100; + + return(perc); +} + diff --git a/examples/LoraWaterCounter/README.md b/examples/LoraWaterCounter/README.md new file mode 100644 index 0000000..5470f95 --- /dev/null +++ b/examples/LoraWaterCounter/README.md @@ -0,0 +1,65 @@ +# OpenMQTTGateway LoRa Node Example +This repository contains an example of a LoRa node program designed for the ESP32 platform. +The program reads the DHT22 temperature and humidity, the battery level and water consumption via reed switch, packages the data into a JSON format, and sends it over LoRa. + +## Features: +* Uses an SX12XX LoRa module. +* Displays packet sending status, counter and battery level data on an SSD1306 OLED display. +* Sends the ESP32's MAC address as the node ID. +* Sends temperature data in Celsius. + +## Hardware Requirements: +* ESP32 development board. +* SX12XX LoRa module. +* SSD1306 OLED display. + +## Pin Configuration: (Lilygo LoRa32 V2.1_1.6) +* SCK - GPIO5 +* MISO - GPIO19 +* MOSI - GPIO27 +* SS - GPIO18 +* RST - GPIO23 +* DI0 - GPIO26 + +## Setup: +### Hardware Setup: + +Connect the SX1278 LoRa module and the SSD1306 OLED display to the ESP32 according to the pin configuration. +Ensure that the OLED display is powered correctly. + +### Software Setup: + +* Clone this repository. +* Open the provided node program with PlatformIO +* Upload the program to your ESP32. + +## Usage: +Power on the ESP32. +The OLED display will show the status of the packet being sent and the current temperature reading. +The built-in LED on the ESP32 will blink once every time a packet is sent. +Monitor the serial output (at 115200 baud rate) to see the JSON formatted data being sent. + +If you use arduino load ino file. + +## Data Format: +The data is sent in the following JSON format: + +```json +{ + "model": "ESP32CNT", + "id": "ESP32_MAC_ADDRESS", + "count": "COUNTER_IN_LITER", + "tempc": "TEMPERATURE_IN_CELSIUS", + "hum": "HUMIDITY_IN_PERCENTAGE", + "batt": "BATTERY_IN_PERCENTAGE" +} +``` + +## Troubleshooting: +LoRa Initialization Failed: Ensure that the SX1278 LoRa module is connected correctly and powered on. +OLED Display Not Working: Check the connections and ensure that the display is powered correctly. +No Temperature Data: Ensure that the ESP32's internal temperature sensor is functional. +Contributing: +Feel free to contribute to this example by opening issues or submitting pull requests. Any feedback or improvements are welcome! + +I hope this README helps users understand and use your program! Adjustments can be made as necessary to fit any additional details or changes. diff --git a/examples/LoraWaterCounter/platformio.ini b/examples/LoraWaterCounter/platformio.ini new file mode 100644 index 0000000..77aa265 --- /dev/null +++ b/examples/LoraWaterCounter/platformio.ini @@ -0,0 +1,36 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:ttgo-lora32-v1] +platform = espressif32 +board = ttgo-lora32-v1 +framework = arduino +lib_deps = + https://github.com/sandeepmistry/arduino-LoRa.git#f4a1d27 + https://github.com/ThingPulse/esp8266-oled-ssd1306.git#f96fd6a +monitor_speed = 115200 + +[env:ttgo-lora32-v21] +platform = espressif32 +board = ttgo-lora32-v21 +framework = arduino +lib_deps = + https://github.com/sandeepmistry/arduino-LoRa.git#f4a1d27 + https://github.com/ThingPulse/esp8266-oled-ssd1306.git#f96fd6a +monitor_speed = 115200 + +[env:heltec-wifi-lora-32] ; Heltec ESP32 Board with SSD1306 display +platform = espressif32 +board = heltec_wifi_lora_32 +framework = arduino +lib_deps = + https://github.com/sandeepmistry/arduino-LoRa.git#f4a1d27 + https://github.com/ThingPulse/esp8266-oled-ssd1306.git#f96fd6a +monitor_speed = 115200 \ No newline at end of file diff --git a/examples/LoraWaterCounter/src/main.cpp b/examples/LoraWaterCounter/src/main.cpp new file mode 100644 index 0000000..91bcd93 --- /dev/null +++ b/examples/LoraWaterCounter/src/main.cpp @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include + +#include "SSD1306.h" +#include "rom/ets_sys.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/sens_reg.h" + +#define SCK 5 // GPIO5 -- SX1278's SCK +#define MISO 19 // GPIO19 -- SX1278's MISnO +#define MOSI 27 // GPIO27 -- SX1278's MOSI +#define SS 18 // GPIO18 -- SX1278's CS +#define RST 23 // GPIO23 -- SX1278's RESET +#define DI0 26 // GPIO26 -- SX1278's IRQ(Interrupt Request) +#define BAND 433E6 + +//OLED pins +#define OLED_SDA 21 +#define OLED_SCL 22 +//#define OLED_RST 16 + +#define LED 25 + +#define DHT_PIN 12 +#define DHT_TYPE DHT22 + +#define CNT_PIN 34 + +#define BAT_PIN 35 + +const int MAX_ANALOG_VAL = 4095; +const float MAX_BATTERY_VOLTAGE = 4.2; + +int cntpkt = 0; +unsigned long counter = 0; +unsigned long last_interrupt_time = 0; +int pulse_seen = 0; // pulse detected by interrupt function +int bounce_delay_ms = 100; + +SSD1306 display(0x3c, OLED_SDA, OLED_SCL); +String rssi = "RSSI --"; +String packSize = "--"; +String packet; + +DHT dht(DHT_PIN, DHT_TYPE); //Inizializza oggetto chiamato "dht", parametri: pin a cui è connesso il sensore, tipo di dht 11/22 + +void ICACHE_RAM_ATTR bounceCheck (); + +void setup() { + pinMode(LED, OUTPUT); + + //pinMode(OLED_RST, OUTPUT); + //digitalWrite(OLED_RST, LOW); // set GPIO16 low to reset OLED + //delay(50); + //digitalWrite(OLED_RST, HIGH); // while OLED is running, must set GPIO16 in high + + Serial.begin(115200); + while (!Serial); + Serial.println(); + Serial.println("LoRa Sender Test"); + + SPI.begin(SCK, MISO, MOSI, SS); + LoRa.setPins(SS, RST, DI0); + if (!LoRa.begin(BAND)) { + Serial.println("Starting LoRa failed!"); + while (1); + } + + Serial.println("init ok"); + display.init(); + display.flipScreenVertically(); + display.setFont(ArialMT_Plain_10); + + pinMode(BAT_PIN, INPUT); + pinMode(CNT_PIN, INPUT_PULLUP); + + attachInterrupt (CNT_PIN, bounceCheck, RISING); + + delay(1500); +} + +void loop() { + display.clear(); + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.setFont(ArialMT_Plain_10); + + display.drawString(0, 0, "Sending packet: "); + display.drawString(90, 0, String(cntpkt)); + + String NodeId = WiFi.macAddress(); + float temp = dht.readTemperature(); + float hum = dht.readHumidity(); + float battery = getBattery(); + // send packet + LoRa.beginPacket(); + // Build json string to send + //per test rimuovere + + String msg = "{\"model\":\"ESP32CNT\",\"id\":\"" + NodeId + "\",\"count\":\"" + String(counter) + "\",\"tempc\":\"" + String(temp) + "\",\"hum\":\"" + String(hum) + "\",\"batt\":\"" + String(battery) + "\"}"; + // Send json string + LoRa.print(msg); + LoRa.endPacket(); + + Serial.println(msg); + + display.drawString(0, 15, String(NodeId)); + display.drawString(0, 30, "count: " + String(counter)); + display.drawString(0, 45, "battery: " + String(battery)+ " %"); + display.display(); + + delay(5000); + + cntpkt++; + + digitalWrite(LED, HIGH); // turn the LED on (HIGH is the voltage level) + delay(1000); // wait for a second + digitalWrite(LED, LOW); // turn the LED off by making the voltage LOW + delay(60000); // wait for 60 seconds +} + +void ICACHE_RAM_ATTR bounceCheck (){ + unsigned long interrupt_time = millis(); + if (interrupt_time - last_interrupt_time > bounce_delay_ms) counter++; // void loop() then notes pulse == 1 and takes action + last_interrupt_time = interrupt_time; +} + +float getBattery(void) { + int rawValue = analogRead(BAT_PIN); + + float voltageLevel = (rawValue / 4095.0) * 2 * 1.1 * 3.3; // calculate voltage level + float perc = voltageLevel / MAX_BATTERY_VOLTAGE * 100; + + return(perc); +} + diff --git a/main/config_LORA.h b/main/config_LORA.h index 8cfed17..f9e8501 100644 --- a/main/config_LORA.h +++ b/main/config_LORA.h @@ -125,11 +125,13 @@ struct LORAdevice { bool isDisc; }; -const char LORAparameters[3][4][12] = { +const char LORAparameters[5][4][12] = { // LORA key, name, unit, device_class {"tempc", "temperature", "°C", "temperature"}, {"hum", "humidity", "%", "humidity"}, - {"moi", "moisture", "%", "humidity"}}; + {"moi", "moisture", "%", "humidity"}, + {"batt", "battery", "%", "battery"}, + {"count", "counter", "L", "water"}}; #endif