ESP32-S2: need to adjust Brown Out Level at runtime

FiwiDev
Posts: 22
Joined: Wed Jan 22, 2020 12:32 am

ESP32-S2: need to adjust Brown Out Level at runtime

Postby FiwiDev » Sun Feb 04, 2024 2:38 am

This may sound a bit strange (but I'm known to "misuse" things all the time): I need to programmatically change the brown-out detector's setpoint from the application firmware.

In short: I have a short-term power backup system from a 3.0v ultracapacitor, followed by a boost converter. (The ESP32-S2 shuts off the boost converter after running shutdown tasks comprising several seconds...but the boost chip does not have a disconnect functionality, so this shutdown does not totally disconnect power to the ESP32-S2. Instead, the ESP32-S2 VDD will drop to ~2.9v, and then slowly drop to zero as the capacitor discharges over the next few minutes.)

The default ESP32-S2 brown-out voltage is perfectly fine for normal operation, where the WiFi/normal operation power spikes can easily cause brief transients on the VDD line--I am not having any issues with processor malfunction or unexpected brown-out resets. As a result, I do not want to change the DEFAULT brown-out voltage (then risking system instability). (My assumption is that this is ~2.43v, which is perfectly fine.)

The problem starts when the ESP32-S2 shuts down the boost converter. When this happens, the ESP32-S2 VDD is going to abruptly drop to <2.7v...but any capacitor/battery voltage will slowly rise after a large load has been disconnected. This has a serious potential to play "blinky lights" with the ESP32-S2's brown-out detector: when the ESP32-S2 is held in brown-out reset, the capacitor voltage will slowly rise until it is above the brown-out threshold...then the ESP32-S2 will start up (= pulling more power) and soon brown out again. Ad infinitum until the capacitor eventually discharges below the ESP32-S2 brown-out threshold.

However, if I programmatically set the brown-out detector threshold to 3.19v right before shutting off the boost converter (remember, the ultracap is 3.0v max), the ESP32-S2 is guaranteed to be held in brown-out reset until VDD reaches 3.30v. That will only happen when main power has been restored--and the resulting brown-out reset will reboot the ESP32-S2 with default configs, setting the brown-out detector back to the default (2.43v?)

In the ESP32-S2 Technical Reference Manual v1.1, I found the following info on page 273: Section 9.3.4.4 Brownout Detector (sorry, don't know how to embed images here, so I copied it):
I2C register ULP_CAL_REG5[2:0] configures the trigger threshold of the brown-out detector;
Table 63: Brown­out Detector Configuration
* ULP_CAL_REG5[2:0] - VDD (Unit: V)
* 0 - 2.67
* 1 - 3.30
* 2 - 3.19
* 3 - 2.98
* 4 - 2.84
* 5 - 2.67
* 6 - 2.56
* 7 - 2.44
Unfortunately, I haven't been able to find anything about this register anywhere else on the entire Internet. Heck, this post here likely will become the #1 Google search result simply by default! The closest I was able to find to the subject was this GitHub issue, which did indicate that it's set by the bootloader: https://github.com/espressif/arduino-esp32/issues/2580

It's not like the brown-out detector's setpoint is in eFuse, so it's not like there's hardware limitations for changing this brown-out detector voltage reference.
How do I change the brown-out detector voltage threshold at runtime?

FiwiDev
Posts: 22
Joined: Wed Jan 22, 2020 12:32 am

Re: ESP32-S2: need to adjust Brown Out Level at runtime

Postby FiwiDev » Mon Feb 05, 2024 2:40 am

Well, still digging...I'd be highly impressed if the "magic of AI" can piece things together like this...

First was to search the entire Github ESP-IDF repository for "Brownout", and start digging through the search results...
From https://github.com/espressif/esp-idf/bl ... ialization I found the following:
The main system initialization function is start_cpu0. [...]
The primary system initialization stage includes:

- Log information about this application (project name, :ref:`app-version`, etc.) if default log level enables this.
- Initialize the heap allocator (before this point all allocations must be static or on the stack).
- Initialize newlib component syscalls and time functions.
- Configure the brownout detector.
- ...
Digging further, I found the defs at https://github.com/espressif/esp-idf/bl ... brownout.h . That file mentions macros in https://github.com/espressif/esp-idf/bl ... i2c_ctrl.h which apparently do the actual work?
Now I just need to find an example of those macros being used for the brownout detector initialization...

A quick Github search later for "I2C_BOD_THRESHOLD" turned up https://github.com/espressif/esp-idf/bl ... t_ll.h#L67 ...aha, there's the magic call for adjusting the brown-out voltage threshold point! The header file has warnings "not for application use", but that never stopped me!

Searching further, I found that the forbidden "brownout_ll_set_threshold" is called from https://github.com/espressif/esp-idf/bl ... _hal.c#L20 . So...what calls "brownout_hal_config"??

https://github.com/espressif/esp-idf/bl ... nout.c#L67 . Well, isn't that special: that's where the brownout voltage threshold is set to the hardcoded value determined at compile-time by the SDKCONFIG file!

I'm not seeing anything "special" (such as a mutex) around the forbidden "brownout_ll_set_threshold". The macros in "brownout_ll.h" are mask-writing the bits, so there isn't going to be problems with overwriting other flags. I honestly don't see any reason it should be "forbidden"...actually, it looks like it's the call to make to accomplish the necessary end goal!

boarchuz
Posts: 611
Joined: Tue Aug 21, 2018 5:28 am

Re: ESP32-S2: need to adjust Brown Out Level at runtime

Postby boarchuz » Mon Feb 05, 2024 4:36 am

FiwiDev wrote:
Sun Feb 04, 2024 2:38 am
However, if I programmatically set the brown-out detector threshold to 3.19v right before shutting off the boost converter (remember, the ultracap is 3.0v max), the ESP32-S2 is guaranteed to be held in brown-out reset until VDD reaches 3.30v.
What is guaranteeing this? I would expect an immediate brownout reset, which would reset all registers to defaults. You also need to handle the case where supply voltage is below recommended minimums in the datasheet. If S2 is anything like ESP32, it may even fail to start without a clean reset signal on the enable pin. Consider an external voltage supervisor, there are many that work in the <300nA range.

FiwiDev
Posts: 22
Joined: Wed Jan 22, 2020 12:32 am

Re: ESP32-S2: need to adjust Brown Out Level at runtime

Postby FiwiDev » Mon Feb 05, 2024 3:28 pm

boarchuz wrote:
Mon Feb 05, 2024 4:36 am
FiwiDev wrote:
Sun Feb 04, 2024 2:38 am
However, if I programmatically set the brown-out detector threshold to 3.19v right before shutting off the boost converter (remember, the ultracap is 3.0v max), the ESP32-S2 is guaranteed to be held in brown-out reset until VDD reaches 3.30v.
What is guaranteeing this? I would expect an immediate brownout reset, which would reset all registers to defaults. You also need to handle the case where supply voltage is below recommended minimums in the datasheet. If S2 is anything like ESP32, it may even fail to start without a clean reset signal on the enable pin. Consider an external voltage supervisor, there are many that work in the <300nA range.
Well, a chip can technically be held in "reset" state indefinitely--but AFAIK hardware register defaults aren't applied until the reset is released and the processor starts to initialize.

If the brownout-reset being triggered ON also resets the brownout-reset threshold, that would logically render the brown-out reset functionality completely useless, no?
If there's a hardware reset state for the brownout-reset threshold (not mentioned in the technical reference manual), it would--at least in my mind--only "reset all registers" when the brownout-reset op-amp RELEASES the internal reset signal, and the processor is allowed to start. Of course, the ESP bootloader will also reset the brownout threshold.

I guess I have some testing to do ;-)

FiwiDev
Posts: 22
Joined: Wed Jan 22, 2020 12:32 am

Re: ESP32-S2: need to adjust Brown Out Level at runtime

Postby FiwiDev » Fri Feb 09, 2024 3:39 pm

Quick test with the default setpoint (== 7, or 2.44v) worked perfectly as expected (lit an LED green). Power On Reset was normal...lowered the voltage down until it hit 2.40v, at which point the chip blanked out (LED went out). At 2.5v, the chip cleanly restarted with a brown-out error code (LED lit red).

However, that's where the good news came to an abrupt end...

With the brown-out reset set to 2 (= 3.19v), Power On Reset was normal at 3.3v.
But at 3.1v, it goes into an infinite crash-reset loop (with a "brown-out" reset code)...which is precisely what I was hoping to avoid by adjusting the brown-out reset peripheral's trigger threshold.

Guess that means that the brown-out peripheral is borderline useless. If it won't hold the chip under RESET condition until VCC exceeds the threshold, then any processor in a poor-power environment is doomed to infinitely reset.


I may have better luck by disabling the brown-out reset itself, and put the chip into a sleep loop, where every (x) seconds it checks the brown-out reset status output, and upon exceeding the threshold, it self-resets.

Craige Hales
Posts: 94
Joined: Tue Sep 07, 2021 12:07 pm

Re: ESP32-S2: need to adjust Brown Out Level at runtime

Postby Craige Hales » Fri Feb 09, 2024 4:37 pm

I've got a similar project, thanks for the idea about enabling/disabling the converter.
In my case I think I'm going to have to add an external reset button. 15F of super-capacitor decays very slowly after the ESP32 shuts down, maybe hours around 2 volts. It prevents a normal restart when the power is restored; "unplug for 10 seconds" is not enough!
Craige

FiwiDev
Posts: 22
Joined: Wed Jan 22, 2020 12:32 am

Re: ESP32-S2: need to adjust Brown Out Level at runtime

Postby FiwiDev » Fri Feb 09, 2024 4:42 pm

Grr....this chip is guaranteeing I can't have my cake and eat it too...

If I disable the brown-out resetting ability, and instead use the output ("RTCCNTL.brown_out.det" from "soc/rtc_cntl_struct.h") to control code behavior, it works quite beautifully.
That is, until I drop below 1.9v (chip blackout--curiously, significantly lower than the default 2.4v brown-out reset threshold). You guessed it: upon bringing the voltage back up to 3.3v, the ESP32-S2 fails to restart, and is in an unrecoverable state. (Which with the brown-out detect enabled at the default 2.43v, it DOES recover when brought back to 3.3v)

Power consumption at 3.3v is ~130mA. Below 2.2v, power consumption abruptly drops by ~70mA to 34mA--some large subsystem cutting out. (It still works fine if brought back to 3.3v.) At 1.8v, it suddenly drops further to ~3mA--but is unrecoverable upon bringing the voltage back up.
When bringing the voltage back up, there's the ~70mA jump at 2.8v, but the chip does not reset.

EDIT: Reverted the brown-out reset settings to the defaults (i.e. removed the code to change them). Turns out that the chip fails to boot if slowly brought up from 1.8v even with the default settings. In this case, yes, I concede that a power-on-reset supervisor WOULD do the trick of ensuring the chip is usable; however, it does not take the place of an adjustable brown-out reset internal circuit.
Last edited by FiwiDev on Fri Feb 09, 2024 5:12 pm, edited 1 time in total.

FiwiDev
Posts: 22
Joined: Wed Jan 22, 2020 12:32 am

Re: ESP32-S2: need to adjust Brown Out Level at runtime

Postby FiwiDev » Fri Feb 09, 2024 4:52 pm

Craige Hales wrote:
Fri Feb 09, 2024 4:37 pm
I've got a similar project, thanks for the idea about enabling/disabling the converter.
In my case I think I'm going to have to add an external reset button. 15F of super-capacitor decays very slowly after the ESP32 shuts down, maybe hours around 2 volts. It prevents a normal restart when the power is restored; "unplug for 10 seconds" is not enough!
The main problem in my case is the boost converter from the ultracap: I used an MT3608, which is a nonsynchronous converter. I totally forgot about the "passive pass-through" in non-synchronous converters (Vin -> inductor -> diode -> Vout), even when the "EN" pin is low.
However, if you use a synchronous boost converter, there's a separate problem: if the boost converter setpoint voltage differs from the power rail voltage in normal operation, it WILL push or pull power from/to the ultracap all the time--resulting in either overcharging or outright discharging the ultracap! (If the boost converter setpoint is higher than the rail, it'll backfeed power into the ultracap. And if the boost converter setpoint is lower than the rail, it'll pull power from the ultracap.)

I found what appeared to be the perfect boost converter (non-synchronous with power disconnect), but it turns out that the "0.9A switch current limit" renders it totally useless: it can boost 3.0v to a maximum of 5v @ ~50mA according to Ti's Webench! (I'm purposely not linking it here.)

