Forum: Mikrocontroller und Digitale Elektronik Strom sparen mit dem STM32L


von Chris (Gast)


Lesenswert?

Hallo,

ich habe meinem STM32L151 in den letzten zwei Tagen das Stromsparen 
beigebracht und bin von 12 mA schon auf 7 mA runter gekommen. Mich würde 
aber interessieren ob da noch mehr (oder weniger) gehen würde.

Der Chiptakt ist 32 MHz, daran kann ich auch nichts ändern da ich nur 
mit hohem Chiptakt eine gute Auflösung für einen Timer hinbekomme. 
Dieser löst ca alle 40 µs einen Interrupt aus, welcher bearbeitet wird 
bevor der STM mit einem __WFI() wieder schlafen geschickt wird.

Abgeschalten habe ich bereits den ADC mitsamt DMA und dazugehörige 
Clocks. Nur bei Bedarf werden 3 Messungen durchgeführt bevor der ADC mit 
DMA wieder abgeschalten wird.

Bislang habe ich aber keine Möglichkeit gefunden den Stromverbrauch 
weiter zu reduzieren. Mehr als den SLEEP-Modus kann ich nicht verwenden, 
da ab dem STOP-Modus die Takte angehalten werden und somit auch mein 40 
µs Interrupt ausbleiben würde.

Gibt es doch noch andere Tricks?

von Coder (Gast)


Lesenswert?

Was passiert im Interrupt?

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

Gibt es unbeschaltetet Eingaenge? Die ziehen gerne Querstrome. Mit den 
internen Pull-Up/Down verhinderst du das Driften der Eingaenge!

von Phantomix X. (phantomix)


Lesenswert?

Zitat aus dem Datenblatt zum STM32L15xxD:

230 µA/MHz Run mode

Das macht bei 32 MHz:

32 * 0,23 = 7,36 mA

Sprich, du bist schon gut "am Anschlag" beim Rest deiner Peripherie usw.
Wie viel musst du in dem Timer-Interrupt rechnen?

Edith: Hast du mal versucht, in deiner Hauptschleife die CPU anzuhalten 
(bin grad nicht sicher, wie das Kommando dazu heißt), sodass sie durch 
den Interrupt weiterläuft ... bis sie wieder die "Haltestelle" erreicht?

von Phantomix X. (phantomix)


Lesenswert?

Im RM0038 steht das unter Punkt 5.3, Seite 103, Tabelle 26

WFI

CPU CLK OFF
no effect on other
clocks or analog
clock sources



(WFI = Wait For Interrupt)

von Lothar (Gast)


Lesenswert?

Phantomix Ximotnahp schrieb:
> Hast du mal versucht, in deiner Hauptschleife die CPU anzuhalten
> (bin grad nicht sicher, wie das Kommando dazu heißt), sodass sie durch
> den Interrupt weiterläuft ... bis sie wieder die "Haltestelle" erreicht?

__WFI();
__enable_irq();
__ISB();
__disable_irq();

von Chris (Gast)


Lesenswert?

Coder schrieb:
> Was passiert im Interrupt?
Im Interrupt wird ein neues Sample mit dem DAC ausgegeben.

Lothar schrieb:
> __WFI();
> __enable_irq();
> __ISB();
> __disable_irq();
__WFI(); hatte ich bereits ans Ende dem main-loops eingebaut und hat 
eine ordentliche Stromersparnis gebracht. Die Interrupts kann ich aber 
nicht deaktivieren, da diese den µC ja wieder aufwecken sollen!

Uwe Bonnes schrieb:
> Gibt es unbeschaltetet Eingaenge? Die ziehen gerne Querstrome. Mit
> den internen Pull-Up/Down verhinderst du das Driften der Eingaenge!
Was verstehst du unter "unbeschaltene Eingaenge"? Es gibt so einige Pins 
die in der Luft hängen, diese werden aber ohnehin im Programm nicht 
initialisiert.

Besten Dank für die bisherigen Antworten, ich bin sehr beruhigt dass ich 
das meiste bereits ausgereizt habe :D

