Forum: Mikrocontroller und Digitale Elektronik Stromverbrauch ATtiny13A im Sleep-Modus


von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Hi,

ich betreibe einen ATtiny13 als Temperatursensor. Dieser soll in diesem 
Beispiel einfach nur die drei angeschlossenen LEDs anschalten, wenn die 
Temperatur unter einen festgelegten Wert sinkt.

Um die Temperatur zu messen kommt ein NTC zusammen mit einem normalen 
Widerstand als Spannungsteiler zum Einsatz. Dieser Spannungsteiler wird 
nur während der Temperaturmessung mit Strom versorgt.

Folgendes soll passieren: Der ATtiny13 soll alle 8 Sekunden per Watchdog 
aufgeweckt werden und die Temperatur messen. Ist diese zu hoch, soll er 
sofort wieder in den Sleep-Modus gehen. Ist die Temperatur ausreichend 
niedrig, so soll er die LEDs anschalten und ab und zu überprüfen, ob die 
Temperatur immernoch ausreichend niedrig ist. Falls ja, soll er das 
Reset des Watchdog verhindern.

Der Code funktioniert soweit sehr gut. Es kommt mir allerdings darauf 
an, dass die Schaltung mit einer Knopfzelle so lange wie möglich 
durchhält. Die LED wird nur sehr selten angehen und daher kommt es vor 
allem auf den Stromverbrauch im Standby an. Das Standby setzt sich aus 
zwei Phasen zusammen. Der Eigenentlichen Sleep-Phase (8 Sekunden) und 
dem kurzen Aufwachen zum Messen der Temperatur (wenige µs).

Ich habe diesen Stromverbrauch nun gemessen und sehe, dass der ATtiny13A 
im Sleep-Modus 50µA benötigt, was mir deutlich zu viel vorkommt (laut 
Datenblatt im nA-Bereich!).

Wo liegt der Fehler?
1
#define LED_RED      PB3
2
#define LED_GRN      PB4
3
#define LED_BLU      PB1
4
#define PIN_TEMP_VCC PB0
5
#define PIN_TEMP_MEA PB2
6
7
#define RED_OFF      PORTB |= (1 << PB3);
8
#define GRN_OFF      PORTB |= (1 << PB4);
9
#define BLU_OFF      PORTB |= (1 << PB1);
10
#define RED_ON       PORTB &=~(1 << PB3);
11
#define GRN_ON       PORTB &=~(1 << PB4);
12
#define BLU_ON       PORTB &=~(1 << PB1);
13
14
#define TEMP_VCC_ON  PORTB |= (1 << PB0);
15
#define TEMP_VCC_OFF PORTB &=~(1 << PB0);
16
17
#define TEMP_THRESHOLD 600
18
19
#include <avr/io.h>
20
#include <util/delay.h>
21
22
#include <avr/sleep.h>
23
#include <avr/wdt.h>
24
25
// Watchdog initialisieren
26
void initSleep()
27
{
28
  wdt_enable(WDTO_8S);      // Watchdog einstellen
29
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // Stromsparmodus einstellen
30
}
31
32
// Reset verhindern
33
void stayAwake()
34
{
35
  wdt_reset();
36
}
37
38
// In den Stromsparmodus wechseln
39
void fallAsleep()
40
{
41
  sleep_mode();
42
}
43
44
// Temperatur messen (ADC)
45
int temp()
46
{
47
  TEMP_VCC_ON;  // NTC-Spannungsteiler mit Strom versorgen
48
49
  int result;
50
  ADMUX = 1;
51
52
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);
53
  ADCSRA |= (1<<ADSC);
54
  while ( ADCSRA & (1<<ADSC) ) {}
55
  result = ADCW;
56
  result = 0;
57
  ADCSRA |= (1<<ADSC);
58
  while ( ADCSRA & (1<<ADSC) ) {}
59
  result = ADCW;  
60
  ADCSRA &= ~(1<<ADEN); 
61
62
  TEMP_VCC_OFF;  // Spannungsteiler stromlos machen
63
64
  return result;
65
}
66
67
int main()
68
{
69
  // Ausgänge
70
  DDRB =   (1 << LED_RED)
71
         | (1 << LED_GRN)
72
         | (1 << LED_BLU)
73
         | (1 << PIN_TEMP_VCC);
74
         
75
76
  // LEDs abschalten
77
  BLU_OFF;
78
  GRN_OFF;
79
  RED_OFF;
80
81
  // Temperaturmesser
82
  DDRB &= ~(1 << PIN_TEMP_MEA);
83
84
  // Watchdog und Sleep-Modus initialisieren
85
  initSleep();
86
87
  // LEDs anschalten?
88
  char on = 1;
89
  
90
  // Temperaturmess-Verzögerung
91
  int temp_count = 0;
92
  
93
  // PWM-Variable
94
  char pwm = 0;
95
  
96
  // Wenn es zu warm ist -> Sleep
97
  if (temp() <= TEMP_THRESHOLD)
98
  {
99
    fallAsleep();
100
  }
101
102
  // Hauptschleife
103
  while(1)
104
  {
105
    // Alle 512000 Zyklen die Temperatur messen und prüfen ob der Schwellenwert unter- oder überschritten wurde
106
    if (pwm == 255)
107
    {
108
      temp_count++;
109
      if (temp_count == 2000)
110
      {
111
        on = (temp() > TEMP_THRESHOLD);
112
        temp_count = 0;
113
      }
114
    }
115
    ++pwm;
116
117
    if (on)
118
    {
119
      stayAwake();  // Reset-Counter zurücksetzen
120
      RED_ON;
121
      GRN_ON;
122
      BLU_ON;
123
      /* An dieser Stelle sind eigentlich Animationen mit den LEDs gewesen die aus Gründen der besseren Übersicht gestrichen wurden und ein reines Anschalten anstelle eingefügt. */
124
    }
125
    else
126
    {
127
      RED_OFF;
128
      GRN_OFF;
129
      BLU_OFF;  // LEDs ausschalten
130
      fallAsleep();  // Einschlafen
131
    }
132
  }
133
}

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Brown out an? Der Watchdog braucht übrigens auch Strom.

von Martin (Gast)


Lesenswert?

Brown-Out-Detection ist aus. Klar braucht der Watchdog Strom, aber doch 
nicht so viel?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Travel Rec. wrote:
> Brown out an? Der Watchdog braucht übrigens auch Strom.

Sind allerdings eher 5 statt 50 µA.

Ansonsten kann das von Flussmittelresten auf der Platine beginnend
über offene Eingänge alles mögliche sein.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jörg Wunsch wrote:

> Ansonsten kann das von Flussmittelresten auf der Platine beginnend
> über offene Eingänge alles mögliche sein.

OK, die offenen Eingänge nehme ich nach Blick auf die Schaltung
zurück. ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Das hier:
1
    // Alle 512000 Zyklen die Temperatur messen und prüfen ob der Schwellenwert unter- oder überschritten wurde
2
    if (pwm == 255)
3
    {
4
      temp_count++;
5
      if (temp_count == 2000)
6
      {
7
        on = (temp() > TEMP_THRESHOLD);
8
        temp_count = 0;
9
      }
10
    }
11
    ++pwm;

würde ich auch nicht gerade als stromsparende Programmierung
bezeichnen.  Dafür kann man auch einen Timer nehmen und die CPU
solange in den idle sleep schicken.

von Martin (Gast)


Lesenswert?

>würde ich auch nicht gerade als stromsparende Programmierung
>bezeichnen.  Dafür kann man auch einen Timer nehmen und die CPU
>solange in den idle sleep schicken.

Ich habe den Code etwas gekürzt. Eigentlich wird hier mit Soft-PWM 
gearbeitet, sodass die Hauptschleife wirklich immer laufen muss, wenn 
die Temperatur-Bedingung erfüllt ist.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nebenbei: "char" ist kein guter Datentyp für einen kleinen (und
noch dazu offenbar in der Erwartungshaltung vorzeichenlosen)
Integer.  Nimm uint8_t aus <stdint.h>.

von Martin (Gast)


Lesenswert?

Hi,

hat keiner mehr eine Idee?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Ich habe diesen Stromverbrauch nun gemessen und sehe, dass der ATtiny13A
> im Sleep-Modus 50µA benötigt
Wie hast du den gemessen (nur uC oder gesamte Schaltung?) und woran 
siehst du das?

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Mein Tiny13 (ohne A) verbraucht mit Brown-Out und mit Watchdog und mit 
Schaltung und einem Meßspannungsteiler 1MOhm um 40µA. Irgendwas ist bei 
Deiner Anordnung nicht richtig. Die LEDs sollen keine Vorwiderstände 
haben oder?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Martin wrote:

> hat keiner mehr eine Idee?

Hab ich doch oben schon geschrieben: Dreck auf der Platine,
insbesondere unter den Bauteilen.  Da ist schon so manches
Mikroampere drin versenkt worden.

Softwaretechnisch kannst du dich auch Stück für Stück
durcharbeiten: erstmal alle Pins auf Ausgang, die LED-Ausgänge
auf High, die Spannungsteiler-Ausgänge auf Low setzen, den
Chip (ohne Watchdog vorerst) in den Sleep schicken.  Der Strom,
den du dabei misst, wird später nicht mehr zu unterbieten sein.

von Peter D. (peda)


Lesenswert?

Versuch mal:

DIDR0 = 0x3F;

Und den ADC abschalten vor dem Power-Down.


Peter

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

So wie ich das sehe, wird der ADC wieder abgeschaltet, nachdem er 
gemessen hat.

von Chris K. (chrisk86)


Lesenswert?

Hat zwar nichts mit dem Thema zu tun, aber die LEDs haben keinen 
Vorwiderstand =)

Lg,
Chris

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Sagte ich schon.

von Chris K. (chrisk86)


Lesenswert?

Ups, überlesen... Sorry ^^

von Martin (Gast)


Lesenswert?

Die LEDs sollen keinen Vorwiderstand haben, das ist schon in Ordnung so. 
Den Stromverbrauch habe ich mit einem Messverstärker gemessen und dabei 
die gesamte Schaltung berücksichtigt. Im Moment ist die Schaltung noch 
fliegend mit Fädeldraht aufgebaut. Ich möchte gerne 5-10µA erreichen. 
Ist das realistisch?

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Wenn Du alles richtig gemacht hast, ist es beinahe realistisch. Bei 
ausgeschaltetem Brownout und laufendem Watchdog solltest Du bei etwa 
15...20µA bei 3V landen. Ohne Watchdog und ohne Brownout sind es unter 
1µA.

von (prx) A. K. (prx)


Lesenswert?

Der Analog Comparator ist blödsinnigerweise von Haus aus eingeschaltet.

von hotstuff (Gast)


Lesenswert?

Spannungsteiler (Temp-sensor und Widerstand) hochohmiger auslegen !

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Der Analog-Komparator ist im Power-Down automatisch aus.

Der Spannungsteiler wird von der Software vor dem Sleep abgeschaltet.

von hans (Gast)


Lesenswert?

Mir fehlen im Listing 2 Register, die Strom sparen:

13.2.2 ACSR– Analog Comparator Control and Status Register
hier
      Bit 7 – ACD: Analog Comparator Disable

und

7.5.3 PRR – Power Reduction Register


Evtl. wird es dann schon etwas besser.

gruß hans

von Olli R. (omr) Benutzerseite


Lesenswert?

Martin wrote:

> Ich habe diesen Stromverbrauch nun gemessen und sehe, dass der ATtiny13A
> im Sleep-Modus 50µA benötigt, was mir deutlich zu viel vorkommt (laut
> Datenblatt im nA-Bereich!).

Wie und womit gemessen?

Olli

von Martin (Gast)


Lesenswert?

>Wie und womit gemessen?
siehe obiges Posting
>Den Stromverbrauch habe ich mit einem Messverstärker gemessen

Den Watchdog kann ich natürlich nicht ausschalten... wie soll der µC 
denn sonst aufwachen, wenn es kalt wird?

von Olli R. (omr) Benutzerseite


Lesenswert?

Martin wrote:

>>Wie und womit gemessen?
> siehe obiges Posting
>>Den Stromverbrauch habe ich mit einem Messverstärker gemessen

Ist zwar keine wirkliche Antwort auf meine Frage, aber wenn Du meinst, 
Du misst richtig, wird's schon stimmen.

Olli

von Martin (Gast)


Lesenswert?

Der Messverstärker ist auf den Bereich 100µA eingestellt und ist eine 
Stunde lang gelaufen bevor die Messung gestartet wurde. Es wurden 
geschirmte Kabel für die Messung verwendet. Das Ausgangssignal liegt 
dann zwischen 0V (0µA) und 10V (10µA). Den Wert habe ich mit einem 
Oszilloskop abgelesen, da ich den zeitlichen Verlauf sehen wollte 
(Sleep-Phase/Wach-Phase).

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.