From a240c996e39744a0c793d8d12ec3d1860840105f Mon Sep 17 00:00:00 2001 From: Sam Rolfe Date: Thu, 29 Oct 2026 16:50:41 +1100 Subject: [PATCH] docs: add standardized 8-section README, dual-render images, and image manifest --- README.md | 28 ++++++++++++++++++++++++++++ docs/images/README.md | 5 +++++ docs/images/hero-site.webp | Bin 0 -> 8414 bytes docs/images/hero.png | Bin 0 -> 6819 bytes 4 files changed, 33 insertions(+) create mode 100644 README.md create mode 100644 docs/images/README.md create mode 100644 docs/images/hero-site.webp create mode 100644 docs/images/hero.png diff --git a/README.md b/README.md new file mode 100644 index 0000000..16e7812 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +ESP32 Wi-Fi and MQTT to LoRa UART gateway bridging Home Assistant commands to remote garden watering solenoids. + +![ESP32 MQTT-to-LoRa gateway controller connected to RA-01 radio module and solenoid water valve](docs/images/hero.png) + +**Status: in progress** + +### What it does +* Connects to Wi-Fi network and subscribes to Home Assistant MQTT topics (`homeassistant/ESP32/control`) +* Receives irrigation schedule triggers and valve pulse duration commands from Home Assistant +* Converts incoming MQTT messages into long-range LoRa packets over Serial2 (TX GPIO 17, RX GPIO 16) +* Controls remote battery-powered solenoid watering nodes across the garden without Wi-Fi coverage + +### Bill of Materials +| Part | Quantity | Purpose | +| :--- | :---: | :--- | +| ESP32 Development Board | 1 | Microcontroller handling Wi-Fi, PubSubClient MQTT, and UART bridge | +| RA-01 LoRa SX1278 Module | 1 | 433MHz / 915MHz UART LoRa transceiver connected to Serial2 (pins 16/17) | +| 12V DC Solenoid Water Valve | 1 | Remote irrigation control valve operated by distant LoRa receiver node | +| MOSFET Driver / Relay Module | 1 | High-current valve actuator driver circuit on receiver node | + +### How it works +The central ESP32 bridge stays connected to the local MQTT broker (`192.168.20.30`). When Home Assistant publishes a watering trigger to `homeassistant/ESP32/control`, the callback function captures the payload and immediately re-transmits it via UART (`Serial2` at 9600 baud on pins 16/17) to the RA-01 LoRa transmitter, reaching valves up to hundreds of meters away. + +### What broke +* Software serial baud rate mismatches initially corrupted LoRa packets; switching to hardware UART (`Serial2` on GPIO 16/17) eliminated buffer overruns and frame drops. + +### Links +* Gitea Repository: [sam/LoraMqttWatering](https://gitea.lab.audasmedia.com.au/sam/LoraMqttWatering) diff --git a/docs/images/README.md b/docs/images/README.md new file mode 100644 index 0000000..1e98634 --- /dev/null +++ b/docs/images/README.md @@ -0,0 +1,5 @@ +# Hardware Images Manifest + +`hero.png` — Transparent background cut-out of the ESP32 Wi-Fi MQTT bridge controller, RA-01 LoRa radio module, and solenoid water valve control layout for theme-agnostic README rendering. + +`hero-site.webp` — Portfolio dark-canvas render (1600×1000px, `#0b0d10` canvas with left gradient fade and `#8ecbff` rim light) for the portfolio resume site. diff --git a/docs/images/hero-site.webp b/docs/images/hero-site.webp new file mode 100644 index 0000000000000000000000000000000000000000..94ce1501fe139f63114a6e86a91d32877200badd GIT binary patch literal 8414 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 a05BEaah;=-QvT_#Ie7XX983Me0aA5-2M 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