Forum: Mikrocontroller und Digitale Elektronik Variablengröße 10-Bit-Integer gesucht


von Timo (Gast)


Lesenswert?

Hallo zusammen,
ich hoffe auf eure Hilfe bei einem kleinen Problem.

Aus AD-Wandlungen müssen viele Daten zwischengespeichert und ausgewertet 
werden.

Das bisherige Variablenarray sieht folgendermaßen aus:
uint16_t temp_i16[1024][3];

Bei einer 16-Bit-Interger Variable bleibt einfach zuviel Speicher 
ungenutzt.

Eine uint10_t Variable wäre mir am liebsten :)

Freue mich über jede Ideen und jeden möglichen Lösungsansatz.

Gruß Timo

von Basti (Gast)


Lesenswert?

wenns dir nicht auf rechenzeit und programmgröße ankommt sondern 
wirklich auf minimalen speicher dann kannst du doch aus je 4 10bit 
werten die "überflüssigen" 2 bit in ein neues byte packen, also aus 4 
10bit variablen 5 8bit variable. könnte aber programmiertechnisch 
aufwendig werden

von crazy horse (Gast)


Lesenswert?

Mit viel Aufwand könntest du in Assembler was basteln.
noch rel. einfach: 3 Byte für 2 Messwerte, also mit nibblen arbeiten. 
Kannst selbstverständlich kannst du auch in 5Byte 4 Messwerte 
unterbringen.
Mit einem Compiler sehe ich da kaum eine Chance.
Du solltest dann entweder in Richtung mehr RAM denken oder über 
Datenreduktion nachdenken.
Das einfachste Verfahren: du speicherst je Messwert nicht die vollen 
10bit, sondern nur die Differenz zum vorherigen. Je nach Signalform und 
Abtastrate reicht das schon. Ist die Differenz zu gross, setzt du als 
Wert 0xff, der nächste Wert ist dann wieder ein Absolutwert.

von Stefan G. (steg13)


Lesenswert?

die 2 High-Bytes liest du ja getrennt aus, also würde ich diese extra 
abspeichern. Immer 4 in einem Byte. Berechnung über MOD 4 aus der 
Speicherstelle.

von Dirk (Gast)


Lesenswert?

Wie wärs damit:

typedef struct FourSamples_tag {
   uint16_t Sample0  : 10;
   uint16_t Sample1  : 10;
   uint16_t Sample2  : 10;
   uint16_t Sample3  : 10;
} FourSamples;  /* Strukturgrösse 40 Bit ==> 5 Byte */

FourSamples Buffer[1024 / 4][3];

Dirk

von Timo (Gast)


Lesenswert?

Hab mir eine mögiche Lösung ausgedacht.
Sie ist nicht schön... nicht kurz... und eigentlich nur aufwendig!

Da für jeden neuen Messwert mehrere If-Abfragen durchlaufen werden, ist 
diese Lösung nichts für gute Performance. Die ständigen Berechnungen und 
das laufende Setzen von Dateninhalten, wirken sich bestimmt auch nicht
vorteilhaft aus :)

Eure Meinungen zu dieser Wurst würden mich aber interessieren!

Gruß Timo

#include<avr/io.h>

//Globale Variable für 1024 Messwerte:
uint8_t messwerte[1024][4];
//

void bit16to10(uint16_t temp_i16_adc, uint16_t messwert_nr)
{
  if(temp_i16_adc>255)
  {
    if(temp_i16_adc>510)
    {
      if(temp_i16_adc>765)
      {
        messwerte[messwert_nr][0]=255;
        messwerte[messwert_nr][1]=255;
        messwerte[messwert_nr][2]=255;
        messwerte[messwert_nr][3]=temp_i16_adc-765;
      }
      else
      {
        messwerte[messwert_nr][0]=255;
        messwerte[messwert_nr][1]=255;
        messwerte[messwert_nr][2]=temp_i16_adc-510;
        messwerte[messwert_nr][3]=0;
      }
    }
    else
    {
      messwerte[messwert_nr][0]=255;
      messwerte[messwert_nr][1]=temp_i16_adc-255;
      messwerte[messwert_nr][2]=0;
      messwerte[messwert_nr][3]=0;
    }
  }
  else
  {
    messwerte[messwert_nr][0]=temp_i16_adc;
    messwerte[messwert_nr][1]=0;
    messwerte[messwert_nr][2]=0;
    messwerte[messwert_nr][3]=0;
  }
}

