Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Système de Surveillance Thermique Scolaire : Précis, Temps Réel et Sécurisé

Composants et Fournitures

Pycom SiPy (Sigfox + MicroPython)×1
Raspberry Pi 3 Modèle B×1
Arduino Nano R3×1
Convertisseur de Niveau Logique Bidirectionnel (SparkFun)×1
Module RFID RC522 (NFC)×1
Capteur Distance Sharp GP2Y0A41SK0F (4-30 cm, analogique)×1
Capteur Température MLX90614-DCI (I2C)×1
Écran LCD I2C 16×2 (DFRobot)×1
LED + Résistance 330 Ω (×2)×2
Buzzer×1

Logiciels et Services

À Propos du Projet

Problématique

En Asie, météo chaude + antécédents SRAS 2003 → mesures de température trimestrielles obligatoires en école primaire/secondaire. Problèmes : thermomètres personnels oubliés/cassés/perdus, interdiction de partage (hygiène), coût d'achat. Saisie manuelle fastidieuse pour les enseignants (~40 élèves/classe).

Solution : Système Automatisé

Thème : Impact Social (SqwidNet) / Objectif Développement Durable « Bonne santé et bien-être ».

Mesure automatique de température pour utilisateurs authentifiés (badge RFID), alerte si seuil dépassé.

Architecture : Raspberry Pi + Arduino

Architecture : Sigfox (SiPy)

SiPy reçoit données série de l'Arduino (userID, température partie entière, partie décimale), envoie en bytes (0-255) vers backend Sigfox → rappel ThingSpeak via callback.

Payload personnalisé : userID, temp_entière, temp_décimale. Configuration callback ThingSpeak dans backend Sigfox (Device Type → Device → CALLBACKS).

Cloud : ThingSpeak + IFTTT

Câblage Arduino Nano (Pinout = Uno)

ModulePins
RFID RC522SDA D10, SCK D13, MOSI D11, MISO D12, IRQ NC, GND, RST D9, 3.3V
LCD I2CSDA A4, SCL A5, GND, 5V
Capteur Distance5V, GND, Signal A0
BuzzerGND, Signal D6
Capteur Temp IRSDA A4, SCL A5, GND, 5V
LEDCathode GND, Anode D7

Installation Raspberry Pi

  1. Flasher Raspbian (balenaEtcher) sur carte SD
  2. Configuration initiale (HDMI), activer SSH/VNC via raspi-config
  3. IP statique optionnelle via /etc/dhcpcd.conf
  4. Installer : apache2, php, mariadb-server php-mysql
  5. Créer utilisateur root MySQL sécurisé (DROP USER 'root'@'localhost'; CREATE USER ... GRANT ALL ... FLUSH PRIVILEGES)
  6. Installer phpMyAdmin

Configuration SiPy (Expansion Board 2.0)

  1. Insérer SiPy sur board (bouton reset vers USB)
  2. Mise à jour firmware (outil Pycom, choisir région RCZ4 pour Asie)
  3. Récupérer Device ID et PAC number via code MicroPython
  4. Enregistrer sur backend Sigfox (choisir pays → entrer ID/PAC → créer compte)
  5. Test envoi : s.send(bytes([1..12]))

Configuration Cloud (ThingSpeak + IFTTT)

  1. IFTTT : Webhooks (Receive web request, event « fever ») → Email (valeurs {{Value1}}, {{Value2}})
  2. ThingSpeak : 2 canaux (Privé + Public)
  3. React sur canal privé : condition champ 3 (userID) ≠ 0 → Action MATLAB Analysis
  4. MATLAB : combine température, écrit sur canal public, si ≥38°C → webwrite vers URL IFTTT

Codes Sources

Arduino Nano (C/C++)

/* 90% codé par Aden (astero.me), 10% libs open-source (RFID, MLX90614) */
#include <SPI.h>
#include <MFRC522.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#include <Adafruit_MLX90614.h>

#define RST_PIN 9
#define SS_PIN 10
#define BUZZER_PIN 7
#define LED_PIN 6
#define DIST_SENSE_PIN A0

MFRC522 mfrc522(SS_PIN, RST_PIN);
LiquidCrystal_I2C lcd(0x27, 16, 2);
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
SoftwareSerial unoSerial(2, 3); // Vers SiPy

boolean tapped = true;
boolean confirmation = false;

String GetUID() {
  String uid = "", uid_nospace = "";
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    uid.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    uid.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  uid_nospace.concat(uid.charAt(1)); uid_nospace.concat(uid.charAt(2));
  uid_nospace.concat(uid.charAt(4)); uid_nospace.concat(uid.charAt(5));
  uid_nospace.concat(uid.charAt(7)); uid_nospace.concat(uid.charAt(8));
  uid_nospace.concat(uid.charAt(10)); uid_nospace.concat(uid.charAt(11));
  return uid_nospace;
}

void setup() {
  Serial.begin(9600);
  while (!confirmation) { Serial.println("ARDUINO"); confirmation = Serial.readString() == "RAPI"; delay(1000); }
  SPI.begin(); mfrc522.PCD_Init(); mlx.begin(); unoSerial.begin(9600);
  pinMode(BUZZER_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT);
  lcd.init(); lcd.backlight();
}

void loop() {
  boolean readySignal = Serial.readString() == "READY";
  if (readySignal) { tapped = true; Serial.println("RECEIVED"); }

  if (tapped) {
    digitalWrite(BUZZER_PIN, 0); digitalWrite(LED_PIN, 0); lcd.clear();
    lcd.setCursor(0,0); lcd.print(" Please tap");
    lcd.setCursor(0,1); lcd.print(" your card.");
    delay(500); tapped = false;
  } else {
    if (!mfrc522.PICC_IsNewCardPresent()) return;
    if (!mfrc522.PICC_ReadCardSerial()) return;
    
    String card_UID = GetUID(); card_UID.toUpperCase();
    Serial.print(card_UID); Serial.print("\n");
    
    String rawData = Serial.readString();
    int commaPos = rawData.indexOf(',');
    String userInitial = rawData.substring(0, commaPos);
    int userID = rawData.substring(commaPos + 1).toInt();
    
    lcd.clear();
    if (userID != 0 && userInitial != "0") {
      lcd.setCursor(0,0); lcd.print("Welcome, ");
      lcd.setCursor(0,1); lcd.print(userInitial);
      
      int dist_val = analogRead(DIST_SENSE_PIN);
      byte temp_H = 0, temp_L = 0;
      float meas_temp = 0.0;
      delay(2000);
      
      while ((dist_val < 170) || (dist_val > 200)) {
        dist_val = analogRead(DIST_SENSE_PIN);
        lcd.setCursor(0,0); lcd.print("Please take");
        lcd.setCursor(0,1); lcd.print("your temperature.");
      }
      
      digitalWrite(BUZZER_PIN, 1); digitalWrite(LED_PIN, 1); lcd.clear();
      meas_temp = (float)mlx.readObjectTempC();
      temp_H = floor(meas_temp);
      temp_L = (meas_temp - temp_H) * 100;
      
      String sMeasTemp = ""; sMeasTemp += userID; sMeasTemp += ","; sMeasTemp += temp_H; sMeasTemp += ","; sMeasTemp += temp_L;
      
      Serial.println("TEMP"); Serial.println(meas_temp);
      
      if ((meas_temp >= 28) && (meas_temp <= 42)) {
        unoSerial.print(sMeasTemp); // Vers SiPy
        lcd.setCursor(0,0); lcd.print("Temperature: ");
        lcd.setCursor(0,1); lcd.print(" " + String(meas_temp));
      }
    } else {
      lcd.setCursor(0,0); lcd.print("Error!");
      lcd.setCursor(0,1); lcd.print("Invalid User.");
    }
    
    rawData = Serial.readString();
    commaPos = rawData.indexOf(',');
    userInitial = rawData.substring(0, commaPos);
    if (userInitial == "0") {
      lcd.clear(); lcd.setCursor(0,0); lcd.print("Error!");
      lcd.setCursor(0,1); lcd.print("Invalid Temperature.");
    }
    Serial.println("STANDBY"); delay(1000);
    mfrc522.PICC_HaltA(); mfrc522.PCD_StopCrypto1();
  }
}

