Forum: Mikrocontroller und Digitale Elektronik Eine weitere Bitumrechnung


von STm32 (Gast)


Angehängte Dateien:

Lesenswert?

Guten Abend,

Komme bei der ganzen Bitumrechnung nicht mehr klar. Habe folgendes 
Problem: Möchte die Dezimalzahl meines AD Wandlers (12-Bit Auflösung, 
3.3V Ref) in die Spannung umrechnen und per UART übertragen. Fordert 
mich mehr als ich dachte.
1
uint8_t buffer[10];
2
3
void scale(uint32_t vol){
4
5
  uint8_t i;
6
  uint8_t a;
7
  uint8_t b;
8
  uint8_t c;
9
10
  i = vol*100*0.0008056640;
11
  a = i/100;
12
  b = (i- (a*100))/10;
13
  c = (i- (a*100 + b*10));
14
15
  sprintf(buffer, "%hd.%hd%hdV\n",a,b,c);
16
  HAL_UART_Transmit(&huart2, buffer, 9, 1000);
17
}

Im Anhang sieht man was ich empfange. Wahrscheinlich ein kleiner dummer 
Fehler aber finde ihn nicht. Vllt hat jemand langeweile und hilft mir. 
Danke

von Irgendwer (Gast)


Lesenswert?

1
uint8_t i = vol * 100 * 0.0008056640;

...und wie ist der Wertebereich von uint8_t und welcher Typ von Zahlen 
wird damit dargestellt?

von STK500-Besitzer (Gast)


Lesenswert?

STm32 schrieb:
> Im Anhang sieht man was ich empfange. Wahrscheinlich ein kleiner dummer
> Fehler aber finde ihn nicht. Vllt hat jemand langeweile und hilft mir.
> Danke

Wenn du sowieso schon sprintf verwendest, kannst du auch gleich %f oder 
in deinem Fall %.2f verwenden.
Einfach mal sprintf googlen.
%hd geh;rt da eh nicht rein. Das gehört zu scanf

von Karl M. (Gast)


Lesenswert?

Das ist doch normaler Dreisatz:

X Bit (ADC Messwert)
max Zählerwert (100%) 4095 Bit (12-Bit Auflösung)
V_max = 3.3V

gesucht:
V_mess

V_mess    X
------ = ----
V_max    4095

nach umformen gilt:

V_mess = X * V_max /4095

man muss nur einen passenden Zahlentyp wählen.

Schau dir bitte mal 32Bit float an.

von STK500-Besitzer (Gast)


Lesenswert?

Irgendwer schrieb:
> uint8_t i = vol  100  0.0008056640;
> ...und wie ist der Wertebereich von uint8_t und welcher Typ von Zahlen
> wird damit dargestellt?

LOL hab ich überlesen.

von my2ct (Gast)


Lesenswert?

Karl M. schrieb:
> Schau dir bitte mal 32Bit float an.

Warum braucht man zur Darstellung von 12-Bit Werten eine 32Bit float 
Zahl.

Nur um bei der Ausgabe einen Dezimalpunkt zu erzeugen?
Dafür reicht es, an passender Stelle ein 0x2E zum UART zu schicken.

von STK500-Besitzer (Gast)


Lesenswert?

my2ct schrieb:
> Warum braucht man zur Darstellung von 12-Bit Werten eine 32Bit float
> Zahl.

Wie soll er dann dann die Umrechnung in Volt hinbekommen?

von Karl M. (Gast)


Lesenswert?

my2ct schrieb:
> Karl M. schrieb:
>> Schau dir bitte mal 32Bit float an.
>
> Warum braucht man zur Darstellung von 12-Bit Werten eine 32Bit float
> Zahl.
>
> Nur um bei der Ausgabe einen Dezimalpunkt zu erzeugen?
> Dafür reicht es, an passender Stelle ein 0x2E zum UART zu schicken.

Ja mir klar, aber der TO muss erst mal einen Fuß auf den Boden bekommen.

Sonst hätte ich auch schon eine Optimierung vorgestellt.

von Karl M. (Gast)


Lesenswert?

STm32,