uint16_t bit10to16(uint16_t messwert_nr)
{
  uint16_t temp_i16_1=0;
  temp_i16_1 = messwerte[messwert_nr][0] + messwerte[messwert_nr][1] + 
messwerte[messwert_nr][2] + messwerte[messwert_nr][3];
  return temp_i16_1;
}

int main(void)
{
  uint16_t temp_i16_1=780;
//Abspeichern der 10-Bit ADC in 4 8-Bit Variablen:
  bit16to10(temp_i16_1,0);
//Überschreiben des temporäre Wertes:
  temp_i16_1=22;
//Wiederherstellen der ADC:
  temp_i16_1=bit10to16(0);
}

von Karl heinz B. (kbucheg)


Lesenswert?

Das ist jetzt aber nicht dein Ernst?

Eine 10 Bit Variable wird gespeichert indem du 4 Bytes
dafür verbrätst ?!?

Da bist du ja noch besser drann, wenn du

uint16_t messwerte[1024];

benutzt.


>      if(temp_i16_adc>765)
>      {
>        messwerte[messwert_nr][0]=255;
>        messwerte[messwert_nr][1]=255;
>        messwerte[messwert_nr][2]=255;
>        messwerte[messwert_nr][3]=temp_i16_adc-765;
>      }

>  temp_i16_1 = messwerte[messwert_nr][0] +
>               messwerte[messwert_nr][1] +
>               messwerte[messwert_nr][2] +
>               messwerte[messwert_nr][3];

So irgendwie hast du noch nicht durchschaut was es mit
einem Stellenwert-System so auf sich hat.

Bei 1456  haben die einzelnen Stellen unterschiedliche
Wertigkeiten! Um die Zahl zu erhalten rechnest du ja
auch nicht   1 + 4 + 5 + 6
sondern   6 + 10 * 5 + 100 * 4 + 1000 * 1

Das ist jetzt im 10-er System. Mit Bytes hast du halt ein
256-er System.



von Karl heinz B. (kbucheg)


Lesenswert?

Bei deinem ersten Posting

uint16_t messwerte[1024][3];

Woher sind die 3 gekommen?
Wieviele Messwerte musst du denn wirklich speichern?

von Timo (Gast)


Lesenswert?

Wichtig sind nur 1024 Messungen mit 10-Bit (ADC)


> Bei 1456  haben die einzelnen Stellen unterschiedliche
> Wertigkeiten! Um die Zahl zu erhalten rechnest du ja
> auch nicht   1 + 4 + 5 + 6
> sondern   6 + 10 * 5 + 100 * 4 + 1000 * 1

Ich glaube nicht, dass du das System der Funktion verstanden hast.

Die ADC ergibt Werte bis 1023 (10 Bit)
Mit einer 16-Bit Variable können Werte bis 65535 gespeicher werden.

Somit verschenke ich 1024 mal massig Speicherplatz!

In den Variablen messwerte[messwert_nr][0]  bis 
messwerte[messwert_nr][3]
Teile ich die max. 1023 auf 4 Variablen (8-Bit) auf. Da diese Variablen 
Werte bis 255 Speichern können, addiere ich am Ende der Rückgabefunktion 
alle Inhalte und erhalte den Ausgangswert. Diesen Wert gebe ich mir 
return zurück.

Für die Abspeicherung der 10-Bit Messwerte benötigt man somit 4*8-Bit 
Variablen und nicht eine mit 16-Bit.

Dies hat nichts mit der Stellenwertigkeit des Messwertes zutun.

