Atmega 328 und Stromverbrauch

combie:
Das tust du aber, da du Ausgaben machst.

An welcher Stelle denn? Ich versteh es nicht. Das müsste dann bei mir doch auch auf dem Serial Monitor angezeigt werden.

Sorry!
Da habe ich was falsch verstanden!

#include <avr/sleep.h>
#include <avr/power.h>

ISR(TIMER1_OVF_vect)
  /* Timer1 Interrupt service Routine */
  {
  }
  
void enter_sleep(void)
  /* Arduino schlafen legen */
  {
  set_sleep_mode(SLEEP_MODE_IDLE);
  sleep_enable();

  /* Weil diesmal nicht der tiefste Schlafmodus gewaehlt wurde,
   * koennen unbenutzte Komponenten noch zusaetzlich abgeschaltet
   * werden, um Energie zu sparen. Noch wichtiger: Die Komponenten
   * koennten ggf. den Arduino ungewollt aufwecken.
   */
  power_adc_disable();    /* Analog-Eingaenge abschalten */
  power_spi_disable();    /* SPI abschalten */
  power_usart0_disable(); /* Serial (USART) */ 
  power_timer0_disable(); /* Timer0 abschalten */
  power_timer2_disable(); /* Timer2 abschalten */
  power_twi_disable();    /* TWI abschalten */

  sleep_mode();
  /** Das Programm läuft ab hier nach dem Aufwachen weiter. **/  
  /** Es wird immer zuerst der Schlafmodus disabled.        **/ 
  sleep_disable();
  power_all_enable();     /* Komponenten wieder aktivieren */
  }

void setup()
  {
  /* Timer konfigurieren */
  TCCR1A = 0x00;  /* Normalbetrieb /*
  TCNT1 = 0x0000; /* Zaehler loeschen */  
  TCCR1B = 0x05;  /* Prescaler: 1024 */
  TIMSK1 = 0x01;  /* Timer-Interrupt einschalten */
  }

void loop() {

    enter_sleep();

}

Hier der Code noch einmal eingekürzt auf das Wesentliche.

Mit folgender Zeile wird nach meiner Erkenntnis die serielle Schnittstelle auch abgeschaltet. Bringt allerdings auch nichts, wenn ich Tx und Rx vom Uno Board abnehme. Es bleibt bei 8mA.

  power_usart0_disable(); /* Serial (USART) */

combie:
Sorry!
Da habe ich was falsch verstanden!

Hast du einen Tipp woran das liegen könnte?

petzlrun:
Hast du einen Tipp woran das liegen könnte?

Nicht wirklich!

Habe deinen Code so umgeschrieben, dass ich ihn auch verstehe.

Er fällt bei 16MHz jeweils für ca 4sec in den Schlafmode.
Nachweislich!

Zusätzlich würde ich noch alle offenen Eingänge abschließen.
z.B. durch aktivieren der Pullup
(wird in setup() gemacht)

Ströme kann ich leider nicht messen.

#include <avr/sleep.h>
#include <avr/power.h>


ISR(TIMER1_OVF_vect)
{
}
 
void enter_sleep(void)
{
  power_adc_disable();    // Analog-Eingaenge abschalten  
  power_spi_disable();    // SPI abschalten  
  power_timer0_disable(); // Timer0 abschalten  
  power_timer2_disable(); // Timer2 abschalten  
  power_twi_disable();    // TWI abschalten  

  sleep_mode();
  
  power_all_enable();     /* Komponenten wieder aktivieren */
}

void setup()
{
  // alle Pullup an
  PORTB = 0xFF;
  PORTC = 0xFF;
  PORTD = 0xFF;
  
  /* Timer konfigurieren */
  cli();
  TCCR1A = 0x00;                   // Normalbetrieb 
  TCCR1B = 0x00;                   // Normalbetrieb 
  TCCR1B = _BV(CS12) | _BV(CS10);  // Prescaler: 1024
  TCNT1  = 0;                      // Zaehler loeschen 
  TIMSK1 = _BV(TOIE1);             // Timer-Interrupt einschalten 
  TIFR1  = _BV(TOV1);              // anstehenden Timer-Interrupt ignorieren 
  sei();

  // Sleep vorbereiten
  set_sleep_mode(SLEEP_MODE_IDLE);
  sleep_enable();

  pinMode(LED_BUILTIN,OUTPUT);
}