wenn man anstatt V_max = 3,3V eine anderen Wertebereich nutzen möchte,
z.B. !!!!! 1mV,
dann wäre V_max = 3300mV und schon passt das in Ergebnis mit 
Nachkommastellen in eine 16Bit Variable.

Bei Berechnungen müssen dann auch Bereichsüberläufe beachtet werden.
D.h. eine Multiplikation von: 16Bit * 16Bit passt in 32Bit.

von MaWin (Gast)


Lesenswert?

STm32 schrieb:
> Wahrscheinlich ein kleiner dummer Fehler a

In i, a, etc. passe  nur Werte von 0 bis 255 ohne Nacbkommastellen.

Deine mathematischen Formeln erzeugen aber weit mehr.

Ein sprintf zu verwenden ist Wahnsinn, das ist eine der aufwändigsten 
Funktionen die es gibt.

Rechne deine vol in eine 10Millivoltzahl um.

int i=(vol x 100L)/1241;

und schreibe selber die Ziffern mit Komma

char buffer[6];
buffer[5]='\0';
buffer[4]='V';
buffer[3]='0'+(i%10);
i/=10;
buffer[2]='0'+(i%10);
i/=10;
buffer[1]='.';
buffer[0]='0'+(i%10);

von STm32 (Gast)


Lesenswert?

Gebe die Werte a, b und c auf meinem LCD-Display aus. Die Umrechnung des 
Dezimalwertes in die Spannung und in die Dezimalstellen passt also. Habe 
gedacht dass es an dem sprintf liegt.

von gcc8 (Gast)


Lesenswert?

Tausche deinen GCC mal durch GCC8 aus und mach -Wall -Werror an.
Dann lässt er dich das nicht kompilieren, weil du sprintf deinen Buffer 
überlaufen kann.

von STm32 (Gast)


Lesenswert?

MaWin schrieb:

>
> char buffer[6];
> buffer[5]='\0';
> buffer[4]='V';
> buffer[3]='0'+(i%10);
> i/=10;
> buffer[2]='0'+(i%10);
> i/=10;
> buffer[1]='.';
> buffer[0]='0'+(i%10);

Mhm. Reicht eigentlich für die kleine Anwendung. Werde dann wohl noch 
etwas den Code verbessern.Danke

von my2ct (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> Wie soll er dann dann die Umrechnung in Volt hinbekommen?

Durch Festkommaarithmetik

Die cV ergeben sich aus X * 5281 / 65536

von foobar (Gast)


Lesenswert?

Variante 1, einfach Millivolt ausgeben:
1
void send_millivolt(uint16_t val)
2
{
3
  char buf[16];
4
  uint16_t x = (val * 3300ul + 2048) / 4095;
5
6
  HAL_UART_Transmit(&huart2, buf, sprintf(buf, "%umV\n", x), 1000);
7
}
Oder etwas anders, diesmal mit Nachkommastellen:
1
void uart_puts(char *buf)
2
{
3
  HAL_UART_Transmit(&huart2, buf, strlen(buf), 1000);
4
}
5
6
void send_volt(uint16_t val)
7
{
8
  char buf[16];
9
  uint16_t x = (val * 330ul + 2048) / 4095;
10
11
  sprintf(buf, "%u.%02uV\n", x/100, x%100);
12
  uart_puts(buf);
13
}

Das "ul" in "* 3300ul" damit eine 32-bit-Multiplikation gemacht wird. 
Das "+ 2048" zum Runden.  Zerlegung der Zahl mittels "/" und "%".

von Peter D. (peda)


Lesenswert?

Karl M. schrieb:
> Bei Berechnungen müssen dann auch Bereichsüberläufe beachtet werden.

Das hat mich früher auch genervt bzw. Fehler verursacht. Daher mache ich 
solche Rechnungen nur noch in float. So schlecht sind die Libs von 
AVR/8051 ja nicht.
Wenn "?" angezeigt werden, muß man noch den float Teil von sprintf dazu 
linken.
Die ersten AVRs litten noch unter Flash-Geiz (nur 1..2kB), aber das ist 
lange her.

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.