It's possible to use a disconnect FET (AO3401 P-channel FET a possibility), but the problem here is that pulling the gate to ground (via ESP32 GPIO) is only going to give you ~3v max potential...and the FET resistance will be pretty high, resulting in a significant voltage loss to the boost converter, which in turn reduces the maximum boost converter output power.

Best bad choice at the current time appears to be to use a synchronous converter (TPS61023)...and hoping that the ESP32 application code is quick enough to detect a power loss & switch the converter on BEFORE ESP32 brownout.

MicroController
Posts: 1750
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32-S2: need to adjust Brown Out Level at runtime

Postby MicroController » Fri Feb 09, 2024 9:05 pm

Another potential option: "5V" ultracap (2x 2.5V in series) hooked up directly to 3V3

FiwiDev
Posts: 22
Joined: Wed Jan 22, 2020 12:32 am

Re: ESP32-S2: need to adjust Brown Out Level at runtime

Postby FiwiDev » Fri Feb 09, 2024 11:52 pm

MicroController wrote:
Fri Feb 09, 2024 9:05 pm
Another potential option: "5V" ultracap (2x 2.5V in series) hooked up directly to 3V3
That doesn't solve the problem of the ESP32 brown-out module being effectively useless. (Also worth noting that boost converter ICs are significantly cheaper than ultracaps: TPS61023 with true disconnect functionality is ~$0.23 + associated parts, and the 3.0v 20F ELDC low-ESR ultracap I am utilizing comes in at ~$1/ea.)

