Mit aktueller Spannung rechnen?

Moin Moin :slight_smile:

Ich verwende einen Analogen Sensor um Temperaturdaten zu sammeln.
Ich habe meinen Arduino auf 3.3V laufen und rechne mir daher auch mit 3.3V die Temperatur heraus:

float tempVoltage = tempReading * 3.3;
    tempVoltage /= 1024.0;


    temperatureC = (tempVoltage - 0.5) * 100 ;
    Serial.println("\t"); 
    Serial.print(temperatureC);


    temperatureF = (temperatureC * 9.0 / 3.3) + 32.0;
    Serial.print("\t"); 
    Serial.println(temperatureF);

Das Problem ist, dass mir das ganze zu ungenau ist, da die Spannung von 3.3V ja nicht konstant gehalten wird. (Ich hoffe ihr wisst was ich meine).

Nun frage ich mich ob es eine genauer Methode gibt das ganze zu rechnen.
Zum Beispiel so etwas wie "CurrentVoltage", statt 3.3V.

Freue mich über Antworten

Ich hoffe ihr wisst was ich meine

Nicht unbedingt :wink:

Woher kommt

 float temperatureC = (tempVoltage - 0.5) * 100 ;

und wie hängt das von der aktuellen Spannung deines Sensors ab ?

Im einfachsten Fall eines NTC kommt unabhängig von der genauen Vcc immer der gleiche AnalogWert raus, wenn der
Spannungsteiler von der gleichen Spannung versorgt wird wie der Arduino und sein ADC (ohne spezielle Vref Verrenkungen).

Der Arduino kann seine eigene Spannung messen, das ist aber nicht trivial ( für mich )

Also der Regler der in den Arduino eingesetzt ist, ist auf 3.3V eingestellt.
Wenn du das ganze aber mal überprüfst, siehst du, dass dieser Wert nicht immer Konstant gehalten wird.

Er springt zum Beispiel hin und wieder auf 3.4V. Ich rechne aber ja mit 3.3V das ganze aus. Wenn durch den
Sensor aber 3.4V fließen ist das Ergebnis ja verfälscht :wink:

Der Link bringt mir leider nichts. Hier wird ja nur ein kürzel für die Spannung festgelegt aber dies ändert die Rechnung nicht

thilo007007:
temperatureF = (temperatureC * 9.0 / 3.3) + 32.0;
...
Nun frage ich mich ob es eine genauer Methode gibt das ganze zu rechnen.

Ja, klar: Es gibt für die Umrechnung von Celsius nach Fahrenheit auch eine richtige Formel!

Kleiner Tipp: Die Umrechnungsformel von Celsius nach Fahrenheit enthält keine Spannung, und daher muß in der Formel auch keine Spannung umgerechnet werden. XD

Er ließt mir 23.24°C und 74.71 Fahrenheit aus.
Wenn ich die 23.24°C online umrechnen lasse kommt da auch 74.71 raus, hier stimmt die Formel scheinbar :smiley:

Das merkwürdige daran ist, dass in der Rechnung die 3.3V echt nichts zu suchen haben...

Die Formel ist ja eigentlich F= C*1.8 +32

Wenn durch den Sensor aber 3.4V fließen ist das Ergebnis ja verfälscht

Wenn der ADC erst bei 3.4V 100% misst, weil das die default Vref ist, ist das Ergebnis auch "verfälscht".
Wie hängen die beiden "Verfälschungen" zusammen, ist die eigentliche Frage...

Er springt zum Beispiel hin und wieder auf 3.4V

Das kann nie und nimmer an deinem Messgerät liegen. :wink:
Wie groß ist die Ungenauigkeit des Spannungsreglers? Im Vergleich: wie genau ist der Temperaturfühler?
Referenz-Temperaturen (selbst 0°C Eiswasser ist nicht ganz sicher) sind noch schwieriger als Referenz-Spannungen.

Ich sehe folgende Fragen:
Musst du wissen, welchen Wert Vcc tatsächlich hat ?
(Oder ist das nur eine ZwischenVariable, deren aktueller Wert sich rauskürzt )

Falls ja, wie kriegst du das mit dem Arduino raus ?
(Das geht nur indirekt, und da könnte evtl. der Link helfen)

Wenn du erstmal Temperaturen sammelst und loggst, und die plausibel sind,
wird das bald deine Referenz-Temperatur und alle anderen Thermometer gehen mehr oder weniger falsch :wink:


Die Formel ist ja eigentlich F= C*1.8 +32

Man schreibt gern mal F= C * 9/5 + 32
Diese 5 solltest du nicht durch 3.3 ersetzen, auch nicht durch 3.4 :wink: , weil das nichts mit den Arduino 5V zu tun hat

thilo007007:
Er ließt mir 23.24°C und 74.71 Fahrenheit aus.
Wenn ich die 23.24°C online umrechnen lasse kommt da auch 74.71 raus, hier stimmt die Formel scheinbar :smiley:

temperatureF = (temperatureC * 9.0 / 3.3) + 32.0 = (23.24 * 9.0 / 3.3) + 32.0 = 74.71
???

OK, solchen Rechenkünstlern wie Dir kann ich offenbar nicht das Wasser reichen!
:~

Ich habe doch gesagt, dass ich es selbst nicht verstehe, aber scheinbar klappt es ja ? :smiley:

Und das verfehlt auch irgendwie meine Frage :astonished:

Ich möchte wissen ob es einen "Code" für die AktuelleSpannung gibt?

Um dann mal auf dein ursprüngliches Problem zurück zu kommen:
Ich kann nur vermuten, dass du einen LM35 o. ä. als Sensor verwendest. Aus deinem Code geht das leider nicht hervor, und auch nicht, mit welcher Referenzspannung du misst.
Ich mache es so:

  analogReference(DEFAULT); // set analog reference voltage to VCC=5V

int getTemperatureTMP35(byte analogPin){ // returns temperature in tenth of centigrade, for TMP35 sensor
  long value; // intermediate results need to be long
  value = analogRead(analogPin); // take three readings and average
  value += analogRead(analogPin); 
  value += analogRead(analogPin); 
  value /= 3;
  value = (5000 * value) / 1024L;
  return(int)value;
}

5000 (mV) ist meine Versorgungsspannung, in deinem Fall also 3300, Ausgabe ist in milliGrad Celsius. Ich verwende keine floats auf Gründen der Geschwindigkeit und Codegröße, ist auch nicht nötig.
Ein LM35 hat eine Genauigkeit von 1 Grad bei Zimmertemperatur, der Spannungsregler ist deutlich genauer und sollte keinen Einfluss auf dein Ergebnis haben.
Wenn die Ausgangsspannung des Spannungsreglers bei mir im Batteriebetrieb unter 5 Volt sinkt, gehen die Messwerte in die Höhe.
Der Tip von michael_x ist in diesem Fall tatsächlich die Lösung, sieht bei mir so aus:

inline int getVcc(){ // Returns actual value of Vcc (in milliVolts), modified code copied from the forum
  const long InternalReferenceVoltage = 1100; // assume perfect 1.1V reference voltage, the absolute error does not matter much
  // REFS1 REFS0          --> 0 1, AVcc internal ref. -Selects AVcc external reference
  // MUX3 MUX2 MUX1 MUX0  --> 1110 1.1V (VBG)         -Selects channel 14, bandgap voltage, to measure
  ADMUX = _BV (REFS0) | _BV (MUX3) | _BV (MUX2) | _BV (MUX1);
  // Start a conversion  
  ADCSRA |= _BV( ADSC );
  // Wait for it to complete
  while((ADCSRA & _BV(ADSC)));
  // Scale the value
  int result = (((InternalReferenceVoltage * 1024L) / ADC) + 5L);
  return result;
}

result ersetzt dann die 5000 aus obiger Berechnung.