工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

学校向けスマート体温監視システム: 正確、リアルタイム、安全

部品と材料

部品数量
Pycom SiPy(Sigfox対応マイコン)1
Raspberry Pi 3 Model B1
Arduino Nano R31
ロジックレベル変換モジュール(双方向)1
NFC RFID-RC522モジュール1
Sharp GP2Y0A41SK0F 距離センサー(4-30cm)1
MLX90614-DCI 赤外線温度センサー(I2C)1
DFRobot I2C 16x2 LCDディスプレイ1
LED(汎用)1
抵抗 330Ω2
ブザー1

使用ソフトウェア・サービス

課題と解決策

課題

アジア地域では暑い気候とSARS経験から、学校で定期的な体温測定が義務付けられています。しかし、生徒が各自で体温計を持参する運用では、紛失・故障・忘れで測定できないケースが多く、衛生面から共有も不可。教職員が40名分のデータを手入力する負担も大きいです。

解決策: 自動化された3層アーキテクチャ

学校向けスマート体温監視システム: 正確、リアルタイム、安全
学校向けスマート体温監視システム: 正確、リアルタイム、安全

テーマ: Social Impact(SqwidNet)、SDGs「すべての人に健康と福祉を」

動作仕組み

1. Raspberry Pi + Arduino Nano(エッジ層)

学校向けスマート体温監視システム: 正確、リアルタイム、安全

2. Sigfox (SiPy)(通信層)

学校向けスマート体温監視システム: 正確、リアルタイム、安全

3. クラウド(ThingSpeak + IFTTT)

学校向けスマート体温監視システム: 正確、リアルタイム、安全
学校向けスマート体温監視システム: 正確、リアルタイム、安全

詳細セットアップガイド

1. Arduino Nano 配線

学校向けスマート体温監視システム: 正確、リアルタイム、安全
学校向けスマート体温監視システム: 正確、リアルタイム、安全
モジュール接続ピン
RFID-RC522SDA:D10, SCK:D13, MOSI:D11, MISO:D12, RST:D9, 3.3V, GND
I2C LCDSDA:A4, SCL:A5, 5V, GND
距離センサーVCC:5V, GND, OUT:A0
ブザーGND, OUT:D6
温度センサーSDA:A4, SCL:A5, 5V, GND
LEDカソード:GND, アノード:D7

2. Raspberry Pi セットアップ

  1. Raspbian OSをbalenaEtcherでSDカードに書き込み
  2. HDMI接続で初期設定、raspi-configでSSH/VNC有効化
  3. 固定IP設定(任意): /etc/dhcpcd.conf に interface eth0 static ip_address=192.168.0.11/24 追加

3. MySQLデータベース構築

sudo apt update && sudo apt upgrade
sudo apt install apache2
sudo apt install php php-mbstring
sudo apt install mariadb-server php-mysql

# MySQL rootユーザー作成(重要: 手順厳守)
sudo mysql --user=root
DROP USER 'root'@'localhost';
CREATE USER 'root'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
exit;

# 動作確認
mysql --user=root --password=yourpassword

# phpMyAdminインストール
sudo apt install phpmyadmin
sudo phpenmod mysqli
sudo /etc/init.d/apache2 restart

以降 https:///phpmyadmin でDB管理可能。

4. SiPy Expansion Board 2.0 セットアップ

  1. SiPyモジュールをリセットボタンがUSBコネクタ側になるよう装着
  2. ファームウェアアップデート(Pycom公式ツール使用、RCZ地域選択に注意)
  3. Visual Studio Code + Pymakr拡張で開発環境構築
  4. ファイル名は main.py でアップロード
  5. 無限ループ書き込み時はFileZillaでFTP接続し main.py 削除で復旧

5. Sigfoxバックエンド登録

from network import Sigfox
import binascii
sigfox = Sigfox(mode=Sigfox.SIGFOX, rcz=Sigfox.RCZ4)  // アジアはRCZ4
print(binascii.hexlify(sigfox.id()))   // Device ID
print(binascii.hexlify(sigfox.pac()))  // PAC番号

取得したID/PACでSigfoxバックエンドにデバイス登録。コールバックでThingSpeak連携設定。

6. クラウド側設定(ThingSpeak + IFTTT)

ソースコード

[C] Arduino Nano

/*** 90% Aden自作 (https://www.astero.me) / 10% オープンソースライブラリ ***/
#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); // SiPy通信用

boolean tapped = true; boolean confirmation = false;