Another thing to keep in mind is that "directly to 3V3" will put a considerable load on the 3.3v rail when the capacitors are completely empty. (That of course is assuming that the ultracaps have a low ESR--which they have to be in order to be able to power the ESP32 without causing random crashing due to chip brownout. The EDLC ultracap I have is rated 50mOhm [0.05 ohms], and Ohm's Law states 3.3v across 50mOhm will pull a cool 66 amps!)


boarchuz wrote: If S2 is anything like ESP32, it may even fail to start without a clean reset signal on the enable pin. Consider an external voltage supervisor, there are many that work in the <300nA range.
As a result of the tests I've run, I've concluded that this is unfortunately the required solution: an external reset supervisor to force-hold the ESP32-S2 in reset when VDD is below 2.5v. My quick-and-dirty solution for the interim likely will be a TL431 (=2.5v) and a transistor to invert the signal; next will be revising the design to include a reset supervisor.

The root of the problem is that the brown-out module is effectively useless--which is what causes the ESP32 to fail to boot if it doesn't have a clean reset signal.
If by implementation, the ESP brown-out module would permanently hold the chip in reset when VDD < threshold (note that the lowest current brown-out threshold setting is 2.43v, which is perfectly fine), this combined with the existing power-on-reset timer would provide a solid baseline for functional operation. There actually doesn't even need to be a brown-out-threshold hardware default, as any of the values are fine for a 3.3v rail--it can be configured (as currently) in the bootloader to whatever value is desired.

Who is online

Users browsing this forum: Baidu [Spider], Majestic-12 [Bot] and 70 guests