Temperatursensor

In diesem Experiment wird die Wärmetransmission unterschiedlicher Oberflächen untersucht.

Drei gleichgrosse Flaschen werden hierzu mit heissem Wasser randvoll befüllt. Die Wassertemperatur im Flascheninnern soll mittels Temperaturfühler über die Zeit gemessen und aufgezeichnet werden. Die Flaschen haben einzig unterschiedliche Oberflächenbeschichtungen (schwarz lackiert, weiss lackiert und alu-gebürstet). Die Fragestellung lautet, welchen messbaren Effekt die Flaschenbeschichtung auf die Abkühlung hat.

Die Messdaten werden über den Microcontroller ESP32 via Bluetooth-Schnittstelle an die PhyPhox Smartphone App gesendet und dort in Echtzeit grafisch dargestellt. Zusätzlich wurden die Messwerte aufgezeichnet und nach Abschluss des Experiments, in einer CSV-Datei zur finalen Auswertung auf den PC übertragen.

Versuchsaufbau / Experiment

Abb. 1: Versuchsaufbau, ESP32 mit Breadboard-Schaltung, Temperaturfühlern und Wasserflaschen

Schaltung

Abb. 2: Schaltbild der Temperatursensoren

Jeder Temperatursensor besitzt 3 Pins, siehe Abbildung 2.

Der Pin 1 (GND) wird jeweils mit der «Ground»-Schiene verbunden, sodass dort 0 Volt anliegen.

Der Pin 2 wird mit einem ESP32-IO Pin verbunden, um Daten übermitteln zu können. Da der Pin 2 eine Hilfsspannung benötigt, wird von der 3.3 Volt Schiene mittels eines Widerstands Pin 2 und Pin 3 verbunden.

Der Pin 3 wird mit 3.3 Volt, der «VDD»-Schiene verbunden.

Die Sensoren können parallel verbunden werden, sodass nur ein Datenkabel zum ESP32 benötigt wird, was auch eine parasitische Schaltung genannt wird. Die Sensoren haben jeweils eine eigene Buskennung und können über ihre ID vom Microcontroller separat nacheinander ausgelesen werden.

Bibliotheken und Module auf dem ESP32

Abb. 3: Bibliotheken und Dateien auf dem ESP32 (Thonny screenshot)
  • phyphoxBLE (Ordner, für Smartphone App)
  • ds18x20.py (Modul des Temperatursensors)
  • onewire.py (Modul für Bus-Schaltung)
  • boot.py (hier nicht verwendet)
  • temp_measurement v0.9.py (Quellcode PhyPhox Experiment)

Resultate – PhyPhox App Experiment «T-Plotter v0.9»

Abb. 4: Screenshot der PhyPhox App nach einer Temperaturmessung von ca. 2 Stunden.

Auswertung des Experiments

Abb. 5: Temperaturverlauf – Gesamtmessung

In Abbildung 5 wird die Wassertemperatur in den drei Wasserflaschen über die gesamte Messdauer von 6803 Messpunkten dargestellt. Das entspricht einem Messzeitraum von knapp 2 Stunden.

Nach Ablauf des Experiments ergibt sich eine deutlich höhere Wassertemperatur in der aluminium-gebürsteten Wasserflasche, welche im Vergleich zu den beiden anderen Wasserflaschen mit 43.5°C um 8.5°C höher liegt.

Die schwarze und die weisse Wasserflasche weisen einen sehr ähnlichen Temperaturverlauf auf.

Abb. 6: Temperaturverlauf – erste 80 Messwerte

Bei genauerer Betrachtung fällt auf, dass die schwarze Wasserflasche schneller abkühlt als die weisse. In Abbildung 6 beträgt die Wassertemperatur zu Beginn der Messung ca. 88°C und damit 1°C mehr als die weisse Wasserflasche.

Temperaturdifferenz zwischen T2 (schwarz) und T3 (weiss)

Abbildung 7 zeigt die Temperaturdifferenz zwischen der schwarzen und der weissen Wasserflasche. Die Temperaturdifferenz wird 0dK nach knapp 1000 Messungen, also ca. 16 Minuten.

Die schwarze Wasserflasche erreicht nach ca. einer Stunde Messdauer mit knapp -1dK Differenz zur weissen Flasche ein relatives Minimum bei 50°C. Mit fortschreitender Messdauer wird die Temperaturdifferenz zwischen weisser und schwarzer Wasserflasche kleiner.

