Probleme mit PWR_DOWN

beckhj

Neues Mitglied
29. Nov. 2010
27
0
1
Rheinstetten
Sprachen
  1. ANSI C
Hallo!

Ich habe hier gerade eine kleine Schaltung mit einem Tiny44A und den Prozessor muss ich mal in den tiefen Schlaf versetzen.

Ich habe da in meinem main() drei Zustände, im dritten mache ich da zwei LEDs sicher aus und hätte erwartet, dass ich da auf einem minimalen Stromverbrauch komme.

Nun muss ich feststellen, dass ich am Prozessor nie unter einen Strombedarf von ca. 3mA komme.

Hat hier jemand einen Tipp??



CodeBox C
 #include <avr/io.h>

#define F_CPU 8000000

#include <avr/wdt.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <stdbool.h>

#define LED_RED  (1<<PORTA7)
#define LED_GREEN (1<<PORTA6)
#define Buzzer (1<<PORTA3)

volatile uint8_t sleep_interval=0;

void init_wdt();

void delay(uint16_t ms);
void sleep(uint8_t s);
void slow_clock();

int main() 
{       
        DDRA |= LED_GREEN | LED_RED | Buzzer;
        PORTA |=  LED_GREEN | LED_RED;
        PORTA &= Buzzer| LED_RED;

        init_wdt();
       
        //slow_clock();

        while (1) 
        {
            sleep(10);
            PORTA |= LED_RED;
            PORTA &= ~LED_GREEN;
            sleep(10);
            PORTA |= LED_GREEN;
            PORTA &= ~LED_RED;
            sleep(10);
            PORTA &= ~(LED_RED | LED_GREEN);   
        }
}


void delay(uint16_t ms) {
        while(ms) {
                _delay_ms(1); // this function must be called with a compile-time CONST, otherwise it pulls in float-math (huge)
                ms--;
        }
}


// Puts MCU to sleep for specified number of seconds using
// WDT to wake every second and track number of seconds
void sleep(uint8_t s)
{
        sleep_interval = 0;
        while (sleep_interval < s) {
               wdt_reset();
               set_sleep_mode(SLEEP_MODE_PWR_DOWN);
               sleep_mode();
        }
}


// Enable watchdog interrupt, set prescaling to 1 sec
void init_wdt()
{
        // Disable interrupts
        cli();
        // Start timed sequence
        // Set Watchdog Change Enable bit
        _WD_CONTROL_REG |= (1<<WDCE);
        // Set new prescaler (1 sec), unset reset enable
        // enable WDT interrupt
        _WD_CONTROL_REG = (1<<WDIE)|(1<<WDP2)|(1<<WDP0);
        sei();
}


// Slow clock to 150kHz, assumes 9.6MHz internal osc with clkdiv disabled
void slow_clock()
{
        // 150kHz
        CLKPR = (1<<CLKPCE);
        CLKPR = (1<<CLKPS2)|(1<<CLKPS1); // scale = /64
        }


ISR(WATCHDOG_vect)
{
        sleep_interval++;
        wdt_reset();
        // Re-enable WDT interrupt. Normally we wouldn't do that here,
        // But we're using this routine purely as a timeout; 
        // WDT is never used for reset
        _WD_CONTROL_REG |= (1<<WDIE);          
        return;
}

 
Hat hier jemand einen Tipp??

Schau mal bei der Zeile 28, da hast du dich eventuell irgendwie vertan, weil hier LED_RED steht. Möglicherweise wird der Buzzer bzw dessen Treiber permanent angesteuert. Sonst habe ich im Moment leider keinen weiteren Tipp.

Ich denke der Watchdog läuft im Moment nach 500ms über, schau hier auch nochmal nach den Prescalerbits (das hat jetzt aber nicht direkt Einfluss auf den hohen Strom im Powerdown Mode).

Dirk :ciao:
 
  • Like
Reaktionen: beckhj
Hallo Dirk,

danke.
Schau mal bei der Zeile 28, da hast du dich eventuell irgendwie vertan, weil hier LED_RED steht. Möglicherweise wird der Buzzer bzw dessen Treiber permanent angesteuert. Sonst habe ich im Moment leider keinen weiteren Tipp.
Da ich das schon abgeklemmt hatte, hatte ich das nicht raus geschmissen. Das habe ich sicherheitshalber noch mal nachgeholt - leider ist der Effekt gleich.

Grüße
Hans-Joachim
 
Hallo Hans-Joachim,

setz mal das SleepEnable-Bit SE im SleepControl-Register, bevor du in den SleepMode gehst.

sleep_enable();

Dirk :ciao:
 
...Tiny44A
...


CodeBox C
...
// Slow clock to 150kHz, assumes 9.6MHz internal osc with clkdiv disabled
void slow_clock()
{
        // 150kHz
        CLKPR = (1<<CLKPCE);
        CLKPR = (1<<CLKPS2)|(1<<CLKPS1); // scale = /64
        }
Der Tiny44A hat keinen internen 9M6-Oszillator, nur einen 8M...
egal ob vorher die CKDIV8Fuse aktiviert war oder nicht, nach slow_clock() greift der 64-Prescaler, der Controller rennt dann mit 125kHz.
Dann könnte man aber auch gleich den Watchdog-Oszillator mit ca 128kHz als Systemtakt nutzen, und den 8MHz-Oszillator ganz aus lassen.


CodeBox C
...
        _WD_CONTROL_REG = (1<<WDIE)|(1<<WDP2)|(1<<WDP0);
...
64K-Zyklen, bei 128kHz. Wie Dirk gesagt hat, 0,5s
Warum resettest Du den Watchdog-Timer in der ISR? Der ist doch dann gerade übergelaufen gewesen...

Schalten die LEDs denn wie erwartet? (wegen WDE)
 
Schau dir im Datenblatt auch mal das Kapitel 7 Power management and sleep modes an.
Du setzt z. B. das PRR nicht, definierst also nicht wie tief er einschlafen darf), AC könntest du auch noch deaktivieren, ggf. BrownOut und interne Vref. Solltest du debugWire nutzen (trifft möglicherweise auch für JTAG zu): Deaktivieren! Sonst geht der Chip (intern) nie in den Sleep Mode.

Edit: Korrigiere, Sleep Mode setzt du ja. Aber der Rest kann ja noch gemacht werden (unbenutztes abschalten, PRR).
Bei dem sleep bin ich mir (als nicht-c-ler) unsicher. du includierst delay, nutzt aber eine eigene Routine. Kommt da vielleicht was durcheinander?
 
Zuletzt bearbeitet:
Hallo!

ES GEHT!!!

LotadaC hatte den entscheidenden Hinweis: Ich war natürlich mit dem Debugger aktiv, also DebugWire on. Jetzt bin ich auf 800uA. Ob noch mehr (also eher weniger :) ) möglich ist - mag sein, aber mir reicht das erst mal aus.Das was ich da gerade gemacht habe poste ich demnächst mal unter Projekte.

Das mit dem 8;Hz Clock war klar, in meinem Programm in Zeile 3 steht auch 8000000. Alles andere war "Müll", da ich das von einem Tiny13 portiert hatte.
Delay stört nicht, das war als Includefile drin, weil ich ja auch mit Delay gespielt hatte, um die unterschiedlichen Stromaufnahmen zu testen.

Danke für alle Hinweis!!!!

Grüße
Hans-Joachim
 
Denn läuft da noch was :)
Oder zieht an den Pins Strom. Laut Datenblatt sollte er im Power-Down Mode < 10µA ziehen ;)
Aber wenn es dir so reicht gehts ja.

dW muss per Fuses deaktiviert werden. Und der Pegelwandler des Programmers zieht auch noch etwas Strom aus der Schaltung. Also beim Messen alles abklemmen.


P.S.: Und @LotadaC heimst meine Lorbeeren ein. Tztztz :p
 
Hallo Thomas,

ja, da bin ich nun wirklich untröstlich :oops: - da habe ich mich wohl massiv verhauen - vielleicht die Freude, dass es endlich ging?
Natürlich Danke an Dich - aber aber auch an alle, die sich des Problems angenommen haben.

Ich habe auch die Quelle des höheren Stromverbrauchs gefunden - die hatte ich bisher unterschlagen, weil ich ja bisher bei über 3mA war. Wenn ich das wegrechne komme ich da bei fast 0 an - das ist das Problem der Messgenauigkeit.
Den Debugger hatte ich vorher schon abgezogen, aber dass da im DW Betrieb der Sleep nicht geht - an das habe ich nicht gedacht bzw. das auch nirgendwo gelesen.
 
Hehe, kein Problem :)
Ich habs auch überlesen und mich gewundert, steht aber tatsächlich im Datenblatt drin :)
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)