Note
Bonjour, bienvenue dans la communauté SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts sur Facebook ! Plongez au cœur de Raspberry Pi, Arduino et ESP32 avec d’autres passionnés.
Pourquoi nous rejoindre ?
Support d’experts : Résolvez les problèmes après-vente et les défis techniques avec l’aide de notre communauté et de notre équipe.
Apprendre et partager : Échangez des astuces et tutoriels pour développer vos compétences.
Aperçus exclusifs : Accédez en avant-première aux annonces de nouveaux produits et aux avant-goûts.
Réductions spéciales : Bénéficiez de réductions exclusives sur nos dernières nouveautés.
Promotions et cadeaux festifs : Participez à des concours et promotions de fêtes.
👉 Prêt à explorer et créer avec nous ? Cliquez sur [Ici] et rejoignez-nous dès aujourd’hui !
3.1.8 Moniteur de surchauffe (MCP3008)
Note
Selon la version de votre kit, veuillez identifier si vous avez ADC0834 ou MCP3008 et suivre la section correspondante.
Introduction
Vous pouvez vouloir réaliser un dispositif de surveillance de surchauffe applicable à diverses situations. Par exemple, dans une usine, si l’on souhaite avoir une alarme et un arrêt automatique immédiat de la machine lorsqu’un circuit surchauffe. Dans ce projet, nous utiliserons une thermistance, un joystick, un buzzer, une LED et un écran LCD pour créer un dispositif intelligent de surveillance de température dont le seuil est réglable.
Composants requis
Pour ce projet, nous avons besoin des composants suivants.
Schéma de câblage
Nom T-Board |
physique |
wiringPi |
BCM |
SPICE0 |
Pin 24 |
10 |
8 |
SPIMOSI |
Pin 19 |
12 |
10 |
SPIMISO |
Pin 21 |
13 |
9 |
SPISCLK |
Pin 23 |
14 |
11 |
GPIO22 |
Pin15 |
3 |
22 |
GPIO23 |
Pin16 |
4 |
23 |
GPIO24 |
Pin18 |
5 |
24 |
SDA1 |
Pin 3 |
||
SCL1 |
Pin 5 |
Procédure expérimentale
Étape 1 : Construire le circuit.
Pour les utilisateurs du langage C
Étape 2 : Accédez au dossier du code.
cd ~/davinci-kit-for-raspberry-pi/c/3.1.8-2/
Étape 3 : Compilez le code.
gcc 3.1.8_OverheatMonitor.c -lm -lwiringPi
Étape 4 : Exécutez le fichier.
sudo ./a.out
Lorsque le code s’exécute, la température actuelle et le seuil de haute température 40 s’affichent sur l’écran I2C LCD1602. Si la température actuelle est supérieure au seuil, le buzzer et la LED se déclenchent pour vous alerter.
Le joystick sert ici à ajuster le seuil de haute température. En le déplaçant sur l’axe X ou Y, vous pouvez augmenter ou diminuer ce seuil. Appuyez à nouveau sur le joystick pour réinitialiser le seuil à sa valeur initiale.
Note
Si une erreur
wiringPi.h: No such file or directoryapparaît, consultez Installer et vérifier WiringPi.Si vous obtenez
Unable to open I2C device: No such file or directory, consultez Configuration I²C pour activer l’I2C et vérifier le câblage.Si le code et le câblage sont corrects mais que l’écran LCD reste vide, tournez le potentiomètre à l’arrière pour augmenter le contraste.
Code
#include <wiringPi.h>
#include <stdio.h>
#include <wiringPiI2C.h>
#include <wiringPiSPI.h>
#include <string.h>
#include <math.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define Joy_BtnPin 3 // GPIO22 -> WiringPi 3
#define buzzPin 4 // GPIO23 -> WiringPi 4
#define LedPin 5 // GPIO24 -> WiringPi 5
#define SPI_CHANNEL 0
#define SPI_SPEED 1000000
int LCDAddr = 0x27;
int BLEN = 1;
int fd;
int upperTem = 40;
// Global variable to store the last joystick change
int lastJoystickChange = 0;
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];
}
void write_word(int data){
int temp = data;
if (BLEN) temp |= 0x08;
else temp &= 0xF7;
wiringPiI2CWrite(fd, temp);
}
void send_command(int comm){
int buf = comm & 0xF0;
buf |= 0x04; write_word(buf); delay(2); buf &= 0xFB; write_word(buf);
buf = (comm & 0x0F) << 4;
buf |= 0x04; write_word(buf); delay(2); buf &= 0xFB; write_word(buf);
}
void send_data(int data){
int buf = data & 0xF0;
buf |= 0x05; write_word(buf); delay(2); buf &= 0xFB; write_word(buf);
buf = (data & 0x0F) << 4;
buf |= 0x05; write_word(buf); delay(2); buf &= 0xFB; write_word(buf);
}
void lcd_init(){
send_command(0x33); delay(5);
send_command(0x32); delay(5);
send_command(0x28); delay(5);
send_command(0x0C); delay(5);
send_command(0x01); wiringPiI2CWrite(fd, 0x08);
}
void lcd_clear(){
send_command(0x01);
}
void write_lcd(int x, int y, const char data[]){
int addr = 0x80 + 0x40 * y + x;
send_command(addr);
for (int i = 0; i < (int)strlen(data); i++)
send_data(data[i]);
}
int get_joystick_value(){
int x = read_ADC(1);
int y = read_ADC(2);
// Dead-band filtering to reduce small fluctuations
if (x > 900) return 1; // else if (x < 100) return -1; // else if (y > 900) return -10; // else if (y < 100) return 10; // else return 0;
}
void upper_tem_setting(){
write_lcd(0,0, "Upper Adjust:");
int change = get_joystick_value();
// Only respond to actual direction change
if (change != 0 && change != lastJoystickChange) {
upperTem += change;
lastJoystickChange = change;
}
else if (change == 0) {
// Allow next change after returning to center
lastJoystickChange = 0;
}
// Display current upperTem
char str[6];
snprintf(str, sizeof(str), "%d", upperTem);
write_lcd(0,1, str);
// Clear remaining LCD characters
write_lcd(strlen(str),1, " ");
delay(100);
}
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;
}
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);
}
}
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);
}
int main(void){
setup_all();
int lastBtnState = HIGH;
int stage = 0;
while (1) {
int curBtn = digitalRead(Joy_BtnPin);
// Switch mode when button changes from LOW to HIGH (button released)
if (curBtn == HIGH && lastBtnState == LOW) {
stage = (stage + 1) % 2;
lastJoystickChange = 0; // Clear debounce status
delay(100);
lcd_clear();
}
lastBtnState = curBtn;
if (stage == 1)
upper_tem_setting();
else
monitoring_temp();
}
return 0;
}
Explication du code
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];
}
Lit une valeur analogique sur 10 bits depuis le canal (CH0–CH7) du MCP3008 via SPI et renvoie un entier entre 0 et 1023.
int get_joystick_value() {
int x = read_ADC(1);
int y = read_ADC(2);
if (x > 900) return 1; // Droite
else if (x < 100) return -1; // Gauche
else if (y > 900) return -10; // Haut
else if (y < 100) return 10; // Bas
else return 0;
}
Lit les valeurs analogiques X et Y du joystick sur CH1 et CH2. Renvoie un entier indiquant la direction du mouvement selon les seuils définis.
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);
}
Permet à l’utilisateur d’ajuster le seuil de température maximale à l’aide du joystick. Évite les changements répétés si la direction est maintenue.
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;
}
Lit la valeur analogique sur CH0 (connecté à la thermistance). Utilise l’équation de Steinhart–Hart pour calculer la température en degrés Celsius.
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);
}
}
Lit en continu la température actuelle et l’affiche avec le seuil. Si la température dépasse le seuil, le buzzer et la LED s’activent.
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);
}
Initialise l’écran LCD, la communication SPI et les broches GPIO pour le bouton du joystick, le buzzer et la LED. Active également la résistance pull-up pour le bouton du joystick.
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;
}
Boucle principale :
Surveillance de la température.
Réglage de la limite supérieure à l’aide du joystick.
Le mode change lorsque le bouton du joystick est relâché (déclenchement sur front montant).
Pour les utilisateurs du langage Python
Étape 2 : Configurez l’interface SPI et installez la bibliothèque spidev (voir Configuration SPI pour des instructions détaillées).
Si vous avez déjà effectué ces étapes, vous pouvez les ignorer.
Étape 3 : Accédez au dossier du code.
cd ~/davinci-kit-for-raspberry-pi/python
Étape 4 : Exécutez le fichier exécutable.
sudo python3 3.1.8-2_OverheatMonitor.py
Lorsque le code s’exécute, la température actuelle et le seuil de température élevée 40 sont affichés sur l’écran I2C LCD1602. Si la température actuelle est supérieure au seuil, le buzzer et la LED se déclenchent pour vous alerter.
Le Joystick permet d’ajuster le seuil de température élevée. En le déplaçant sur l’axe X ou Y, vous pouvez augmenter ou diminuer le seuil actuel. Appuyer à nouveau sur le Joystick réinitialise le seuil à sa valeur initiale.
Note
Si vous obtenez l’erreur
FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1', vous devez vous référer à Configuration I²C pour activer l’I2C.Si vous obtenez l’erreur
ModuleNotFoundError: No module named 'smbus2', exécutez :sudo apt install python3-smbus2.Si l’erreur
OSError: [Errno 121] Remote I/O errorapparaît, cela signifie que le module est mal câblé ou défectueux.Si le code et le câblage sont corrects mais que l’écran LCD n’affiche rien, vous pouvez tourner le potentiomètre à l’arrière pour augmenter le contraste.
Avertissement
Si le message d’erreur RuntimeError: Cannot determine SOC peripheral base address apparaît, veuillez consulter Si gpiozero ne fonctionne pas..
Code
Note
Vous pouvez Modifier/Réinitialiser/Copier/Exécuter/Arrêter le code ci-dessous.
Mais avant cela, vous devez vous placer dans le chemin source du code comme davinci-kit-for-raspberry-pi/python.
Après modification, vous pouvez l’exécuter directement pour voir le résultat.
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import spidev
import time
import math
import LCD1602
# Définition des broches GPIO
JOY_BTN_PIN = 22 # Bouton du joystick
BUZZER_PIN = 23 # Buzzer
LED_PIN = 24 # LED
# Initialisation 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)
# Seuil initial de température haute
upperTem = 40
# Initialisation SPI pour MCP3008
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1000000 # 1 MHz
# Initialisation de l’écran LCD1602
LCD1602.init(0x27, 1)
def read_adc(channel):
"""
Lecture de la valeur analogique du 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():
"""
Lit les valeurs du joystick et retourne un changement à appliquer
au seuil selon la 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():
"""
Ajuste et affiche le seuil de température haute sur le 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():
"""
Lit la température actuelle depuis le capteur et la retourne en °C.
"""
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():
"""
Surveille et affiche la température et le seuil.
Active le buzzer et la LED si la température dépasse le seuil.
"""
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)
# Boucle principale
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()
Explication du code
Importation des bibliothèques
Cette section charge les bibliothèques nécessaires pour le GPIO, le SPI, l’affichage LCD, les temporisations et les calculs mathématiques.
#!/usr/bin/env python3 import RPi.GPIO as GPIO import spidev import time import math import LCD1602
Configuration des GPIO et des périphériques
Définit les numéros de broches GPIO pour le bouton du joystick, le buzzer et la LED, puis configure les modes GPIO.
JOY_BTN_PIN = 22 # Button pin BUZZER_PIN = 23 # Buzzer 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)
Initialisation SPI et LCD
Démarre l’interface SPI pour le MCP3008 et initialise l’écran LCD1602 à l’adresse I2C 0x27.
upperTem = 40 spi = spidev.SpiDev() spi.open(0, 0) spi.max_speed_hz = 1000000 LCD1602.init(0x27, 1)
Lecture de la valeur ADC
Lit la donnée analogique du MCP3008 via SPI. Le canal doit être compris entre 0 et 7.
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
Détection du mouvement du joystick
Vérifie les valeurs des axes X/Y du joystick et retourne la variation à appliquer au seuil.
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
Ajustement du seuil de température haute
Affiche « Upper Adjust » sur le LCD et ajuste le seuil à l’aide du joystick.
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)
Calcul de la température
Convertit la lecture du capteur analogique en tension, résistance, puis température (°C) en utilisant l’approximation de Steinhart–Hart.
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)
Surveillance de la température
Vérifie en continu la température et le seuil. Allume le buzzer et la LED si la température dépasse le seuil.
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)
Logique principale du programme
Alterne entre le mode surveillance et le mode réglage du seuil lorsque le bouton du joystick est pressé.
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()
Nettoyage à la sortie
Libère correctement les ressources GPIO et SPI lorsque Ctrl+C est pressé.
except KeyboardInterrupt: pass finally: LCD1602.clear() GPIO.cleanup() spi.close()