.. 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 [|link_sf_facebook|] et rejoignez-nous dès aujourd’hui ! .. _3.1.8_c_mcp3008: 3.1.8 Moniteur de surchauffe (MCP3008) ====================================== .. note:: .. image:: img/mcp3008_and_adc0834.jpg :width: 25% :align: left 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. .. image:: img/list2_Overheat_Monitor.png :align: center 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 ============ ======== ======== === .. image:: img/Schematic_three_one8.png :align: center Procédure expérimentale ----------------------- **Étape 1 :** Construire le circuit. .. image:: img/july24_3.1.8_overheat_monitor_mcp3008.png **Pour les utilisateurs du langage C** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **Étape 2 :** Accédez au dossier du code. .. code-block:: cd ~/davinci-kit-for-raspberry-pi/c/3.1.8-2/ **Étape 3 :** Compilez le code. .. code-block:: gcc 3.1.8_OverheatMonitor.c -lm -lwiringPi **Étape 4 :** Exécutez le fichier. .. code-block:: 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 directory`` apparaît, consultez :ref:`install_wiringpi`. * Si vous obtenez ``Unable to open I2C device: No such file or directory``, consultez :ref:`i2c_config` 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 ---- .. code-block:: c #include #include #include #include #include #include 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 ------------------- .. 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]; } Lit une valeur analogique sur 10 bits depuis le canal (CH0–CH7) du MCP3008 via SPI et renvoie un entier entre 0 et 1023. .. code-block:: c 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. .. 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); } 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. .. 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; } Lit la valeur analogique sur CH0 (connecté à la thermistance). Utilise l’équation de Steinhart–Hart pour calculer la température en degrés Celsius. .. 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); } } 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. .. 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); } 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. .. 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; } Boucle principale : 1. Surveillance de la température. 2. 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 :ref:`spi_configuration` 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. .. raw:: html .. code-block:: cd ~/davinci-kit-for-raspberry-pi/python **Étape 4 :** Exécutez le fichier exécutable. .. raw:: html .. code-block:: 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 à :ref:`i2c_config` 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 error`` apparaî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. .. warning:: Si le message d’erreur ``RuntimeError: Cannot determine SOC peripheral base address`` apparaît, veuillez consulter :ref:`faq_soc`. **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. .. raw:: html .. code-block:: python #!/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 ------------------- 1. **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. .. code-block:: python #!/usr/bin/env python3 import RPi.GPIO as GPIO import spidev import time import math import LCD1602 2. **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. .. code-block:: python 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) 3. **Initialisation SPI et LCD** Démarre l’interface SPI pour le MCP3008 et initialise l’écran LCD1602 à l’adresse I2C 0x27. .. code-block:: python upperTem = 40 spi = spidev.SpiDev() spi.open(0, 0) spi.max_speed_hz = 1000000 LCD1602.init(0x27, 1) 4. **Lecture de la valeur ADC** Lit la donnée analogique du MCP3008 via SPI. Le canal doit être compris entre 0 et 7. .. 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. **Détection du mouvement du joystick** Vérifie les valeurs des axes X/Y du joystick et retourne la variation à appliquer au seuil. .. 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. **Ajustement du seuil de température haute** Affiche « Upper Adjust » sur le LCD et ajuste le seuil à l’aide du joystick. .. 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. **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. .. 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. **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. .. 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. **Logique principale du programme** Alterne entre le mode surveillance et le mode réglage du seuil lorsque le bouton du joystick est pressé. .. 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. **Nettoyage à la sortie** Libère correctement les ressources GPIO et SPI lorsque Ctrl+C est pressé. .. code-block:: python except KeyboardInterrupt: pass finally: LCD1602.clear() GPIO.cleanup() spi.close()