Unaktive Schaltung schlafen lassen

Gast #628422
Lesenswert?

HI,

ich würde meine Schaltung gerne nach einer gewissen unaktiven Zeit in 
den Sleep Modus versetzen. Ich benutze einen ATMEGA32 mit 16 MHZ Takt 
und wollte dies über einen Timer realisieren. Also dachte ich mir ich 
nehme den 16Bit Timer und lasse diesen laufen. Bei einem Overflow wird 
eine volatile Variable hochgezählt und wenn diese den Wert 10 erreicht, 
dann wird der Sleep Modus des Atmel eingeschalten.

Nun das mit dem Sleep Modus klappt nur nach ungefähr 10ms schon ;-(. Ich 
hatte mir das so gedacht.

16 000 000 Hz / (1024 * 65536) = 0,238s

Das heisst, ein Interrupt bei einem 1024 Prescaler sollte alle 0,24s 
eintreffen. Lasse ich die Interruptvariable nun bis 45 zählen, dann 
komme ich ungefähr auf 10s.

((16 000 000 Hz) / (1024 * 65536)) * 45 = 10,73s

Leider geht die Schaltung immer sofort in den Sleep Modus. D.h. irgendwo 
programmiere ich Mist. Genug der Erklärung, hier der Code.
1
void count_unactive_time(void)
2
{
3
   countclock = 0;
4
   TCNT1 = 0;
5
   TCCR1A = 0;
6
   TCCR1B = ((1<<CS12) | (1<<CS10));
7
   TCCR1B &= ~(1<<CS11);
8
   
9
   TIMSK |= (1<<TOIE1);
10
}
11

12
ISR(TIMER1_OVF_vect)
13
{
14
   countclock++;
15
   if(countclock == 45)
16
   {
17
      go_to_sleep();
18
      TIMSK &= ~(1<<TOIE1);
19
   }
20
}
Gast #628572
Lesenswert?

Also mein Timer geht jetzt. Lag daran, dass ich die interrupt.h in 
dieser c file nicht eingebunden hatte. In meiner go_to_sleep steht 
folgendes
1
void go_to_sleep(void)
2
{
3
   LCDCls();
4
   LCDWrite("Standbye Mode aktiv");
5
   set_sleep_mode(SLEEP_MODE_IDLE);
6
   sleep_mode();
7
}
Moderator Persönliche Seite #628700
Lesenswert?

Matthias wrote:

> Ich will mit
> INT0 aufwecken.

Du denkst aber dran, dass auf einem ATmega32 das Aufwecken durch
einen Externinterrupt ausschließlich durch (low-)pegelgesteuerten
Interrupt möglich ist, ja?  Die Varianten mit der Flankensteuerung
brauchen für die Erkennung der Flanke einen laufenden IO clock.

Der Pin-Change-Interrupt der neueren AVRs funktioniert meiner
Erinnerung nach dagegen auch ohne IO clock.  Du könntest also ggf.
einen Upgrade auf einen ATmega324P erwägen.
#628711
Lesenswert?

@ Jörg
Er verwendet den Idle Modus, da läuft der IO Takt weiter.

@ Matthias

Poste doch mal deine Initialisierung, vom Interrupt und die 
Interruptroutine, dann kann man dir vielleicht weiterhelfen.
Wie Jörg schon angedeutet hat: Es gibt noch andere Sleep Modi, die 
effektiver sind als der Idle Modus. Der Power Down Modus könnte für dich 
interessant sein, dann wird der AVR aber komplett stillgelegt und kann 
eben nur durch den Leven Interrupt geweckt werden.
Gast #628764
Lesenswert?

Das zusammenspiel dieser Funktionen soll das Auswachen und Einschlafen 
gestalten:
1
//****************************************************************
2
void count_unactive_time(void)
3
{
4
  countclock=0;
5
  TCNT1 = 0;
6
  TCCR1A=0; // keine PWM Optionen
7
  TCCR1B = ((1<<CS12) | (1<<CS10) ); // prescaler 
8
  TCCR1B &= ~(1<<CS11);      // 1024 => 16MHz/1024 = 1,6 MHz
9

10
  TIMSK|=(1<<TOIE1);   // enable timer1 int
11
}
12

13
//****************************************************************
14
void stop_counting_time(void)
15
{
16
  TIMSK &= ~(1<<TOIE1);     // disable timer1 int
17
  countclock = 0;      // Zähler rücksetzen
18
  TCNT1 = 0;      // Counterregister rücksetzen
19
  IN_SLEEP = 0;      // System ist wach
20
}
21

22

23
//****************************************************************
24
void camera_go_to_sleep(void)
25
{
26
  camera_send_command(SYNC_power_down);
27
}
28

29
//****************************************************************
30
void atmel_go_to_sleep(void)
31
{
32
  LCDCls();
33
  LCDWrite("Standbye Mode active");
34
  IN_SLEEP = 1;
35
  GREEN_OFF();
36
  RED_OFF();
37
  MCUCR = 0x83;
38
  while(IN_SLEEP == 1);
39
}
40

41
//****************************************************************
42
void camera_system_wake_up(void)
43
{
44
  GREEN_ON();
45
  IN_SLEEP=0;
46
  while(!camera_send_SYNC());  // Zum Aufwachen zwingen
47
          // Atmel is bis dahin eh wach 
48
}
49

50
//****************************************************************
51
ISR(TIMER1_OVF_vect) 
52
{
53
  countclock++;
54
  if(countclock == 4)
55
  {
56
    TIMSK &= ~(1<<TOIE1);   // disable timer1 int
57
    //camera_go_to_sleep();
58
    atmel_go_to_sleep();
59
  }
60
}
61

62

63
  
64
//****************************************************************
65
unsigned char volatile DO_PICTURE=0;
66

67
//****************************************************************
68
ISR(INT0_vect)
69
{
70
  if(IN_SLEEP)
71
  {
72
    LCDCls();
73
    LCDWrite("Wake UP...");
74
    MCUCR = 0x03;
75
    camera_system_wake_up();
76
  }  
77
  else
78
  {
79
    stop_counting_time();    
80
  }
81

82
  DO_PICTURE = 1;
83
}
84

85
//****************************************************************
86
void sensor_Init(void)
87
{
88
  MCUCR = ((1<<ISC01) | (1<<ISC00));   
89
  GICR  = (1<<INT0);      // INT0 Interrupt enabled
90
}
#628799
Lesenswert?

Ich glaube ich habe den Fehler: Du setzt den AVR in einem Interrupt in 
den Schlafmodus. Und im Interrupt sind andere Interrupts ausgeschaltet 
-> Kein Externer Interrupt, kein Aufwachen.
Was lernen wir daraus: Nicht alles einfach in den Interrupt paken, 
sondern im Interrupt Flags setzen die in der Main Schleife dann 
abgearbeitet werden.
Daher wird while (IN_SLEEP == 1); auch nie verlassen. Diese Zeile kannst 
du dir sparen, denn wenn der Controller schläft, kann er nicht 
überprüfen ob er schläft.
Gast #629411
Lesenswert?

Was ich nicht verstehe, wenn ich die Zeile

GREEN_OFF();
  RED_OFF();
  MCUCR = 0x83;

nehme, hört dann der uC ab MCUCR = 0x83; auf und macht an dieser Stelle 
bei einem Interrupt dann weiter oder was macht der im Schlafmodus, wo 
fängt er wieder an ?
#629421
Lesenswert?

Matthias wrote:
> nehme, hört dann der uC ab MCUCR = 0x83; auf und macht an dieser Stelle
> bei einem Interrupt dann weiter oder was macht der im Schlafmodus, wo
> fängt er wieder an ?
Nö. Der hört da gar nicht auf. Das "MCUCR = 0x83;" setzt lediglich das 
Sleep-Enable (und konfiguriert nebenbei den externen Interrupt 0 auf 
"steigende Flanke"). Geschlafen wird erst dann, wenn der Befehl "sleep" 
ausgeführt wird.
Moderator Persönliche Seite #629561
Lesenswert?

Ich denke übrigens, dass du durchaus auch aus einer IRQ heraus den
sleep mode anwerfen kannst (auch wenn ich es unästhetisch finde :).
Das Aufwachen hängt nicht davon ab, ob der Interupt gerade wirklich
in eine ISR gehen kann oder nicht, die CPU fängt trotzdem wieder
an zu arbeiten.  Danach wird die alte ISR zu Ende abgearbeitet, und
gleich nach der Rückkehr aus dieser die ISR für den Externinterrupt.
#629569
Lesenswert?

Jörg Wunsch wrote:
> Ich denke übrigens, dass du durchaus auch aus einer IRQ heraus den
> sleep mode anwerfen kannst (auch wenn ich es unästhetisch finde :).
> Das Aufwachen hängt nicht davon ab, ob der Interupt gerade wirklich
> in eine ISR gehen kann oder nicht, die CPU fängt trotzdem wieder
> an zu arbeiten.

Sicher ? Ich habe mich das auch gefragt, und nichts dazu im Datenblatt 
gefunden. Dann habe ich mir das überlegt:
Sobald ein Interrupt eintritt, wird automatisch das globale Interrupt 
Enable Flag gelöscht, demzufolge alle Interrupts deaktiviert. Erst beim 
reti (=ret + sei in einem) werden die Interrupts wieder freigeschaltet.
Gast #629709
Lesenswert?

Doch noch eine kleine Frage zum Abschluss. Wenn ich wie oben beschrieben 
den Sleep Modus durch einen externen Interrupt an INT0 verlasse, wie 
weit kann ich dann den Stromverbrauch meines Atmels senken. Ich würde in 
dieser Hinsicht gerne das absolute Maximum rausholen.
Moderator Persönliche Seite #629743
Lesenswert?

Außerdem kannst du ihn auch mit einem flankengesteuerten Interrupt an
INT2 (aber nur an diesem) aus dem Sleep befördern:

`` ... Low level interrupts on INT0/INT1 and the edge interrupt on
INT2 are detected asynchronously. This implies that these interrupts
can be used for waking the part also from sleep modes other than Idle
mode. The I/O clock is halted in all sleep modes except Idle mode.''
Gast #629747
Lesenswert?

You are the Best :-)
Genau das war es. Ich habe die angewohnheit nicht zwischen den Zeilen zu 
lesen und deshalb solche die wie "LEVEL" Interrupt mal schnell zu 
überlesen. Jetzt geht es einwandfrei und ich sag mal wieder: Danke dir !
Gast #629772
Lesenswert?