String GetUID() { /* UIDを16進文字列に変換 */ }

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);
      delay(2000);
      int dist = analogRead(DIST_SENSE_PIN);
      byte temp_H = 0, temp_L = 0; float meas_temp = 0.0;
      while((dist < 170) || (dist > 200)) { // 測定距離待ち
        dist = 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 = String(userID) + "," + String(temp_H) + "," + String(temp_L);
      Serial.println("TEMP"); Serial.println(meas_temp);
      if(meas_temp >= 28 && meas_temp <= 42) {
        unoSerial.print(sMeasTemp); // 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.");
    }
    // Raspberry Piからの温度妥当性判定結果を受信
    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();
  }
}

[Python] Raspberry Pi

''' Coded by Aden for Hackster.io Sigfox Competition. https://www.astero.me '''
import mysql.connector, serial, os, time

host="localhost"; user="root"; password="password"; databaseName="smartTemp"
conn = mysql.connector.connect(host=host, user=user, passwd=password)
comPort = 'ttyUSB0'; baudRate = 9600
ser = serial.Serial('/dev/' + comPort, baudRate, timeout=0)

# COMポート自動検出・確認
for x in range(2):
    time.sleep(2); ser.write("RAPI")
    if ser.readline().strip() == "ARDUINO": break
    comPort = 'ttyUSB1'

ser = serial.Serial('/dev/' + comPort, baudRate)  # timeoutなしで再オープン

countFile = open("count.txt", "a++")
cursor = conn.cursor(buffered=True)
cursor.execute("USE `" + databaseName + "`")

# DB/テーブル自動作成
cursor.execute("CREATE DATABASE IF NOT EXISTS " + databaseName)
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 else int(open("count.txt").read())

while True:
    cursor = conn.cursor(buffered=True)
    cursor.execute("USE `" + databaseName + "`")
    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())
        countFile.close(); countFile = open("count.txt", 'w')

        tempSignal = False
        while not tempSignal:
            tempSignal = ser.readline().strip() == "TEMP"
            tempData = float(ser.readline().strip())
            if 28 <= tempData <= 42:
                cursor.execute("INSERT INTO `tempData` VALUES (" + str(count) + ",'" + userID + "','" + currentDate + "','" + currentTime + "','" + str(tempData) + "')")
                conn.commit(); count += 1; countFile.write(str(count))
            else:
                ser.write(b"0, 0")  # 無効温度通知
    else:
        ser.write(b", 0")  # 無効ユーザー通知

    # ハンドシェイクで次のサイクル待ち
    readySignal = ser.readline().strip() == "STANDBY"
    while readySignal:
        ser.write(b"READY")
        if ser.readline().strip() == "RECEIVED": readySignal = False

    cursor.close()

[MicroPython] SiPy

''' 100% coded by 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)  # アジア
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")
            split_val = dataList.split(",")
            userID = int(split_val[0])
            temp_H = int(split_val[1])
            temp_L = int(split_val[2])
            bData = [userID, temp_H, temp_L]
            sk1.send(bytes(bData))
            sk1.close()
            time.sleep(5)
    except KeyboardInterrupt:
        sys.exit()

[ThingSpeak] MATLABスクリプト

%% Made by Aden for Hackster.io Sigfox Competition. https://www.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

回路図・接続図

学校向けスマート体温監視システム: 正確、リアルタイム、安全
学校向けスマート体温監視システム: 正確、リアルタイム、安全
学校向けスマート体温監視システム: 正確、リアルタイム、安全
学校向けスマート体温監視システム: 正確、リアルタイム、安全
学校向けスマート体温監視システム: 正確、リアルタイム、安全
学校向けスマート体温監視システム: 正確、リアルタイム、安全
学校向けスマート体温監視システム: 正確、リアルタイム、安全

貢献者

製造プロセス

  1. Raspberry PiとDS18B20によるプロフェッショナルな温度監視
  2. Raspberry Piでサーバークローゼットの温度を正確に監視
  3. DIY自家醸造温度制御:Arduinoで監視・調節
  4. K30 CO2センサで室内空気質をリアルタイム監視する
  5. スマートブラインド:Arduinoとソーラー電源で実現する自動光制御
  6. 非接触温度スクリーニングゲート:Arduino MKR1000で迅速・高精度な検温
  7. Arduino UNO + WiFiシールドで温度をWebリアルタイム表示 — シリアル出力だけでグラフ化
  8. Arduino用8ビットI/Oポートライブラリ:デジタル制御を拡張
  9. スマート手話グローブ:ジェスチャーをテキスト/音声に変換
  10. ヘルスバンド:高齢者を見守る信頼のスマートウェアラブルアシスタント
  11. スマート農業:未来の農業のためのIoT対応包括的監視