Forum: Mikrocontroller und Digitale Elektronik Anzahl Ereignisse innerhalb der letzten Stunde


von jörg k- (Gast)


Lesenswert?

Hallo!
Ich habe folgendes Problem und mir fällt kein Algorithmus dazu ein.

Ich muss eine Anzahl von Ereignissen innerhalb der letzten Stunde 
zählen.
Timer usw hab ich ja schon programmiert.

So, wenn in der ersten Stunde die Ereignisse eintreten, ist das kein 
Problem. Nur, wenn die Stunde rum ist, wie muss ich dann weiter machen??

Zum Beispiel:
In den ersten 5min der Messung tritt 20 mal dieses Ereignis ein.
In der ersten Stunde insgesamt 200.
In den 5min nach der ersten Stunde sind es 5.

Dann muss die aktuelle Anzahl nach 1 Stunde und 5min 185 betragen.


Meine Fragen:
- Was soll ich nach Erreichen der 1. Stunde mit dem Timerwert machen?
- Wie kann ich wirklich nur die Ereignisse innerhalb der letzten stunde 
zählen?

von holger (Gast)


Lesenswert?

>- Wie kann ich wirklich nur die Ereignisse innerhalb der letzten stunde
>zählen?

Timeoutzähler pro Ereignis. Wenn eine Stunde abgelaufen ist, Ereignis
löschen und Speicher freigeben.

von A. R. (redegle)


Lesenswert?

Jedes Ereigniss abspeichern und mit einem Zeitwert versehen.
Sobald ein Wert älter als eine Stunde ist diesen rauswerfen.

von ozo (Gast)


Lesenswert?

Hmm, naja - als erstes brauchst du eine Zeitbasis, um überhaupt das 
Vergehen einer Stunde erkennen zu können. Da du nicht weißt, wieviele 
Ereignisse insgesamt auftreten können, wäre eine Liste als Datenstruktur 
ganz sinnvoll. In dieser Liste stehen aufsteigende nach Zeitstempeln 
geordnet deine Ereignisse. Alte stehen am Anfang, neue werden hinten 
angefügt. Bei jedem Tick deiner (wie auch immer gearteten Zeitbasis) 
werden die Ereignisse, deren Lebenszeit abgelaufen ist, vom Listenanfang 
entfernt.
So sollte die Liste zu jedem diskreten Zeitpunkt nur Elemente enthalten, 
die innerhalb der letzten Stunde aufgetreten sind.
Wenn eine zeitliche Auflösung von einer Minute ausreicht, kommt dabei 
niemand ins Schwitzen. Da du keine Angaben über die maximale Anzahl der 
Ereignisse, ihren minimalen zeitlichen Abstand usw. gegeben hast, ist 
das zwar eine naive, aber in Grenzen sinnvolle Lösung...

Grüsse

von Verwirrter Anfänger (Gast)


Lesenswert?

Oder wenn du viele Ereignisse hast und die zeitliche Auflösung nicht so 
wichtig ist:
Ereignisse pro Minute
Ein Array von 60 uint32_t, ein total, ein Array index.

Nach jeder Minute wird das Gesamtergebnis um den Array Inhalt an der 
aktuellen Position reduziert, die Anzahl der letzten minute in das Array 
geschrieben, auf das Gesdamtergebnis addiert und der Array index erhöht.

Array index läuft natürlich immer nur von 0-60 in der Runde.

Hat ne fixe Speicherlast für eine fixe Auflösung und braucht nur ein 
paar Takte pro minute.

Geht natürlich auch pro Sekunde mit einen Array von 3600 ints

von Reiner Zufall (Gast)


Lesenswert?

Hallo, wie viel Speicher hast du? Wie oft tritt das Ereignis auf? Wie 
geanu muss die Zeitliche Auflösung sein?

Wenn du es nur Minuten ganau brauchst würde ich ein Arry nehmen und jede 
Minute das den Index erhöhen. (Ringbuffer)

Wenn du es genauer brauchst aber es weniger Ereignisse sein würde ich 
eine Liste nutzen, Jedes Ereignis bekommt ein Element.

von urich R. (Gast)


Lesenswert?

Hallo,

