Gleichzeitige kontinuierliche Timerabfrage und Digitaleingang Überwachung ?

Hallo,
ich habe eine Frage zum Arduino Uno/Duemilanove. Das Herz des Arduinos ist ja der Atmega328P mir ist die Frage aufgekommen, ob es möglich ist ein Digitaleingang zu überwachen und gleichzeitig ein Countdown (2 Jahre) runterzuzählen bzw hochzuzählen? Ich weiß das gleichzeitige Befehle in einem MCU nicht möglich sind, jedoch verfügt der Atmega328p einen zusätzlichen RTC Eingang. Kann man diesen benutzen, um im Sleep-Modus (geringer Stromverbrauch, erst mit dem Arduino später nur der Atmega328p) den Countdown zu zählen und den Arduino über einen Interrupt aufzuwecken, falls sich am Pegel des Digitaleingangs etwas ändert? Wie könnte das konkret in der Programmierung aussehen?
Gruß gibsonuser

http://www.mikrocontroller.net/articles/Sleep_Mode

Du willst hier sicherlich nicht wirklich "gleichzeitig". Bei 16MHz hast du 62.5ns pro Takt. Und auf ein Assembler Befehl braucht i.d.R. maximal 4 Takte. Da es ein RISC Prozessor ist gehen die meisten Befehle in 1-2 Takten.

Wenn also zwei Befehle nacheinander kommen dann ist das meistens immer noch schnell genug. Vor allem in deinem Fall. Wieso muss das "gleichzeitig" sein? Das sind doch zwei völlig unterschiedliche Dinge. Mit der Fragestellung gehst du am eigentlichen Thema vorbei.

Wie man einen Arduino schlafen legt und aufweckt wird hier erklärt:

Bei "Waking from sleep with a signal" wird gezeigt wie man mit einem externen Interrupt aufwacht.

Wenn der Arduino aber schläft, dann schläft er und zählt nichts. Du kannst das der Timer Variante kombinieren (Waking from sleep with a timer). Dann wacht der Arduino auch alle 8 Sekunden auf um was zu machen (andere Zeiten gehen auch, z.B. 1s). Man kann das auch zählen wie oft er schon aufgewacht ist um dann alle x * 8 Sekunden was zu machen.

@Serenifly: Sorry, deine Erörterung über "gleichzeitig" und 62,5ns bei 16 MHz geht ziemlich an der Frage

"ein Digitaleingang zu überwachen und gleichzeitig ein Countdown (2 Jahre) runterzuzählen bzw hochzuzählen?"

vorbei, fürchte ich.

Ich denke, Gibsonuser will einen atmega328p als RTC verwenden und z.B. nur jede Sekunde aufwachen, aber auch durch andere externe Interrupts (pinchange?) geweckt werden.

http://www.mikrocontroller.net/topic/227450 ist ein hübscher Einstieg mit Links.

Ich bin der Meinung, das macht mit Arduino keinen Sinn, höchstens mit einem nackten atmega328p und zusätzlicher backup-Batterie
(und sehe microcontroller.net als das geeignetere Forum, auch wenn hier die netteren Leute sind :wink: )

Einfacher wäre eine externe RTC mit eigener Batterie und ein separater Arduino mit "normaler" Stromversorgung, der nicht unbedingt 2 Jahre durchlaufen muss, damit keine Sekunde verpasst wird.

Gibsonuser:
mir ist die Frage aufgekommen, ob es möglich ist ein Digitaleingang zu überwachen und gleichzeitig ein Countdown (2 Jahre) runterzuzählen bzw hochzuzählen? Ich weiß das gleichzeitige Befehle in einem MCU nicht möglich sind, jedoch verfügt der Atmega328p einen zusätzlichen RTC Eingang. Kann man diesen benutzen, um im Sleep-Modus (geringer Stromverbrauch, erst mit dem Arduino später nur der Atmega328p) den Countdown zu zählen und den Arduino über einen Interrupt aufzuwecken, falls sich am Pegel des Digitaleingangs etwas ändert? Wie könnte das konkret in der Programmierung aussehen?

Die Frage ist, welcher Stromverbrauch Dir dabei vorschwebt? Ein Atmega328 kann zwar im PowerDown-Sleepmode für sich auf unter 1µA Verbrauch getrimmt werden, aber eine RTC im Standby zieht dann immer noch ca. 200µA Standby-Verbrauch, um den I2C-Bus aktiv zu halten und darauf reagieren zu können.

