Forum: Mikrocontroller und Digitale Elektronik BASCOM ADC Spannung in mV berechnen mit Kalibrierung ohne Fließkomma


von Robert G. (petrock)


Lesenswert?

Hallo zusammen,

Ausgangssituation: Controller wird mit 3,3V versorgt.
Spannungsteiler mit 220K und 68K, um bei der anliegenden LiPo-Spannung 
von 3,35V bis 4,25V unter die interne Referenzspannung von 1,1V zu 
kommen.
Die LiPo-Spannung soll permanent überwacht werden und mit dem Wert in mV 
intern weitergerechnet werden.

Gewünschte Messgenauigkeit: 4 Stellen, Ausgabe und interne 
Weiterverarbeitung in mV

Code-Idee:
1
Config Adc = Single , Prescaler = Auto , Reference = Internal_1.1
2
3
Dim N As Byte
4
Dim Adc_messergebnis As Word                                'Der ADC liefert 10 Bit, die passen nicht in 1 Byte (8 Bit), von daher Word (= 2 Byte, 16 Bit)
5
Dim Millivolt As Single                                     'Gegen LONG austauschen!
6
7
Const Adc_multipli = 1.07421875                             'interne Referenzspannung 1100 Millivolt / 1024
8
Const Rvh = 3.235294117647059                               'Verhältnis der Widerstände am Spannungsteiler. R1 (in kOhm) / R2 (in kOhm)    220(K) / 68(K)
9
'Const Kalibrierung = 1.288                                  'Kalibrierung: Wert multiplizieren ->ANPASSEN! Wert solange anpassen, bis das Ergebnis dem Wert am Multimeter entspricht
10
Const Kalibrierung = 830                                    'Kalibrierung: Wert in mV addieren -> ANPASSEN! Wert solange anpassen, bis das Ergebnis dem Wert am Multimeter entspricht
11
12
Do
13
14
    Adc_messergebnis = Getadc(0)
15
    Millivolt = Adc_messergebnis * Adc_multipli
16
    'STATT ADC_MULTIPLI: Millivolt = Adc_messergebnis * 1100                     'ADC-Messergebnis * interne Referenzspannung (1100 mV)  -> Ergebnis würde in eine LONG Variable passen
17
    'STATT ADC_MULTIPLI:Millivolt = Millivolt / 1024
18
    Millivolt = Millivolt * Rvh
19
    'Millivolt = Millivolt * Kalibrierung
20
    Millivolt = Millivolt + Kalibrierung
21
22
   Print N ; " ADC-Wert: " ; Adc_messergebnis
23
   Print "Spannung: " ; Millivolt ; " mV"
24
25
   Incr N
26
   Wait 1
27
28
Loop

Berechnung zu Fuß:
Bei (laut Multimeter) 3,73 V am Spannungsteiler liegen am ADC Pin (laut 
Multimeter) 0,88V an.
Ausgegebener ADC Wert: 835 * 1.07421875 = 896.97265625 (Millivolt)
* Verhältnis der Widerstände 3.235294117647059 = 2901.970358455883
+ Kalibrierwert 830 = 3731.970358455883 = ~ 3731mV (= ~ 3,73V)

Stimmt das grundsätzlich so vom Ablauf?

Passt das mit der Kalibrierung? Besser multiplizieren oder addieren 
(oder egal!?).

Ich möchte vollständig auf Fließkommaberechnungen verzichten und die 
Single Variable durch Long oder noch besser Word ersetzen. Wie muss ich 
hierbei vorgehen? Mach das mit den Const FestKOMMAwerten dann überhaupt 
noch Sinn bei Long/Word?

Wie werde ich die Nachkommastellen los? Wenn ich Single durch Long 
ersetze, sind die Nachkommastellen verständlicherweise weg aber der Wert 
stimmt natürlich auch nicht mehr.


Danke vorab!

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?


von Robert G. (petrock)


Lesenswert?

Meinst du damit ich soll als erstes die Festkommawerte so erhöhen, dass 
bei denen das Komma verschwindet?
Aus "Const Adc_multipli = 1.07421875" würde 1074 und aus "Const Rvh = 
3.235294117647059" würde 3235.

von Falk B. (falk)


Lesenswert?

@Robert G. (petrock)

>Meinst du damit ich soll als erstes die Festkommawerte so erhöhen, dass
>bei denen das Komma verschwindet?

Ja. Man rechnet einfach alles in mV.

>Aus "Const Adc_multipli = 1.07421875" würde 1074 und aus "Const Rvh =
>3.235294117647059" würde 3235.

Bingo!

von Robert G. (petrock)


Lesenswert?

OK, Festkommawerte in normale Integerzahlen (ganzzahlig ohne 
Kommastellen) umgewandelt.

Nochmal zu Fuß:
ADC-Wert 835 * 1074 = 896790
/ 100, da sonst zu lang beim nächsten Rechenschritt (würde 2901115650 
ergeben) = 8967
8967 * 3235 = 29008245 <- passt in LONG rein
/ 10000, um auf mV zu kommen = 2900
2900 + Kalibrierwert von 830 = 3730 mV

Passt das so? Die zusätzlichen Teilungs-Rechenschritte sind immer noch 
besser als Fließkommazahlen? Macht der Controller das per "Shift"?

Ist das grundsätzlich mit der Kalibrierung so korrekt (mal abgesehen von 
eventuellen Temperaturanpassungen in Zukunft...)? 830mV als 
Kalibrierwert erscheint mir sehr hoch.

von AVR-User (Gast)


Lesenswert?

Hast Du Dir mal die Genauigkeit der internen Referenzspannung 
angeschaut? Beim ATmega168 z.B. kann sie laut Datenblatt eine Toleranz 
von +/- 100mV haben; da ist die Messgenauigkeit entsprechend fragwürdig.

Für genaue Ergebnisse im mV-Bereich muss entweder das System mit einer 
bekannten genauen Eingangs-Spannung (software-)kalibriert werden, oder 
man verwendet eine sehr genaue externe Referenzspannungsquelle.

von Robert G. (petrock)


Lesenswert?

AVR-User schrieb im Beitrag #4930825:
> Für genaue Ergebnisse im mV-Bereich muss entweder das System mit einer
> bekannten genauen Eingangs-Spannung (software-)kalibriert werden, oder
> man verwendet eine sehr genaue externe Referenzspannungsquelle.

Meinst du damit, die Berechnung ist in Ordnung und der happige 
Kalibrierwert aufgrund von Bauteiltoleranzen ebenfalls?


Adc_messergebnis = Getadc(0)
Millivolt = Adc_messergebnis * Adc_multipli
Millivolt = Millivolt / 100                             '/ 100, da sonst 
beim nächsten Rechenschritt zu lang für LONG
Millivolt = Millivolt * Rvh
Millivolt = Millivolt / 100                             'statt / 10000, 
um auf mV zu kommen
Millivolt = Millivolt / 100                             'nochmal (statt 
10000)
Millivolt = Millivolt + Kalibrierung

: Bearbeitet durch User
von Robert G. (petrock)


Lesenswert?

Also die Kalibrierung geht so nicht. Bei angelegten 3,73V passt es (da 
der Kalibrierwert darauf angepasst wurde) aber bei 4,2V oder 3,3V 
driftet der angezeigte Wert in mV total ab.

Wie kann ich das anpassen?

von Karl M. (Gast)


Lesenswert?

Hallo,

dein Spannungsteiler ist sehr Hochohmig: 220K und 68K

verwende einen Puffer OPV mit vu = 1, so dass die Quellimpendanz unter 
dem Wert im Datenblatt liegt.
Verwende mehrere Messungen um einen Mittelwert zu bilden.

von Ralf-Peter G. (ralfpeter)


Lesenswert?

Hallo Robert,

> Wie werde ich die Nachkommastellen los? Wenn ich Single ...

Probiere mal

CONFIG SINGLE = SCIENTIFIC , DIGITS = value

näheres in der Hilfe.

mfg

Grelli

von Allu (Gast)


Lesenswert?

Robert G. schrieb:
> Berechnung zu Fuß:
> Bei (laut Multimeter) 3,73 V am Spannungsteiler liegen am ADC Pin (laut
> Multimeter) 0,88V an.
> Ausgegebener ADC Wert: 835 * 1.07421875 = 896.97265625 (Millivolt)
> * Verhältnis der Widerstände 3.235294117647059 = 2901.970358455883
> + Kalibrierwert 830 = 3731.970358455883 = ~ 3731mV (= ~ 3,73V)


Also gilt für deine realisierte Schaltung:
Multimeter = 3,73V,  ADC-Wert   = 835

Rückwärts gerechnet unter Einbeziehung von Spannungsteiler und Referenz:
3730mV / 835ADC-Schritte = 4,467065  mV/ADC-Schritt

Berechnung mit Bascom:

Const Adc_multipli = 4,467065

Adc_messergebnis = Getadc(0)
Millivolt = Adc_messergebnis * Adc_multipli

Fertig, aber vielleicht habe auch ich dein Ziel nicht verstanden.

Gruß Alex

von Karl M. (Gast)


Lesenswert?

Hallo,

nochmal, wenn die elektrische Beschaltung nicht "passt", dann kann man 
so viel in ein ADC-Ergebnis hinein interpretieren wie man möchte !

von Robert G. (petrock)


Lesenswert?

Die interne Referenzspannung liefert übrigens 1085mV und nicht 1100mV.
Durch die Anpassung auf 1085 passt es soweit mit der Kalibrierung über 
den gesamten Spannungsbereich, wenn der Wert multipliziert wird.

Const Adc_multiplikator = 10595                             'AREF = 1085 
Millivolt / 1024 = 1.0595703125
Const Rvh = 3235                                            'Verhältnis 
der Widerstände am Spannungsteiler. 220(K) / 68(K) = 3.235294117647059
Const Kalibrierung = 130

Adc_messergebnis = Getadc(0)
Millivolt = Adc_messergebnis * Adc_multiplikator
Millivolt = Millivolt / 100                             '/ 100, da sonst 
beim nächsten Rechenschritt zu lang für LONG
Millivolt = Millivolt * Rvh
Millivolt = Millivolt / 100
Millivolt = Millivolt * Kalibrierung
Millivolt = Millivolt / 1000                            'statt / 10000, 
um auf mV zu kommen
Millivolt = Millivolt / 100                             'nochmal (statt 
/10000)

: Bearbeitet durch User
von Robert G. (petrock)


Lesenswert?

Allu schrieb:
> Berechnung mit Bascom:
>
> Const Adc_multipli = 4,467065
>
> Adc_messergebnis = Getadc(0)
> Millivolt = Adc_messergebnis * Adc_multipli
>
> Fertig, aber vielleicht habe auch ich dein Ziel nicht verstanden.
>
> Gruß Alex

Tjoa, so einfach kann es sein. Danke für den Rechenweg! Ich probier 
beide Wege in der Liveschaltung aus.

von Peter D. (peda)


Lesenswert?

Karl M. schrieb:
> dein Spannungsteiler ist sehr Hochohmig: 220K und 68K
>
> verwende einen Puffer OPV mit vu = 1, so dass die Quellimpendanz unter
> dem Wert im Datenblatt liegt.
> Verwende mehrere Messungen um einen Mittelwert zu bilden.

Ein OPV ist unnötig, eine 100nF Pille reicht völlig aus, um den kurzen 
ADC-Samplepuls zu puffern.
Einen OPV brauchst Du nur für sehr schnelle Wandlungen, wie z.B. 
Audioaufzeichnung.

von Axel R. (Gast)


Lesenswert?

33Kund 11K ergibt einen Spannungsteiler von 1 zu 4.
Nurmal so...

Btw.
77K (75K+2.0K) und 11K ergibt einen Spannungsteiler von 1 zu 8.

150K und 10K dann 1 zu 16.

Dann muss man nicht mit "krummen Werten" rumzirkeln...

StromTuner

von Allu (Gast)


Lesenswert?

Robert G. schrieb:
> 4 Stellen, Ausgabe und interne
> Weiterverarbeitung in mV

Möglich sind immer viele Wege, einer könnte in deine Struktur eingesetzt 
sein:

'  +++  Vorgaben hier Eintragen   +++++++
Const U_multimeter = 3730               ' in mV
Const Adc_wert = 835                    ' in Schritten von 0 bis 1023


'  Vorbereitung für Berechnung
Const Adc_multipli = U_multimeter / Adc_wert       ' = 4 . 467065

'  Variablen
Dim N As Byte
Dim Adc_messergebnis As Word
Dim Millivolt_single As Single
Dim Millivolt As Word


'  Hauptprogramm
Do

'  Messen und Ergebnis berechnen
Adc_messergebnis = Getadc(0)
Millivolt_single = Adc_messergebnis * Adc_multipli

'   4-stellig in mV
Millivolt_single = Millivolt_single + 0.5       ' +0,5 zum Runden in mV
Millivolt = Int(millivolt_single)


Print N ; " ADC-Wert: " ; Adc_messergebnis
   Print "Spannung: " ; Millivolt ; " mV"

   Incr N
   Waitms 1
Loop

Peter D. schrieb:
> Ein OPV ist unnötig, eine 100nF Pille reicht völlig aus, um den kurzen
> ADC-Samplepuls zu puffern.

Finde ich auch besser als einen niederohmigen Spannungsteiler, schont 
die Batterie.

Gruß  Alex

von Paul B. (paul_baumann)


Lesenswert?

Allu schrieb:
> Finde ich auch besser als einen niederohmigen Spannungsteiler, schont
> die Batterie.

Das Datenblatt findet aber normalerweise niederohmige Quellen besser.

MfG Paul

von allu (Gast)


Lesenswert?

Paul B. schrieb:
> Das Datenblatt findet aber normalerweise niederohmige Quellen besser.

Peter D. schrieb:
> Ein OPV ist unnötig, eine 100nF Pille reicht völlig aus, um den kurzen
> ADC-Samplepuls zu puffern.
> Einen OPV brauchst Du nur für sehr schnelle Wandlungen, wie z.B.
> Audioaufzeichnung.

Nach meiner Meinung ist unter diesen Betriebsbedingugen ein 100nF eine 
niederohmige Quelle.

Gruß  Alex

von Joachim B. (jar)


Lesenswert?

Falk B. schrieb:
> Ja. Man rechnet einfach alles in mV.
>>Aus "Const Adc_multipli = 1.07421875" würde 1074 und aus "Const Rvh =
>>3.235294117647059" würde 3235.
>
> Bingo!

warum mV?

wenn 2 Nachkommastellen reichen dann nehme ich immer dV -> deziV, das 
Komma füge ich in den Ausgabestring an der drittletzten Stelle ein.

von Manfred (Gast)


Lesenswert?

Robert G. schrieb:
> Also die Kalibrierung geht so nicht. Bei angelegten 3,73V passt es (da
> der Kalibrierwert darauf angepasst wurde) aber bei 4,2V oder 3,3V
> driftet der angezeigte Wert in mV total ab.
Ich verstehe den gesamten Ablauf nicht. Die Rechnerei mit 
Spannungsteiler und Referenz macht keinen Sinn, da alle Komponenten 
Toleranzen haben.

Wenn ich eine Spannung messen will, lasse ich mir den AD-Wert auf die 
serielle Schnittstelle oder das Display ausgeben. Ich lege Spannung an, 
z.B. 4,3Volt. Kommt dann als Digitalwert 1015 raus, ergibt sich 
4300/1015=4,2365. Das machst Du an mindestens zwei Punkten und nimmst 
ggfs. den Mittelwert daraus.

Also ist meine Spannung Digitalwert mal 4,236: Bei einem Wert von 600 
wären das 2,54Volt.

Robert G. schrieb:
> Gewünschte Messgenauigkeit: 4 Stellen,
Das ist fernab jeglicher Realität. Du hast 4,25V auf 1024 Schritte, also 
eine Quantisierung auf rund 4mV. Ein bischen Rauschen und dazu 
Rundungsfehler - wenn Du die zweite Stelle hinter dem Komma halbwegs 
halten kannst, 20mV Ablage, bist Du schon gut bedient. Mal etwas suchen, 
das Thema Meßgenauigkeit war erst vor wenigen Tagen hier im Forum.

von Robert G. (petrock)


Lesenswert?

Manfreds Antwort entspricht der von Allu, weiter oben.
Dieser simple Vorgang reicht vollkommen aus.

Danke euch für die Infos!

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.