Hallo, Ich habe einen Drucksensor mit einem Messbereich von 0 - 10 bar und einen mit -1 - +1 bar. Beide geben eine analoge/lineare Spannung von 1-5 Volt aus. Die wird runter geteilt auf 1,235V und mit einem 10bit ADC eingelesen.
Bei einer Spannungsausgabe von 0-5 Volt wäre ja die Rechnung für den Druck ganz "normal":
U = 1,235 * (ADC/1023)
Druck = 10 * (U/1,235)
Da mein Spannungsbereich am Sensor aber erst bei einem Volt beginnt, beträgt die Spannung am ADC 0,247 - 1,235V bzw. seine Werte von 205 - 1023 (Hab ich mir zumindest so zusammengereimt).
Kann mir jemand sagen wie ich die Formel mit dem o.ä. Spannungsbereich aussehen müsste und wie würde sie mit dem Sensor: -1 - +1 Bar aussehen.
Danke im Voraus.
Alex
na ja, der Messbereich umfasst halt 2 Bar zwischen -1 und +1. Damit liegt "0" bar genau "in der Mitte", also bei 512, 0 enspricht "-1" Bar und 1023 "+1" bar. Oder in deiner Formel Druck = -1 + 2*(U/Umax)
Das "Da mein Spannungsbereich am Sensor aber erst bei einem Volt beginnt" verstehe ich nicht
Ich gehe in gar keine Klasse und arbeite üblicherweise auch nicht in der
Branche ;)
Schon mal was von einer linearen Geradengleichung gehört?
1
Sensor ADC-Eingang ADC-Wert Druck1 Druck2
2
1V 0,247V 205 0bar -1bar
3
3V 0,741V 615 5bar 0bar
4
5V 1,235V 1023 10bar 1bar
5
6
p = f(adc) = M*ADC+N
7
8
// 10 Bar Sensor
9
M = dy/dx = (10bar-0bar)/(1023-205)=0,0122 bar/LSB
10
N = P2-M*ADC = 10bar - 0,0122bar/LSB*1023 = -2,506bar
11
12
// +/-1 Bar Sensor
13
M = dy/dx = (1bar- -1bar)/(1023-205)=0,002445 bar/LSB
14
N = P2-M*ADC = 1bar - 0,002445bar/LSB*1023 = -1,5bar
Man kann das mit Fließkomma rechnen und ist fertig. Man kann aber auch 5 Minuten nachdenken und Festkommaarithmetik benutzen. Wenn man alles in Millibar rechnet, braucht es keine Kommas. Dabei darf im Zwischenergebnis kein Überlauf auftreten, also Rechnung mit 32 Bit. Beim +/1bar Sensor reichen die Millibar nicht, da muss man eher auf Mikrobar gehen. Klingt komisch, ist aber so. Kann man aber am Ende wieder auf Millibar umrechnen.
1
intp;
2
p=122*(int32_t)ADC-2506;// 10 bar Sensor
3
p=(2445*(int32_t)ADC-1500000)/1000;// +/-1 bar Sensor
Moin,
ich habe so einen Drucksensor in mein Heizungsrohr eingebaut. Liefert auch von 1 bis 5 V. Dann ist es etwas in Vergessenheit geraten. Ich hatte vor, wie in anderen Schaltungen die Werte mit einem ATtiny84 zu messen und zu speichern. Abfrage über I2C. Der hat die Möglichkeit über“ Differential ADC Channel“ zu messen. Leider ist der Minuspol mit dem Gehäuse verbunden und somit der „Rauschabstand“ kleiner. Dadurch ist es für mich günstiger mit 5V VCC ADC Input Voltage Range zu messen.
Gruß
Carsten
> M = dy/dx = (10bar-0bar)/(1023-205)=0,0122 bar/LSB
10
> N = P2-M*ADC = 10bar - 0,0122bar/LSB*1023 = -2,506bar
11
>
12
> // +/-1 Bar Sensor
13
> M = dy/dx = (1bar- -1bar)/(1023-205)=0,002445 bar/LSB
14
> N = P2-M*ADC = 1bar - 0,002445bar/LSB*1023 = -1,5bar
15
>
16
>
Man kann das mit Fließkomma rechnen und ist fertig. Man kann aber auch 5
Minuten nachdenken und Festkommaarithmetik benutzen. Wenn man alles
in Millibar rechnet, braucht es keine Kommas. Dabei darf im
Zwischenergebnis kein Überlauf auftreten, also Rechnung mit 32 Bit. Beim
+/1bar Sensor reichen die Millibar nicht, da muss man eher auf Mikrobar
gehen. Klingt komisch, ist aber so. Kann man aber am Ende wieder auf
Millibar umrechnen.
1
>intp;
2
>p=12,2*(int32_t)ADC-2506;// 10 bar Sensor
3
>p=(2445*(int32_t)ADC-1500000)/1000;// +/-1 bar Sensor
4
>
Danke für die konkrete Lösung! Funktioniert gut (nachdem ich deinen Kommafehler ausgebessert habe ;))
Für die 10 Bar Ausführung hätte ich mir jetzt auch die Formel zusammengereimt:
1
intp;
2
p=(10/819)*(adc-205);
Lineargleichnug dürfte aber die universellere Lösung sein.?
Beide geben eine analoge/lineare Spannung
von 1-5 Volt aus. Die wird runter geteilt auf 1,235V und mit einem 10bit
ADC eingelesen.
Diesen Satz solltest du noch mal überdenken. Herunterteilen eines Bereichs auf einen festen Wert?? Ich nehme mal an, die wird mit 1,235/5 multipliziert. Sauber formulieren ist oft die halbe Lösung.
Ausgangslage bei dem +-1 Sensor:
U_adc = U_sensor * 1,235/5
ADC = U_adc * 1024/1,235
U_sensor = 2*Druck + 3
was spricht dagegen mit einem float oder double zu arbeiten?
Der 8-Bit Programmierer Ehrencodex ;-)
Heutzutage schert sich kaum noch einer um Resourcenbedarf und sinnvoll Lösungen, da darf auch mal ein 32 Bit Controller ne LED blinken. Dagegen ist ne Fließkommaberechnung harmlos. Nimm sie und gut. Es gibt andere, echte Probleme auf dieser Welt.
Na, nicht nur, Fließkommazahlen sind verbuggt. Mit Integern ist man da schon eher auf der sicheren Seite.
Darüber hinaus kann man öfter auch (positive) Überraschungen erleben wenn man sich Mühe gibt, und kommt auch eher vom Automatismus weg, Fließkommazahlen benutzen zu müssen.
Im Zweifelsfall kann man es einfacher machen, und fehlerfreier.
Wie gesagt, im Zweifelsfall, aber nicht im Sinne von voreiliger Optimierung. Die ist nämlich zu recht als Wurzel allen Übels verpönt.
Erstmal gucken, dass überhaupt was läuft.
Also durchaus keine triviale Frage ;)
Wenn Moby das liest, eröffnet er gleich die nächsten 10 Threads.
Wäre ja gar nicht so schlimm, wenn das nicht ständig der selbe neuaufgegossene kalte Kaffee wäre.
Ich fand z.B. diese zugeHolmten Threads gar nicht so übel, auch wenn ich gelegentlich recht dankbar war für das ein oder andere Stoppschild da.
"verbuggt" ist vielleicht der falsche Begriff.
Eine Zahl wie 1,235 lässt sich z.B. nur näherungsweise als Fließkommazahlen darstellen. Deswegen ist beispielsweise von einem Vergleich von Fließkommazahlen auf Gleichheit in den meisten Fällen unbedingt abzuraten.
Tipp: Sage "immer"!
Denn wüsste man vorher, ob sie exakt gleich sind, bräuchte man keinen
Vergleich mehr.
Nein, sag ich nicht. Und natürlich können die Binärpräsentationen zweier Float Zahlen gleich sein, auch wenn man vorher nicht weiß, dass sie gleich sind.
Wenn klar ist, dass die Binärpräsentation der beiden zu vergleichenden Zahlen auf gleiche Weise entsteht, d.h. im Fall der "Gleichheit" beide binär gleich werden müssen, kann der Vergleich kappen ;-)
Warum sollte eine Programmiersprache das verbieten? Float Variablen
können den gleichen Wert enthalten.
Naja, sie können schon, aber häufig tun sie es nicht obwohl sie gleich sein müssten - wenn man es mit dem Taschenrechner nachrechnet.
Verbieten muss man es nicht, aber vielleicht warnen? [Vielleicht tut das ein Compiler auch, habe schon lange keine Floats mehr verwendet].
Ich möchte nicht wissen, wie viele da schon darüber gestolpert sind ...
Wenn man sie noch nicht ganz verstanden hat, dann mutet es einen leicht so an, wenn man einen Vergleich wie z.B.
1
f=2.0+1.33
2
if(f==3.33)
3
tuwas();
macht und tuwas() nicht aufgeriufen wird.
Mich stört an floats eher, dass sie zwar eine gewaltige Dynamik haben, aber nur 6 signifikante Stellen. Man kann also nicht sicher sein, dass nach dieser Rechnung wie erwartet f = 100.001 ist.
1
f=1000.0;
2
f+=0.001;
Drum nehme ich float nur dort, wo es nötig ist. Und sonst eben einen Integer in "Dezigrad" oder "Centibar" oder "Millimeter", wenn ich wegen einer höheren Auflösung 0,1 Grad oder 0,01 bar oder 0,001 m auflösen will.
Von einem 8-Bit Andruiden war in der gesamten Diskussion, bis auf meine
Anmerkung des 8-Bit Programmierer Ehrenkodex, keine Rede.
Da hast du durchaus Recht.
Allerdings habe ich einfach auf den Eröffnungspost einen Wahrscheilichkeitsalgorithmus angewendet und besonders diese Information linear extrapoliert, wo
So allgemein kann man nur sagen, dass Zahlen, wie z.B. 3,1415 für sich gesehen erstmal nicht problematisch sind. Die Probleme kommen in der Computeranwendung u.a. durch (statisches) Rundungsverhalten bei (iterierenden) Funktionen oder beim Zahlen konvertieren oder rund um Registerbitbreiten.
Beim Heron-Verfahren zum Wurzelziehen, da sind die Fließkommazahlen ganz gut, denn das funktioniert über Annäherungen an die Genauigkeit.
Wenn es aber um hergeleitete Genauigkeit geht:
die Fließkommazahlen gaukeln Genauigkeit vor, obwohl sie nur als Annäherung zu verstehen sind und man aufpassen muss.
die Probleme, die sie mitbringen sind mehrdimensional, und man kann nicht alle Problemfälle überblicken -
man muss aber die Schwierigkeiten verstehen z.B. für Testprogramme, die dann wichtiger werden. Gibt man sich keine Mühe, kann es zum Unfall kommen, und das ist sch..
Fuzzy Logic könnte man eventuell auf Fließkommazahlen anwenden. Das ist aber wo implementiert?
Und sonst eben einen
Integer in "Dezigrad" oder "Centibar" oder "Millimeter", wenn ich wegen
einer höheren Auflösung Z0,1 Grad oder 0,01 bar oder 0,01 m auflösen
will.
me too und wenn ich größer oder gleich wissen will nehme ich strcmp will ich Kommata einsetzen durch umrechnen mache ich das im String um aus 500 CentiVolt 5,00V zu machen.
Ich frage mich, wie viele sich die Mühe gemacht und wirklich einmal überprüft haben wie lange einfache FP-Rechenoperationen dauern.
Ich hab's vor langer Zeit schon, deshalb benutze ich FP selbst auf 8-Bittern ziemlich oft.
WIMRE waren das nämlich so um die 300-500 CPU-Zyklen pro Operation bei den kleinen AVRs.
Also 1/2ms bei einer CPU Geschwindigkeit von 1MHz.
Oder 1/32ms bei 16MHz.
Wenn man eine Berechnung nur ein paar zehn- oder hundertmal pro Sekunde macht, interessiert das fast niemanden.(#)
Bei einer simplen Mul/Div Operation um ADC Werte umzurechnen, muss man sich auch keine Gedanken um die Genauigkeit von float/double machen. Oder um Error-Propagation, …
Wenn man eine Berechnung nur ein paar zehn- oder hundertmal pro Sekunde
macht, interessiert das fast niemanden.
Außer, wenn man Strom sparen muss, z. B. bei Batteriebetrieb. Da ist es schon ein Unterschied, ob der µP in den Tiefschlaf gehen kann oder in der Zeit rechnen muss.
Sicherlich richtig.
Wenn man im Batteriebetrieb ist. Dann weiß man aber auch um diese Dinge.
Nebenbei: Auch die FixPoint Arithmetik braucht ein Tütchen CPU-Zyklen. Vor allem wenn man versucht eine halbwegs akzeptable Genauigkeit heraus zu holen und mit 16, evtl. sogar 32 Bit rechnet.
WIMRE waren das nämlich so um die 300-500 CPU-Zyklen pro Operation bei
den kleinen AVRs.
Also 1/2ms
Eine einzige Rechenoperation macht kein Programm. Der Witz ist, dass jede einzelne derartige float-Rechnung eben 50 mal langsamer ist als die integer-Rechnung, die das selbe Ergebnis bringt.
Und dann nennt der Programmierer den Controller "zu langsam", statt sein Programm "ungeeignet geschrieben".
Wenn man ein klein wenig Gehirnschmalz in sein Programm steckt, dann muss man oft überhaupt gar nicht umrechnen. Oder erst dann, wenn irgendwer irgendwelche Werte auf einer Anzeige sehen will.
Der Witz ist, dass
jede einzelne derartige float-Rechnung eben 50 mal langsamer ist als
die integer-Rechnung
Nö Lothar, das ist kein Witz, das ist einfach so. Allerdings muss ich zugeben, das die CPUs nun nicht mehr zu 90% herum-idlen, sondern nur noch zu 89%.
Das ist zugegebenermaßen nur schwer zu ertragen, aber man muss auch mal bereit sein ein Opfer zu bringen.
PS. Wenn ich auf anderen Systemen 500ksps per DMA vom ADC bekomme, diese verarbeiten und weiterschieben muss, dann nehme ich auch FixPoint. Dann, nur dann.
Eine einzige Rechenoperation macht kein Programm. Der Witz ist, dass
jede einzelne derartige float-Rechnung eben 50 mal langsamer ist als
die integer-Rechnung, die das selbe Ergebnis bringt.
Das halte ich für einen Irrtum. Miss mal nach, wenn mit 16 oder eher 32 Bit grerechnet wird! Ich würde vermuten, daß Float weniger als Faktor 5 langsamer ist.
meist geht es nicht um die Dauer sondern das einem der RAM ausgeht weil
alles auf dem Stack passiert, das kann schöne versteckte Fehler ergeben.
Das tritt aber auch mit anderen Funktionalitäten auf und hat nichts direkt mit Floatingpoint zu tun.
Ich empfehle bei Embedded Systemen immer Stacküberwachung einzubauen.
Die Diskussion scheint Richtung Glaubenskrieg zu gehen.
Ich nutze das was am besten passt. Und auch auf kleinen 8Bittern funktioniert float gut.
Und manchmal braucht man auch Integer/Fixpoint Operationen auf 32Bittern.
Und morgen geht die Welt unter! Nein! Der Norbert hat schon recht!
Nein, man redet hier ein Problem herbei, was man in einfachen Anwendungen kaum hat.
Mit dem Rechnen ist das auch so eine Sache: 16 MHz sind 0,0625µs. Mal 500 komme ich auf 32 MIKROsekunden, nicht ms!
Mein 8MHz-Arduino liest vom angeschlossenen ADS1115 alle 10 Sekunden zwei Spannungen und schreibt diese auf eine SD-Karte. Ich habe mich um Variablentypen nicht geschert, da fliegen 4 Nachkommastellen herum. Das läuft mit einer 18650-LiIon an die 500 Stunden, mit aktivem OLED natürlich weniger.
Mein Spannungslogger kann auch jede Sekunde zur Karte schreiben, da bin ich weder in Zeitnot noch stürzt irgendwas ab.
Zeitnot habe ich mal an anderer Stelle gefangen, wo die A/D des ATMega benutzt werden und damit eine Regelung im Millisekunden-Bereich läuft. Das war nicht die Float-Rechnerei, sondern zweistellige Millisekunden für mein I2C-LCD.
Ich hätte gerne ein Problem passt hier wohl besser.
Ich hab mal gemessen. Einmal im Simulator im staubigen AVR-Studio mit dem ollen 2010er avr gcc (der noch einen "Bug" hat und sich in einigen Situationen viel RAM gönnt, so auch hier) und einmal mit Arduino UNO. Im AVR-Studio mit Optimierung -Os (minimale Codegröße) compiliert. Beim Arduino wurde die Zeit per Oszi gemessen. In beiden Fällen mit 16 MHz CPU-Takt.
1
WinAVR-20100110
2
FLASH /B RAM /B Zeit /us
3
float 2860 264 197,0
4
int32 186 0 4,1
5
6
Arduino 1.8.13
7
FLASH /B RAM /B Zeit /us
8
float 1666 9 23,0
9
int32 920 9 4,2
Ziemliche Unterschiede! Aber bei ein paar handvoll oder auch hundert Berechnungen/s kein wirkliches Problem. Bei größeren Arduinos mit 32 Bit geht es noch schneller, wenn ne FPU vorhanden ist bedeutungslos.
Eine Sache die hier nicht berücksichtigt wird:
Bei Integer-Operationen kann es unüberlegt schnell zu Überläufen kommen.
So geschehen bei der Kalibration eines Sensors über eine Polynom-Funktion.
Trotz Optimierungen konnte der Überlauf nur sehr aufwändig abgefangen werden,
da sich die Faktoren in den Einzelgeräten stark unterschieden.
Mit float hatte sich das Problem erledigt.
Hallo,
wenn man über “ Differential ADC Channel“ messen würde und dir Referenzspannung und Eingang mit einem Trimmer auf 4 V und 1V regeln würde, würden 1V =0bar =0 und 10bar =4V =1023 bzw. 1000 ergeben können (je nach Trimmung). Dadurch würden 1/5 der Werte nicht „verschenkt“ werden also 0-1V.
Gruß
Carsten
wenn man über “ Differential ADC Channel“ messen würde und
Du hast mitbekommen, dass Alexander K. ausgestiegen ist und hofft, nach den Schulferien endlich Grundrechnen zu lernen?
Differential ist nett gedacht, aber er hat es ja nicht nötig, seinen ADC zu benennen. 10-Bit lässt einen AVR vermuten, der das vermutlich nicht kann.
Es fehlen auch Details zu den Drucksensoren. Dass die als Endwert 5 Volt liefern, lässt vermuten, dass es deren Betriebsspannung sein könnte. Da wäre eine ratiometrische Messung sinnvoll - also µC-Referenz und Sensoren an der selben Versorgung.
Generell finde ich, dass "unüberlegt" und "programmieren" nicht
zusammenpassen.
Mit immer leistungsfähigeren Prozessoren und immer unübersichtlicheren Abstraktionsebenen/Bibliotheken fällt das leider immer häufiger zusammen.
Die Beziehung zu dem, was der µC wirklich tut, gerät oft weit ins Hintertreffen.
Generell finde ich, dass "unüberlegt" und "programmieren" nicht
zusammenpassen.
Mit immer leistungsfähigeren Prozessoren und immer unübersichtlicheren
Abstraktionsebenen/Bibliotheken fällt das leider immer häufiger
zusammen.
Die Beziehung zu dem, was der µC wirklich tut, gerät oft weit ins
Hintertreffen.
Bist du des Mobys! ;-)
Stimmt aber leider. Sieht man auch fast jeden Tag, was da an Softwareungetümen zusammengebacken wird, die immmer größer und träger werden! Bloatware at it's best!
Ich hab mal gemessen. Einmal im Simulator im staubigen AVR-Studio mit
dem ollen 2010er avr gcc (der noch einen "Bug" hat und sich in einigen
Situationen viel RAM gönnt, so auch hier) und einmal mit Arduino UNO.
Der Ramverbrauch its das eine, aber daß der (leicht staubige) arduino-gcc (7.3.0) bei float einen fast um den Faktor 10 schnelleren Code produzieren soll als der staubige 2010er (vermutlich ein 4.5), ist dann doch nicht nachvollziehbar.
Irgendwie eine sehr vorteilhafte Wahl, wenn der Rechner sowieso im
Binärsystem arbeitet
Das war ja der Plan. Man kann - so wie du - zeigen, das man sich Probleme einfangen kann wenn man im Dezimalsystem über die Genauigkeit einer float Variablen hinaus noch weiter arbeiten will.
Oder das man eine erstaunliche Genauigkeit erreicht, wenn man die Mantisse im dualen System massiert.
Beides ist richtig, beides muss man wissen.
PS. Die Schleifen wurden nicht rechtzeitig abgebrochen, sondern erst nachdem der erste Rechenfehler auftrat. So ehrlich bin ich dann doch… ;-)