Damit kann hinreichend belegt werden, dass eine schwarze Oberflächenbeschichtung zu einer stärkeren Wärmeabgabe an die Umgebung führt als eine weisse Oberflächenbeschichtung oder gar eine alu-gebürstete Aluminiumoberfläche.

Versuchsaufbau / Experiment

Anhang: Source Code

Der nachfolgende python Quelltext enthält das PhyPhox-Experiment T-Plotter v0.9 und stammt aus der Datei: „temp_measurement v0.9.py“

from phyphoxBLE import PhyphoxBLE, Experiment
import time
import machine, onewire, ds18x20		#OV: from T-Sensor

# Variablen- und Funktionsdefinition
p = PhyphoxBLE()
editValue = 123.0
firstCall = True

ds_pin = machine.Pin(22)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))
roms = ds_sensor.scan()

# -------- main() Function --------------------------------------
def main():
    # Name max length is 26 characters
    p.start("ESP32_PhyPhox_Messung")
    p._write_callback = receivedData
    
    #Define Experiment
    TempPlotter = Experiment()   
#generate experiment on ESP32 which plots temperatures over time
    TempPlotter.setTitle("T-Plotter v0.9")
    TempPlotter.setCategory("Micropython Experiments")
    TempPlotter.setDescription("In diesem Experiment werden Temperaturen mittels 3 Temperatursensoren gemessen. Eine grafische und numerische Auswertung dient der Vergleichbarkeit der Signale.")

    #Define Views
    firstView = Experiment.View()
    firstView.setLabel("3-Graphs")              #Create a "view"
    secondView = Experiment.View()
    secondView.setLabel("Values")          	    #Create a "view"
    thirdView = Experiment.View()
    thirdView.setLabel("T_amb")         	    #Create a "view"

    #Define Graphs
    firstGraph = Experiment.Graph()             
 #Create graph which will plot temperatures over time
    firstGraph.setLabel("Temperature 1")
    firstGraph.setUnitX("s")
    firstGraph.setUnitY("°C")
    firstGraph.setLabelX("time")
    firstGraph.setLabelY("T_1")
    firstGraph.setChannel(0, 1)

    secondGraph = Experiment.Graph()             
#Create graph which will plot temp_2 over time
    secondGraph.setLabel("Temperature 2")
    secondGraph.setUnitX("s")
    secondGraph.setUnitY("°C")
    secondGraph.setLabelX("time")
    secondGraph.setLabelY("T_2")
    secondGraph.setColor("2E728E")               #Sets Color of line
    secondGraph.setChannel(0, 2)

    thirdGraph = Experiment.Graph()              
#Create graph which will plot temperatures over time
    thirdGraph.setLabel("Temperature 3")
    thirdGraph.setUnitX("s")
    thirdGraph.setUnitY("°C")
    thirdGraph.setLabelX("time")
    thirdGraph.setLabelY("T_3")
    thirdGraph.setColor("2E727E")                #Sets Color of line
    thirdGraph.setChannel(0, 3)


# ---------------------------------------------------------------
# Definition der Elemente (Objekte) fuer die zweite Seite (View)
# (wieder eingefuegt aus dem Template)

    #Info
    myInfo = Experiment.InfoField()             
#Creates an info-box.
    myInfo.setInfo("Hier stehen momentante Temperaturwerte. Die Umgebungstemperatur kann manuell eingegeben werden")
    myInfo.setColor("FFFFFF")                   
#Sets font color. Uses a 6 digit hexadecimal value in "quotation marks".
    myInfo.setXMLAttribute("size=\"1.2\"")

    #Separator
    mySeparator = Experiment.Separator()        
#Creates a line to separate elements.
    mySeparator.setHeight(2.3)                  
#Sets height of the separator.
    mySeparator.setColor("404040")              
#Sets color of the separator. Uses a 6 digit hexadecimal value in "quotation marks".

    #Value1 (Temp1)
    myValue1 = Experiment.Value()  		#Creates a value-box.
    myValue1.setLabel("Temp_1")                  #Sets the label
    myValue1.setPrecision(1)                   
#The amount of digits shown after the decimal point.
    myValue1.setUnit("°C")                        
#The physical unit associated with the displayed value.
    myValue1.setColor("FFFFFF")                  
#Sets font color. Uses a 6 digit hexadecimal value in "quotation marks".
    myValue1.setChannel(1)
    myValue1.setXMLAttribute("size=\"3\"")

    #Value2 (T2)
    myValue2 = Experiment.Value()  		#Creates a value-box.
    myValue2.setLabel("Temp_2")                  #Sets the label
    myValue2.setPrecision(1)                     
#The amount of digits shown after the decimal point.
    myValue2.setUnit("°C")                        
