ESP32 reboots when reading voltage from INA219

I'm not sure whether I have faulty hardware or have missed something in the configuration...

I am adding a water sprinkler to my greenhouse ESP32. The solenoid is 12V but adafruit advise it works down to 6V. I don't want to drain my main LiPo by holding the solenoid open so thought I would use a common 9V battery for this - and of course to monitor the 9V battery voltage. I already have an INA3221 monitoring my LiPo voltage, and the INA3221 states it works up to 26V, so have wired it all up as here...

But ... when I switch the Latching Relay to make the connection, my ESP32 reboots.

I have swapped to a different Latching Relay, tried a INA219 (DFRobot Digital Wattmeter), and checked the wiring with multimeter. Curiously the INA219 reports Bus Voltage of 0.86V when the battery is not connected !

To start with, is my concept wrong ? Do the diagram and parts make sense ?

Disclaimer: I haven't checked your wiring - the diagram is incomplete and truncated. I'm going by your description of what happens.

Go back to the design stage and component choices.

Is the 9v battery able to satisfy the solenoid current requirements? As the voltage goes down, the current goes up. They are usually specified as 24V with a VA rating. Use Ohms law to work out the current requirements of your solenoid at 24v, 12v, and 9V. AC or DC operation (it usually doesn't matter)? Are you using that 9v battery because your rechargeable battery doesn't have enough grunt?

Is your wattmeter recording and reporting peaks, or just sampling? You may not be getting the whole picture from it. An analog (non-sampling) oscilloscope is the more appropriate tool for this where you can see short spikes in real time that sampling or a multimeter (analog or digital) can often miss.

Look at the data sheets of each and every component to check maximum current draw. You can then decide if it will work in circuit.

Are your power supplies connected correctly? Common where needed and not where shorts develop, especially with relays. Is your 9v battery life long enough to keep the solenoid closed?

Does your latching relay have dry contacts? Does it need to be powered at high current draw on both on and off modes? Is the pulse to toggle coming from the correct GPIO port? You havent showed any code.

Are you using your ESP32 in WiFi mode? Are you allowing for the extra current requirements during session times?

Is the ESP32 suitable for battery operation at all? See the discussion elsewhere in these forums regarding the letterbox monitor, and other threads regarding ESP sleep modes and low power operations.

What INA3221 module are you using ?? Some of them have a common ground on the sense pins.

Yes, that's because my goal was to power the solenoid from a different battery than the LiPo which is running the ESP32 and rest of the system - specifically to avoid many of the issues you raised.

My understanding is that (a) the power being switched by a relay is separate from the signals being used to do the switching; and similarly (b) the current being measured by an INA219 is separate from the i2c signals which report on the measurements. Thus the 9V battery circuit is simply 9V battery - measure by INA219 (or INA3221) - connection at the relay - power the solenoid - 9V battery.

If the 9V battery isn't enough to drive the solenoid then I expect the latching relay would still click as it changes (it does) but the solenoid doesn't open (I haven't got to testing it with water yet). I am having trouble seeing how closing the 9V circuit is causing the ESP32 to reboot

gaz99 i'm using the Adafruit INA3221 module through a local adafruit retailer.

You don’t have a GND connection from your 9v battery to the INA3221 module, if your diagram is correct all it will be able to measure from the battery is current. You would normally common up the GNDs for something like this. Doubt this would cause the ESP32 to reboot though.

Quick check to verify this: Disconnect the current sensor and have your solenoid connected only to the relay and battery.

Still reboots? You have a possible unrelated wiring or power issue.

Doesn't reboot? Your current sensor is probably not isolated from the other circuits. Check your wiring and the data sheet.

Another check: We are measuring by physical observation, not by automation. Disconnect the wires from your relay output. Bridge them. Does your solenoid pull in? Fast or sluggish? What happens with the rest of your circuit? How long does the solenoid stay activated? (Listen and peer down the solenoid pipe to watch the valve move, and feel the click with your fingers). Repeat and advise what (if anything) changes after a few attempts.

Your circuit drawing should include Esp and all power supplies. How are relay and INA powered?
Your battery positive should go to + terminal on INA, your image shows inverted.
Solenoid needs flyback diode.

Why don't you simply use latching solenoid like all commercial battery powered irrigation systems do?

I agree, the missing parts of the diagram hold the key to the conundrum.

Mainly to protect the current sensor semiconductors?

In the final operational circuit, I would expect the current sensors would be disconnected, having being used to confirm the device datasheet information is correct and being redundant.

The latching relay could become a simple FET/Transistor GPIO interface (with the obligatory resistor and diode) if the water solenoid valve became latching, and you would just send a suitably short pulse to toggle it.

The final result would be the realization that battery operation using an ESP may not be suitable, but that is further down the track, and a bit more research...

Thanks guys, a few things for me to follow up ... tomorrow.

  • Connect GND from the 9V battery to ESP32's GND
  • investigate "Latching Solenoid"

IOT7712 i have already noticed that the ESP32 reboot does not happen when the relay is closed, but a little while later when the first voltage measurement is taken ... so I expect the tests you suggest will confirm that it is the current sensor at issue.

Karosm I didn't use a latching solenoid because i'm trying to automate my little hobby greenhouse, and didn't know such a thing exists. My primary local supplier only stocks a couple of solenoid valves - none of them latching. Latching the solenoid should reduce power consumption enough that I could drive it off the main 6000mAh LiPo.

Since you already have all the components to get the job equally done, go with those.
Just disconnect INA for next test and you can narrow down the issue.

Maybe share your YAML code to get some extra eyes on it, too? I recently had an issue where I was printing into the log a boolean value without using a conversion on it (like ONOFF()) and that was causing a kernel panic/reboot condition -- it took me a bit of debug to determine that was the case and would have happened quicker if I had more eyes to review it.

Just a general comment:
Your requirements are not unique. There have been countless versions of sprinkler controllers using your components - a simple relay, solenoid valve, and ESP32, powered by a rechargeable battery and a solar panel. The things that stood out as different was use of the current sensor and 9v battery, making a simple thing complicated.

More information about your wiring will help clarify where it may be having issues. Your current monitor board is not necessary, and will draw extra current you can ill afford to lose. The device spec sheets will show you maximum and average current draw for your ESP32 and relay, and the sprinkler valve can be calculated by simple Ohms law and voltage and resistance measurement by your multimeter in series and parallel with your solenoid valve. Having a latching valve is an option, but you shouldn't need to go that route if you have adequate power for your circuit, and your 6Amps solar backed battery should be adequate for more than a few hours of operation.

says it uses 240mA

says it has ~500mAh

Says you might be able to get the solenoid valve to operate at least once, but likely not too many times.

A standard 9V battery uses the equivalent of AAAA batteries. They are not designed to deliver high current.

If you want a life of many months you need at least a 6V lantern battery. It uses cells that have more capacity than a D cell.

Six amps. Should last a lot longer than a 9V battery. Lantern batteries are one use and discard, unsuited for this requirement. Use an old car battery with some residual life if you are desperate and float charge it as necessary.

I agree, smoke detector battery is not practical with this hardware. On the other hand, battery powered irrigation with latching solenoid can easily make whole year with that. You draw power only ~0.5s to toggle the solenoid on or off.

OK. Disconnected the Wattmeters i2c and the ESP32 worked without reboot. I did note however (from checking voltage across the relay's A-COM-B connections) that the relay stayed in the A setting despite pressing the switch.
FYI here is the cut-down yaml for testing (the original greenhouse.yaml is 680 lines long)

###################################################################
#                                                                 #
#   To control the greenhouse I have an ESP32-S3-devkitC-1        #
#                                                                 #
###################################################################
#                                                                 #
# May 2026 - incorporate water module. the solenoid used to turn
#     the misting water on/off uses 12V, and this may be held ON
#     for fairly long periods of time - draining the battery. 
#   I could boost from 5V to 12V but this would drain the main LIPo 
#     battery even faster.  The Solenoid works with 6V-12V, so I 
#     think its worth trying a regula 9V battery.  Of course I will
#     want to monitor how long it lasts, so another voltage sensor. 
#   9V is outside the ESP32's ADC range so need a voltage divider 
#     and ADC pin or ads1115.  However INA3221 claims to range 
#     0-26V 2A - so lets use INA3221 channel 1 (was USB-In).
#                                                                 #
###################################################################

substitutions:
  devicename:     "test_9volts"
  deviceIP:       "124"                     # last octet of the IP Address
  update_interval_network:  2 min         # How often to measure and report network values
  update_interval_sensor:   60s          # How often to measure and report sensor values
  latching_switch_delay: 30ms            # how long a pulse to activate the latching relay

logger:
  level: DEBUG      # VERBOSE

packages:
  board: !include _common_esp32-s3-devkitc-1.yaml         # devkit from AliExpress
  wi-fi: !include _common_wifi.yaml

i2c:
  - id: i2c_control
    scl: GPIO12
    sda: GPIO11
    scan: true

switch:
  # power for the main control i2c
  - platform: gpio
    pin:  GPIO14
    id:   enable_i2c_control
    name: enable_i2c_control
    restore_mode: ALWAYS_ON

  # we have latching relay, with A and B switches 
  #     (which we use for ON and OFF respectively) which require a GPIO pin each.
  # - turning on latchswitch_on momentarily sends the pulse to latch COM-to-A, and 
  # - turning on latchswitch_off momentarily sends the pulse to latch COM-to-B (which is not connected, therefore off)
  # The template makes them look like an on/off switch, so the GPIO pins can be hidden
  - platform: gpio
    pin: GPIO21
    id:   mist_latch_on     # COMmon to A makes the connection = ON
    name: mist_latch_on
    restore_mode: ALWAYS_OFF

  - platform: gpio
    pin: GPIO20
    id:   mist_latch_off    # COMmon to B has no connection = OFF
    name: mist_latch_off
    restore_mode: ALWAYS_OFF


  # create a template to remember the state of the latching switch
  - platform: template
    id:   mist_relay
    name: Misting Latching Relay
    restore_mode: RESTORE_DEFAULT_OFF
    turn_on_action:
      - switch.turn_on: mist_latch_on
      - delay: $latching_switch_delay
      - switch.turn_off: mist_latch_on
    turn_off_action:
      - switch.turn_on: mist_latch_off
      - delay: $latching_switch_delay
      - switch.turn_off: mist_latch_off

sensor:
  - platform: ina219
    address: 0x44
    shunt_resistance: 0.1 ohm
    current:
      name: "INA219 Current"
    power:
      name: "INA219 Power"
    bus_voltage:
      name: "INA219 Bus Voltage"
    shunt_voltage:
      name: "INA219 Shunt Voltage"
    max_voltage: 32.0V
    max_current: 3.2A
    update_interval: 15s

  #
  # monitor the power, and warn if battery getting low
  #
  # INA3221 is essentially 3 of INA 219 in one module, default to 0x40 address
  - platform: ina3221
    address: 0x40
    i2c_id: i2c_control
    update_interval: 15s        # $update_interval_sensor
    channel_1:          # 9V power for water solenoid
      shunt_resistance: 0.1 ohm
      bus_voltage:
        id: water_voltage
        name: water Voltage
        accuracy_decimals: 2
    channel_2:          # Solar Panel
      shunt_resistance: 0.1 ohm
      bus_voltage:
        name: Solar Voltage
        accuracy_decimals: 2
    channel_3:          # record ALL of the actual battery voltage readings for later analysys
      shunt_resistance: 0.1 ohm
      bus_voltage:
        name: Battery Voltage actual
        id: batt_voltage_actual
        accuracy_decimals: 2
        filters:
          offset: 0.10

###############################################################################

esphome:
  name: $devicename
  platformio_options:
    board_build.flash_mode: dio 
  on_boot: 
    - priority: -100
      then:
      - logger.log: " "
      - logger.log: "##### on_boot -100 finished" 
      - logger.log: " "

  on_shutdown:
    - priority: -100
      then:
      # before everything else, while all is still operational
      - switch.turn_off:  enable_i2c_control    # save power by turning off i2c while asleep
      - logger.log: "##### on_shutdown -100 finished. " 

Thinking that this may be caused by my programming, I after moved the code to make pulses from the switch template to the individual switch GPIOs

  - platform: gpio
    pin: GPIO21
    id:   mist_latch_on     # COMmon to A makes the connection = ON
    name: mist_latch_on
    restore_mode: ALWAYS_OFF
    on_turn_on:
    - logger.log: "turn_on mist_latch_on"
    - delay: 30ms
    - switch.turn_off: mist_latch_on

... and that's when it got weird !

Welcome to minicom 2.9

OPTIONS: I18n 
Port /dev/ttyUSB1

Press CTRL-A Z for help on special keys

ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-20210327
ESP-ROM:esp32s�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP
-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-
202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:e
sp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ES
P-ROM:esp32s3-202�ESP-ROM:esp32s3-20210327�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:es
p32s3-202�ESP-ROM:esp32s3-20210327�ESP-ROM:esp32s3-20210327�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32
s3-20210327�ESP-ROM:esp32s3-20210327�ESP-ROM:esp32s3-20210327
[2026-05-24 15:41:23] ESP-ROM:esp32s3-20210327
[2026-05-24 15:41:23] ESP-ROM:esp32s3-20210327�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-20210327�ESP-ROM:esp32s3-20210
327�ESP-ROM:esp32s3-20210327�ESP-ROM:esp32s3-20210327�ESP-ROM:esp32s3-20210327
[2026-05-24 15:41:23] ESP-ROM:esp32s3-20210327
[2026-05-24 15:41:23] ESP-ROM:esp32s3-20210327�ESP-ROM:esp32s3-20210327�ESP-ROM:esp32s3-20210327�ESP-ROM:esp32s3-202�ESP-ROM:esp32s3-
202�

Got to take a few steps back.

Thanks Neel, that definitely suggests the 9V battery won't last long holding a regular solenoid open.
I found a DC 4.5V 1/2" Electric Solenoid Valve Water Flow Pulse Electromagnetic Valve Brass Solenoid Valve which I guess should do the job ... and it only needs 4.5V in 30ms pulses, so should be able to run off the main battery.

There's no voltage across relay contact.
You still haven't posted your wiring between Esp and rest of the circuit and how relay and INA are powered.

That one didn't specify how much current it needs. There was another one there that indicated the coil's resistance, which indicates it draws 500mA. If you have a big enough battery that might be okay.

Have you considered using a product that is more designed to do what you want?

The Sonoff Duo looks interesting and claims battery life of a year on AA batteries. I would guess that depends on the usage.

Since it is Zigbee and already supported by z2m, how to control it is already figured out.

It depends on your goal.

  1. Watering the plants?
  2. Figuring out how to use interesting technology to achieve some goal?
  3. Playing with electronics?

You got me ! I used the multimeter's continuity tester (without the battery connected) figuring that the relay should do the switching whether or not there is current flowing on the other side. I'm probably wrong about that too :frowning:

I'm guessing the issue is not that a few 30ms pulses will drain the 6600mAh battery, but that suddenly switching that much current may cause brownouts, especially as the battery power reduces ?

Sonoff Duo does look interesting ... unfortunately it is not yet available, and uses Zigbee2MQTT.
My hobby greenhouse is well out of range of the ZHA in my upstairs apartment, and I consider the wi-fi link to be questionable - so I prefer something to connect to my ESP32 directly.

It get the definite impression that quite a few members here assume that everyone sees HA as just a step towards the real objective of becoming a professional electrical/systems engineer. I have long been interested in technology, but at age 66 with my eyesight and unsteady hands I am interested in what the technology can do for me - preferably without inflicting my soldering iron skills on the world :wink:


I have recovered the ESP32 and reloaded my test program

###################################################################
#                                                                 #
#   To control the greenhouse I have an ESP32-S3-devkitC-1        #
#                                                                 #
###################################################################

substitutions:
  devicename:     "test_9volts"
  deviceIP:       "124"                  # last octet of the IP Address
  update_interval_network:  2 min        # How often to measure and report network values
  update_interval_sensor:   60s          # How often to measure and report sensor values
  latching_switch_delay: 30ms            # how long a pulse to activate the latching relay

logger:
  level: DEBUG      # VERBOSE

packages:
  board: !include _common_esp32-s3-devkitc-1.yaml         # devkit from AliExpress
  wi-fi: !include _common_wifi.yaml

i2c:
  - id: i2c_control
    scl: GPIO12
    sda: GPIO11
    scan: true

switch:
  # power for the main control i2c
  - platform: gpio
    pin:  GPIO14
    id:   enable_i2c_control
    name: enable_i2c_control
    restore_mode: ALWAYS_ON

  # I have a latching relay, with A and B switches 
  #     (which we use for ON and OFF respectively) which require a GPIO pin each.
  # - turning on mist_latch_on momentarily sends the pulse to latch COM-to-A, and 
  # - turning on mist_latch_off momentarily sends the pulse to latch COM-to-B (which is not connected, therefore off)
  # The template makes them look like an on/off switch, so the GPIO pins can be hidden
  - platform: gpio
    pin: GPIO21
    id:   mist_latch_on     # COMmon to A makes the connection = ON
    name: mist_latch_on
    restore_mode: ALWAYS_OFF
    on_turn_on:
    - logger.log: "turn_on mist_latch_on"
    - delay: 30ms
    - switch.turn_off: mist_latch_on

  - platform: gpio
    pin: GPIO20
    id:   mist_latch_off    # COMmon to B has no connection = OFF
    name: mist_latch_off
    restore_mode: ALWAYS_OFF
    on_turn_on:
    - logger.log: "turn_on mist_latch_off"
    - delay: 30ms
    - switch.turn_off: mist_latch_off


  # create a template to remember the state of the latching switch
  - platform: template
    id:   mist_relay
    name: Misting Latching Relay
    restore_mode: RESTORE_DEFAULT_OFF
    turn_on_action:
      - switch.turn_on: mist_latch_on
    turn_off_action:
      - switch.turn_on: mist_latch_off

sensor:
  - platform: ina219
    address: 0x44
    shunt_resistance: 0.1 ohm
    current:
      name: "INA219 Current"
    power:
      name: "INA219 Power"
    bus_voltage:
      name: "INA219 Bus Voltage"
    shunt_voltage:
      name: "INA219 Shunt Voltage"
    max_voltage: 32.0V
    max_current: 3.2A
    update_interval: 15s

  - platform: ina3221
    address: 0x40
    i2c_id: i2c_control
    update_interval: 15s        # $update_interval_sensor
    channel_2:          # Solar Panel
      shunt_resistance: 0.1 ohm
      bus_voltage:
        name: Solar Voltage
        accuracy_decimals: 2
    channel_3:          # record actual battery voltage readings for later analysys
      shunt_resistance: 0.1 ohm
      bus_voltage:
        name: Battery Voltage actual
        id: batt_voltage_actual
        accuracy_decimals: 2
        filters:
          offset: 0.10

###############################################################################

esphome:
  name: $devicename
  platformio_options:
    board_build.flash_mode: dio 
  on_boot: 
    - priority: -100
      then:
      - logger.log: " "
      - logger.log: "##### on_boot -100 finished" 
      - logger.log: " "

  on_shutdown:
    - priority: -100
      then:
      # before everything else, while all is still operational
      - switch.turn_off:  enable_i2c_control    # save power by turning off i2c while asleep
      - logger.log: "##### on_shutdown -100 finished. " 

and strangely toggling the mist_relay switch results on the latching relay being turned ON and ON

[2026-05-26 15:45:31] [D][wifi:2434]: Roam check skipped, signal good (-45 dBm, attempt 1/3)
[2026-05-26 15:46:20] [D][main:262]: turn_on mist_latch_on
[2026-05-26 15:46:33] [D][main:262]: turn_on mist_latch_on
[2026-05-26 15:46:39] [D][main:262]: turn_on mist_latch_on
[2026-05-26 15:46:43] [D][main:262]: turn_on mist_latch_on
[2026-05-26 15:50:31] [D][wifi:2434]: Roam check skipped, signal good (-47 dBm, attempt 2/3)
[2026-05-26 15:55:31] [D][wifi:2434]: Roam check skipped, signal good (-47 dBm, attempt 3/3)
[2026-05-26 20:42:39] [W][api.connection:2463]: ESPHome Logs 2026.5.0 (192.168.1.97): Reading failed CONNECTION_CLOSED errno=128
[2026-05-26 20:42:39] [D][main:113]: #####     >>>>>>>>>> API client disconnected!
[2026-05-26 20:57:36] [D][web_server_idf:626][httpd]: Event source connection closed (fd: 54)
[2026-05-27 16:17:18] [D][main:262]: turn_on mist_latch_on
[2026-05-27 16:17:23] [D][main:262]: turn_on mist_latch_on
[2026-05-27 16:17:27] [D][main:262]: turn_on mist_latch_on
[2026-05-27 16:28:02] [D][main:262]: turn_on mist_latch_on

Never mind. I have ordered the Latching Solenoid, and now that I know it exists there is no point using the non-latching version for my remote application.

Thank you guys for your assistance.