mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik [S] Ringspeicher [msp430]


Autor: Bergie B. (bergie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Ich messe mit meinem µC (MSP430) Temperaturen. Da meine Temperaturn nur 
selten Sprunghaft ansteigen mache ich eine Mittelwert bildung um 
Messefehler zu minimiren.

Dieses möchte ich in einem Rign Speicher Realiesiernen, bzw habe ich das 
schon gemacht. Die funktion ist auch gegeben, nur die übersichtlichkeit 
ist absulut nicht mehr vorhanden, deswegen würde ich gerne von euch ein 
Beispiel für einen übersichtihcen Ringspeicher sehen über den ich eine 
Mittelwertbildung mache.  Die größe des Speichers soll im Code änderbar 
sein und zwischen 0x02<x<0xFE liegen .. wobei ein Wert um 9 Realistisch 
seien wird denke ich. Darüber hinaus möchte ich einen Mittelwert über 
die letzten 2(oder3,4) Werte Bilden und die mit dem Gesammten Mittelwert 
vergleichen. Fals nun eine zu Große abweichung (+/- Delta_X oder +- 5%) 
bestehen sollte werden die Ringspeicher daten verworfen und neu 
aufgenommen.


LG Bergie

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <stdio.h>

#define RINGBUFFER_SIZE  9
#define INVALID_VALUE    -1000
#define LAST_MEAN_VALUES 3

int RingBuffer[ RINGBUFFER_SIZE ];
int RingBufferCurrent;               // zeigt an, wo der nächste Wert abgelegt wird

void InitRingBuffer( void )
{
  unsigned char i;
  
  RingBufferCurrent = 0;
  for( i = 0; i < RINGBUFFER_SIZE; ++i )
    RingBuffer[i] = INVALID_VALUE;
}

void AddValue( int Value )
{
  RingBuffer[RingBufferCurrent++] = Value;
  if( RingBufferCurrent == RINGBUFFER_SIZE )
    RingBufferCurrent = 0;
}

int MeanValue( void )
{
  unsigned char i;
  unsigned char nrValues = 0;
  long Summ = 0;
  
  for( i = 0; i < RINGBUFFER_SIZE; ++i ) {
    if( RingBuffer[i] != INVALID_VALUE ) {
      Summ += RingBuffer[i];
      nrValues++;
    }
  }
  
  if( nrValues == 0 )
    return INVALID_VALUE;
    
  return Summ / nrValues;
}

int MeanValueOfLast( void )
{
  long Summ = 0;
  unsigned char i = RingBufferCurrent;
  unsigned char nrValues = 0;
  
  do {
    if( i == 0 )
      i = RINGBUFFER_SIZE - 1;
    else
      --i;
    
    if( RingBuffer[i] != INVALID_VALUE ) {
      Summ += RingBuffer[i];
      nrValues++;
    }
  } while( nrValues != LAST_MEAN_VALUES && i != RingBufferCurrent );
  
  if( i == RingBufferCurrent )
    return INVALID_VALUE;
    
  return Summ / nrValues;
}

void PrintValues( void )
{
  unsigned char i = RingBufferCurrent;
  
  printf( "Buffer: " );
  do {
    if( RingBuffer[i] != INVALID_VALUE )
      printf( "%d ", RingBuffer[i] );

    i++;
    if( i == RINGBUFFER_SIZE )
      i = 0;
  } while( i != RingBufferCurrent );
  printf( "\n" );
}

      
int main()
{
  InitRingBuffer();
  
  PrintValues();
  printf( "%d  %d\n", MeanValue(), MeanValueOfLast() );
  
  AddValue( 5 );
  PrintValues();
  printf( "%d  %d\n", MeanValue(), MeanValueOfLast() );

  AddValue( 7 );
  PrintValues();
  printf( "%d  %d\n", MeanValue(), MeanValueOfLast() );
 
  AddValue( 9 );
  PrintValues();
  printf( "%d  %d\n", MeanValue(), MeanValueOfLast() );

  AddValue( 11 );
  PrintValues();
  printf( "%d  %d\n", MeanValue(), MeanValueOfLast() );

  AddValue( 20 );
  AddValue( 20 );
  AddValue( 20 );
  AddValue( 20 );
  AddValue( 20 );
  AddValue( 20 );
  AddValue( 20 );

  PrintValues();
  printf( "%d  %d\n", MeanValue(), MeanValueOfLast() );
}

Anstelle des Sonderfalls INVALID_VALUE, welcher nur am Anfang zum Tragen 
kommt, wenn der Ringspeicher noch nicht vollständig gefüllt ist, 
könntest du ganz einfach auch den Speicher mit deinem ersten Messwert 
fluten. Dann fallen viele Sonderfälle weg und der Code wird noch 
einfacher.

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.