Bemerkung

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 [hier] und trete noch heute bei!

2.2.2 Thermistor (MCP3008)

Bemerkung

_images/mcp3008_and_adc0834.jpg

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.

_images/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.

_images/image3251.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:

RT = RN expB(1/TK – 1/TN)

RT ist der Widerstand bei Temperatur TK (Kelvin). RN ist der Widerstand bei der Referenztemperatur TN (25°C → 298,15K) und beträgt hier 10 kΩ. TK 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: TK = 1 / (ln(RT / RN) / B + 1 / TN) → T(K) − 273,15 = Temperatur in °C.

Diese empirische Formel ist nur im angegebenen Bereich genau.

Schaltplan

T-Board-Name

Physisch

WiringPi

BCM

SPICE0

pin24

10

8

SPIMOSI

pin19

12

10

SPIMISO

pin21

13

9

SPISCLK

pin23

14

11

_images/schematic_2.2.2_thermistor_mcp3008.png

Experimentelle Schritte

Schritt 1: Baue die Schaltung auf.

_images/july24_2.2.2_thermistor_mcp3008.png

Für C-Sprach-Nutzer

Schritt 2: Wechsle in den Quellcode-Ordner.

cd ~/davinci-kit-for-raspberry-pi/c/2.2.2-2/

Schritt 3: Kompiliere den Code.

gcc 2.2.2_Thermistor.c -o Thermistor -lwiringPi -lm

Bemerkung

-lm bindet die Mathematikbibliothek ein. Nicht weglassen, sonst gibt es einen Fehler.

Schritt 4: Führe die ausführbare Datei aus.

./Thermistor

Während der Code läuft, misst der Thermistor die Umgebungstemperatur und gibt das Ergebnis nach Berechnung auf dem Bildschirm aus.

Bemerkung

Falls es nach dem Start nicht funktioniert oder die Fehlermeldung „wiringPi.h: No such file or directory“ erscheint, siehe Installieren und Überprüfen von WiringPi.

Code

#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <stdio.h>
#include <math.h>

#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

#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <stdio.h>
#include <math.h>

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.

#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.

int read_ADC(int channel)

Diese Funktion liest analoge Daten von einem angegebenen Kanal des MCP3008-ADCs.

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.

wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);

Überträgt den SPI-Befehl und empfängt die 10-Bit-ADC-Daten vom MCP3008.

int value = ((buffer[1] & 3) << 8) | buffer[2];

Extrahiert und kombiniert das 10-Bit-ADC-Ergebnis aus dem zurückgegebenen SPI-Puffer.

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.

analogVal = read_ADC(0);

Liest das analoge Signal von MCP3008-Kanal 0, an dem der Thermistor-Spannungsteiler angeschlossen ist.

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.

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.

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

cel = temp - 273.15;

Wandelt die Temperatur von Kelvin in Grad Celsius um.

Fah = cel * 1.8 + 32;

Wandelt die Temperatur in Grad Celsius in Grad Fahrenheit um.

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 SPI-Konfiguration). Falls du dies bereits getan hast, überspringe diesen Schritt.

Schritt 3: Wechsle in den Quellcode-Ordner.

cd ~/davinci-kit-for-raspberry-pi/python

Schritt 4: Führe die Datei aus.

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.

Warnung

Falls RuntimeError: Cannot determine SOC peripheral base address erscheint, siehe Wenn gpiozero nicht funktioniert..

Code

#!/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

  1. 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)

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import spidev
    import time
    import math
    import RPi.GPIO as GPIO
    
  2. 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.

    # 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
    
  3. 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).

    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
    
  4. 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.

    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)
    
  5. 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.

    except KeyboardInterrupt:
        pass
    
    finally:
        spi.close()
        GPIO.cleanup()