Gesamtverbrauch im Powerdown also: 201 µA = 0,201 mA

Ist das akzeptabel oder schwebt Dir ein deutlich niedrigerer Stromverbrauch vor?

Eine DS1307 (nur als Beispiel, bitte keine Genauigkeitsdiskussion) braucht 0.3 µA um die Zeit weiterzuzählen.
Der Arduino/atmega328 könnte dann ganz aus sein, oder im PowerDown sleep mode mit 1µA. (lt. jurs)
I²C braucht in diesem Zustand niemand.

Wenn der atmega328 die RTC Rolle selbst spielt, muss er im PowerSave Modus ( mit Timer2 aktiv ) laufen, und braucht, nach dem was ich gefunden habe, deutlich mehr ...

Aber Gibsonuser sollte tatsächlich ein bisschen mehr erzählen, was er eigentlich will.

Hallo,
vielleicht ein mal ein paar mehr Infos:

Ich denke, Gibsonuser will einen atmega328p als RTC verwenden und z.B. nur jede Sekunde aufwachen, aber auch durch andere externe Interrupts (pinchange?) geweckt werden.

Ganz genau! Warum will ich keinen externe RTC? Weil das zusätzliche Hardware wäre, die unnötig ist da man die selbe Aufgabe mit dem Atmega erledigen kann.

Wenn der Arduino aber schläft, dann schläft er und zählt nichts. Du kannst das der Timer Variante kombinieren (Waking from sleep with a timer). Dann wacht der Arduino auch alle 8 Sekunden auf um was zu machen (andere Zeiten gehen auch, z.B. 1s). Man kann das auch zählen wie oft er schon aufgewacht ist um dann alle x * 8 Sekunden was zu machen.

Das hört sich gut an, das wäre genau das was ich brauche: Atmega jede Sekunde aufwecken, um zu gucken, ob sich ein Pegel eines Digitaleneingangs verändert hat und die RTC Clock zusätzlich alle 8 Sekunden aufwecken um zu zählen, aber wie genau wäre dann die RTC noch und wie sieht der Verbrauch aus?

Ist das akzeptabel oder schwebt Dir ein deutlich niedrigerer Stromverbrauch vor?

Der Atmega (ich schreibe bewusst nicht Arduino) sollte im Batteriebetrieb 2 Jahre halten.

(und sehe microcontroller.net als das geeignetere Forum, auch wenn hier die netteren Leute sind :wink: )

Da hast du sowas von recht genau deswegen Frage ich hier, weil ich das Forum schätze. Ein anderer Grund ist weil ich keinerlei Erfahrung mit der Programmierung gemacht habe. Dennoch könnte ich den Atmega mit der Arduino IDE über isp programmieren oder gebe es irgwelche Nachteile, weil wohlmöglich die Befehle nicht so effizient sind?

Was ich vergessen hatte bezüglich der Genauigkeit: bei 2 Jahren darf es ruhig ein Monat verzögern also erst nach 2 Jahre und einem Monat die 2 Jahre zählen. Könnte man ja auch gegebenenfalls sogar Softwaretechnisch ausbessern.

Keine Sorge, da gehen keine 4% ( 1/24 ) der Quarz-Schwingungen verloren, sobald es überhaupt geht.

2 Jahre sind allerdings lang. Da sucht man nach Batterien die kaum Selbstentladung haben, die dann aber nicht die Riesen-Kapazität haben.

Wenn das Digital-Signal nur relativ selten kommt, solltest du dir wirklich überlegen, ob du den atmega328 zeitgetriggert wecken willst.

Oder nur dann, wenn ein Signal kommt, der atmega ( attiny ?) aus dem Tiefschlaf aufwacht und auf die externe RTC guckt, ob die 2 Jahre um sind... ( Hat nach meiner unbegründeten Meinung deutlich weniger Strombedarf )

Wir sind evtl. nett, aber auch neugierig: Was soll das Ganze überhaupt? Was ist das für ein Digital-Signal?
In zwei Jahren ist bald 2017, wieviel Reserve soll die Batterie dann noch haben und wofür? :wink:

Hallo,
das ganze soll eine Art Lichtschranke werden, die mit Infrarot Licht arbeitet. Die Lichtschranke wird dauerhaft unterbrochen, um jetzt möglich effizient zu arbeiten habe ich mir folgendes Gedacht:

Der Atmega wird in einem bestimmten Zeitintervall geweckt. Es wird ein kurzer Impuls mit der IR-LED gesendet. Das reflektierte Licht wird vom Empfänger detektiert, der Countdown Zähler wird um dem bestimmten Zeitintervall erhöht, der Atmega legt sich wieder schlafen.

To reduce power consumption, the AVR spends most of its time in Power-save mode, in which all on-chip modules are
disabled, except for the RTC. As shown in Table 1-1, the MCU typically consumes less than 10µA in this mode. Each
timer overflow interrupt will bring the device out of power-save mode, and back into active mode. When in active mode,
the timer overflow interrupt routine is executed, before the device re-enters power-save mode.

In der Application Note Atmel AVR134 habe ich lesen können das der Atmega also mit angeschlossenem Quarz nach einem overflow ein interrupt erhält, sodass er aufweckt und die interrupt routine durchläuft.
Könnte man in dieser interrupt routine den Impuls + das detektieren mit hinzufügen, ohne dass sich die Zeiten verschieben? Ich denke mal schon, weil das zählen der Zeit nur von Timer 2 durchgeführt wird oder? Die anderen Aufgaben werden dann von den anderen Timern erfüllt. Nach der Routine würde er sich wieder schlafen legen und erst wieder aufwachen bei erneutem overflow.

Wenn ich das richtig verstehe muss ich jetzt schauen wie lange der Atmega im Power Safe Modus und wie lange im Akitv Modus bleibt. Dann muss ich noch wissen wie viel Strom dieser Impuls der IR LED und das Detektieren des Empfängers + dem Atmega im Aktivmodus halten verbraucht, dann könnte ich den Gesamtstrom verbrauch berechnen oder?

Wenn du den regulären Timer Interrupt verwendest, hast du eine ziemlich Breite Kontrolle über das Intervall, je nach verwendendem Prescaler und wie man das Counter Register vorbesetzt.

Auf der Seite von Nick Gammon wird dafür der Watchdog Timer verwendet. Dadurch ist man mit den Zeiten mehr eingeschränkt, aber man spart noch mal etwas Strom da die normalen Timer abgeschaltet sind. Der Watchdog Timer braucht aber auch ca. 6µA. Ist also nicht viel Ersparnis.

Auch Vorsicht dabei:
Wenn du da nicht aufpasst, wachst du glaube ich alle 1ms auf, da auf dem Arduino Timer0 für millis() und delay() läuft.

Man kann aber Timer0 getrennt von den anderen abschalten:
http://www.nongnu.org/avr-libc/user-manual/group__avr__power.html
Oder einfacher vielleicht alles abschalten und dann den gewünschten Timer wieder aktivieren

Gibsonuser:
Könnte man in dieser interrupt routine den Impuls + das detektieren mit hinzufügen, ohne dass sich die Zeiten verschieben? Ich denke mal schon, weil das zählen der Zeit nur von Timer 2 durchgeführt wird oder?

Du hast mit den drei Themen Timer-, Interrupt- und Sleepmodeprogrammierung extrem wenig Erfahrung und möchtest trotzdem ein ganz ausgebufftes Programm mit direkter Programmierung der Hardware und ihrer Register erstellen, das extrem gute Kenntnisse in diesen Themengebieten erfordert?

Ein Programm, das es so noch nicht gibt und zu dem es auf der Arduino-Plattform nicht einmal ansatzweise irgendwo veröffentlichten Beispielcode gibt?

Na dann viel Spass!

Zu Deiner Frage: Der Interrupt weckt das Programm aus dem Standby-Sleepmode auf. Nach dem Aufwachen wird zuerst die Interrupt-Behandlungsroutine ausgeführt. Und danach setzt das Programm mit der Anweisung fort, die unmittelbar nach der Anweisung folgt, mit der Du das Programm schlafen gelegt hast.

Was Du dann zwischen den Schlafphasen an Code ausführst, ist Dir überlassen.
Nur gilt auch dabei wie bei allen Interrupts, die Ausführungszeit der Interruptbehandlung kurz zu halten.

Typischerweise würdest Du bei einem Programm, das sich hauptsächlich im Sleepmode befindet und durch verschiedene Interruptquellen aufgeweckt werden kann, in der Interruptbehandlung einfach eine Flag-Variable setzen, mit der angezeigt wird, durch welche Interruptquelle das Aufwecken erfolgte. So dass das Programm beim Fortsetzen nach Ende der Interruptbehandlung weiß, wovon es geweckt wurde und entsprechend darauf reagieren kann.

