Bitte um Review: Neuer Battery Code, Ausschalten bei Akku leer und MAX17055

Zum Thema LiFePO4 noch ein interessantes Video von Andreas Spiess.

@SZenglein Ich habe das Review nicht vergessen. Ist nur gerade so ein bisschen die Luft raus. Ich kümmere mich darum.

Ja ist von meiner Seite kein Problem. Kann auch total verstehen wenn dir der pull request etwas zu umfangreich ist. Die Änderungen haben sich einfach ein wenig ineinander verknotet :smiley:

Wenn du den pull lieber in kleinere Häppchen unterteilt haben willst sag einfach Bescheid.

Ich habe das Thema nicht vergessen und habe es lokal inzwischen nochmal gebrancht. Beim Drücken des Buttons des Drehencoders wird auf meinem Port-Expander-Lolin D32pro-PCB „rot“ angezeigt. Das passt so nicht; muss ich nochmal schauen, woran das liegt. Dann hast du ein paar neue NVS-Variablen eingeführt; da ist ein Copy’n’Paste-Fehler drin (das habe ich bei mir schon gefixt).

Port_Init() habe ich mal nach oben geschoben - das behebt das Problem, dass ich weiter oben hier schon beschrieben habe, dass man auf dem Lautsprecher nix hört nach dem Einschalten. Nur habe ich mit dem Lolin D32 pro in o.g. PCB so ein elendiges Problem, in das ich anderweitig auch schon gelaufen bin. Und zwar wird der Power-GPIO ja zuerst deklariert und im Anschluss (in deinem Code später) dann HIGH drauf geschickt. Ohne Kopfhörerplatine startet der D32 pro verzögert und mit Kopfhörerplatine gar nicht. Ich habe zwei D32 pro hier, wobei der Erste irgendwie einen „Schlag“ hat. Jedenfalls mit dem hatte ich im Code, der aktuell online ist, auch so ein Problem. Das habe ich in den Griff bekommen, wenn ich zwischen der Deklaration und dem Draufschalten von High kein delay() hatte:

Mir ist leider völlig unklar an was das liegt. Äußern tut sich das Ganze so, dass man die geschalteten 3.3 V messen kann, sie jedoch immer wieder einbrechen. Man hört das auch ganz ganz leise. Also irgendwie versucht er zu starten aber es klappt nicht.

Vielleicht hat irgendwer ja nen Tipp dazu. Ich hatte das so noch bei keinem anderen ESP32.

@SZenglein Was meinst du mit folgendem Kommentar?

Was spricht denn gegen System_RequestSleep() an dieser Stelle?. Das setzt System_GoToSleep = true und damit wird System_DeepSleepManager() durchlaufen und der ganze Shutdown-Prozess wird ausgeführt.

Und noch eine Frage: Für was steht eigentlich „SOC“?

Der gleiche Grund aus dem im Rfid code auch manuell esp_deep_sleep_start() aufgerufen wird. Die RequestSleep Funktion greift erst nachdem die ganze Initialisierung durch ist, also Wifi, Neopixel, etc. Es ist etwas problematisch wenn bei sehr geringer Batterie dafür Energie verschwendet wird, aber viel unschöner ist dass der ESPuino nur angeht um dann sofort wieder auszugehen.

Kurzgesagt: Weil ich an der Stelle sofort wieder runterfahren will.

SOC steht für State of Charge (der Batterie). Ist eben die Lingo von dem chip.

Ich fühle mich ein wenig schlecht weil du so viel Arbeit in diesen Pull steckst, aber das ist ja letztendlich deine Entscheidung.
Ich kann die nächsten Wochen dazu leider gar nichts beitragen, aber danach kann ich mir das ganze nochmal in Ruhe anschauen…

Nee, keine Angst. Ist jetzt nicht so, dass ich da seit Wochen stundenlang pro Tag dran hänge. Die Hardware-Probleme, die ich zuvor beschrieben habe mit diesem PCB, habe ich gestern mit einem zusätzlichen Kondensator gefixt bekommen. @tueddy Du hattest mir das ja auch mal in einer PM geschrieben, dass man das vielleicht machen sollte. Also mit 100 uF geht’s auf jeden Fall.

Da läuft halt auch die generische Spannungsmessung drüber. Daher wollte ich das einfach gerne verstehen.

Das mit der Spannungsmessung klappt doch, weiß nicht, was ich da beim letzten Mal falsch gemacht habe. Was mir nicht so gefällt, das ist die Umwidmung der Farben bei der Spannungsanzeige auf dem Neopixel. Orange ist jetzt critical und greift erst bei einer vergleichsweisen tiefen Spannung. Ich wollte das aber eher so als „halb voll“. Da werde ich nochmal ne Runde drüber nachdenken, wie wir da vorgehen.

Ansonsten muss statt „…Impl“ für mich da was Anderes hin. Ich bin immer sehr für sprechende Funktions/Methodennamen zu haben.

