Initial commit

This commit is contained in:
Will Bradley 2025-01-05 18:13:07 -08:00
commit 4646a78a93
Signed by: will
GPG Key ID: 1159B930701263F3
4 changed files with 188 additions and 0 deletions

BIN
MultiSoilMoistureSensor.fzz Normal file

Binary file not shown.

113
MultiSoilMoistureSensor.ino Normal file
View File

@ -0,0 +1,113 @@
//#include <Wire.h>
//#include <SFE_MicroOLED.h> //Click here to get the library: http://librarymanager/All#SparkFun_Micro_OLED
#include <SparkFun_Qwiic_OLED.h> // http://librarymanager/All#SparkFun_Qwiic_OLED
#include "EspMQTTClient.h" // http://librarymanager/All#EspMQTTClient https://github.com/plapointe6/EspMQTTClient
EspMQTTClient client(
"Your WiFi SSID",
"Your WiFi Password",
"192.168.1.100", // homeassistant mqtt
"espmqtt", // Can be omitted if not needed
"Your MQTT Password", // Can be omitted if not needed
"espmqtt" // Client name that uniquely identify your device
);
#define reportingInterval 10000 // how often to sample/publish, in milliseconds
#define PIN_RESET 4
#define LED_BUILTIN 0 // ESP32
//#define LED_BUILTIN 13 // Teensy
//MicroOLED oled(PIN_RESET); // The TwoWire I2C port is passed to .begin instead
QwiicMicroOLED oled;
//int plant1Pin = A0; // Teensy
int plantPin[] = {35,34,39,38}; // ESP32
int maxSensorValue = 4095; // ESP32
// Qwiic Pro Mini pins
int pin_SDA = 15;
int pin_SCL = 5;
unsigned long last_run = 0;
void onConnectionEstablished() {
client.publish("esp/status", "{\"status\": \"connected\"}");
}
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(115200);
Serial.println("Running MultiSoilMoistureSensor on: ");
pinMode(LED_BUILTIN, OUTPUT);
// esp32 doesn't have analog pullups
// for(int i=0;i<(sizeof(plantPin)/sizeof(plantPin[0]));i++){
// pinMode(plantPin[i],INPUT_PULLUP);
// }
Serial.begin(115200);
// Wire.begin(); // Teensy
// oled.begin(0x3D, Wire);
Wire.begin(pin_SDA, pin_SCL); //Qwiic Pro Mini
if (!oled.begin()){
Serial.println("Failed to initialize OLED");
}
delay(1000); // Delay 1000 ms
}
// 0-based index read
// returns false for no water
bool readAndPublishSensor(int i) {
int n = i+1; // plant number
// maxSensorValue (1023,4095) is bad, 1 is good, 0 is no connection
int sensorValue = analogRead(plantPin[i]);
// invert the values so 1.0 is good and 0.01 or value==0 is bad
int sensorPercent = round(100.0*(maxSensorValue-sensorValue)/maxSensorValue);
if (sensorValue == 0) {
sensorPercent = 0;
}
char sensorText[32];
snprintf(sensorText, 31, "%d", sensorPercent); // send MQTT 0 thru 100
char topic[32];
snprintf(topic, 31, "esp/plants/%d", n); // 1-based plant number
client.publish(topic, sensorText);
Serial.print(topic);
Serial.print(": ");
Serial.print(sensorValue);
Serial.print(" - ");
Serial.println(sensorText);
// show on LED with 1-based plant number and 0-100%
snprintf(sensorText, 31, "%d: %d%%", n, sensorPercent);
oled.text(0, n*8, sensorText);
return sensorPercent > 50; // over 50% is true/good, under 50% is false/bad
}
// the loop function runs over and over again forever
void loop() {
unsigned long time_trigger = millis();
if (last_run == 0 || time_trigger-last_run > reportingInterval) {
oled.erase();
oled.text(0, 0, "Water:");
bool showLed = false;
// read + output plant sensors
for(int i=0;i<(sizeof(plantPin)/sizeof(plantPin[0]));i++){
if (!readAndPublishSensor(i)) {
showLed = true;
};
}
if (showLed) {
digitalWrite(LED_BUILTIN, HIGH);
} else {
digitalWrite(LED_BUILTIN, LOW);
}
oled.display();
last_run = time_trigger;
}
client.loop();
sleep(1);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

75
README.md Normal file
View File

@ -0,0 +1,75 @@
# Multiple Soil Moisture Sensors with ESP32
## Parts
- ESP32 or similar low-power WiFi-enabled board. I used this: https://www.sparkfun.com/products/23386
- Simple soil moisture sensors that are readable with either analog voltage or digital (1/0) output. There are others that use i.e. RS-485 but this guide doesn't cover that. I used these: https://www.amazon.com/dp/B0C6XGRKS5
- Optional: Qwiic OLED screen to view moisture without another device. I used this: https://www.sparkfun.com/products/22495 however in the future I'll likely go without in order to save battery power.
## Code
See the .ino file in this repo.
## Installation
- Edit the .ino file to modify the WiFi and MQTT settings to fit your environment.
- Set the IDE to use the "ESP32 Dev Module" board, or whatever fits your hardware.
- Upload the code to the board. You may need to hold a button after resetting to enter into flashing mode (see the hardware instructions).
- Plug in your moisture sensors according to this Fritzing wiring diagram (the 3-pin connectors represent the sensors; adjust accordingly to match the pins on your actual sensors. The ESP32 also may not match your ESP32; check the correct pinout for Analog Inputs):
![MultiSoilMoistureSensor_bb.png](MultiSoilMoistureSensor_bb.png)
- Plug the ESP32 into power if not already. Test the sensors with a piece of metal or a damp finger. The measurements should output via serial, OLED screen, and MQTT. By default it will refresh every 10 seconds, however in the future I'll likely greatly reduce this or even put the hardware into a long low-power sleep to save battery.
- Add the following to your Home Assistant configuration (presuming you have the MQTT integration configured and running properly; use MQTT Explorer to test):
```
mqtt:
sensor:
- name: "Plant 1 Water"
unique_id: esp_plant1
state_topic: "esp/plants/1"
qos: 2
unit_of_measurement: "%"
device_class: moisture
state_class: measurement
value_template: "{{ value }}"
- name: "Plant 2 Water"
unique_id: esp_plant2
state_topic: "esp/plants/2"
qos: 2
unit_of_measurement: "%"
device_class: moisture
state_class: measurement
value_template: "{{ value }}"
- name: "Plant 3 Water"
unique_id: esp_plant3
state_topic: "esp/plants/3"
qos: 2
unit_of_measurement: "%"
device_class: moisture
state_class: measurement
value_template: "{{ value }}"
- name: "Plant 4 Water"
unique_id: esp_plant4
state_topic: "esp/plants/4"
qos: 2
unit_of_measurement: "%"
device_class: moisture
state_class: measurement
value_template: "{{ value }}"
```
- Restart Home Assistant.
- Create a HA graph Card:
```
chart_type: line
period: 5minute
type: statistics-graph
entities:
- sensor.plant_1_water
- sensor.plant_2_water
- sensor.plant_3_water
- sensor.plant_4_water
stat_types:
- mean
days_to_show: 1
```
PRs, suggestions, and project photos welcome!