Lolin D32 pro mit SD_MMC, PN5180, max. fünf Buttons und Port-Expander (SMD)

Da via AliExpress die Post noch unterwegs ist und mir bei der letzten Lieferung Brückengleichrichter anstelle 6401 geliefert wurden + die freundliche „Mosfet-Hilfe“ von @compactflash auch schon eine Woche bei der Post hängt und weil bei Reichelt der 6401 nicht beikommt (Liefertermin ist 10/2022 wie ich vorhin per Telefon erfahren habe, obwohl im Webshop lieferbar steht), habe ich zwischenzeitlich via Ebay 20 Stk. 2244 geordert. Die kamen zu meiner Freude endlich gestern und ich habe gleich 9 davon direkt eingelötet. Das mache ich sonst NIE ohne zu testen, aber da ich keine Bauteile und keinen PCB geändert habe, fühlte sich das diesmal ok an.

Ergebnis: Ich sehe schon beim Einschalten, dass der Neopixel leicht flackert; dazu fiese Störungen auf der Kopfhörerplatine. Geschaltete Spannung gemessen: 2,6 V.

Blick auf den Code:


Und Blick ins Datenblatt verrät: U = IRLML6344 (N-Mosfet).

Also manchmal läuft’s einfach…

Übrigens habe ich dabei auch gelernt, dass ich die ganze Zeit IRML geschrieben habe und nicht IRLML. Zungenbrecher! :joy:.

Es gibt inzwischen eine neue Version 3.2. Unterschiede zu 3.1 sind:

  • Unten habe ich noch zwei Leiterbahnen zur Seite gezogen.
  • Die Beschriftung von JLCPCB liegt jetzt unterhalb des Port-Expanders, so dass man das nach dem Einlöten nicht mehr sieht.

Was ich leider vergessen habe, ist den Beschriftungstext für die Widerstände R7/R8 zu korrigieren. Da war ja ein Fehler drin unten in der Beschriftung der Gain-Selection.

Gelötet sieht es dann so aus:

Hallo,
sind von den PCBs noch welche Verfügbar? Ich glaube ich probier’s erstmal mit dem Lolin D32 Pro aus bevor ich mich an das schlecht dokumentierte TTGO Teil wage.

@aelray Habe dir eine PM geschrieben.

Mir ist vor ein paar Tagen mit diesem PCB noch ein kleines Problem aufgefallen, das mir bisher so nicht bekannt war. Und zwar gibt es ja den Pin HP_DETECT, der erkennt, ob eine Kopfhörerplatine angeschlossen und in deren Buchse ein Klinkenstecker eingesteckt ist. Ist kein Stecker eingesteckt, so wird HP_DETECT dauerhaft über einen 10k-Pullup-Widerstand, der auf der Kopfhörerplatine sitzt, auf 3.3 V „gezogen“. Umgekehrt wird er auf GND gezogen, wenn ein Stecker eingesteckt ist. Bei allen PCBs, die ich zuvor gemacht habe, war HP_DETECT an einen eigenen GPIO angeschlossen, hier jedoch am Port-Expander. Der Port-Expander besitzt 16 I/Os und bei allen Anschlüssen, die als Input konfiguriert sind (per Default sind das alle - man muss Outputs explizit in Software konfigurieren), überwacht er kontinuierlich, ob sich ein Signalzustand ändert. Ist das der Fall, so wirft er einen Interrupt, den der ESP32 registriert. Über diesen Mechanismus weckt man den ESP32 aus dem Deepsleep auch auf.

Problem:
Geht der ESP32 in den Deepsleep, so schaltet die Mosfet-Schaltung u.a. an der Kopfhörerplatine die 3.3 V weg. Aufgrund verschiedener Querströme, die es dann noch gibt, ist die 3.3 V-Schiene dann jedoch nicht spannungslos, sondern pendelt sich so bei 0.7 / 0.8 V etwa ein. Ist nun kein Klinkenstecker eingesteckt, wenn der ESP32 in Deepsleep gehen soll, so erzeugt dieser Vorgang offenbar kurzzeitig ein Floating, das dazu führt, dass der Port-Expander einen Interrupt wirft und der ESP32 sofort wieder aufwacht. Blöd.

