Probleme beim power_down() des HX711 unter ArduinoCore für ESP32

Bisher ist mir das noch nicht aufgefallen wahrscheinlich weil der ESP8266 (oder zumindest mein Huzzah) den Strom für die Wägezelle im deep sleep abdreht.

Nun ist mir aber aufgefallen, dass beim ESP32 (getestet mit TTGO T-Call und WiPy) scale.power_down(); der bogde-lib nichts bringt und z.B. der WiPy danach im deep sleep immer noch 8 mA verbraucht. Ohne angeschlossene Waage sind es etwas unter 20 uA und wenn ich vom HX711 den Strom abziehe sind es ebenfalls 20 uA.

Ich frage mich gerade, ob die 8 mA nur das high des SCK-pins sein können, siehe GitHub - bogde/HX711: An Arduino library to interface the Avia Semiconductor HX711 24-Bit Analog-to-Digital Converter (ADC) for Weight Scales. > Features

2. It provides a power_down() function, to put the ADC into a low power mode. According to the datasheet,

When PD_SCK pin changes from low to high and stays at high for longer than 60μs, HX711 enters power down mode.

Oder ob da was anderes nicht passt?

Immer dran denken, daß die GPIOs je nach Typ nicht ihren state im deep sleep maintainen. Wenn das aber gewünscht ist oder sein muß, daß müssen diese genutzen GPIOs in der RTC power domain sein und Du mußt sie vor dem sleep ‘einfrieren’:

Dein GPIO ändert also wieder seinen state, wenn der ESP pennen geht. Für Arduino müßtest Du also diese Definition laden:
#include <driver/rtc_io.h> , und dann mit rtc_gpio_hold_en(desired_GPIO_in_RTC_domain); rtc_gpio_deep_sleep_hold_en(); // danach schlafen schicken - Syntax kann abweichen ;) .

Referenz z.B. hier:

https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/gpio.html#_CPPv412gpio_hold_en10gpio_num_t

Hier zum Vergleich die derzeit verwendete Implementierung in MicroPython:

Danke! Habe zwischenzeitlich auch das hier gefunden

und versucht. Was auf Anhieb aber nicht ging, sondern ich habe die gleiche Fehlermeldung wie im issue bekommen. Nun habe ich aber auf den aktuellen ESP32-Arduino-Core upgedatet und nun läuft es (auch ohne #include "esp_sleep.h").

Allerdings läuft die Schose nach einem reset nur einmal durch, im deep sleep messe ich um die 50 uA! Nach dem Aufwachen scheint der aber nicht mehr in den deep sleep zu gehen obwohl ein scale.power_up(); das Ganze wieder antriggern sollte.

  scale.power_down();  // put the ADC in sleep mode

  // freeze SCK pin state in deep sleep 
  gpio_hold_en(GPIO_NUM_19);
  gpio_deep_sleep_hold_en();
  
  delay(10000);         // wait 10 s
  // ESP32 deep sleep 
  esp_sleep_enable_timer_wakeup(uS_TO_S_FACTOR * TIME_TO_SLEEP);
  esp_deep_sleep_start(); // sleep for ESP32 

Merkt der sich gpio_hold_ über den deep sleep-Zyklus und muss ich das irgendwo wieder deaktivieren? Eigentlich ja nicht: GPIO & RTC GPIO — ESP-IDF Programming Guide v4.1-dev-2039-g50466a5e4 documentation

when not in sleep mode, the digital gpio state can be changed even you have called this function.

Nochmal nachgemessen, und zwar bei E+ / E- am HX711-Ausgang mit angeschlossener Wägezelle, die bogde-lib schaltet die Spannung dort ab, wenn der WiPy auf dem extension board sitzt und das expansion board über USB mit 5 V versorgt wird. Stöpsle ich aber das USB-Kabel ab und versorge den WiPy über einen LiPo – entweder über das expansion board oder direkt über Vin / GND – hat die Wägezelle immer Strom, hmm seltsam?!

Nun habe ich mit gpio_hold_en bzw. gpio_deep_sleep_hold_en() den state auch im deep sleep festgetackert und das geschilderte Problem.

Wohl doch, wenn ich den code wie oben habe läuft das 1x durch und dann tut sich nichts mehr (vermutlich weil der HX711) durch den “festgestellten” pin nicht mehr initialisiert werden kann.

Wenn ich aber nun in setup()

gpio_hold_dis(GPIO_NUM_19);

aufrufe funktioniert es. Pffff!

Hier nochmal Verbrauchswerte des WiPys bzw. des HX711 mit / ohne Wägezelle

  • die Bosche H30-Waage und der HX711 verbrauchen ab scale.power_up();11 mA
  • wenn ich die Wägezelle abklemme braucht der HX711 alleine noch 3 mA
  • HX711 und angeschlossene Waage alleine nach scale.power_down(); und WiPy im deep sleep 450 n(!)A
  • der WiPy braucht mit nur deep sleep-sketch 15 uA
  • das Gesamtsystem aus WiPy, HX711 und Wägezelle braucht 45 mA wenn das System “wach” ist
  • im deep sleep braucht das Gesamtsystem 40 uA

Das ist doch Mist! D.h. der für die [edit, s.u.] scale.power_down();-Funktion auf high gehaltene SCK braucht 40 - 15 = 25 uA!! Echt Grütze!

Code dazu:

// timekeeping / deep sleep 
#define uS_TO_S_FACTOR 1000000  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  20        /* Time ESP32 will go to sleep (in seconds) */

// HX711
#include "HX711.h"

HX711 scale;
const int scalePinDout = 12;  // HX711.DOUT  
const int scalePinSck  = 13;  // HX711.PD_SCK
  
void setup() {
  // deactivate pin freezing after deep sleep 
  gpio_hold_dis(GPIO_NUM_13);
    
  // scale 
  scale.begin(scalePinDout, scalePinSck);
  scale.set_scale(22158); 
  scale.set_offset(-32625);
}

void loop() {
  // output weight 
  scale.power_up();
  float weight = scale.get_units(5); 
  delay(10000);
  scale.power_down();  // put the HX711 in sleep mode

  // freeze SCK pin state in deep sleep 
  gpio_hold_en(GPIO_NUM_13);
  gpio_deep_sleep_hold_en();
  
  // repeat every x seconds
  delay(5000);   // wait 5 s to see difference between scale.power_down(); und system deep sleep
  esp_sleep_enable_timer_wakeup(uS_TO_S_FACTOR * TIME_TO_SLEEP);
  esp_deep_sleep_start(); // sleep for ESP32 
}

A post was split to a new topic: HX711-breakout von Sparkfun, Stromverbrauch im deep sleep

zuvor noch:

wie kann das sein, wer sollte denn das sonst includen? wird das irgendwo implizit hereingeholt? Die von Dir verwendete Funktionen

esp_sleep_enable_timer_wakeup(uS_TO_S_FACTOR * TIME_TO_SLEEP);
esp_deep_sleep_start(); // sleep for ESP32 

werden schließlich aus esp_sleep.h bereitgestellt?!


BTW, in esp_sleep.h sehe ich gerade folgende Bemerkung in bezug auf die Funktion:
void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn));

Mit esp_deep_sleep(uint64_t time_in_us) kann man offenbar mindestens Schreibarbeit sparen.

1 Like

Gerade nochmal bei anderen Beispielen im Netz geschaut, die nutzen esp_deep_sleep[...] auch ohne explizites include von esp_sleep.h, ich vermute der ArduinoCore bindet das default ein.

Danke für die einzeilige Abkürzung!

wo hast Du denn eigentlich die Ströme gemessen - zwischen LiPo und seinen Anschluß auf dem Board?

Mindestens 1R18 kannst Du ablöten (das hatten wir hier festgestellt), das spart schon mal auch 25µA (auf dem 5V -rail namens “+5V”; siehe power tree).

Der Wert von 25 µA ist etwas verwunderlich, denn es ist nicht so ganz klar, wie der sich zusammensetzt:

  • 25 µA an 3,3V wäre ein 130 kOhm -R , die weak pull-ups im ESP32 haben aber eher zwischen ‘nur’ 30 - 70 kOhm (nominell 45 kOhm)
  • über die drive strength der GPIO im deep sleep ist leider nix bekannt: es waren mal 2 µA , das wurde wieder auf undefined geändert (finde Quellen dafür gerade nur für den ESP8266)
  • über input leakage ist natürlich im HX711-Datenblatt nichts zu finden (beim ADS1231 wären es ±10 µA)

Dann hilft also nur ein externer (very) weak pull-up: probiere doch mal 470k (ca. 7µA) oder 1 M (ca. 3,3 µA) von SCK nach 3V3. Vor dem Schlafengehen aber das pin von der IOMUX trennen, damit kein leakage current fließen kann, also irgendwie so hier:

rtc_gpio_isolate(SCK_GPIO)
esp_deep_sleep(..)

Ergänzung

Hier noch zwei Referenzen zu den entsprechenden commits im ESP-IDF:

Gedanken

Leicht off-topic bzgl. ArduinoCore, aber ich frage auch für einen Freund (MicroPython): Wir sollten das dann dort genauso machen, ja?

Sollte das dann bei allen GPIOs passieren, also von 0…N? Es scheint mir irgendwie auch für diejenigen relevant, die nicht nur für die Ansteuerung von Peripheriegeräten benutzt werden.


Referenzen

Ja high side mit dem CurrentRanger zwischen LiPo und dem Vin des WiPy.

Ich habe “als Referenz” erst mal beim WiPy gemessen, da man da weniger zusätzliche Teile hat und der als ESP32 board auch den kleinsten Verbrauch, soweit ich bisher recherchiert habe, hat. Die Werte stammen also nicht vom T-Call! Sorry, wenn ich da Verwirrung gestiftet habe!