Wie auch immer: Wenn ich mit der Arbeit durch bin, dann werde ich zum Testen einen eigenen Branch aufmachen und die vielen Commits (von mir sind auch welche dabei) mittels eines Squash-Merge in einen einzigen packen.

@SZenglein Du hattest ja kürzlich die Power.cpp eingeführt. Geändert hat sich dabei, dass die Initialisierung des Power-Pins und das anschließende Beschalten nicht mehr zwei Anweisungen hintereinander sind. @compactflash verwendet ja mit dem LTC2954 einen Powerswitch und hat seit dieser Aufspaltung offenbar ein Problem mit seiner Complete.
@compactflash Vielleicht willst du nochmal kurz was dazu schreiben, was das Problem ist.

@biologist @SZenglein
Ich verwende auf meinem PCB den Einschaltkontroller LTC2954-1. Dieser wird über den Eigang KILL durch den Power-Pin mit LOW ausgeschaltet. Das passiert beim Aussschalten per Tastendruck durch die Software, über WebGui oder nach Zeit). Pin KILL liegt über einen Pullup 100kOhm an VBat. Bis zum Commit vom 13.01.2022 hat das immer funktioniert. Danach nicht mehr weil ca. 2 Sekunden nach Booten ein LOW-Impuls auf dem Pin Power erzeugt wird. Siehe Bild. Der LTC schaltet das Board wieder aus.


Gelb = Strahl1 3,3V
Blau = Strahl2 Pin Kill des LTC = Pin Power Espuino , liegt über Pullup 100kOhm an VBat .

In Ruhe , ausgeschaltet , liegt an Strahl 2 die Akkuspannung. Im Fehlerfall kommt ca. 2 Sekunden nach Einschalten oder Reset ein LOW-Impuls und dadurch die Abschaltung.

Mit der folgenden Änderung in der main.cpp (commit vom 20.2.2022) geht es wieder.

main.cpp

126 // If port-expander is used, port_init has to be called first, as power can be (possibly) done by port-expander
127 //Power_Init();
128 pinMode(21, OUTPUT);
129 digitalWrite(21, HIGH);

VG

Also verstehe ich das richtig, es muss immer HIGH anliegen damit der controller anbleibt und LOW damit er ausbleibt? Oder ist der Flankengesteuert?

Steuerst du mit dem Controller nur die Peripherie oder auch den ESP32?

Ursprünglich hatte ich in der Power_Init direkt poweroff aufgerufen damit der pin einen definierten Zustand hat. Aus deshalb da ich sicher gehen wollte dass alle Steuerausgänge richtig initialisiert sind bevor ich die Peripherie anschalte (Knacken am Verstärker z.B.)

Nach power_init ist der Pin nach @biologist Änderung einfach unitialisiert, kann schon sein dass der dann auch erstmal LOW gezogen wird.

Der Controller schaltet alles aus, also auch den ESP32. Genau das ist das Problem . Mein ESP32 geht nie in deep sleep da vorher in der Ausschalteroutine der LTC über Pin Power mit LOW getriggert wird und damit die 3,3V abgeschaltet werden . Der Pin liegt über einen Pullup immer an VBat , es geht auch mit den 3,3V . Habe ich probiert aber auf diesem PCB nicht umgesetzt.

Eigentlich müßte es nach deiner Beschreibung gehen , da der Pin durch den Pullup auf High liegt , es kommt aber ein LOW . Im Oszillogramm sieht das wie ein Impuls aus . Ob das so ist kann man nicht sehen weil die 3,3V dann weg sind und damit auch der ESP32.

Wie gesagt, ich schätze das ist der Zeitraum zwischen dem setzen des Pins als output und dem schreiben des Wertes. Dass INVERT_POWER auskommentiert ist nehme ich mal an, sonst klappt es natürlich nicht.

Das ganze ist halt mit der Annahme geschrieben dass es nur Peripherie betrifft, ich nehme an vorher hat das auch mehr oder weniger „durch Zufall“ mit dem LTC2954-1 funktioniert. Probier mal aus unter das pinMode(…) im unteren Code noch dein digitalWrite zu setzen, dann sollte alles wieder gehen.

void Power_Init(void) {
    #if (POWER >= 0 && POWER <= 39)
        pinMode(POWER, OUTPUT);     // Only necessary for GPIO. For port-expander it's done (previously) via Port_init()
    #endif
}

Man kann jetzt überlegen das wieder reinzunehmen, wobei mir eigentlich die Trennung von Peripherie und ESP32 Stromversorgung besser gefällt. Zum einen wegen dem Knacken des Lautsprechers das manchmal bei mir auftritt, zum anderen weil man z.B. auch die LEDs bei falschen wakeups (rfid, batterie leer) aus lassen möchte.

