.. note:: Hallo, willkommen in der SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasten-Community auf Facebook! Tauche tiefer in Raspberry Pi, Arduino und ESP32 ein – gemeinsam mit anderen Enthusiasten. **Warum beitreten?** - **Expertenunterstützung**: Löse Probleme nach dem Kauf und technische Herausforderungen mit Hilfe unserer Community und unseres Teams. - **Lernen & Teilen**: Tausche Tipps und Tutorials aus, um deine Fähigkeiten zu erweitern. - **Exklusive Vorschauen**: Erhalte frühzeitigen Zugang zu neuen Produktankündigungen und Vorschauen. - **Sonderrabatte**: Genieße exklusive Rabatte auf unsere neuesten Produkte. - **Festliche Aktionen und Gewinnspiele**: Nimm an Gewinnspielen und Feiertagsaktionen teil. 👉 Bereit, mit uns zu entdecken und zu erschaffen? Klicke auf [|link_sf_facebook|] und trete noch heute bei! .. _2.2.2_c_mcp3008: 2.2.2 Thermistor (MCP3008) ========================== .. note:: .. image:: img/mcp3008_and_adc0834.jpg :width: 25% :align: left Abhängig von deiner Kit-Version identifiziere bitte, ob du **ADC0834** oder **MCP3008** hast, und fahre mit dem entsprechenden Abschnitt fort. Einführung ---------- So wie ein Fotowiderstand Licht erfassen kann, ist der Thermistor ein temperaturempfindliches elektronisches Bauteil, das für Temperaturregelungsfunktionen verwendet werden kann – zum Beispiel für einen Hitzealarm. Benötigte Komponenten --------------------- In diesem Projekt benötigen wir die folgenden Komponenten. .. image:: img/list2_2.2.2_thermistor.png Funktionsprinzip ---------------- Ein Thermistor ist ein thermisch empfindlicher Widerstand, dessen Widerstand sich präzise und vorhersehbar proportional zu kleinen Temperaturänderungen verändert. Wie stark sich der Widerstand ändert, hängt von seiner spezifischen Zusammensetzung ab. Thermistoren gehören zur Gruppe der passiven Bauteile und sind – im Gegensatz zu aktiven Bauteilen – nicht in der Lage, eine Leistungsverstärkung zu erzeugen. Es gibt zwei Arten von Thermistoren: Negativer Temperaturkoeffizient (NTC) und Positiver Temperaturkoeffizient (PTC). Beim PTC steigt der Widerstand mit der Temperatur, beim NTC ist es umgekehrt. In diesem Experiment verwenden wir einen NTC. .. image:: img/image325.png Das Prinzip: Der Widerstand des NTC-Thermistors ändert sich mit der Temperatur der Umgebung. Steigt die Temperatur, sinkt der Widerstand des Thermistors. Die Spannung wird anschließend vom A/D-Wandler digitalisiert und per Programm in Grad Celsius oder Fahrenheit umgerechnet. In diesem Experiment werden ein Thermistor und ein 10-kΩ-Pull-up-Widerstand verwendet. Der Thermistor hat bei 25 °C einen Widerstand von 10 kΩ. Beziehung zwischen Widerstand und Temperatur: R\ :sub:`T` = R\ :sub:`N` exp\ :sup:`B(1/TK – 1/TN)` **R\ T** ist der Widerstand bei Temperatur **T\ K** (Kelvin). **R\ N** ist der Widerstand bei der Referenztemperatur **T\ N** (25°C → 298,15K) und beträgt hier 10 kΩ. **T\ K** ist die Temperatur in Kelvin: 273,15 + Celsius. **B** ist der Materialkonstante des NTC-Thermistors (Wärmeempfindlichkeitsindex), hier 3950. **exp** steht für die Exponentialfunktion (Basis e ≈ 2,7). Umstellen der Formel: T\ :sub:`K` = 1 / (ln(R\ :sub:`T` / R\ :sub:`N`) / B + 1 / T\ :sub:`N`) → T(K) − 273,15 = Temperatur in °C. Diese empirische Formel ist nur im angegebenen Bereich genau. Schaltplan ---------- .. list-table:: :widths: 30 30 30 30 :header-rows: 1 * - T-Board-Name - Physisch - WiringPi - BCM * - SPICE0 - pin24 - 10 - 8 * - SPIMOSI - pin19 - 12 - 10 * - SPIMISO - pin21 - 13 - 9 * - SPISCLK - pin23 - 14 - 11 .. image:: img/schematic_2.2.2_thermistor_mcp3008.png Experimentelle Schritte ----------------------- **Schritt 1:** Baue die Schaltung auf. .. image:: img/july24_2.2.2_thermistor_mcp3008.png Für C-Sprach-Nutzer ^^^^^^^^^^^^^^^^^^^ **Schritt 2:** Wechsle in den Quellcode-Ordner. .. code-block:: cd ~/davinci-kit-for-raspberry-pi/c/2.2.2-2/ **Schritt 3:** Kompiliere den Code. .. code-block:: gcc 2.2.2_Thermistor.c -o Thermistor -lwiringPi -lm .. note:: -lm bindet die Mathematikbibliothek ein. Nicht weglassen, sonst gibt es einen Fehler. **Schritt 4:** Führe die ausführbare Datei aus. .. code-block:: ./Thermistor Während der Code läuft, misst der Thermistor die Umgebungstemperatur und gibt das Ergebnis nach Berechnung auf dem Bildschirm aus. .. note:: Falls es nach dem Start nicht funktioniert oder die Fehlermeldung „wiringPi.h: No such file or directory“ erscheint, siehe :ref:`install_wiringpi`. **Code** -------------------- .. code-block:: c #include #include #include #include #define SPI_CHANNEL 0 // CE0 #define SPI_SPEED 1000000 // 1MHz int read_ADC(int channel) { if (channel < 0 || channel > 7) return -1; unsigned char buffer[3]; buffer[0] = 1; // Startbit buffer[1] = (8 + channel) << 4; // Single-Ended-Modus + Kanal buffer[2] = 0; wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3); int value = ((buffer[1] & 3) << 8) | buffer[2]; return value; } int main(void) { int analogVal; double Vr, Rt, temp, cel, Fah; if (wiringPiSetup() == -1) { printf("setup wiringPi fehlgeschlagen!\n"); return 1; } if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) { printf("SPI-Setup fehlgeschlagen!\n"); return 1; } while (1) { analogVal = read_ADC(0); // Lese von CH0 // MCP3008 ist 10-Bit ADC (0–1023) Vr = 3.3 * analogVal / 1023.0; // Vref = 3,3V Rt = 10000.0 * Vr / (3.3 - Vr); // Spannungsteiler mit 10kΩ temp = 1 / ((log(Rt / 10000.0) / 3950.0) + (1 / (273.15 + 25.0))); cel = temp - 273.15; Fah = cel * 1.8 + 32; printf("Celsius: %.2f C Fahrenheit: %.2f F\n", cel, Fah); delay(1000); } return 0; } **Code-Erklärung** ---------------------------- .. code-block:: c #include #include #include #include Diese Header-Dateien binden Bibliotheken für GPIO-Steuerung (``wiringPi.h``), SPI-Kommunikation (``wiringPiSPI.h``), Standard-Ein-/Ausgabeoperationen (``stdio.h``) und mathematische Funktionen (``math.h``) in C ein. .. code-block:: c #define SPI_CHANNEL 0 #define SPI_SPEED 1000000 Definiert Konstanten für den SPI-Kanal und die SPI-Kommunikationsgeschwindigkeit. Hier wird SPI-Kanal 0 (CE0) und eine Taktrate von 1 MHz verwendet. .. code-block:: c int read_ADC(int channel) Diese Funktion liest analoge Daten von einem angegebenen Kanal des MCP3008-ADCs. .. code-block:: c buffer[0] = 1; buffer[1] = (8 + channel) << 4; buffer[2] = 0; Diese Zeilen formatieren den SPI-Befehl gemäß dem MCP3008-Protokoll: Startbit, Konfiguration für den Single-Ended-Modus und die Kanalnummer. .. code-block:: c wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3); Überträgt den SPI-Befehl und empfängt die 10-Bit-ADC-Daten vom MCP3008. .. code-block:: c int value = ((buffer[1] & 3) << 8) | buffer[2]; Extrahiert und kombiniert das 10-Bit-ADC-Ergebnis aus dem zurückgegebenen SPI-Puffer. .. code-block:: c if (wiringPiSetup() == -1) { ... } if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) { ... } Diese Zeilen initialisieren WiringPi und konfigurieren SPI. Falls die Initialisierung fehlschlägt, beendet das Programm die Ausführung. .. code-block:: c analogVal = read_ADC(0); Liest das analoge Signal von MCP3008-Kanal 0, an dem der Thermistor-Spannungsteiler angeschlossen ist. .. code-block:: c Vr = 3.3 * analogVal / 1023.0; Wandelt den digitalen ADC-Wert in eine analoge Spannung um. Der ADC-Bereich beträgt 0–1023 bei einer Referenzspannung von 3,3 V. .. code-block:: c Rt = 10000.0 * Vr / (3.3 - Vr); Berechnet den Widerstand des Thermistors unter Verwendung der Spannungsteilerformel. Es wird ein 10-kΩ-Widerstand in Reihe mit dem Thermistor angenommen. .. code-block:: c temp = 1 / ((log(Rt / 10000.0) / 3950.0) + (1 / (273.15 + 25.0))); Verwendet die B-Parameter-Gleichung, um den Widerstand des Thermistors in eine Temperatur in Kelvin umzuwandeln. **T(K) = 1 / [ln(Rt/R₀)/B + 1/T₀]**, wobei - R₀ = 10 kΩ - B = 3950 - T₀ = 25 °C = 298,15 K .. code-block:: c cel = temp - 273.15; Wandelt die Temperatur von Kelvin in Grad Celsius um. .. code-block:: c Fah = cel * 1.8 + 32; Wandelt die Temperatur in Grad Celsius in Grad Fahrenheit um. .. code-block:: c printf("Celsius: %.2f C Fahrenheit: %.2f F\n", cel, Fah); Zeigt die Temperatur sowohl in Celsius als auch in Fahrenheit mit zwei Nachkommastellen im Terminal an. Für Python-Sprach-Nutzer ^^^^^^^^^^^^^^^^^^^^^^^^ **Schritt 2:** Richte das SPI-Interface ein und installiere die Bibliothek ``spidev`` (siehe :ref:`spi_configuration`). Falls du dies bereits getan hast, überspringe diesen Schritt. **Schritt 3:** Wechsle in den Quellcode-Ordner. .. code-block:: cd ~/davinci-kit-for-raspberry-pi/python **Schritt 4:** Führe die Datei aus. .. code-block:: sudo python3 2.2.2-2_thermistor.py Während der Code läuft, misst der Thermistor die Umgebungstemperatur und gibt die Werte nach Berechnung aus. .. warning:: Falls ``RuntimeError: Cannot determine SOC peripheral base address`` erscheint, siehe :ref:`faq_soc`. **Code** ------------------ .. code-block:: python #!/usr/bin/env python3 # -*- coding: utf-8 -*- import spidev import time import math import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) spi = spidev.SpiDev() spi.open(0, 0) # Bus 0, Gerät 0 (CE0) spi.max_speed_hz = 1000000 # 1 MHz def read_adc(channel): if channel < 0 or channel > 7: return -1 adc = spi.xfer2([1, (8 + channel) << 4, 0]) value = ((adc[1] & 0x03) << 8) | adc[2] return value try: while True: analogVal = read_adc(0) Vr = 3.3 * analogVal / 1023.0 Rt = 10000.0 * Vr / (3.3 - Vr) tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0))) Cel = tempK - 273.15 Fah = Cel * 1.8 + 32 print('Celsius: %.2f °C Fahrenheit: %.2f °F' % (Cel, Fah)) time.sleep(0.2) except KeyboardInterrupt: pass finally: spi.close() GPIO.cleanup() **Code-Erklärung** ------------------------------- #. Dieser Abschnitt importiert die benötigten Bibliotheken: - ``spidev`` für die SPI-Kommunikation mit dem MCP3008 - ``time`` für Verzögerungsfunktionen - ``math`` für logarithmische Operationen in der Steinhart–Hart-Temperaturformel - ``RPi.GPIO`` zum Initialisieren und Aufräumen der GPIOs (der Vollständigkeit halber enthalten) .. code-block:: python #!/usr/bin/env python3 # -*- coding: utf-8 -*- import spidev import time import math import RPi.GPIO as GPIO #. Initialisiert den GPIO-Modus als BCM und konfiguriert die SPI-Schnittstelle auf Bus 0 und Gerät 0 (CE0) mit einer Geschwindigkeit von 1 MHz. .. code-block:: python # GPIO-Modus festlegen GPIO.setmode(GPIO.BCM) # Initialisierung von SPI für MCP3008 (Bus 0, CE0) spi = spidev.SpiDev() spi.open(0, 0) # Bus 0, Gerät 0 (CE0) spi.max_speed_hz = 1000000 # 1 MHz #. Definiert eine Funktion ``read_adc(channel)``, um analoge Werte von einem angegebenen MCP3008-Kanal (0–7) zu lesen. Sie sendet einen 3-Byte-SPI-Befehl und empfängt ein 10-Bit-Analogresultat (0–1023). .. code-block:: python def read_adc(channel): """ Lese analogen Wert vom MCP3008-Kanal (0–7) """ if channel < 0 or channel > 7: return -1 adc = spi.xfer2([1, (8 + channel) << 4, 0]) value = ((adc[1] & 0x03) << 8) | adc[2] return value #. Hauptschleife: Liest die analoge Spannung von einem Thermistor an Kanal 0, wandelt diese in einen Widerstand um und nutzt dann die Steinhart–Hart-Gleichung, um die Temperatur in Celsius und Fahrenheit zu berechnen. Die Werte werden alle 0,2 Sekunden aktualisiert. .. code-block:: python try: while True: # Lese analogen Wert von CH0 des MCP3008 analogVal = read_adc(0) # Umrechnen in Spannung (bei Annahme von 3,3 V Referenz) Vr = 3.3 * analogVal / 1023.0 # Thermistorwiderstand berechnen (R2 im Spannungsteiler ist 10 kΩ) Rt = 10000.0 * Vr / (3.3 - Vr) # Steinhart–Hart-Berechnung tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0))) # Umrechnen in Celsius und Fahrenheit Cel = tempK - 273.15 Fah = Cel * 1.8 + 32 # Ergebnis ausgeben print('Celsius: %.2f °C Fahrenheit: %.2f °F' % (Cel, Fah)) time.sleep(0.2) #. Der ``finally``-Block sorgt für einen sauberen Programmabschluss. Er schließt die SPI-Schnittstelle und führt ein GPIO-Cleanup durch, um alle Hardware-Ressourcen freizugeben. .. code-block:: python except KeyboardInterrupt: pass finally: spi.close() GPIO.cleanup()