void loop() 
{
  digitalWrite(LED_BUILTIN, not digitalRead(LED_BUILTIN));
  enter_sleep();
}

combie:
Zusätzlich würde ich noch alle offenen Eingänge abschließen.
z.B. durch aktivieren der Pullup
(wird in setup() gemacht)

Damit komme ich auf 2,45mA. Das ist zwar nicht weit weg von den 0,35mA, allerdings 7x so viel. Mit deinem Code komm ich auf ca. 2,1mA.

Hi

Wenn ich in den combie-Sketch Serielle Ausgaben bastel, benötige ich VOR dem Schlaf-Aufruf ein delay( 8 );, sonst rennt loop() durch.
Benutzt Serial.begin(9600); in setup() und delay( 8 ); (oder größer) direkt vor dem enter_sleep();.

Also durchaus möglich, daß der Sketch des TO bei mir nicht schlafen wollte, weil ich mir die Debug-Ausgaben eingebaut hatte.

MfG

Benutzt Serial.begin(9600); in setup() und delay( 8 ); (oder größer) direkt vor dem enter_sleep();.

Du meinst so? Ich hab keine serielle Ausgabe.

#include <avr/sleep.h>
#include <avr/power.h>

ISR(TIMER1_OVF_vect)
  {
  }
  
void enter_sleep(void)
  {
  /* Weil diesmal nicht der tiefste Schlafmodus gewaehlt wurde,
   * koennen unbenutzte Komponenten noch zusaetzlich abgeschaltet
   * werden, um Energie zu sparen. Noch wichtiger: Die Komponenten
   * koennten ggf. den Arduino ungewollt aufwecken.
   */
  power_adc_disable();    /* Analog-Eingaenge abschalten */
  power_spi_disable();    /* SPI abschalten */
  power_usart0_disable(); /* Serial (USART) */ 
  power_timer0_disable(); /* Timer0 abschalten */
  power_timer2_disable(); /* Timer2 abschalten */
  power_twi_disable();    /* TWI abschalten */

  sleep_mode();
  /** Das Programm läuft ab hier nach dem Aufwachen weiter. **/  
  /** Es wird immer zuerst der Schlafmodus disabled.        **/ 

  power_all_enable();     /* Komponenten wieder aktivieren */
  }

void setup()
  {
   
  Serial.begin(9600); 
  // alle Pullup an
  PORTB = 0xFF;
  PORTC = 0xFF;
  PORTD = 0xFF;
  
  // Timer konfigurieren 
  cli();
  TCCR1A = 0x00;                    // Normalbetrieb 
  TCCR1B = 0x00;                    // Normalbetrieb   
  TCCR1B = _BV(CS12) | _BV(CS10);   // Prescaler: 1024
  TCNT1  = 0;                       // Zaehler loeschen
  TIMSK1 = _BV(TOIE1);              // Timer-Interrupt einschalten 
  TIFR1  = _BV(TOV1);               // anstehenden Timer-Interrupt ignorieren 
  sei();

  //Sleep vorbereiten
  set_sleep_mode(SLEEP_MODE_IDLE);
  sleep_enable();
  
  }

void loop() {

    delay(10);
    enter_sleep();

}

Delay ist auch in so einem Fall suboptimal.

Besser warten bis Serial.availableForWrite() wieder die Buffergröße zurückgibt
Und dann noch ein kleines wohl kalkuliertes Delay, um Zeit für die letzten paar Bit zu bekommen

@petzrun
Naja - Etwas müsstest Du dann auch noch ausgeben :wink:

//Quelle combie
//https://forum.arduino.cc/index.php?topic=662132.msg4469816#msg4469816

byte anzpuffer;

#include <avr/sleep.h>
#include <avr/power.h>


ISR(TIMER1_OVF_vect)
{
}
 
