www.mikrocontroller.net

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


Autor: jörg k- (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A. R. (redegle)
Datum:

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

Autor: ozo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Verwirrter Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Reiner Zufall (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: urich R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: jörg k- (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Verwirrter Anfänger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pseudo Code:
#define RESOLUTION 60

uint32_t samples[RESOLUTION]
uint32_t total = 0;
uint16_t index = 0;

// Setup
void setup(){
  for(int i = 0; i < RESOLUTION; i++) {
    samples[i] = 0;
  }
}


//Pro minute ausführen
void step(uint32_t count){
  total -= samples[index];  
  total += count;
  samples[index] = count;
  index = (++index % RESOLUTION);
}


Autor: Reiner Zufall (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include <stdint.h>
#include <stdbool.h>

bool event_occurred;  // wird gesetzt, wenn ein Event auftritt
uint16_t half_second; // 0..7199, zaehlt "Halbsekunden"
uint16_t event_count;
uint8_t event_bitmap[7200/8];

void every_half_second(void)
{       
    uint16_t map_index = half_second/8;
    uint8_t map_shift = half_second%8;
    uint8_t map_bit = 1<<map_shift;

    if ((event_bitmap[map_index]&map_bit) != (event_occurred<<map_shift)) {
        event_bitmap[map_index] ^= map_bit;
        event_count += event_occurred?1:-1;
    }       
        
    event_occurred = false;
    half_second = (half_second+1)%7200;
}

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

Autor: jörg k- (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

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.