Berichtige mich bitte,wenn ich nur Müll von mir gebe.

Timo

von fieser, klugscheissender Rahul (Gast)


Lesenswert?

>Mit einer 16-Bit Variable können Werte bis 65535 gespeicher werden.
>Somit verschenke ich 1024 mal massig Speicherplatz

Interessante Annahme. Es sind aber nur 6Bit...

>Für die Abspeicherung der 10-Bit Messwerte benötigt man somit 4*8-Bit
>Variablen und nicht eine mit 16-Bit.

Da braucht man zum speichern von 10Bit auf einmal 32...
Interessant.

Lernt man Multiplikation und sowas nicht in der Grundschule?

4*8 = 32 = 2*16...

von fieser, klugscheissender Rahul (Gast)


Lesenswert?

>Berichtige mich bitte,wenn ich nur Müll von mir gebe.

Berichtigung...

Vielleicht solltest du dir mal das binäre Zahlensystem genauer angucken.
Dass man inzwischen auch Bits komprimieren kann, wusste ich bis jetzt 
noch nicht.

von Karl heinz B. (kbucheg)


Lesenswert?

>> Bei 1456  haben die einzelnen Stellen unterschiedliche
>> Wertigkeiten! Um die Zahl zu erhalten rechnest du ja
>> auch nicht   1 + 4 + 5 + 6
>> sondern   6 + 10 * 5 + 100 * 4 + 1000 * 1
>
> Ich glaube nicht, dass du das System der Funktion verstanden hast.

Ich glaube nicht, dass du das binäre System oder
Zahlensystem im Allgemeinen verstanden hast.

von Timo (Gast)


Lesenswert?

man darf sich ja auch mal irren, oder?

von Karl heinz B. (kbucheg)


Lesenswert?

> Teile ich die max. 1023 auf 4 Variablen (8-Bit) auf

1023 kann mit 10 Bit dargestellt werden.
4 Variablen zu je 8 Bit macht aber in Summe 32 Bit.

Du willst mir doch jetzt nicht erzählen, dass es effizienter
ist, 10 Bit in insgesammt 32 Bit zu speichern anstatt in
einer Variable die 16 Bit gross ist.

Wenn du

uint16_t messwert[1024]

als Speichermedium benutzt, 'verschenkst' du bei jedem
Messwert 6 Bit

Wenn du

uint8_t messwert[1024][4]

als Speichermedium benutzt, 'verschenkst' du bei jedem
Messwert 22 Bits

Was ist also effizienter?

von Karl heinz B. (kbucheg)


Lesenswert?

> Für die Abspeicherung der 10-Bit Messwerte benötigt man somit 4*8-Bit
> Variablen und nicht eine mit 16-Bit.

Den Satz solltest du dir nochmal auf der Zunge zergehen
lassen.
Um 10 Bit abzuspeichern kann ich jeden Datentyp nehmen
der größer oder gleich 10 Bit ist. Und dann nehme ich
vorzugsweise den Datentyp der möglichst wenig über den
10 Bit liegt.

von tastendrücker (Gast)


Lesenswert?

Die optimale Lösung wäre wohl

 uint8_t messwert[10][128]

und die 1024 Messwerte 'vertikal' zu speichern. Viel Spass beim 
Bitschieben... ;-)

von Karl heinz B. (kbucheg)


Lesenswert?

> und die 1024 Messwerte 'vertikal' zu speichern

Bring ihn nicht durcheinander :-)
Er hat so schon grosse Schwierigkeiten zu verstehen
wie ein Zahlensystem im Allgemeinen funktioniert.

von Karl heinz B. (kbucheg)


Lesenswert?

@Timo

Das was du gemacht hast, ist equivalent zu:

Du musst dir merken wieviele Schafe auf der Weide sind.
Dazu sperrst du sie immer in 255-er Gruppen in eine
Koppel. Anschliessend sagst du: Um rauszukriegen wieviele
Schafe das sind, gehe ich alle Koppeln durch und addiere
die Anzahl der Schafe in jeder Koppel.