Weiterhin:

  • Ist ein Stecker eingesteckt, so gibt es dieses Problem nicht. Weil dann wird HP_DETECT stabil auf GND gezogen.
  • Ist ein Stecker eingesteckt und er wird im Deepsleep ausgesteckt, so wacht der ESP32 nicht auf. Das ist auch der Grund, weswegen ich „kurzzeitiges Floating“ oben geschrieben habe.
  • Interessanterweise scheint das Problem beim PCA9555 (von NXP) nicht aufzutreten, während das aber beim PD9555 der Fall ist. Ich habe meine Port-Expander immer beim gleichen Händler bestellt und zuerst PCA9555 erhalten, zuletzt jedoch PD9555. Die scheinen sich an dem Punkt offenbar einen „Tick“ zu unterscheiden.

Gar nicht so einfach…
Auf meiner Kopfhörerplatine gibt es den Widerstand R17, den ich bisher unbestückt gelassen habe. Lötet man hier einen 10k-Widerstand ein, so ist das Problem weg. Ich kann den R17 jedoch in die Kopfhörerplatine nicht einfach immer einlöten, weil wenn jemand die Kopfhörerplatine ohne ein Board mit Port-Expander verwendet, so würde dieser 10k-Widerstand MAX98357a.SD auf GND ziehen und es käme kein Ton mehr aus dem Lautsprecher. Umgekehrt tritt der Fehler bei solchen Boards aber auch gar nicht auf, so dass man den R17 hier ohnehin nicht benötigt. Man muss also abwägen, welcher Fall vorliegt.

Fix:

  • Im Bereich des IDC-Konnektors kann man zwischen zwei Pins extern einen 10k-Widerstand löten. Verwendet man die die Kopfhörerplatine auf Basis des PCM5102 so ist dies sogar notwendig, weil man das Problem nicht anders in den Griff kriegt (da gibt es keinen „R17“).
  • Verwendet man die Kopfhörerplatine auf Basis des UDA1334, so kann man sich aussuchen, ob man den Widerstand R17 einlötet oder ob man einen Widerstand unten an den IDC-Konnektor lötet. Problem mit dem R17 ist so ein bisschen, dass er zwischen dem IDC-Konnektor und der Kopfhörerbuchse liegt und man da ohne Auslöten der IDC-Buchse nicht wirklich drankommt. Ja, mit heißer Luft schon, aber dann schmilzt der IDC-Konnektor weg.
  • Für künftige Revisionen für PCBs für den Lolin D32 pro werde ich direkt auf dem PCB einen Widerstand vorsehen, der im Bereich des IDC-Konnektors liegt. Ist dieser eingelötet, so braucht’s keinen R17 mehr und man kann die Kopfhörerplatine universal verwenden.

Edit: Wie in den nachfolgenden Beiträgen beschrieben, führt 10k anderweitig zu Problemen. Ich bin jetzt letztlich doch wieder bei der Variante ohne R17 gelandet und habe es in Software gelöst, indem ich den Pin am Port-Expander kurz vor dem Shutdown auf Output schalte. Damit kann der „falsche“ Interrupt nicht mehr ausgelöst werden.

wenn ich deine Ausführungen richtig verstehe, tritt das „Problem“ aber nur auf wenn überhaupt eine KH-Platine vorhanden ist?

D.h. wenn kein KH-Platine da, alles läuft wie erwartet?

(btw ich hab über 1V an den abgeschalteten 3,3V, der ESP scheint aber nicht wieder aufzuwachen (LEDs bleiben aus))

Ja, korrekt. Und mit KH-Platine offenbar auch nur dann, wenn ein PD9555 und kein PCA9555 verwendet wird.

Ich hatte die Tage übrigens ne Mail von einem User, bei dem hat der MAX keinen Ton gemacht. Am Ende kam raus, dass der unsauber gelötet war (also der SMD-Chip selbst - nicht das gesamte Modul) und es eine Lötbrücke gab. Hatte hier bestimmt schon 50 solcher Module in der Hand, aber das hatte ich noch nie.

Man lernt nie aus, hehe.

Meldet euch gerne, wenn ihr da Probleme habt - da finden wir eine Lösung.
Allerdings hält sich die Anzahl der Kopfhörerplatinen, die ich rausgeschickt habe, bisher in Grenzen (keine zehn Stück). Insofern betrifft dieses Problem potentiell auch eh nur wenige User. Aber ich möchte halt schon so transparent sein, dass ich etwaige Probleme hier offen mitteile.

2 „Gefällt mir“

Ich glaube ich muss an der Stelle doch nochmal mit dem Wert des PullDown-Widerstands (R17) experimentieren. Wie mir heute aufgefallen ist, kommt es sporadisch kurz zu Aussetzern. Ich höre ja fast immer Webstreams und dachte es läge daran, dass der Stream kurz aussetzt. Aber tatsächlich ist es so, dass 10k im laufenden Betrieb das Ganze offenbar zu weit runterzieht, so dass immer mal wieder kurzzeitig (1s) erkannt wird, dass ein Kopfhörer eingesteckt ist, obwohl das gar nicht der Fall ist.
Vielleicht teste ich mal 15 bis 20k.

ich vermute mal die Platine für mich die letztens rausging, fällt unter die fehlerbehafteten oder? :sweat_smile:

Im Grunde hätte ich das Thema vielleicht eher im Thread mit der Kopfhörerplatine aufmachen müssen. Also mit dem PCB hier gibt’s kein Problem. Das Problem geht eher von der Kopfhörerplatine aus. Hier geht’s einfach drum, beim Übergang in den Deepsleep für einen definierten Zustand zu sorgen.
Insofern: Ohne Kopfhörerplatine gibt’s kein Problem :slight_smile:.

Ich habe HP_DETECT gerade mal gemessen gegen GND und das sind 2,24 V. Das Datenblatt des PCA9555 sagt, dass für logisch HIGH auf einem Eingang des Port-Expanders mindestens eine Spannung anliegen muss, die Versorgungsspannung * 0,7 entspricht. Das wären dann 2,31 V. Das passt dann ja gut zu dem, wie sich das Ganze verhält: Es ist gerade so an der Grenze und „kippt“ manchmal.

Edit:
R17=15k hebt die Spannung von HP_DETECT auf 2,5 V und behebt das Problem weitgehend. Ich werde es mit 20k nochmal testen.

Edit2:
R17=20k hebt die Spannung von HP_DETECT auf 2,65 V. Scheint ok zu sein.

Edit3:
R17=30k hebt die Spannung von HP_DETECT auf 2,83 V. Ist dann ein halbes Volt über der Minimalspannung. Ich denke da kann man mit leben. Passt.

Never ending story irgendwie.
Mit 30k lief zwar der Betrieb 100% reibungslos, aber das Pulldown war damit im Gegenzug wieder zu schwach, so dass es immer wieder zum Aufwachen kurz nach dem Einschlafen kam. Grrr.

Ich habe mir dann nochmal (als ich schon im Bett war, hehe) das Datasheet des Port-Expanders hergenommen und kam zu einer anderen Lösung: Ich konfiguriere kurz vor dem Shutdown den Input-Pin für HP_DETECT am Port-Expander zu einem Output-Pin um. Weil ein Output-Pin kann zu keinem Interrupt führen, wenn eine Signaländerung stattfindet.