void enter_sleep(void)
{
  power_adc_disable();    // Analog-Eingaenge abschalten  
  power_spi_disable();    // SPI abschalten  
  power_timer0_disable(); // Timer0 abschalten  
  power_timer2_disable(); // Timer2 abschalten  
  power_twi_disable();    // TWI abschalten  

  sleep_mode();
  
  power_all_enable();     /* Komponenten wieder aktivieren */
}

void setup()
{
  // alle Pullup an
  PORTB = 0xFF;
  PORTC = 0xFF;
  PORTD = 0xFF;
  
  /* Timer konfigurieren */
  cli();
  TCCR1A = 0x00;                   // Normalbetrieb
  TCCR1B = 0x00;                   // Normalbetrieb
  TCCR1B = _BV(CS12) | _BV(CS10);  // Prescaler: 1024
  TCNT1  = 0;                      // Zaehler loeschen
  TIMSK1 = _BV(TOIE1);             // Timer-Interrupt einschalten
  TIFR1  = _BV(TOV1);              // anstehenden Timer-Interrupt ignorieren
  sei();

  // Sleep vorbereiten
  set_sleep_mode(SLEEP_MODE_IDLE);
  sleep_enable();

  pinMode(LED_BUILTIN,OUTPUT);
  Serial.begin(9600);
  anzpuffer=Serial.availableForWrite();  //der Puffer sollte ja beim Start frei sein
  Serial.print("Puffer:");
  Serial.println(anzpuffer);
}


void loop()
{
  digitalWrite(LED_BUILTIN, not digitalRead(LED_BUILTIN));
  while (anzpuffer!=Serial.availableForWrite());
  enter_sleep();
  Serial.println("oops...");
}

Ich hatte das delay(8); an der Steppe, wo jetzt die While steht.

MfG

@postmaster-ino

Achso, dann haben wir wohl aneinander vorbei geredet :slight_smile:

Wie der Herr Prof. Plate im Idle Modus auf die 0,35mA kommt und wo der Unterschied zu meiner Schaltung ist, wäre für mich noch interessant. Vielleicht hat er den Controller nicht mit den 16Mhz am laufen?

Wenn ich mir das http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf so anschaue

Figure 35-7. ATmega328P: Idle Supply Current vs. Frequency (1MHz - 20MHz)
Dann liegt man bei 5V und 16MHz ca bei 2,4mA

Ich betreibe auch einige ATMega328P an Batterien.

Ein Beispiel:
Interner Takt 1MHz
An einer CR2032
Hauptsächlich im DeepSleep
Mit Uhrenquarz an Timer2 zum sekündlichen wecken
Laufzeit der letzten (Schnäppchenmarkt) Knopfzelle: 5 Monate und ca 10 Tage

Dann liegt man bei 5V und 16MHz ca bei 2,4mA

Also sind die 0,35mA nicht mit den 16Mhz Quarz. Wenn ich allerdings auf 1Mhz reduzieren würde, dann würde ich da hinkommen. Wobei wir wieder beim ursprünglichen Thema wären.

Laufzeit der letzten (Schnäppchenmarkt) Knopfzelle: 5 Monate und ca 10 Tage

Das hört sich gut an, die Frage ist was du mit den Controller machst und was noch dran hängt. Wenn es nur um den reinen DeepSleep Modus geht, hilft es mir nicht wirklich weiter. Weil ich in der Wachphase einen Sensorwert abfragen und abspeichern möchte.

Mit Uhrenquarz an Timer2 zum sekündlichen wecken

Ich wollte den Sensor über einen RTC stündlich wecken lassen. Der RTC DS1307 hat leider keinen externen Alarm. Hast du hier eine Idee? Es gibt wohl Chips die das haben, allerdings verbraucht der RTC auch Strom und die sind gar nicht so einfach im Internet zu bestellen.

petzlrun:
.....
Ich wollte den Sensor über einen RTC stündlich wecken lassen. Der RTC DS1307 hat leider keinen externen Alarm. Hast du hier eine Idee? Es gibt wohl Chips die das haben, allerdings verbraucht der RTC auch Strom und die sind gar nicht so einfach im Internet zu bestellen.

Bitte was ?

Du kennst das Internet nicht.