Wenn es nach mir ginge würde ich für solche Fälle in Power zusätzlich zu Power_PeripheralOn/Off noch Funktionen für Power_MainOn/Off hinzufügen und dementsprechend einen eigenen Pin definieren. Die Abstraktion für Power ist immerhin jetzt da und man könnte da einfacher Optionen hinzufügen als zwei im Grunde genommen verschiedene Anwendungsfälle mit einem Pin zu lösen (vielleicht baut ja mal einer eine Platine mit Einschaltkontroller und will trotzdem eine getrennte Peripherie-Steuerung, zum Beispiel um zwischen Standby und Aus zu unterscheiden).

Im Endeffekt sollte @biologist entscheiden was er supporten möchte bzw. welche Rolle für ihn der POWER pin spielt.

@SZenglein
So, ich habe, um nochmal auf das eigentliche Topic hier zurückzukommen, deinen Code gemerged. Im Nachgang habe ich:
a) Den Code noch etwas eingerückt.
b) Einen Bugfix im Bereich der Spannungsberechung vorgenommen (Faktor 100 zu viel)
c) Das automatische Abschalten, wenn der Spannungslevel kritisch ist, nach oben verschoben, damit das prominenter ist. Das war mir vorher, so als nachträgliche Änderung mit doch auch ordentlich Impact, so weit unten zu implizit.

Ansonsten passt das soweit.

2 „Gefällt mir“

Super, danke dir dafür. In BatteryMeasureVoltage hast du glaube ich aber ein wenig zu viel eingerückt ^^.

b) Naja wie man es sieht, von 0-1 oder als Prozentwert von 0-100, so lange man weiß was gemeint ist. Wurde ja daher in led.cpp auch durch 100 geteilt. Aber grundsätzlich natürlich egal.
EDIT: du hast recht, ich habe gerade nochmal nachgeschaut und gemerkt dass ich da selbst nicht konsistent war.

Ähh, ups :slight_smile:

Ja das Problem war, dass ein Wert wie z.B. 50 aus der Funktion rauskam, jedoch aber zB in Led.cpp mit 0.x verglichen wurde. Aber dafür teste ich das ja, hehe.

1 „Gefällt mir“

Hi @SZenglein @biologist
Geht natürlich auch so . Ohne LTC ist der Ruhestrom ca. 50 µA höher , das kann man verschmerzen .
Ich werde das mal testen ob es für mich in Frage kommt . Würde aber meine ganze Philosophie umwerfen .
Zu Tonuino-Zeiten hatte ich anfangs auch die Spannung mit einem Mosfet geschaltet. Habe lange gebraucht um da einen funktionierenden zu finden, der IRLML6401 ging, aber letztendlich hatte ich immer wieder das Problem dass bei Vollausteuerung und satten Bässen die Spannung einbrach und der Arduino hat gebootet . Ich habe das dann mit einem eigenen Netzteil und einem Spannungsregler mit EN-Eingang gelöst. Damals auch schon mit LTC. Die Endstufe war der HXJ8002 im DFPlayer-Mini und ein baugleiches IC den NS5140 verwende ich jetzt auch . Ich weiß nicht ob dann der alte Stress wieder anfängt…
Ich kann mit der momentanen Lösung gut leben und Knacken beim Einschalten ist selten und sehr leise und eigentlich nur im Kopfhörer etwas deutlicher .
Schauen wir mal…

Läuft das bei euch einwandfrei auch wenn man den MAX98357 mal fordert ?

Also ich habe keinerlei Probleme.

Wie gesagt, ich finde es ist nicht unbedingt eine schlechte Idee einen Einschaltcontroller zu haben, alleine schon weil man damit quasi einen reset hat sollte der ESP32 sich wirklich mal aufhängen (ist bei mir aber noch nicht aufgetreten, sauber programmiert :smiley:). Nur sollte man das meiner Ansicht nach im Code getrennt behandeln, wäre jetzt auch keine riesige Änderung.
EDIT: Hier mal ein quick and dirty commit wie ich mir das vorstellen würde, hat so aber noch wenig Mehrwert. add main power supply control switch · SZenglein/ESPuino@b800316 · GitHub

Ich habe mal wieder einen Pull Request eröffnet, danach sollte die Geschichte mit meinem MAX17055 dann auch endlich abgeschlossen sein ^^.

Das habe ich gestern auch integriert.

Hab mal angefangen mit einer Platine. Bin da kein Profi. Würde mich freuen, wenn ihr Euch das anschaut und gerne Rückmeldung zu Fehlern, Verbesserungen, Ideen…





1 „Gefällt mir“

Sieht sehr gut aus! Mir gefällt die „Kelvin“ Verbindung zum Messwiderstand. Sieht richtig aus :smile:

Hast du einen Grund dafür die Logikanschlüsse auf die andere Seite zu machen? Sonst würde ich eher alle Anschlüsse auf eine Seite legen.
Und wenn man schon eine Platine entwirft würde ich erwägen zwecks Flexibilität den Anschluss für den Thermistor rauszuführen.

Man könnte sich auch an der von dir verlinkten „Micro Fuel Gauge“ orientieren und alles noch etwas schrumpfen.