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
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.
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.
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 |
Experimentelle Schritte
Schritt 1: Baue die Schaltung auf.
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
Dieser Abschnitt importiert die benötigten Bibliotheken:
spidevfür die SPI-Kommunikation mit dem MCP3008timefür Verzögerungsfunktionenmathfür logarithmische Operationen in der Steinhart–Hart-TemperaturformelRPi.GPIOzum 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
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
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
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)
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()