DS3231 z.B.
Nur ein Beispiel von vielen.

Hallo Dieter,

doch den kenne ich. Den gibt es allerding schwer als DIP Variante und oftmals nur als Modul.

petzlrun:
doch den kenne ich. Den gibt es allerding schwer als DIP Variante und oftmals nur als Modul.

Ja, klar...das ist auch einanderes Problem, als Dip ist der mir auch nicht bekannt.
Das wird auch immer schwerer.

Und kleiner gibt es die auch.

Das hört sich gut an, die Frage ist was du mit den Controller machst und was noch dran hängt. Wenn es nur um den reinen DeepSleep Modus geht, hilft es mir nicht wirklich weiter. Weil ich in der Wachphase einen Sensorwert abfragen und abspeichern möchte.

Es wird per NTC (alle 1/4 Stunde) eine Temperatur gemessen und in einem FRAM gespeichert.
Die Stromversorgung der beiden wird per P-Chanel FET, nur bei Bedarf aktiviert.
Das FRAM wird erst beschrieben, wenn ein Buffer im RAM voll ist.
Das Fram wird alle paar Wochen getauscht, und "Zuhause" ausgelesen..

Es gibt wohl Chips die das haben, allerdings verbraucht der RTC auch Strom und die sind gar nicht so einfach im Internet zu bestellen.

Wie gesagt: Für den Zweck nutze ich den Uhrenquarz.
Drift, ca 3 sec pro Tag

Ansonsten suche mal nach "ChronoDot".
Dessen Knopfzelle hält bisher 2 Jahre, Test läuft noch.

Es wird per NTC (alle 1/4 Stunde) eine Temperatur gemessen und in einem FRAM gespeichert

Wieso weckst du dann den C jede Sekunde aus dem Schlaf? Lässt du dann eine Variable hoch zählen oder wie stell ich mir das vor?

Hi

Da weder bisher klar ist, Was Du eigentlich willst, Du bisher auch nicht auf die Überlegungen eingegangen bist, daß man zwar weniger Strom braucht, wenn man laaaangsam macht, aber eben auch länger braucht und in Summe wesentlich weniger Strom braucht, wenn man sich beeilt, weil man in wesentlich kürzerer Zeit fertig ist, Dir ein RTC-Modul mit Stiftleisten nicht 'DIL-genug' ist (zugegeben, wäre eher SIL) - WAS hast Du eigentlich vor?

Am meisten Strom wirst Du sparen, wenn Du den µC ganz einfach nicht verbaust - auch werden dann keine Sensoren unnötig Strom fressen - mit Wem sollten Die nun auch schwätzen - also auch hier wieder gespart.

MfG

PS: JA - diese Sekunde ist die größte Zeitspanne, Die man als genaue Zeit von so einer RTC bekommen kann.
Also wach werden, 'SEKUNDE++' rechnen, pennen legen.
Ausnahme: Irgend eine Zeit ist gekommen, daß man mehr machen möchte - dann macht man halt mehr.
Wenn's nicht so genau werden muß, könnte man mit dem WDT auch 8 Sekunden-Happen verschlafen - dann ist's aber Essig mit einer Uhr - zu ungenau.
Wobei die RTC wohl 'billiger' läuft, als der eingeschaltete WDT - müsste man nachlesen.

PS: JA - diese Sekunde ist die größte Zeitspanne, Die man als genaue Zeit von so einer RTC bekommen kann.
Also wach werden, 'SEKUNDE++' rechnen, pennen legen.

Hatte ich mir schon gedacht, bin aber davon ausgegangen, dass wäre eine typische Anfängerlösung :slight_smile:

Du bisher auch nicht auf die Überlegungen eingegangen bist, daß man zwar weniger Strom braucht, wenn man laaaangsam macht, aber eben auch länger braucht und in Summe wesentlich weniger Strom braucht, wenn man sich beeilt, weil man in wesentlich kürzerer Zeit fertig ist,

Ui was für ein Satz. Da schlaf ich am Besten mal drüber. Ich glaube ich weiß was du sagen wolltest, aber das sprengt jetzt mein Fähigkeiten. Danke dir trotzdem.