.. note::
Hallo und willkommen in der SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasten-Community auf Facebook!
Tauche tiefer in Raspberry Pi, Arduino und ESP32 ein – gemeinsam mit anderen Technik-Begeisterten.
**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 verbessern.
- **Exklusive Vorschauen**: Erhalte frühen Zugang zu neuen Produktankündigungen und Einblicken.
- **Sonderrabatte**: Genieße exklusive Rabatte auf unsere neuesten Produkte.
- **Festliche Aktionen und Gewinnspiele**: Nimm an Verlosungen und Feiertagsaktionen teil.
👉 Bereit, mit uns zu entdecken und zu kreieren? Klicke [|link_sf_facebook|] und trete noch heute bei!
.. _3.1.8_c_mcp3008:
3.1.8 Überhitzungsmonitor (MCP3008)
====================================
.. note::
.. image:: img/mcp3008_and_adc0834.jpg
:width: 25%
:align: left
Abhängig von deiner Kit-Version überprüfe bitte, ob du **ADC0834** oder **MCP3008** hast,
und fahre mit dem passenden Abschnitt fort.
Einführung
-------------------
Vielleicht möchtest du ein Überhitzungs-Überwachungsgerät bauen, das in verschiedenen Situationen eingesetzt werden kann.
Zum Beispiel in einer Fabrik: Wenn eine Schaltung überhitzt, soll ein Alarm ausgelöst und die Maschine automatisch abgeschaltet werden.
In diesem Projekt verwenden wir einen Thermistor, Joystick, Summer, LED und ein LCD,
um ein intelligentes Temperatur-Überwachungsgerät mit einstellbarem Schwellenwert zu bauen.
Benötigte Komponenten
------------------------------
Für dieses Projekt benötigen wir die folgenden Komponenten:
.. image:: img/list2_Overheat_Monitor.png
:align: center
Schaltplan
--------------------------
============ ======== ======== ===
T-Board Name Physikal wiringPi BCM
SPICE0 Pin 24 10 8
SPIMOSI Pin 19 12 10
SPIMISO Pin 21 13 9
SPISCLK Pin 23 14 11
GPIO22 Pin 15 3 22
GPIO23 Pin 16 4 23
GPIO24 Pin 18 5 24
SDA1 Pin 3
SCL1 Pin 5
============ ======== ======== ===
.. image:: img/Schematic_three_one8.png
:align: center
Versuchsschritte
-----------------------------
**Schritt 1:** Baue die Schaltung auf.
.. image:: img/july24_3.1.8_overheat_monitor_mcp3008.png
**Für C-Sprach-Nutzer**
^^^^^^^^^^^^^^^^^^^^^^^^^^
**Schritt 2:** Gehe in den Code-Ordner.
.. raw:: html
.. code-block::
cd ~/davinci-kit-for-raspberry-pi/c/3.1.8-2/
**Schritt 3:** Kompiliere den Code.
.. raw:: html
.. code-block::
gcc 3.1.8_OverheatMonitor.c -lm -lwiringPi
**Schritt 4:** Führe die ausführbare Datei aus.
.. raw:: html
.. code-block::
sudo ./a.out
Während der Code läuft, werden die aktuelle Temperatur und der Hochtemperatur-Schwellenwert **40**
auf dem **I2C LCD1602** angezeigt.
Wenn die aktuelle Temperatur größer als der Schwellenwert ist, werden Summer und LED aktiviert,
um dich zu warnen.
Mit dem **Joystick** kannst du den Hochtemperatur-Schwellenwert einstellen.
Bewegen des Joysticks entlang der X- und Y-Achse erhöht oder verringert den aktuellen Schwellenwert.
Ein erneutes Drücken des Joysticks setzt den Wert auf den Anfangswert zurück.
.. note::
* Falls der Fehler ``wiringPi.h: No such file or directory`` erscheint, siehe :ref:`install_wiringpi`.
* Falls der Fehler ``Unable to open I2C device: No such file or directory`` erscheint,
siehe :ref:`i2c_config`, um I2C zu aktivieren und die Verdrahtung zu prüfen.
* Falls Code und Verdrahtung stimmen, aber das LCD dennoch nichts anzeigt,
drehe am Potentiometer auf der Rückseite, um den Kontrast zu erhöhen.
Code-Erklärung
----------------------
.. code-block:: c
int read_ADC(int channel) {
if (channel < 0 || channel > 7) return -1;
unsigned char buffer[3];
buffer[0] = 1;
buffer[1] = (8 + channel) << 4;
buffer[2] = 0;
wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);
return ((buffer[1] & 0x03) << 8) | buffer[2];
}
Liest einen 10-Bit-Analogwert vom MCP3008-Kanal (CH0–CH7) über SPI und gibt einen Wert von 0 bis 1023 zurück.
.. code-block:: c
int get_joystick_value() {
int x = read_ADC(1);
int y = read_ADC(2);
if (x > 900) return 1; // Rechts
else if (x < 100) return -1; // Links
else if (y > 900) return -10; // Hoch
else if (y < 100) return 10; // Runter
else return 0;
}
Liest die analogen X- und Y-Werte des Joysticks von CH1 und CH2.
Gibt eine Ganzzahl zurück, die die Bewegungsrichtung anhand von Schwellenwerten angibt.
.. code-block:: c
void upper_tem_setting() {
write_lcd(0,0, "Upper Adjust:");
int change = get_joystick_value();
if (change != 0 && change != lastJoystickChange) {
upperTem += change;
lastJoystickChange = change;
}
else if (change == 0) {
lastJoystickChange = 0;
}
char str[6];
snprintf(str, sizeof(str), "%d", upperTem);
write_lcd(0,1, str);
write_lcd(strlen(str),1, " ");
delay(100);
}
Ermöglicht es, den oberen Temperatur-Schwellenwert mit dem Joystick einzustellen.
Verhindert wiederholte Änderungen, wenn die Richtung gehalten wird.
.. code-block:: c
double temperature() {
int raw = read_ADC(0);
double Vr = 3.3 * ((double)raw / 1023.0);
double Rt = 10000.0 * Vr / (3.3 - Vr);
double tempK = 1.0 / ((log(Rt/10000.0)/3950.0) + 1.0/(273.15+25.0));
return tempK - 273.15;
}
Liest den analogen Wert von CH0, an dem der Thermistor angeschlossen ist.
Berechnet die Temperatur in Grad Celsius mithilfe der Steinhart–Hart-Gleichung.
.. code-block:: c
void monitoring_temp() {
char str[6];
double cel = temperature();
snprintf(str, sizeof(str), "%.2f", cel);
write_lcd(0,0, "Temp: ");
write_lcd(6,0, str);
snprintf(str, sizeof(str), "%d", upperTem);
write_lcd(0,1, "Upper: ");
write_lcd(7,1, str);
delay(100);
if (cel >= upperTem) {
digitalWrite(buzzPin, HIGH);
digitalWrite(LedPin, HIGH);
} else {
digitalWrite(buzzPin, LOW);
digitalWrite(LedPin, LOW);
}
}
Liest kontinuierlich die aktuelle Temperatur und zeigt sie zusammen mit dem Schwellenwert an.
Überschreitet die Temperatur den Schwellenwert, werden Summer und LED aktiviert.
.. code-block:: c
void setup_all() {
fd = wiringPiI2CSetup(LCDAddr);
lcd_init();
if (wiringPiSetup() == -1 || wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) {
printf("Setup failed!\n");
return;
}
pinMode(Joy_BtnPin, INPUT);
pullUpDnControl(Joy_BtnPin, PUD_UP);
pinMode(buzzPin, OUTPUT);
pinMode(LedPin, OUTPUT);
}
Initialisiert LCD, SPI und GPIO-Pins für Joystick-Taste, Summer und LED.
Setzt außerdem den Pull-up-Widerstand für die Joystick-Taste.
.. code-block:: c
int main(void) {
setup_all();
int lastBtnState = HIGH;
int stage = 0;
while (1) {
int curBtn = digitalRead(Joy_BtnPin);
if (curBtn == HIGH && lastBtnState == LOW) {
stage = (stage + 1) % 2;
lastJoystickChange = 0;
delay(100);
lcd_clear();
}
lastBtnState = curBtn;
if (stage == 1)
upper_tem_setting();
else
monitoring_temp();
}
return 0;
}
Die Hauptschleife wechselt zwischen zwei Modi:
1. Temperaturüberwachung.
2. Einstellung des oberen Grenzwerts mit dem Joystick.
**Für Python-Sprachbenutzer**
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
**Schritt 2:** Richten Sie die SPI-Schnittstelle ein und installieren Sie die ``spidev``-Bibliothek (siehe :ref:`spi_configuration` für detaillierte Anweisungen). Wenn Sie diese Schritte bereits abgeschlossen haben, können Sie diesen Schritt überspringen.
**Schritt 3**: Gehen Sie in den Ordner mit dem Code.
.. raw:: html
.. code-block::
cd ~/davinci-kit-for-raspberry-pi/python
**Schritt 4**: Führen Sie die ausführbare Datei aus.
.. raw:: html
.. code-block::
sudo python3 3.1.8-2_OverheatMonitor.py
Während der Code ausgeführt wird, werden die aktuelle Temperatur und die Hochtemperaturschwelle **40** auf dem **I2C LCD1602** angezeigt.
Wenn die aktuelle Temperatur größer als die Schwelle ist, werden Summer und LED aktiviert, um Sie zu warnen.
Der **Joystick** dient hier dazu, die Hochtemperaturschwelle durch Drücken anzupassen.
Das Bewegen des **Joysticks** entlang der X- und Y-Achse kann die aktuelle Hochtemperaturschwelle erhöhen oder verringern.
Drücken Sie den **Joystick** erneut, um die Schwelle auf den Anfangswert zurückzusetzen.
.. note::
* Wenn der Fehler ``FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'`` auftritt, müssen Sie gemäß :ref:`i2c_config` den I2C aktivieren.
* Wenn der Fehler ``ModuleNotFoundError: No module named 'smbus2'`` auftritt, führen Sie bitte ``sudo apt install python3-smbus2`` aus.
* Wenn der Fehler ``OSError: [Errno 121] Remote I/O error`` erscheint, ist das Modul entweder falsch verdrahtet oder defekt.
* Wenn Code und Verdrahtung korrekt sind, das LCD jedoch weiterhin nichts anzeigt, drehen Sie das Potentiometer auf der Rückseite, um den Kontrast zu erhöhen.
.. warning::
Wenn die Fehlermeldung ``RuntimeError: Cannot determine SOC peripheral base address`` erscheint, lesen Sie bitte :ref:`faq_soc`
**Code**
.. note::
Sie können den folgenden Code **ändern/zurücksetzen/kopieren/ausführen/stoppen**.
Bevor Sie dies tun, müssen Sie jedoch in das Quellcode-Verzeichnis wie ``davinci-kit-for-raspberry-pi/python`` wechseln.
Nach einer Änderung können Sie den Code direkt ausführen, um die Auswirkung zu sehen.
.. raw:: html
.. code-block:: python
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import spidev
import time
import math
import LCD1602
# GPIO pin definitions
JOY_BTN_PIN = 22 # Button pin
BUZZER_PIN = 23 # Buzzer pin
LED_PIN = 24 # LED pin
# Initialize GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(JOY_BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(BUZZER_PIN, GPIO.OUT)
GPIO.setup(LED_PIN, GPIO.OUT)
# Set initial upper temperature threshold
upperTem = 40
# Initialize SPI for MCP3008
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1000000 # 1 MHz
# Initialize LCD1602
LCD1602.init(0x27, 1)
def read_adc(channel):
"""
Read analog value from MCP3008 (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
def get_joystick_value():
"""
Reads the joystick values and returns a change value based on the joystick's position.
"""
x_val = read_adc(1)
y_val = read_adc(2)
if x_val > 800:
return 1
elif x_val < 200:
return -1
elif y_val > 800:
return -10
elif y_val < 200:
return 10
else:
return 0
def upper_tem_setting():
"""
Adjusts and displays the upper temperature threshold on the LCD.
"""
global upperTem
LCD1602.write(0, 0, 'Upper Adjust: ')
change = int(get_joystick_value())
upperTem += change
strUpperTem = str(upperTem)
LCD1602.write(0, 1, strUpperTem)
LCD1602.write(len(strUpperTem), 1, ' ')
time.sleep(0.1)
def temperature():
"""
Reads the current temperature from the sensor and returns it in Celsius.
"""
analogVal = read_adc(0)
Vr = 3.3 * analogVal / 1023.0
if Vr == 0:
return 0
Rt = 10000.0 * (3.3 - Vr) / Vr
tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0)))
Cel = tempK - 273.15
return round(Cel, 2)
def monitoring_temp():
"""
Monitors and displays the current temperature and upper temperature threshold.
Activates buzzer and LED if the temperature exceeds the upper limit.
"""
global upperTem
Cel = temperature()
LCD1602.write(0, 0, 'Temp: ')
LCD1602.write(0, 1, 'Upper: ')
LCD1602.write(6, 0, str(Cel))
LCD1602.write(7, 1, str(upperTem))
time.sleep(0.1)
if Cel >= upperTem:
GPIO.output(BUZZER_PIN, GPIO.HIGH)
GPIO.output(LED_PIN, GPIO.HIGH)
else:
GPIO.output(BUZZER_PIN, GPIO.LOW)
GPIO.output(LED_PIN, GPIO.LOW)
# Main loop
try:
lastState = GPIO.input(JOY_BTN_PIN)
stage = 0
while True:
currentState = GPIO.input(JOY_BTN_PIN)
if currentState == GPIO.HIGH and lastState == GPIO.LOW:
stage = (stage + 1) % 2
time.sleep(0.1)
LCD1602.clear()
lastState = currentState
if stage == 1:
upper_tem_setting()
else:
monitoring_temp()
except KeyboardInterrupt:
pass
finally:
LCD1602.clear()
GPIO.cleanup()
spi.close()
Code-Erklärung
----------------------------
1. **Bibliotheken importieren**
Dieser Abschnitt lädt die erforderlichen Bibliotheken für GPIO, SPI, LCD-Anzeige, Zeitverzögerungen und mathematische Operationen.
.. code-block:: python
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import spidev
import time
import math
import LCD1602
2. **GPIO- und Geräteeinrichtung**
Definiert die GPIO-Pinnummern für den Joystick-Knopf, den Summer und die LED, und konfiguriert die GPIO-Modi.
.. code-block:: python
JOY_BTN_PIN = 22 # Taster-Pin
BUZZER_PIN = 23 # Summer-Pin
LED_PIN = 24 # LED-Pin
GPIO.setmode(GPIO.BCM)
GPIO.setup(JOY_BTN_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(BUZZER_PIN, GPIO.OUT)
GPIO.setup(LED_PIN, GPIO.OUT)
3. **SPI- und LCD-Initialisierung**
Startet die SPI-Schnittstelle für MCP3008 und initialisiert den LCD1602-Bildschirm mit der I2C-Adresse 0x27.
.. code-block:: python
upperTem = 40
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1000000
LCD1602.init(0x27, 1)
4. **ADC-Wert lesen**
Liest analoge Daten vom MCP3008-ADC über SPI. Der Kanal sollte im Bereich 0–7 liegen.
.. code-block:: python
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
5. **Joystick-Bewegungserkennung**
Überprüft die X/Y-Achsenwerte des Joysticks und gibt zurück, um wie viel der Schwellenwert geändert werden soll.
.. code-block:: python
def get_joystick_value():
x_val = read_adc(1)
y_val = read_adc(2)
if x_val > 800:
return 1
elif x_val < 200:
return -1
elif y_val > 800:
return -10
elif y_val < 200:
return 10
else:
return 0
6. **Obere Temperaturschwelle einstellen**
Zeigt „Upper Adjust“ auf dem LCD an und passt die Schwelle anhand der Joystick-Eingaben an.
.. code-block:: python
def upper_tem_setting():
global upperTem
LCD1602.write(0, 0, 'Upper Adjust: ')
change = int(get_joystick_value())
upperTem += change
strUpperTem = str(upperTem)
LCD1602.write(0, 1, strUpperTem)
LCD1602.write(len(strUpperTem), 1, ' ')
time.sleep(0.1)
7. **Temperaturberechnung**
Wandelt den analogen Sensorwert in Spannung, Widerstand und schließlich Temperatur (Celsius) unter Verwendung der Steinhart–Hart-Annäherung um.
.. code-block:: python
def temperature():
analogVal = read_adc(0)
Vr = 3.3 * analogVal / 1023.0
if Vr == 0:
return 0
Rt = 10000.0 * (3.3 - Vr) / Vr
tempK = 1.0 / (((math.log(Rt / 10000.0)) / 3950.0) + (1.0 / (273.15 + 25.0)))
Cel = tempK - 273.15
return round(Cel, 2)
8. **Temperaturüberwachung**
Überprüft und zeigt kontinuierlich Temperatur und obere Grenze an. Aktiviert Summer und LED, wenn die Temperatur die Schwelle überschreitet.
.. code-block:: python
def monitoring_temp():
global upperTem
Cel = temperature()
LCD1602.write(0, 0, 'Temp: ')
LCD1602.write(0, 1, 'Upper: ')
LCD1602.write(6, 0, str(Cel))
LCD1602.write(7, 1, str(upperTem))
time.sleep(0.1)
if Cel >= upperTem:
GPIO.output(BUZZER_PIN, GPIO.HIGH)
GPIO.output(LED_PIN, GPIO.HIGH)
else:
GPIO.output(BUZZER_PIN, GPIO.LOW)
GPIO.output(LED_PIN, GPIO.LOW)
9. **Hauptprogrammlogik**
Wechselt zwischen Temperaturüberwachungs- und Schwellenwerteinstellungsmodus, wenn der Joystick-Knopf gedrückt wird.
.. code-block:: python
try:
lastState = GPIO.input(JOY_BTN_PIN)
stage = 0
while True:
currentState = GPIO.input(JOY_BTN_PIN)
if currentState == GPIO.HIGH and lastState == GPIO.LOW:
stage = (stage + 1) % 2
time.sleep(0.1)
LCD1602.clear()
lastState = currentState
if stage == 1:
upper_tem_setting()
else:
monitoring_temp()
10. **Aufräumen beim Beenden**
Sorgt für die ordnungsgemäße Freigabe von GPIO- und SPI-Ressourcen, wenn Strg+C gedrückt wird.
.. code-block:: python
except KeyboardInterrupt:
pass
finally:
LCD1602.clear()
GPIO.cleanup()
spi.close()