So funktionieren Zahlensysteme aber nicht. Ein Stellenwert-
system funktioniert anders. Es sagt: Wieviele Koppeln
sind denn mit 255 Schafen voll? Aha. Ich habe insgesammt
3 volle Koppeln und 1 Koppel mit 12 Schafen. Insgesamt
habe ich also: 3 * 255 + 12 gleich 777 Schafe. Um mir
das merken zu können brauche ich mir aber nur die Zahlen
3 und 12 zu merken. Nicht: 255, 255, 255, 12

Dieser Übergang vom:
  In einem Beutel mit Steinen repräsentiert jeder Stein ein
  Schaf. Wenn die Schafe auf die Weide gehen wird ein Stein
  in den Beutel geworfen; wenn das Schaf nach Hause kommt
  wird ein Stein aus dem Beutel genommen. Ist der Beutel
  leer, so sind wieder alle Schafe zu Hause

zu
  Für jeweils 10 Schafe wird ein Stein aus dem Beutel genommen
  und dafür ein Stein in einen anderen Beutel getan (der
  dann jeweils 10 Schafe repräsentiert). Ansonsten bleibt
  alles andere gleich

..., dieser Übergang ist die Geburtsstunde der Mathematik
in der Menschheitsgeschichte. Ohne ihn würden wir heute
nicht dort sein, wo wir heute sind. Das ist die Geburtsstunde
eines Stellenwertsystems wo die gleichen Ziffern unterschiedliche
Dinge bedeuten, jenachdem an welcher Stelle einer Zahl sie
eingesetzt werden. Und es unterscheidet sich fundemental von
simplen Abzählsystemen.

von Falk (Gast)


Lesenswert?

@Karl heinz Buchegger

> ..., dieser Übergang ist die Geburtsstunde der Mathematik
> in der Menschheitsgeschichte. Ohne ihn würden wir heute
> nicht dort sein, wo wir heute sind.

Kurz vor dem Abgrund?

;-)

MFG
Falk

von Karl heinz B. (kbucheg)


Lesenswert?

Falk wrote:
> @Karl heinz Buchegger
>
>> ..., dieser Übergang ist die Geburtsstunde der Mathematik
>> in der Menschheitsgeschichte. Ohne ihn würden wir heute
>> nicht dort sein, wo wir heute sind.
>
> Kurz vor dem Abgrund?
>
> ;-)

Wie ich immer sage:
Diesem Planeten kann nichts besseres passieren,
als dass wir uns selbst ausrotten.

Sagt ein Planet zum anderen
"Mir gehts gar nicht gut. Ich hab Homo Sapiens."
Sagt der andere
"Das geht vorbei"

:-)

von Timo (Gast)


Lesenswert?

Ich muss zugeben... ein sehr dummer Denkfehler von mir.
Egal sag ich da nur! :)

Fie Geschichte mit den Schafen hätte man sich sparen können. Hatte 
meinen Irrtum bereits erkannt:

> Datum: 10.01.2007 16:10
> man darf sich ja auch mal irren, oder?

Auch wenn meine "Lösung" sehr dürftig und völlig am Ziel 
vorbeigeschossen ist, sollte das noch kein Grund sein sich über die 
betreffene Person(diesmal leider Ich) lustig zu machen!

Warscheinlich sitzt ihr einfach schon zu lange am Computer und schaut 
nur aus dem Kellerfenster...

von Martin #. (martin-)


Lesenswert?

