Mittelwert Zweierkomplement

Gast #2258193
Lesenswert?

Ich habe ein kleines Problem: Ein 16Bit ADC liefert sein Ergebnis im 
Zweierkomplement, und zwar 2x 8Bit. Nun möchte ich das Ergebnis 16x 
Mitteln, um das Rauschen wegzubekommen.
Eingelesen wird der Wert so:
1
HighByte = DataRead();
2
LowByte = DataRead();
Wie kann ich davon am schnellsten auf einem AVR den Mittelwert bilden 
und am Ende den 16Bitigen Wert erhalten?
#2258221
Lesenswert?

Bist du sicher das dein 16Bit ADC dir 2x8Bit gibt die du mitteln kannst?

Für mich hört sich das eher nach MSB und LSB an.
1
ushort Messwert = (MSB << 8) + LSB;

Zum mitteln brauchst du dann mehr als einen Messwert.

Summe der Messwerte / Anzahl der Messwerte.

Das der ADC dir seinen Wert als 2er komplement bereitstellt ist ein 
Vorteil, du kannst einfach deine Messwerte aufaddieren ohne etwas zu 
beachten.

Falls du auf Genauigkeit verzichten kannst, dann benutze einfach nur das 
MSB als Messwert, das LSB infach ignorieren. Aber pass auf das du beim 
umrechenen zurück zu Spannung dann auch alles richtig machst.

Vref / 8  != Vref / 16
Gast #2258222
Lesenswert?

1
HighByte = DataRead();
ist doch wohl recht eindeutig C/C++...
Pascal hätte := und Basic kein ;

Würde es also so funktionieren?
1
uint32_t erg = 0;
2

3
for (i=0; i<16; i++) {
4

5
  HighByte = DataRead();
6
  LowByte = DataRead();
7

8
  erg += ( ( HighByte * 256) + LowByte );
9

10
}
11

12
erg /= 16;
Gast #2258224
Lesenswert?

Du machst Dir eine 32 Bit "Akkumulatorvariable"

1) Jeden neuen ADC Wert zum Akkumulator addieren
2) Das jeweilige Ergebnis sichern und durch 16 teilen, also um 4 Bit 
nach links schieben.
3) Diese Ergebnis vom ursprünglichen Akkumulatorergebnis abziehen
4) Das so resultierende Ergebnis wieder 4 Bit nach links geschoben 
ergibt den (ungefähren) Mittelwert.
#2258235
Lesenswert?

Ja, dieser Code sollte korrekt sein.

Aber je nach Anwendung (z.B. sharp Infrarot Sensor) würde ich eher die 
LSBs maskieren anstelle eine Schleife zu betretten.

Aber kommt halt immer drauf an, eine Wetterstation wird wohl kaum wegen 
zu langsamer Sensorauswertung gegen die Wand fahren.

Du musst einfach Anhand deiner Daten zusehen inwiefern sich das rauschen 
bemerkbar macht. Es kann gut sein das deine Schleife sich auch durch
1
short Messwert = (MSB << 8) + (LSB & 0xF0);

ersetzen ließe ohne dass es einen Unterschied macht.


BTW.

Dein 16 Bit ADC gibt dir sein Ergebnis als Zweierkomplement zurück. Bist 
du sicher, dass er auch negative Ergebnisse liefern kann? Ansonsten 
würde ich eifach mal behaupten es ist ein 15 Bit ADC ;)

So oder so, signed Variable wirds schon packen. Aber wenn er 16 Bit 
genauigkeit hat, also Vin = Vref -> Mess = 0xFFFF dann musst du 
unbedingt unsigned verwenden.

Bei 15 Bit währe dein Ergebniss ohnehin 0x7FFF und damit in jedem Fall 
unkritisch.
Gast #2258238
Lesenswert?

Der ADC ist differenziell und liefert tatsächlich 16Bit im 
Zweierkomplement. Also Werte von 1000000000000000 bis 0111111111111111.
Und der angeschlossene Sensor rauscht tatsächlich, daher soll gemittelt 
werden und nicht maskiert, dann könnte ich auch einen 12Bit ADC nehmen.
#2258430
Lesenswert?

Dem Mittelwert ist es wurscht, ob signed oder unsigned, er funktioniert 
immer richtig.
Beim Teilen mußt Du bei signed das arithmetic Shift right (ASR) nehmen, 
der C-Compiler macht das automatisch richtig. In Assembler mußt Du es 
selber auswählen.
Vorausgesetzt, Du teilst durch 2-er Potenzen.


Peter

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren