Closed peterbarbosa closed 3 months ago
Can you post your yaml here? I have a suspicion but I just want to confirm.
esphome:
name: ourdoor-plant-soil-1
includes:
- april_soil_sensor.h
libraries:
- Wire
esp32:
board: esp32-s2-saola-1
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
power_save_mode: none
mqtt:
broker: XXX.XXX.XX.XXX
username: {hidden}
password: !secret mqtt_password
logger:
level: DEBUG
sensor:
- platform: adc
pin: 7
attenuation: 11dB
raw: true
id: "vbatt"
name: "Battery Voltage"
update_interval: 30s
disabled_by_default: true
device_class: "voltage"
state_class: "measurement"
icon: "mdi:battery-outline"
accuracy_decimals: 2
entity_category: "diagnostic"
# derive battery percentage 3300mV=0%, 3950mV=100%
- platform: template
lambda: |-
float x = id(vbatt).state;
if (x < 3300) {
x = 3300;
}
if (x > 3950) {
x = 3950;
}
float y = (x - 3300) / 650 * 100;
return y;
name: "Battery Percentage"
update_interval: 5s
unit_of_measurement: "%"
device_class: "battery"
state_class: "measurement"
icon: "mdi:battery"
accuracy_decimals: 0
- platform: adc
pin: 9
raw: true
id: rMoisture
name: "Raw Moisture reading"
update_interval: never
unit_of_measurement: raw
disabled_by_default: true
state_class: "measurement"
icon: "mdi:water-alert"
entity_category: "diagnostic"
#derive moisture level 3800=100% 6800=0%
- platform: template
name: "Moisture Level (Instant)"
id: "iMoisture"
unit_of_measurement: "%"
update_interval: never
state_class: "measurement"
disabled_by_default: true
icon: "mdi:water-percent"
accuracy_decimals: 0
lambda: |-
float x = id(rMoisture).state;
if (x < 3800) {
x = 3800;
}
if (x > 6800) {
x = 6800;
}
float y = (x - 3800) / 3000 * 100;
y = 100 - y;
return y;
# average over 5 readings to smooth
- platform: template
name: "Moisture Level"
id: "aMoisture"
unit_of_measurement: "%"
update_interval: 5s
state_class: "Measurement"
icon: "mdi:water-percent"
accuracy_decimals: 0
lambda: |-
return id(iMoisture).state;
filters:
- quantile:
window_size: 5
send_every: 5
send_first_at: 5
quantile: 0.9
output:
- platform: ledc
pin: 17
frequency: 1500000Hz
id: moisture_gen
interval:
- interval: 1500ms
then:
- output.turn_on: moisture_gen
- output.set_level:
id: moisture_gen
level: 34%
- delay: 500ms
- component.update: rMoisture
- component.update: iMoisture
- component.update: aMoisture
- output.turn_off: moisture_gen
deep_sleep:
run_duration:
default: 1min
sleep_duration: 30min
wakeup_pin: 2
@illuzn here is the code for april_soil_sensor.h
#include "esphome.h"
#include "driver/adc.h"
#include "driver/ledc.h"
#include <esp_adc_cal.h>
#include <Wire.h>
// I2C address for temperature sensor
const int TMP_ADDR = 0x48;
const adc_channel_t MOISTURE_CHANNEL = ADC_CHANNEL_8; // GPIO9
const adc_bits_width_t WIDTH = ADC_WIDTH_BIT_13;
const adc_atten_t MOISTURE_ATTEN = ADC_ATTEN_DB_2_5;
#define LEDC_LS_TIMER LEDC_TIMER_1
#define LEDC_LS_MODE LEDC_LOW_SPEED_MODE
#define LEDC_LS_DUTY_RES LEDC_TIMER_3_BIT
#define LEDC_LS_CH0_GPIO (17)
#define LEDC_LS_CH0_CHANNEL LEDC_CHANNEL_0
// %50 duty: 2 ^ (LEDC_LS_DUTY_RES - 1)
#define LEDC_TEST_DUTY (4)
class AprilSoilSensor : public PollingComponent, public Sensor {
private:
float readTemp_() {
float temp;
Wire.beginTransmission(TMP_ADDR);
// Select Data Registers
Wire.write(0X00);
Wire.endTransmission();
// Request 2 bytes , Msb first
Wire.requestFrom(TMP_ADDR, 2);
// Read temperature as Celsius (the default)
while(Wire.available()) {
int msb = Wire.read();
int lsb = Wire.read();
int rawtmp = msb << 8 |lsb;
int value = rawtmp >> 4;
temp = value * 0.0625;
return temp;
}
return 0;
}
public:
Sensor *temperature_sensor = new Sensor();
Sensor *soil_sensor = new Sensor();
AprilSoilSensor() : PollingComponent(3000) {}
void setup() override {
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LS_MODE, // timer mode
.duty_resolution = LEDC_TIMER_3_BIT, // resolution of PWM duty
.timer_num = LEDC_LS_TIMER, // timer index
.freq_hz = 8000000, // frequency of PWM signal
.clk_cfg = LEDC_AUTO_CLK, // Auto select the source clock
};
ledc_timer_config(&ledc_timer);
ledc_channel_config_t ledc_channel = {
.gpio_num = LEDC_LS_CH0_GPIO,
.speed_mode = LEDC_LS_MODE,
.channel = LEDC_LS_CH0_CHANNEL,
.timer_sel = LEDC_LS_TIMER,
.duty = LEDC_TEST_DUTY,
.hpoint = 0,
};
ledc_channel_config(&ledc_channel);
//Configure ADC
adc1_config_width(WIDTH);
adc1_config_channel_atten((adc1_channel_t)MOISTURE_CHANNEL, MOISTURE_ATTEN);
const int sdaPin = 8;
const int sclPin = 10;
Wire.begin(sdaPin, sclPin);
delay(2000);
}
void update() override {
float temp = readTemp_();
temperature_sensor->publish_state(temp);
uint32_t adc_reading = adc1_get_raw((adc1_channel_t)MOISTURE_CHANNEL);
soil_sensor->publish_state(adc_reading);
}
};
Ive also tried your code and cant get the device to appear in MQTT integration on HA (why I originally found the other code).
Please read the instructions again:
1. Install ESPHome e.g. docker pull esphome/esphome (Tested and working upto v2022.11.5 - there are some issues with v2022.12.* and v2022.2.* bootlooping)
2. Copy default-template.yaml, testunit.yaml and secrets.yaml to your ESPHome folder e.g. on HomeAssistant this is /config/esphome/
3. Configure your secrets.yaml
4. Connect device via USB to your ESPHome host. Install firmware. Click the dropdown next to testunit and install. N.B. Do not install the default-template it will fail (it is only the template configuration). N.B. The device should automatically reboot into CDC mode to receive the firmware however if it does not you may need to hold the IO0 button down while pushing the EN button (the two black buttons on the right of the PCB).
5. Within around 30s logs should become available in ESPHome (and a new device should appear in HomeAssistant if you are using that).
6. (Optional) Depending on the type of soil you should calibrate your soil sensor. See the theory of operation section.
You can duplicate testunit.yaml as many times as you wish just remember to change the name of your device as well e.g. soil-sensor-1.yaml->device-name: "soil-sensor-1"
You are using this in a completely unsupported manner.
This works via the esphome integration (which uses direct HomeAssistant API access and is much faster/ more power efficient):
Seperately, if Im plugging the USB cable into the board to charge the battery, the unit only stays on for a few minutes then powers off (red LED turns off and MQTT does not get updates).
The red LED is only lit when the device is charging. This is internal behaviour on the PCB and cannot be altered in software.
When I use only the battery, the unit does not stay powered on.
This is by design, if you have it connected 24/7 your device will drain its battery in ~1 day. In fact, using your configuration, the battery will drain very quickly:
deep_sleep:
run_duration:
default: 1min
sleep_duration: 30min
wakeup_pin: 2
This runs the device for 1 minute every 30 minutes. For comparison, I run my device for 1 minute every 6 hours (this is plenty for soil moisture levels unless you have your plants next to a furnace). If you want it to be constantly powered you can set the
I have removed the board from the case to ensure it has proper connection for both battery and USB cable. When I have the battery unplugged and just the USB cable, it always reports to MQTT and red LED stays on.
With the battery unplugged the charging light will remain lit because it detects a battery voltage of 0V (and hence tries to constantly charge the battery).
I have no idea why the ESP32 remains running - it shouldn't do so, but I suspect you just have not hit the 1 min run_duration.
Amazing - I got this working! Thanks for the support!
Hello,
I have received 2 April Soil Moisture sensors. I have successfully programmed them and they seem to be reporting to HA/MQTT great.
When I use only the battery, the unit does not stay powered on.
Seperately, if Im plugging the USB cable into the board to charge the battery, the unit only stays on for a few minutes then powers off (red LED turns off and MQTT does not get updates).
I have removed the board from the case to ensure it has proper connection for both battery and USB cable. When I have the battery unplugged and just the USB cable, it always reports to MQTT and red LED stays on.
Any ideas on what can be happening?