Ich habe mir dazu folgendes ausgedacht 3x10bit in eine 32bit Variable, 
man Verliert jeweils 2 Bits bei 1024 werten sind das also ca. 85.5byte 
verlust.
Man brauxht also 1024/3=341.3 ~ 342x32bit Variablen: uint32_t temp[342]
und das macht 1368Byte anstatt 2048 wenn man einfach ein uint16_t Array 
verwendet.
Hier beispiel:
1
#include <stdio.h>
2
#include <inttypes.h>
3
4
int main()
5
{
6
    
7
    uint32_t temp, var32;
8
    /*es werden hoestens 10bit verwendet*/
9
    uint16_t a=342 , b=1023, c=987;
10
11
    /*3 10Bit a,b,c Variablen in eine 32Bit Variable codieren*/
12
    var32 = 0;
13
14
    temp = a;
15
    temp = temp<<20;
16
    var32 |= temp;
17
18
    temp = b;
19
    temp = temp<<10;
20
    var32 |= temp;
21
22
    temp = c;
23
    temp = temp<<0;
24
    var32 |= temp;
25
    printf("a:%u  b:%u  c:%u\n", a, b, c);
26
27
    /*3 10Bit Variablen aus einer 32Bit Variable decodiern*/
28
    temp = var32;
29
    temp = temp>>20;
30
    a = temp & 0x3ff;
31
32
    temp = var32;
33
    temp = temp>>10;
34
    b = temp & 0x3ff;
35
36
    temp = var32;
37
    temp = temp>>0;
38
    c = temp & 0x3ff;
39
    printf("a:%u  b:%u  c:%u\n", a, b, c);
40
41
    return 0;
42
}

Das funktioiert vorausgesetzt der Compiler trimmt die Arrays nicht auf 
Werte 2^N.

von Karl H. (kbuchegg)


Lesenswert?

> sollte das noch kein Grund sein sich über die
> betreffene Person(diesmal leider Ich) lustig zu machen!

Ich mach mich doch nicht über dich lustig.
Das würde dann etwas anders aussehen.

Mir ist nur wichtig, dass du auch verstehst wo und
vor allen Dingen warum du falsch liegst und ev.
noch ein paar Dinge zum drüber nachdenken dazuzumixen.
Man kann sehr viele Dinge lernen wenn man die ganz
banalen Dinge im Leben beobachtet wie zb. wie sind
eigentlich unsere Zahlen aufgebaut, welche Eigenschaften
liegen da zugrunde. Diese Dinge sind ganz banal und einfach,
nur entdecken muss man sie erst mal.
Genauso wie ich ein eifriger Verfechter des 'gesunden
Hausverstandes' bin. Und der Hausverstand muss Alarm schlagen
wenn ich die Idee verteidige 10 bit in 32 bit zu speichern.

Aber hey. Ich verenne mich auch manchmal in Ideen bis jemand
kommt und sagt: Geh mal 2 Schritte zurück und schau dir das
nochmal an. Das kann so nicht sein, weil ...



von fieser, klugscheissender Rahul (Gast)


Lesenswert?

>Ich mach mich doch nicht über dich lustig.

Ich aber.
Wer s0lchenen Mist verzapft, hat es meiner Meinung nach nicht anders 
verdient. Zumindest wurde ich bisher genauso behandelt...

>Warscheinlich sitzt ihr einfach schon zu lange am Computer und schaut
>nur aus dem Kellerfenster...

Mein PC steht auf dem Dachboden.
Wenn die Sonne scheint und das Wetter es zu lässt (die Sonne scheint 
grundsätzlich, es sind nur häufig viele Wolken dazwischen, die auch noch 
Pipi machen...), setze ich mich mit meinem Notebook auch gerne in den 
Garten.

>Ok,Ok Arschloch.
>Höflichkeit ist wohl nicht eine deiner Stärken...

Zumindest bin ich nicht ausfallend geworden...

von Ralph (Gast)


Lesenswert?

Hallo

Jetzt mal zurück zur eigentlichen Frage.

Warum speicherst du denn die kompletten 10 bit ?
Wenn du die oberen 8 Bit speicherst, hast du eine Genauigkeit die in den 
meisten Fällen wohl ausreichen wird.
Mindestens das letzte, wenn nicht sogar die letzten beiden Bits sind 
sowieso durch das Signalrauschen am Eingang unbrauchbar.

Und somit benötigst du nur N * 1 Byte.