Würde die ganze Schaltung nämlich gerne über eine Solarzelle betreiben, 
habe allerdings keine Ahnung von Solarzellen. Vielleicht weiss jemand ob 
man bei so einem Nennstrom eine Versorgung über z.B. 2 Batterien mit 
Solarzellenanbindung hinkriegt. Kennt ihr da Projekte ?
Moderator Persönliche Seite #629797
Lesenswert?

Für stromsparenden Betrieb solltest du dir auch einen moderneren
Prozessor zulegen.  Den ATmega324P hatte ich ja schon einmal genannt.
Der Grundverbrauch im aktiven Betrieb würde dadurch von 23 mA auf
13 mA sinken.  Im Powerdown sinkt der Strom von 1 µA auf 0,6 µA, das
wirst du aber kaum merken. ;-)

Der Reset deiner Schaltung braucht vermutlich tatsächlich ein
Redesign...
Gast #629878
Lesenswert?

Ja ja ja :-) is ja schon gut ich weiss das es nicht der Atmel ist. Also 
zu meiner Schaltung:

Bisher noch auf der Platine jedoch bald draussen sind:

1 x MAX232
1 x poti 150 Ohm

Dazu kommt allerdings ein PIR Sensor der jedoch auch so gut wie nix 
ziehen soll. Ich frag mich nur ob der LM1086 3,3 soviel zieht. Das kann 
ich mir nicht vorstellen und Pull-ups verwende ich keine.

Ich habe noch eine SD-Karte und eine UART Camera dranhängen. Die Cam 
versetze ich in den Sleep Modus und dann zieht die nur noch 100 uA. Alsp 
geh ich jetzt gleich nochmal an den Lötkolben und bau oben genannte 
Teile weg, da sie keinen nutzen haben (ist ja nur ne Testplatine).
Gast #629930
Lesenswert?

So nu bin ich bei ca. 27 mA was immer noch zu viel ist, allerdings sieht 
es auf der Testplatine echt wüst aus und bevor ich da weitermache, mach 
ich ne neue mit dem MEGA(L).

Meine letzte Frage wäre nur noch: Kennt jemand eine Beschaltung, wo ein 
Akku per Solarzelle geladen wird, jedoch die Schaltung sich gleichzeitig 
von diesem versorgt. Ich bin auf dem Gebiet vollkommen unerfahren und 
würde mich mit Ladeschaltungen von Akkus über Solarzellen gerne mal 
informieren.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren