mikrocontroller.net

Forum: Compiler & IDEs Sleep Mode Probleme -Atmega169P


Autor: Marcel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Moin zusammen,
ich habe jetzt schon die Wiki-Seiten von Mikrocontroller.net, sowie die 
Erklärung in der sleep.h gelesen, doch irgendwie will mein uC nicht so 
recht mit dem Schlafmodus:

Er geht zwar ohne Probleme in den Schlafmodus über, doch lässt sich 
nicht mehr aufwachen. Das interessante ist, dass wenn ich mehrere Male 
schnell hintereinander eine Taste (PCINT-Interrupt) drücke, dann kann es 
sein, dass er den Tastendruck registiert, doch passiert das nur sehr 
selten

Nebenbei benutze ich noch einen externen Uhrenquarz für eine RTC. Habe 
ein Oszi mal an den Quarz gehalten und der schwingt auch noch wenn er im 
Schlaf ist (Soll ja auch so sein!)

Meinen Source-Code findet ihr im Anhang.

Vielen Dank!

Marcel

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ISR(PCINT0_vect)
{
  volatile static uint8_t i;
  if( (PINE & FLAG_CODE_Taster) == i )
  {
    //DISABLE_S1_S2;
    OCR2A = TCNT2 +5; //20ms
    TIMSK2 |= (1<<OCIE2A); //Starte Capture-Interrupt fuer 
Entprellroutine
  }
}

Welchen Wert hat i ?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beschreib dochmal, wie das Programm ablaufen soll (Programmablaufplan), 
insbesondere diese ganze Rum-Flag-serei.

Kommentare sind überhaupt nicht überflüssig, sie helfen einem selbst, in 
seinen Programmen den Überblick zu behalten.


Peter

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Marcel (Gast)

>sein, dass er den Tastendruck registiert, doch passiert das nur sehr
>selten

Dein Programm ist etwas kryptisch. Vor allem ein cli() nach dem 
et_sleep_mode(SLEEP_MODE_PWR_SAVE); sieht gefährlich aus. Und auch deine 
Verwendung von sleep_enable, sleep_cpu etc. sieht chaotisch aus. Mach es 
wie im Artikel Sleep Mode, und alles ist paletti.

MfG
Falk

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Flo schrieb:
> Welchen Wert hat i ?

Sry, das war ein Fehler meinerseits, War hier nicht sauber genug mit dem 
Copy-Paste:
ISR(PCINT0_vect)
{  
  volatile static uint8_t i;
  if( (PINE & FLAG_CODE_IMPULS) == i )
  {
    timer.stop = TCNT2;
    timer.overfl = timer.tmp_overfl;
    timer.tmp_overfl=0;
    
    if( i== 0)
    {
      i = FLAG_CODE_IMPULS;
    }
    
    else
    {
      i = 0;
    }
    
    FLAG1_LOC |= (1 << FLAG_IMPULS); //dann setze die Flag erneut
  }
  
  else //Impuls fand statt - entweder falling oder rising Edge
  {

    //DISABLE_S1_S2;
    OCR2A = TCNT2 +5; //20ms
    TIMSK2 |= (1<<OCIE2A); //Starte Capture-Interrupt fuer Entprellroutine

  }
}

Der Grund ist, dass ich nebenbei noch die Zeit zwischen 2Impulsen messe. 
Wenn i=1 ist. Immer wenn ich eine Rising Edge habe, dann wird es auf 1 
gesetzt. Wenn ich eine Falling habe, dann wieder auf 0.
Detektiere ich ein PCINT und passt der momentane Zustand nicht mit dem 
gespeicherten i, kann nur einer der beiden Taster gedrückt worden sein.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falk Brunner schrieb:
> Dein Programm ist etwas kryptisch. Vor allem ein cli() nach dem
> et_sleep_mode(SLEEP_MODE_PWR_SAVE); sieht gefährlich aus. Und auch deine
> Verwendung von sleep_enable, sleep_cpu etc. sieht chaotisch aus. Mach es
> wie im Artikel Sleep Mode, und alles ist paletti.

Ich habe mich hierbei aber genau an die Anweisung in der sleep.h 
gehalten, die macht das wie folgt:

<http://www.nongnu.org/avr-libc/user-manual/group__...
    #include <avr/interrupt.h>
    #include <avr/sleep.h>

    ...
      set_sleep_mode(<mode>);
      cli();
      if (some_condition)
      {
        sleep_enable();
        sei();
        sleep_cpu();
        sleep_disable();
      }
      sei();


Peter Dannegger schrieb:
> Beschreib dochmal, wie das Programm ablaufen soll (Programmablaufplan),
> insbesondere diese ganze Rum-Flag-serei.

Ja da hast du Recht, etwas verwirrend ist das schon für einen 
Außenstehenden.
/**
* Ort wo bitweise die Flags gespeichert werden - schneller Zugriff, da unter 0x1F!
*/ 
#define FLAG1_LOC GPIOR0 

/**
* Wird gesetzt, wenn ein Impuls gekommen ist
*/ 
#define FLAG_IMPULS   2

/**
* Nach Entprellroutine - Taster1 (Weiter) gedrueckt
*/ 
#define FLAG_S1_PRESSED  3 

/**
* Nach Entprellroutine - Taster2 (Bestaetigung) gedrueckt
*/ 
#define FLAG_S2_PRESSED  7 


PS: Die Entprellroutine habe ich weitesgehend von dir übernommen :-). 
Mit einer Ausnahme, dass ich diese nur aktiviere, wenn wirklich eine 
Taste gedrückt wurde.
ISR(TIMER2_COMP_vect )
{
  static uint8_t ct0, ct1,rpt, counter;
  uint8_t i;
  
  OCR2A = TCNT2 + 2; //20ms
  i = key_state ^ ( (~PINE) & FLAG_CODE_TASTER);    // key changed ?
  ct0 = ~( ct0 & i );      // reset or count ct0
  ct1 = ct0 ^ (ct1 & i);    // reset or count ct1
  i &= ct0 & ct1;      // count until roll over ?
  key_state ^= i;      // then toggle debounced state
  FLAG1_LOC |= key_state & i;    // 0->1: key press detect
  
  if( (key_state & (1<<FLAG_S1_PRESSED) ) == 0 )  // check repeat function
  {
    rpt = 40;    // start delay
  }
  
  
  if(++counter == 5)
  {
    if( (PINE & (1<<FLAG_S1_PRESSED) ) ) //Ist Taster1 nicht gedrückt
    {
      TIMSK2 &= ~(1<<OCIE2A); //Stoppe Overflow
      counter = 0;
    }
    
    else
    {
      OCR2A = TCNT2 + 51; //200ms
    }
  }
  if( --rpt == 0 )
  {
    FLAG1_LOC |= (1<<FLAG_S1_LONG);
    TIMSK2 &= ~(1<<OCIE2A); //Stoppe Overflow
  }
}

Vielen Dank für eure schnellen Antworten :-)

Grüße Marcel

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich bin jetzt schonmal ein gutes Stück weitergekommen.
Habe die Entprellroutine rausgenommen und komischer weise registriert er 
jetzt die Tastendrücke, aber unglaublich langsam. Er müsste jetzt 
prellen und gleich 2/3 Tastendrücke registrieren, doch da tut sich mal 
einer, wenn man lange draufdrückt. :(

Gibt es da etwa Probleme das der Taktgeber des uC gleich der Taktgeber 
der RTC ist, denn wenn ich den internen Taktgeber als uC-Takt gebe, dann 
läuft der Tastendruck wesentlich schneller.

Vielen Dank für eure Hilfe

Grüße!
Marcel

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich arbeite lieber nach der Methode: teile und herrsche.
Ich würde den Sleep-Mode immer ganz zum Schluß implementieren, wenn die 
anderen Funktionen alle fertig sind.

Der Timer2 im Async-Mode ist etwas tricky. Man muß nach jeder Aktion 
erstmal testen, ob sie beendet wurde, ehe man in Sleep geht. Dazu gibt 
es 3 Flags.

Auch ein Interrupt ist eine Aktion (Löschen des Interrupt-Flags), für 
die es aber kein Updatebit gibt. Man muß dann ein Dummy-Write ausführen 
und warten, bis dieses beendet ist.

Ich würde daher das Entprellen besser mit T0 oder T1 machen. Dann muß 
man aber warten, bis das Entprellen der Aufwachtaste beendet ist:
uint8_t get_key_idle( uint8_t key_mask )        // check if ready for power down
{
  return (KEY_PIN ^ key_state) & key_mask;
}
...
static inline void power_down( void )
{
  ATOMIC_BLOCK(ATOMIC_FORCEON){
    if( get_key_idle( 1<<KEY_ON_OFF )){         // if debounce done
      ADCSRA = 0;                               // ADC off
      PCICR = 1<<KEY_ON_OFF_ENABLE;             // enable wake up
      set_sleep_mode( SLEEP_MODE_PWR_DOWN );
    }
  }
  sleep_cpu();
}
...
ISR( PCINT2_vect )                              // wake up from power down
{
  set_sleep_mode( SLEEP_MODE_IDLE );
  PCICR = 0;
}
...
static inline void power_on_off( void )         // handle key press
{
  if( get_key_press( 1<<KEY_ON_OFF )){
    if( state == OFF )
      state = ON;
    else
      state = OFF;
  }
}


Peter

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.