von Peter D. (peda)


Lesenswert?

Chris schrieb:
> Dieser löst ca alle 40 µs einen Interrupt aus, welcher bearbeitet wird

Da würde ich ansetzen.
Warum müssen es 40µs sein und 32MHz?

Viele MCs haben RTC und Pin-Change zum Aufwachen, um komplett zu 
schlafen, bis es etwas zu tun gibt.

von Peter D. (peda)


Lesenswert?

Chris schrieb:
> Was verstehst du unter "unbeschaltene Eingaenge"? Es gibt so einige Pins
> die in der Luft hängen, diese werden aber ohnehin im Programm nicht
> initialisiert.

Genau das.
Wenn Pins floaten, können beide FETs des Eingangsgatters leiten und 
erhöhen damit den Stromverbrauch merklich.
Nehmen wir mal 100µA an, sind das bei 64 Eingängen schon 6,4mA.

Bei unbenutzten Pins sollte wenigstens der Pullup an sein.

von Lothar (Gast)


Lesenswert?

Chris schrieb:
>> __WFI();
>> __enable_irq();
>> __ISB();
>> __disable_irq();
> __WFI(); hatte ich bereits ans Ende dem main-loops eingebaut und hat
> eine ordentliche Stromersparnis gebracht. Die Interrupts kann ich aber
> nicht deaktivieren, da diese den µC ja wieder aufwecken sollen!

Das ist ja genau der Trick: auch wenn die Interrupts deaktiviert sind 
(was noch etwas mehr Strom spart), führt WFI zum Aufwecken (der 
aufweckende Interrupt wird dann Pending). Dann werden mit enable_irq die 
Interrupts aktiviert, und durch ISB wird genau ein Assembler-Befehl 
ausgeführt, und das ist der Sprung in Deinen Interrupt-Handler (dorthin 
müsstest Du die Bearbeitung verlegen). Sobald der fertig ist, erfolgt 
der Rücksprung ins Hauptprogramm und die Interrupts werden wieder mit 
disable_irq deaktiviert. Und dann kommt wieder WFI

von Chris (Gast)


Lesenswert?

Coder schrieb:
> Was passiert im Interrupt?
Sorry, hatte die Frage übersehen. Im Interrupt wird nur ein neues Sample 
mit dem DAC ausgegeben und anschließend ein neuer Wert für den nächsten 
Interrupt berechnet, also keine große Sache.

Lothar schrieb:
> __WFI();
> __enable_irq();
> __ISB();
> __disable_irq();
Ich habe das eben mal getestet, das Programm läuft nach wie vor ohne 
Probleme, der Stromverbrauch ist allerdings "deutlich" hoch gegangen (um 
ca 1 mA).

Peter Dannegger schrieb:
> Wenn Pins floaten, können beide FETs des Eingangsgatters leiten und
> erhöhen damit den Stromverbrauch merklich.
> Nehmen wir mal 100µA an, sind das bei 64 Eingängen schon 6,4mA.
>
> Bei unbenutzten Pins sollte wenigstens der Pullup an sein.
Deinen Vorschlag habe ich ebenfalls getestet und tatsächlich noch etwas 
herausholen können. Im Manual hatte ich schon mal darüber gelesen, dass 
die Konfiguration als analoger Eingang empfohlen wird. Mit der 
Kombination analog (GPIO_Mode_AN) und PullDown (GPIO_PuPd_DOWN) bin ich 
mittlerweile bei 6,4 mA (RMS) gelandet, das muss erst mal genügen :)

von Lothar (Gast)


Lesenswert?

Chris schrieb:
>> __WFI();
>> __enable_irq();
>> __ISB();
>> __disable_irq();
> Ich habe das eben mal getestet, das Programm läuft nach wie vor ohne
> Probleme, der Stromverbrauch ist allerdings "deutlich" hoch gegangen (um
> ca 1 mA).

Hast Du ausser dem Timer-IRQ zum Aufwecken noch andere IRQ? Kannst Du 
die Weglassen bzw. alles im Timer-ISR erledigen?

von Phantomix X. (phantomix)


Lesenswert?

Überhaupt versuchen, alle nichtbenötigten peripheral Clocks 
abzuschalten. Wenn du die Genauigkeit vom HSE nicht brauchst, versuchen 
mit HSI zu arbeiten

von Chris (Gast)


Lesenswert?

Lothar schrieb:
> Hast Du ausser dem Timer-IRQ zum Aufwecken noch andere IRQ? Kannst Du
> die Weglassen bzw. alles im Timer-ISR erledigen?
Nein, da ist nicht mehr viel machbar. Ich habe ohnehin nur noch einen 
einzigen Timer sowie zwei externe Interrupts. Ich benötige aber alle, da 
alle auf verschiedene aber gleich wichtige Ereignisse warten.

Phantomix Ximotnahp schrieb:
> Wenn du die Genauigkeit vom HSE nicht brauchst, versuchen mit HSI zu arbeiten
Hatte ich schon einmal getestet, aber keine große Veränderung 
feststellen können. Ich habe mich dann dazu entschieden den HSE zu 
verwenden

Bin aber wie gesagt schon ganz zufrieden mit der Einsparung :)

von Der Experte (Gast)


Lesenswert?

Lothar schrieb:
> Das ist ja genau der Trick: auch wenn die Interrupts deaktiviert sind
> (was noch etwas mehr Strom spart), führt WFI zum Aufwecken (der
> aufweckende Interrupt wird dann Pending).
Wozu das denn? Wo ist der Vorteil gegenüber einfach "while(1) __WFI ();" 
? Da schläft die CPU genauso bis ein Interrupt kommt, der wird 
ausgeführt, und die CPU geht wieder schlafen.

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

Chris schrieb:
> Was verstehst du unter "unbeschaltene Eingaenge"? Es gibt so einige Pins
> die in der Luft hängen, diese werden aber ohnehin im Programm nicht

Genau solche Beinchen. Die Pins laden sich ueber Leckstroeme im Chip und 
aussen auf und schweben dann irgendwo zwischen Masse und VCC. Je naeher 
die Pins an VCC/2 liegen, umso groesser ist der Querstrom.

von Dörle (Gast)


Lesenswert?

Es ist durchaus möglich durch die Compiler Einstellungen noch Strom zu 
sparen. Ob das bei dem Umfang deines Codes allerdings etwas bringt weiß 
ich nicht.
Prinzipiell sollte jedenfalls auf Zeit optimiert werden nicht auf 
Speicherplatz.

Auch das Aufrufen von Unterfunktionen benötigt in der Regel mehr Strom. 
Daher ist bei stukturierter Programmierung der inline Befehl zu 
empfehlen.

Mathematische Berechnungen möglichst vermeiden oder versuchen auf 
Controller eigene Bibliotheken umzusteigen. Was der STM32 für deinen 
Rechenaufwand hergibt weiß ich natürlich nicht.

Gut ist auch Schleifen möglichst abwärts zählen zu lassen statt 
aufwärts.
Außerdem ist es sinnvoll die Schleifenzahl gering zu halten. Nicht nur 
ansich die Anzahl der Schleifen sondern auch die Anzahl der durchläufe, 
also bei einer hohen Anzahl nach Möglichkeit einen Teiler finden und 
lieber den Code noch einmal einkopieren.

Und dann natürlich call-by-reference und all so ein Kram. Aber da bist 
du sicher schon selbst drauf gekommen.

Wenn es dich stark interessiert verantstalltet gerade STM jedes Jahr 
kostenlose Seminare zur Low-Power-Programmierung. Sind natürlich von 
Verkaufsgelaber überflutet, aber es sind nützliche Tipps dabei und die 
kennen ihre Controller eben sehr gut und können viele Fragen gezielt 
beantworten. Allerdings sind dieses Jahr in Deutschland glaube ich keine 
mehr vorgesehen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.