Raspberry Pi (Python)

''' Codé par Aden pour Hackster.io Sigfox Competition. astero.me '''
import mysql.connector, serial, os, time

host = "localhost"; user = "root"; password = "password"; databaseName = "smartTemp"
comPort = 'ttyUSB0'; baudRate = 9600

def queryConnection():
    cursor = conn.cursor(buffered=True)
    cursor.execute("USE `" + databaseName + "`")
    return cursor

conn = mysql.connector.connect(host=host, user=user, passwd=password)
ser = serial.Serial('/dev/' + comPort, baudRate, timeout=0)

# Confirmation port série Arduino
connected = False
for x in range(2):
    time.sleep(2); ser.write("RAPI")
    if not connected:
        if ser.readline().strip() == "ARDUINO": comPort = 'ttyUSB0'; connected = True
        else: comPort = 'ttyUSB1'; connected = True
ser = serial.Serial('/dev/' + comPort, baudRate)
print("COM PORT confirmed: " + comPort)

countFile = open("count.txt", "a++")
cursor = queryConnection()

# Création BDD + tables
try:
    cursor.execute("CREATE DATABASE " + databaseName)
    print("Database created.")
except: print("Database exists.")

cursor.execute("CREATE TABLE IF NOT EXISTS `userInfo` (id int, cardID VARCHAR(9), userID VARCHAR(4), userInitial VARCHAR(8))")
cursor.execute("CREATE TABLE IF NOT EXISTS `tempData` (id int, userID VARCHAR(4), dateMeas date, timeMeas time, tempMeasure decimal(5,2))")

count = 1
if os.stat("count.txt").st_size != 0:
    for line in countFile: count = int(line)
    print("Count restored: " + str(count))

while True:
    cursor = queryConnection()
    cardID = str(ser.readline().strip())
    cursor.execute("SELECT * FROM userInfo WHERE cardID = '" + cardID + "'")
    items = cursor.fetchone()
    
    if items:
        userID = str(items[2])
        userDetails = str(items[3] + ", " + items[2])
        currentDate = time.strftime("%Y-%m-%d", time.gmtime())
        currentTime = time.strftime("%H:%M:%S", time.gmtime())
        ser.write(userDetails.encode())
        
        tempSignal = False
        while not tempSignal:
            tempSignal = ser.readline().strip() == "TEMP"
            tempData = float(ser.readline().strip())
            print(tempData)
            if 28 <= tempData <= 42:
                cursor.execute("INSERT INTO `tempData` VALUES (" + str(count) + ", '" + userID + "', '" + currentDate + "', '" + currentTime + "', '" + str(tempData) + "')")
                conn.commit(); count += 1
                countFile = open("count.txt", 'w'); countFile.write(str(count))
            else:
                ser.write(b"0, 0")
    else:
        ser.write(b", 0"); print("Nothing found")
    
    # Handshake
    readySignal = ser.readline().strip() == "STANDBY"
    while readySignal:
        ser.write(b"READY"); print("sending")
        if ser.readline().strip() == "RECEIVED": readySignal = False; print("received")
    
    cursor.close(); conn.close()

SiPy / MicroPython

''' 100% par Reginald '''
from machine import UART
from network import Sigfox
import binascii, socket, time, pycom, sys