Gibsonuser:
Wenn ich das richtig verstehe muss ich jetzt schauen wie lange der Atmega im Power Safe Modus und wie lange im Akitv Modus bleibt. Dann muss ich noch wissen wie viel Strom dieser Impuls der IR LED und das Detektieren des Empfängers + dem Atmega im Aktivmodus halten verbraucht, dann könnte ich den Gesamtstrom verbrauch berechnen oder?

Ja, um den Gesamtstromverbrauch durch Rechnung zu ermitteln, brauchst Du Informationen über die Schaltung:

  • wieviel Strom im Sleepmode gezogen wird
  • wieviel Strom im Aktivmode gezogen wird
  • und wie das Verhältnis von Schlafzeit zu Aktivzeit ist

hatte bisschen viel um die Ohren die letzte zeit, heute konnte ich mich wieder ein bisschen damit beschäftigen und habe ein kleines Programm geschrieben.

Dabei sind mir ein paar fragen aufgekommen:
was ist effektiver einen Interrupt auszulösen einen Overflow Interrupt oder ein Compare Interrupt? Macht sich das überhaupt bemerkbar?
Wie kann ich die einzelnen Befehlszeilen in längen umrechnen (damit meine ich Befehl xy braucht bei 1 MHZ so und so lange)?
Braucht der Atmega beim start seines Internen Oscillators eine gewisse Einschwingzeit, die ich beachten muss?
Darf ich grundsätzlich alles abschalten was ich nicht brauche oder kommt es zu ungeahnten Problemen?
Ist die ISR bei mir schon zu lange? Wann weiß ich das sie zu lange ist?

Hier mal der Code, ich freue mich auf Kritik und Verbesserungsvorschläge.

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

#define F_CPU 8000000L 

volatile uint8_t flag;

int main(void)
{

 

 
 DDRC |= (1<<PC5) | (1<<PC4); 
 DDRC &= ~(1<<PC3);
 
 
 GTCCR |= (1<<TSM) | (1<<PSRASY);
 ASSR |= (1<<AS2); 
 TCCR2A |= (1<<WGM21); 
 TCCR2B |= (1<<CS22) | (1<<CS21); 
 OCR2A = 256-1; 
 TIMSK2 |= (1<<OCIE2A); 
 GTCCR &= ~(1<<TSM); 
 

 
 sei(); 
 
 
 
 while(1)
    {

   
   set_sleep_mode(SLEEP_MODE_PWR_SAVE);
   sleep_mode();
 
 
   
   
   
   PORTC |= (1<<PC4); 
   _delay_ms(1); 
   
   while(!(PINC &= (1<<PINC3)))
   {
   PORTC |= (1<<PC5); 
   }
   
   PORTC &= ~(1<<PC5); 
   PORTC &= ~(1<<PC4); 
   
   
     
   while(flag==1)
   {
   PORTC|= (1<<PC5); 
   }
   
    }
 return (0);
}




ISR(TIMER2_COMPA_vect)
{
 static uint8_t zweitesekunde;
 static uint8_t minute=0;
 static uint8_t stunde=0;
 static uint8_t tag=0;
 
 zweitesekunde++;
 if(zweitesekunde==30)
 {
 zweitesekunde=0;
 minute++;
 }
    if(minute == 60)
    {
    stunde++;
    minute = 0;
    }
    if(stunde == 24)
    {
    stunde = 0;
 tag++;
 flag=1; 
    }
 
}

Hier ist es egal, aber der Compare Match Interrupt ist besser. Es ist auch aus Anwender-Sicht irgendwie logischer wenn du nicht den Startwert vorgibst, sondern den Zeitpunkt an dem das Counter-Register zurückgesetzt wird.

Über die Geschwindigkeit brauchst du dir hier aber keine großen Gedanken zumachen. Die Anwendung ist nicht zeitkritisch.
Um das genau zu beurteilen, müsste man sich den Assembler-Code ansehen.

Das heißt, dass ich die länge nicht über den C-Code berechnen kann und erst Assembler lernen muss :smiley: ?
Gibt es irgwie nicht doch eine Möglichkeit an die längen zu kommen? Es muss nur theoretisch sein, werde es später mit dem Oszi dann genauer messen.

keiner noch irgwelche tipps?