von Martin #. (martin-)


Lesenswert?

Woher willst du wissen, dass da so ein riesen Rauschen gibt, dass bei 
10Bit Auflösung 1 oder 2 bits unbrauchbar sein sollen?
Wenn der Messbereich z.B 0-2V liegt, dann beträgt die Auflösung etwa 
2mV, meistens ist doch das Rauschen erheblich kleiner.

von Ralph (Gast)


Lesenswert?

1.
Les mal die Spec vom ADC. In (fast ) jeder Spec steht drin das die 
Wandlung mit der Genauigkeit von +- 1 Bit erfolgt.

2.
Die Messung ist nur so genau wie die Referencespannung, d.h. Istzde Ref 
Spannung von einem zb 7805 ist dort ein größerer Fehler drauf als wenn 
es eine präzise Spannungsreference ist. Eine solche präzise 
Spannungsreference ist vom Preis mit Sicherheit außerhalb einer 
einfachen Bastelschaltung.


von Peter D. (peda)


Lesenswert?

Super, wie sich hier gefetzt wird.


Ich habs jedenfalls gleich verstanden, was er meinte:

10 Bit in 16 Bit ergibt 37% Verlust
3 Worte a 10 Bit in 32 Bit aber nur 6%.


Ich denke aber eher, die Optimierung sollte besser an anderer Stelle 
ansetzen:

Warum müssen unbedingt 3 * 1024 Meßwerte gespeichert werden ?

Wenn man diese Zahl verringert (Vorverarbeitung, Differenzspeicherung), 
dann spart man wirklich was.


Peter

von Philipp S. (philipp)


Lesenswert?

> Warum speicherst du denn die kompletten 10 bit ?
> Wenn du die oberen 8 Bit speicherst, hast du eine Genauigkeit
> die in den meisten Fällen wohl ausreichen wird.

Sehr pessimistisch. Was aber wohl richtig ist: in den meisten 
Anwendungen wird keine so hohe relative Auflösung gebraucht, d.h. bei 
Werten über 100 interessiert das letzte Bit nicht mehr usw.

In solchen Fällen kann man mit sehr wenig Aufwand eine 10-Bit-Zahl in 6 
Bit plus 2 Bit Exponent umwandeln, die dann in einem Byte gespeichert 
wird. Dann hat man bei kleinen Signalen noch einen Wert, bei größeren 
Werten sinkt die absolute Genauigkeit, aber die relative Auflösung 
bleibt.

Habe ich nie verstanden, weshalb das z.B. bei der Audio-CD nicht so 
gemacht wurde (z.B. 12 Bit Mantisse + 4 Bit Exponent statt 16 
Bit-Integer). Im Fortissimo werden Bits verplempert für Feinheiten, die 
für das Ohr nicht wahrnehmbar sind, dafür hört man im Pianissimo das 
Quantisierungsrauschen. Ist doch doof! Unser Ohr funktioniert relativ!

Zurück zum Thema: die Mantisse/Exponent-Codierung trägt auch dem Umstand 
Rechnung, daß eine der größten Fehlerquellen die Nichtlinearität ist, 
bei großen Werten ist die letzte Stelle also noch deutlich weniger wert.

von Karl heinz B. (kbucheg)


Lesenswert?

> Ich habs jedenfalls gleich verstanden, was er meinte:
>
> 10 Bit in 16 Bit ergibt 37% Verlust
> 3 Worte a 10 Bit in 32 Bit aber nur 6%.

Nur hat er das nicht implementiert :-)
Er hat 1 Wort a 10 Bit in 32 Bit

> Ich denke aber eher, die Optimierung sollte besser an anderer Stelle
> ansetzen:
>
> Warum müssen unbedingt 3 * 1024 Meßwerte gespeichert werden ?

Jetzt kommt der Clou.
Es sind gar nicht 3*1024 Messwerte.
Es sind nur 1024 Messwerte. Aber er hatte jeden Messwert auf 3
uint16 verteilt.

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.