einen Ringspeicher verwenden. Den Wert jede Minute Speichern dann müssen 
nur 60 Werte gespeichert werden. Oder alle 5min oder 10min je nachdem 
wie genau man es brauch.

Gruß
Uli

von jörg k- (Gast)


Lesenswert?

Okay, ich werde es mal versuchen, den Zeitwert immer in einem Array 
abzuspeichern. Hm, frühestens könnte jede 0,5 sekunden ein Ereignis 
eintreten :D Aber nur theoretisch...1 sekunde möglich, aber auch nur 
selten.

Am liebsten wäre mir, wenn man es dann direkt sehen würde.
Dann versuche ich es mal mit einem Riesen-Array mit ner Größe von 3600 
:D

von Verwirrter Anfänger (Gast)


Lesenswert?

Pseudo Code:
1
#define RESOLUTION 60
2
3
uint32_t samples[RESOLUTION]
4
uint32_t total = 0;
5
uint16_t index = 0;
6
7
// Setup
8
void setup(){
9
  for(int i = 0; i < RESOLUTION; i++) {
10
    samples[i] = 0;
11
  }
12
}
13
14
15
//Pro minute ausführen
16
void step(uint32_t count){
17
  total -= samples[index];  
18
  total += count;
19
  samples[index] = count;
20
  index = (++index % RESOLUTION);
21
}

von Reiner Zufall (Gast)


Lesenswert?

jörg k- schrieb:
> Dann versuche ich es mal mit einem Riesen-Array mit ner Größe von 3600

Naja Riesengroß ist das nicht in einem PC oder MC mit SDRam ist das 
nicht viel. Auf einem Atmega oder MSP340 mit 4k ist das gewaltig mit.

Wenn du ein Byte in 2Bit Felder aufteilst kannst du eine 2 sec (max 4 
Ereignisse) Auflösung erreichen und hast nur 450 Byte verbraucht. Sind 
schonmal mehr als 80% gespart :)

von Andreas F. (aferber)


Lesenswert?

jörg k- schrieb:
> Okay, ich werde es mal versuchen, den Zeitwert immer in einem Array
> abzuspeichern.

Wenn nur selten Ereignisse auftreten (wobei durchaus mal zwei kurz 
hintereinander dabei sein dürfen, nur eben nicht permanent), dann ist 
das ein probater Weg.

Wenn die Ereignisse aber meistens dicht aufeinanderfolgen, dann 
verbrauchst du so unnötig eine ganze Menge Speicher, besser ist dann ein 
Ringbuffer, der die Ereignisse pro Zeitintervall zählt. Wenn höchstens 
ein Ereignis pro 0,5 Sekunden auftritt (deine Angabe), und du ca. 1kB 
Speicher erübrigen kannst, kann man das z.B. so machen:
1
#include <stdint.h>
2
#include <stdbool.h>
3
4
bool event_occurred;  // wird gesetzt, wenn ein Event auftritt
5
uint16_t half_second; // 0..7199, zaehlt "Halbsekunden"
6
uint16_t event_count;
7
uint8_t event_bitmap[7200/8];
8
9
void every_half_second(void)
10
{       
11
    uint16_t map_index = half_second/8;
12
    uint8_t map_shift = half_second%8;
13
    uint8_t map_bit = 1<<map_shift;
14
15
    if ((event_bitmap[map_index]&map_bit) != (event_occurred<<map_shift)) {
16
        event_bitmap[map_index] ^= map_bit;
17
        event_count += event_occurred?1:-1;
18
    }       
19
        
20
    event_occurred = false;
21
    half_second = (half_second+1)%7200;
22
}

Wenn ein Event auftritt, muss event_occurred auf true gesetzt werden, 
ausserdem muss (z.B. via Timer) dafür gesorgt werden, dass 
every_half_second() genau jede halbe Sekunde aufgerufen wird.

Je nach Plattform und restlichem Code müssen die Variablen natürlich 
noch zumindest teilweise volatile deklariert werden.

Andreas

von jörg k- (Gast)


Lesenswert?

wow,

also mit dem ersten quelltext klappt es jedenfalls!!

Mit dem Speicher muss ich mal gucken. Werde dann sicherlich auch die 
speichersparende Variante versuchen!!

Besten Dank für die Beispiele!

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.