Forum: Compiler & IDEs bis 30 Minuten zählen


von Tobias (Gast)


Lesenswert?

Hallo,

ich bastle gerade ein Alarmierungssystem mit einem Atmega16 das 8 
Schleifen überwacht und je nach dem bestimmte SMS über ein Handy 
verschickt. Jetzt möchte ich das Handy alle 30 Minuten nach dem 
Ladezustand fragen und entsprechend reagieren.
Idee war es den 8bit Timer zu nutzen(da einfacher zu konfigurieren), bei 
Überlauf im der Interrupt-Routine eine 16bit Variable hochzählen zu 
lassen. Diese wird dann im Hauptprogramm mit einem einfachen if 
überprüft.
Takt sind 16 MHz, Prescaler 1024 ergibt 15,625kHz. Bei 256 Zählschritten 
ergibt das alle 0,016384 s einen Überlauf. Macht das Sinn oder sollte 
ich den 16bit Timer nehmen, wobei ich auch hier immer noch die externe 
Zählvariable benötige.

Gruß

von 42 (Gast)


Lesenswert?

Wenn das Handy den Rest der Zeit schläft auf jeden Fall einen 
16-Bit-Timer nutzen, je seltener das Gerät aufwacht desto besser für den 
Akku.

Mal nebenbei: 30*60/0,016384=~109000 > 2^16-1

von Testfall (Gast)


Lesenswert?

Ich bin mir nicht sicher, ob du Murks gerechnet hast, oder ich einfach 
nicht wach bin. Ich komme auf:

16 000 000 Hz Systemtakt
    15 625 Hz Nach Prescaler von 1024
        61 Hz Overflows

Eine in dem Overflow-Interrupt hochgezählte 8-Bit Zahl läuft also alle 4 
Sekunden über.
Also alle 7 bis acht Overflows der eigenen Zählvariablen im Interrupt 
die Aktion auslösen.

Oder?

von 42 (Gast)


Lesenswert?

Testfall schrieb:
> [...]

Alles richtig, aber: Er schrieb 30 Minuten.

von 42 (Gast)


Lesenswert?

42 schrieb:
> Wenn das Handy den Rest der Zeit schläft
Das sollte natürlich "der µC" heißen. Ich glaube der der nicht wach ist 
bin ich. :-(

von Testfall (Gast)


Lesenswert?

Uh, ja, hab' nen Schritt im Kopf übersprungen.

Ich habe also 61 Hz in der Interrupt Routine. Macht ca. alle 0,2 
Sekunden.
Hier zähle ich eine 8 bit Zahl hoch (meinetwegen temp1). 61Hz durch 256 
macht ca. 4.4. Also habe ich alle 4.2 Sekunden einen "Überlauf" von 
"temp1". Wenn dem so ist, zähle ich "temp2" hoch.
Wenn temp2 überläuft sind rund 18 Minuten vergangen.
Das macht man zwei mal.
Rund 30 Minuten.

Wenn man das "T"-Flag noch nicht brauchte, kann man es nehmen, um die 
"zweite Rund temp2" anzuzeigen.

von Testfall (Gast)


Lesenswert?

Wenn man die Register braucht, kann man die Zahlen, zwischendurch ins 
RAM schmeißen. Man braucht sie ja nur in der Interrupt-Routine.

von Tobias (Gast)


Lesenswert?

42 schrieb:
> Mal nebenbei: 30*60/0,016384=~109000 > 2^16-1

Hmm stimmt, das hab ich irgendwie beim Rechnen übersehen. :-)

Den Controller einschlafen zu lassen ist momentan nicht 
geplant/umgesetzt. Bin gerade erst dabei micht in die 
Controllerprogrammierung einzuarbeiten. Der überprüft gerade in einer 
Endlosschleife die Eingänge.

Momentanes Ergebnis der Diskussion:

Benutze den 16bit Timer mit einer Zusatzvariablen. Wobei es doch dann 
eigentlich auch keinen Unterschied macht obe ich den 8 oder 16bit Timer 
benutzte, nur dass ich eben beim 8bit Timer eine größere Zusatzvariable 
zum Zählen benötige.

Wichtig vielleicht noch, es ist nicht zwingend nötig die 30 Minuten 
einzuhalten. Ein paar Minuten hin oder her ist egal.

Gruß

von Tobias (Gast)


Lesenswert?

Ich hab hier mal die Timer1 Konfiguration eingestellt. Stimmt das dann 
so?

Der Timer erzeugt dann alle 4 Sekunden ein Interrupt, der den zaehler1 
um 1 erhöht. In der Hauptschleife frage ich zaehler1 ab. Bei zaehler1 
größer gleich 449( was dann 4 Sekunden x 450 Zählschritten = 1800 
Sekunden = 30 Minuten ergibt) wird der Ladezustand abgefragt.
1
void main (void)
2
{
3
...
4
uint8_t zaehler1=0;
5
TCCR1B |= (1<<WGM12); // CTC Modus einschalten, Vergleichen mit OCR1A
6
TCCR1B |= (1<<CS00) | (1<<CS02);   // Prescaler 1024
7
OCR1A=62499; //Vergleichszahl für Timer1
8
TIMSK |= (1<<OCIE1A);  // Compare Interrupt erlauben
9
10
if (zaehler1>=449)  
11
{
12
     zaehler1=0; //zaehler1 zurücksetzten
13
     hier wird der Ladezustand abgefragt und entsprechend reagiert
14
}
15
...
16
}
17
18
ISR (TIMER1_COMPA_vect)
19
{
20
  zaehler1++;
21
}

von Stefan E. (sternst)


Lesenswert?

1) Wie soll denn der Interrupt eine lokale Variable verändern können?

2) Wie soll ein uint8_t jemals größer (oder gleich) 449 sein können?

3) Informiere dich über "volatile".

von Tobias (Gast)


Lesenswert?

Oh man, manchmal hab ich echt Tomaten auf den Augen und nen Knoten im 
Hirn.

Danke

von Tobias (Gast)


Lesenswert?

Man sollte den Code dann doch kopieren und nicht einfach nochmal aus dem 
Kopf abschreiben...
so siehts eigentlich aus:
1
volatile uint16_t zaehler1=0;
2
3
void main (void)
4
{
5
...
6
TCCR1B |= (1<<WGM12); // CTC Modus einschalten, Vergleichen mit OCR1A
7
TCCR1B |= (1<<CS00) | (1<<CS02);   // Prescaler 1024
8
OCR1A=62499; //Vergleichszahl für Timer1
9
TIMSK |= (1<<OCIE1A);  // Compare Interrupt erlauben
10
11
if (zaehler1>=449)  
12
{
13
     zaehler1=0; //zaehler1 zurücksetzten
14
     hier wird der Ladezustand abgefragt und entsprechend reagiert
15
}
16
...
17
}
18
19
ISR (TIMER1_COMPA_vect)
20
{
21
  zaehler1++;
22
}

zaehler1 ist außerhalb der main-Schleife mit volatile als uint16_t 
deklariert und sollte doch somit global verfügbar sein oder?

Gruß

von Stefan E. (sternst)


Lesenswert?

Eine Kleinigkeit noch, die aber vermutlich weiter keine Rolle spielt: 
wenn du den Zähler bei >=449 zurücksetzt, hast du nur 449 Zählschritte, 
keine 450.

von Tobias (Gast)


Angehängte Dateien:

Lesenswert?

Ja stimmt, Danke.

Ich hab jetzt aber nochmal ein Problem.
Der Compiler mault:
207: error: static declaration of '__vector_6' follows non-static 
declaration
207: error: previous declaration of '__vector_6' was here
260: error: expected declaration or statement at end of input
und ich kann nichts damit anfangen. Kann mir nochmal jemand dabei 
helfen? Der Code ist angehängt.

Danke

von Stefan E. (sternst)


Lesenswert?

Tobias schrieb:
> Kann mir nochmal jemand dabei helfen?

Bei main die schließende Klammer vergessen.

von Tobias (Gast)


Lesenswert?

Ok nochmals Danke.

Ich hör glaub am besten für heute auf und mach was anderes. ;-)

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.