pycom.heartbeat(False)
sigfox = Sigfox(mode=Sigfox.SIGFOX, rcz=Sigfox.RCZ4)  # RCZ4 = Asie

uart1 = UART(1, baudrate=9600)
uart1.init(9600, bits=8, parity=None, stop=1, pins=('P3', 'P4'), timeout_chars=20)

while True:
    try:
        recv = uart1.readline()
        if recv:
            print(binascii.hexlify(sigfox.id()))
            print(binascii.hexlify(sigfox.pac()))
            
            sk1 = socket.socket(socket.AF_SIGFOX, socket.SOCK_RAW)
            sk1.setblocking(False)
            sk1.setsockopt(socket.SOL_SIGFOX, socket.SO_RX, False)
            
            dataList = recv.decode("utf-8")
            print("dataList: %s" % dataList)
            split_val = dataList.split(",")
            userID = int(split_val[0])
            temp_H = int(split_val[1])
            temp_L = int(split_val[2])
            print("userID: %d temp_H: %d temp_L: %d" % (userID, temp_H, temp_L))
            
            bData = [userID, temp_H, temp_L]
            meas_temp = temp_H + (temp_L * 0.01)
            print("measure temperature: %.2f" % meas_temp)
            
            sk1.send(bytes(bData))
            sk1.close()
            time.sleep(5)
    except KeyboardInterrupt:
        sys.exit()

ThingSpeak – Script MATLAB

%% Par Aden pour Hackster.io Sigfox Competition. astero.me
readChannelID = 870479;
webhookTrigger = 'https://maker.ifttt.com/trigger/student_fever/with/key/...';
readAPIKey = 'QGHINBPNJQKULBH2';
writeChannelID = 870482;
writeAPIKey = 'R6NJIM8NT5A42R9N';

wholeNumber = thingSpeakRead(readChannelID, 'ReadKey', readAPIKey, 'Fields', 1);
decimalNumber = thingSpeakRead(readChannelID, 'ReadKey', readAPIKey, 'Fields', 2) / 100;
userID = thingSpeakRead(readChannelID, 'ReadKey', readAPIKey, 'Fields', 3);

analyzedData = wholeNumber + decimalNumber;
thingSpeakWrite(writeChannelID, 'Fields', [1,2], 'Values', {analyzedData, userID}, 'WriteKey', writeAPIKey);

if (analyzedData >= 38)
    webwrite(webhookTrigger, 'value1', analyzedData, 'value2', userID);
end

Schémas de Câblage

Système de Surveillance Thermique Scolaire : Précis, Temps Réel et Sécurisé

Système de Surveillance Thermique Scolaire : Précis, Temps Réel et Sécurisé

Système de Surveillance Thermique Scolaire : Précis, Temps Réel et Sécurisé

Système de Surveillance Thermique Scolaire : Précis, Temps Réel et Sécurisé

Système de Surveillance Thermique Scolaire : Précis, Temps Réel et Sécurisé

Système de Surveillance Thermique Scolaire : Précis, Temps Réel et Sécurisé

Système de Surveillance Thermique Scolaire : Précis, Temps Réel et Sécurisé

Processus de fabrication

  1. Surveillance de température professionnelle sur Raspberry Pi avec DS18B20
  2. Surveillance précise de la température dans un placard serveur avec Raspberry Pi
  3. Contrôle de température brassage maison DIY : Surveiller et réguler avec Arduino
  4. Capteur CO2 K30 : Surveillance en temps réel de la qualité de l'air intérieur
  5. Stores intelligents : contrôle automatisé de la lumière avec Arduino et énergie solaire
  6. Portique de contrôle de température sans contact pour dépistage rapide et précis
  7. Arduino UNO & Shield WiFi : Affichage température temps réel sur le Web via série
  8. Health Band : Bracelet intelligent fiable d'assistance pour personnes âgées
  9. Agriculture intelligente : Surveillance complète IoT pour l'agriculture du futur