Das habe ich heute Morgen gut 25mal getestet und es kam zu keinem erneuten Aufwachen. Auch dann nicht, wenn gar kein Pulldown-Widerstand vorhanden ist.

Im Prinzip ist diese Vorgehensweise etwas, was man auch als Feature nutzen könnte. Weil Stand jetzt ist es ja so, dass alle Buttons, die am Port-Expander angeschlossen sind, den ESP32 aufwecken können. Wenn man das einschränken möchte auf vielleicht nur einen Button oder zwei Buttons, so sollte das mit der gleichen Vorgehensweise (Umkonfiguration auf Output) möglich sein. Könnt ja mal schreiben, ob ihr an sowas Bedarf hättet.

bei einem Button würde dann aber ein „Kurzschluss“ zwischen dem Out und GND kommen, wenn einer drauf drückt…

Kann sein das der PE das verträgt… bzw. dann den Strom begrenzt hoffentlich…

Aber nicht, wenn man bei OUT den Pegel nicht auf HIGH schaltet. Also OUT heißt nicht automatisch, dass da 3.3 V rauskommen. Ich würde hier natürlich LOW setzen und bei GND auf GND passiert dann nix.

Im Datasheet steht, dass man extern für Strombegrenzung sorgen muss. Für den Fall Input ist das offenbar kein Thema, weil man hier intern halt nur einen schwachen (was auch immer das heißt) PullUp-Widerstand hat. Aber bei OUTPUT sieht das wohl anders aus, da hier offenbar dann wirklich GND draufgeschaltet wird.

Also ich denke mal es hat schon seinen Grund, warum alles per Default auf INPUT geschaltet ist. Vermutlich ist das ein Zustand, der Schäden am PCA unwahrscheinlich(er) macht. Wenn man das auf OUTPUT schaltet, dann wäre es vermutlich schon besser, da Widerstände reinzumachen, so dass auch bei Fehlbedienung keine Ströme entstehen können, die den PCA kaputt machen.

klar stimmt einfach auf GND ziehen, löst das Problem :smiley:

Deshalb hab ich den Port-Expander AW9523BTQR für mein Board im Visier. Da ist die Interrupt Möglichkeit für jeden Port einstellbar. und zudem zu einem 10tel des PCA zu haben :wink:

Das ist natürlich nicht schlecht.

Das gilt aber auch nur für JLCPCB, wo der AW… aktuell nicht verfügbar ist. Dass der PCA bei JLC so teuer ist, scheint mir am Chipmangel zu liegen. Der Preis dort ist derzeit tatsächlich echt übel.
Bei AliExpress unterscheiden die sich preislich auf jeden Fall kaum.

So, ich habe den Fix eben hochgeladen:

Paar Infos dazu:

  • Es ist so viel Code, weil man den aktuellen Zustand, ob ein Pin als Input oder Output konfiguriert wird, nicht abrufen kann vom PCA. Bevor ich jetzt anfange, den Zustand selbst zu verwalten (und dann läuft es doch wieder auseinander), gehe ich einfach auf Nummer sicher und konfiguriere alle Ausgänge erneut als Ausgänge. Bisher sind das nur die Enable-Pins für Kopfhörer oder Amp).
  • Zusätzlich wird, das habe ich zuvor ja beschrieben, HP_DETECT als Output konfiguriert. Das verhindert, dass wegen diesem Pin ein Interrupt geworfen wird. Beim nächsten Neustart wird der wieder auf Input gesetzt, so dass man davon nix mitkriegt.
  • Anschließend werden alle Outputs auf logisch NULL gesetzt. Das ist vermutlich nicht notwendig, aber sicher ist sicher.
  • Zwischen den Funktionen Port_WriteInitMaskForOutputChannels() und Port_MakeSomeChannelsOutputForShutdown() haben wir ein Stück weit Code-Duplikation. Vielleicht betreibe ich da auch noch ein wenig Refactoring. Aber grundsätzlich wollte ich das so ein bisschen trennen.