#The physical unit associated with the displayed value.
    myValue2.setColor("FFFFFF")                  
#Sets font color. Uses a 6 digit hexadecimal value in "quotation marks".
    myValue2.setChannel(2)
    myValue2.setXMLAttribute("size=\"3\"")

    #Value3 (T3)
    myValue3 = Experiment.Value()  		#Creates a value-box.
    myValue3.setLabel("Temp_3")                  #Sets the label
    myValue3.setPrecision(1)                    
#The amount of digits shown after the decimal point.
    myValue3.setUnit("°C")                        
#The physical unit associated with the displayed value.
    myValue3.setColor("FFFFFF")                  
#Sets font color. Uses a 6 digit hexadecimal value in "quotation marks".
    myValue3.setChannel(3)
    myValue3.setXMLAttribute("size=\"3\"")

    #Value4 (Samples Counter, the integer i in the while loop below in the code)
    myValue4 = Experiment.Value()  		#Creates a value-box.
    myValue4.setLabel("n-te Lesung")                  #Sets the label
    myValue4.setPrecision(1)                     
#The amount of digits shown after the decimal point.
    myValue4.setUnit("")                        
#The physical unit associated with the displayed value.
    myValue4.setColor("FFFFFF")                  
#Sets font color. Uses a 6 digit hexadecimal value in "quotation marks".
    myValue4.setChannel(4)
    myValue4.setXMLAttribute("size=\"1\"")

    #Value5 (Hier ist nur der editValue Wert drin)
    myValue5 = Experiment.Value()  				
#Creates a value-box.
    myValue5.setLabel("Eingegeben")                  #Sets the label
    myValue5.setPrecision(1)                     
#The amount of digits shown after the decimal point.
    myValue5.setUnit("°C")                        
#The physical unit associated with the displayed value.
    myValue5.setColor("FFFFFF")                  
#Sets font color. Uses a 6 digit hexadecimal value in "quotation marks".
    myValue5.setChannel(5)
    myValue5.setXMLAttribute("size=\"1\"")

    #Edit
    myEdit = Experiment.Edit() 
    myEdit.setLabel("Umgebung")
    myEdit.setUnit("°C")
    myEdit.setSigned(False)
    myEdit.setDecimal(False)
    myEdit.setChannel(1)					
    myEdit.setXMLAttribute("max=\"100\"")

    #Export
    mySet = Experiment.ExportSet()              
#Provides exporting the data to excel etc.
    mySet.setLabel("meineDaten")

    myData1 = Experiment.ExportData() 
    myData1.setLabel("T1")
    myData1.setDatachannel(1)

    myData2 = Experiment.ExportData() 
    myData2.setLabel("T2")
    myData2.setDatachannel(2)

    myData3 = Experiment.ExportData() 			
    myData3.setLabel("T3")
    myData3.setDatachannel(3)




#  ---------------------------------------------------------------
# attach above defined elements (objects) to experiment
    firstView.addElement(firstGraph)            #attach graphs to view
    firstView.addElement(secondGraph)            
    firstView.addElement(thirdGraph)            

    secondView.addElement(myInfo)               #attach info to view
    secondView.addElement(mySeparator)       #attach separator to view
    secondView.addElement(myValue1)             #attach value to view
    secondView.addElement(myValue2)             #attach value to view
    secondView.addElement(myValue3)             #attach value to view

    thirdView.addElement(mySeparator)       #attach separator to view
    thirdView.addElement(myValue4)             #attach value to view
    thirdView.addElement(myValue5)             #attach value to view
    thirdView.addElement(myEdit)               
#attach editfield to view (Linked to value)

    TempPlotter.addView(firstView)          #attach view to experiment
    TempPlotter.addView(secondView)
    TempPlotter.addView(thirdView)

   
    p.addExperiment(TempPlotter)         #attach experiment to server

    
# --- Erste Schleife ---- Programm
# Code von DS18 Temperatursensor

    i = 0

    while True:
        ds_sensor.convert_temp()
        time.sleep_ms(900)
    
        i = i+1;
        t1 = ds_sensor.read_temp(roms[0])
        t2 = ds_sensor.read_temp(roms[1])
        t3 = ds_sensor.read_temp(roms[2])
        t_amb = 123;
        
        p.write(t1, t2, t3, i, 123)

        time.sleep_ms(100)




def receivedData():          # get data from PhyPhox app
    global editValue
    global firstCall
    if not firstCall:
        editValue = float(p.read())
    firstCall = False
    
if __name__ == "__main__":
    main()