산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

부품 및 소모품

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한Pycom SiPy×1
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한Raspberry Pi 3 Model B×1
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한Arduino Nano R3×1
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한SparkFun 양방향 로직 레벨 컨버터×1
NFC RFID-RC522×1
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한Sharp GP2Y0A41SK0F (4cm-30cm) 아날로그 거리 센서×1
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한MLX90614-DCI I2C 온도 센서×1
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한DFRobot I2C 16x2 아두이노 LCD 디스플레이 모듈×1
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한LED×1
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한330옴 저항×2
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한부저×1

앱 및 온라인 서비스

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한Arduino IDE
Visual Studio Code (Pymakr)
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한ThingSpeak API
IFTTT
Putty
IDLE IDE

프로젝트 소개

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

문제 정의

아시아에서는 더운 날씨와 2003년 사스(SARS) 사태로 인해 초중고생이 매 분기마다 체온 측정을 실시해 학생 건강을 확인합니다. 체온 측정 기간에는 학생 각자 디지털 체온계를 지참해야 합니다. 하지만 체온계를 분실/파손하거나 깜빡해 참여 못 하는 학생이 있습니다. 개인 위생상 체온계 공유는 금지되며, 새 체온계 살 돈이 없는 학생도 있습니다. 이로 인해 체온 측정 실시율에 영향을 줍니다. 측정 후 교직원이 모든 학생 체온 데이터와 인적 사항을 수동으로 데이터베이스에 입력해야 하는데, 담임교사 한 명이 약 40명 분을 입력하느라 매우 번거롭고 시간 많이 걸립니다.

해결책은?

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

프로젝트 테마는 SqwidNet의 Social Impact, 지속가능개발목표(SDG)의 '좋은 건강과 웰빙' 영역입니다. 우리 시스템은 유효 사용자의 체온을 자동 측정해 모니터링하고, 임계값 초과 시 알림을 보냅니다.

작동 원리: 라즈베리파이 & 아두이노

라즈베리파이에 파이썬 프로그램과 MySQL 데이터베이스가 있습니다.

파이썬 프로그램 실행 시 데이터베이스 존재 여부 확인 후 자동 생성, 테이블도 필요 시 자동 생성돼 교직원 수작업을 줄여줍니다.

데이터베이스 쿼리 연결을 맺고 아두이노가 시리얼 통신으로 정보를 보내길 대기합니다.

아두이노에 RFID 카드 태그하면 카드 정보를 아두이노에 저장한 뒤 시리얼로 라즈베리파이에 전송. 라즈베리파이가 DB에서 유효 사용자인지 확인 후 유효하면 아두이노에 확인 신호 보내고 아두이노 LCD에 "Welcome, 이름" 표시. 유효하지 않으면 "Error! Invalid User!" 표시.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

유효 사용자 태그 후 아두이노가 체온 측정 안내. 거리 센서로 사용자 준비 감지 시 체온 측정해 LCD에 표시. 유효 온도 범위(28~42℃)면 라즈베리파이(MySQL)와 시그폭스(ThingSpeak)에 동시 저장. MySQL에는 사용자 ID, 날짜, 타임스탬프, 체온 저장.

라즈베리파이는 아두이노에서 온도 데이터 수신 시 제대로 전달됐는지 지속 확인 후 진행합니다. 아두이노와 파이썬 코드 실행 타이밍이 달라 한 번만 체크하면 데이터가 아직 안 왔을 수 있기 때문입니다.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

참고: 라즈베리파이 파이썬 코드와 아두이노 코드 모두 핸드셰이킹(Handshaking) 동기화 방식을 사용합니다. 라즈베리파이가 다음 데이터 받을 준비 안 되면 아두이노가 카드 태그를 허용 안 하고, 그 반대도 마찬가지입니다.

간단한 구현: 상대방이 "RECEIVED" 신호 보낼 때까지 "READY" 신호 계속 전송해 서로 준비됐음을 확인.

// 아두이노 측
boolean readySignal = Serial.readString() == "READY";
if (readySignal) {
  tapped = true;
  Serial.println("RECEIVED");
}

// 파이썬 측
while (readySignal == True) {
  ser.write(b'' + "READY");
  receivedSignal = ser.readline().strip() == "RECEIVED";
  if (receivedSignal == True) { readySignal = False; }
}

쿼리 작업 끝나면 매번 연결 닫아 메모리 누수 방지 및 좋은 습관 유지.

작동 원리: 시그폭스 (SiPy)

아두이노에서 온도 데이터 수신 후 SiPy가 사용자 ID, 온도 정수부, 소수부로 분리. 모든 데이터를 바이트로 시그폭스 백엔드에 전송(유비닷츠와 ThingSpeak 모두에 전송 가능). 전송 데이터 예시:

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

시그폭스 백엔드에서 이 데이터를 디코딩해 ThingSpeak로 전송. 백엔드 설정 방법:

시그폭스 백엔드 > Device Type > Device Name > CALLBACKS에서 커스텀 페이로드를 정확히 일치시켜야 함(SiPy 코드 변경하지 않는 한). 커스텀 페이로드 첫 번째 값이 사용자 ID가 되므로 순서 중요. Body에 Write API Key를 위에 두고, 필드에 커스텀 데이터 매핑.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

작동 원리: 클라우드

데이터가 ThingSpeak에 도달하면 첫 번째 프라이빗 채널에서 MATLAB Analysis 스크립트가 데이터를 분석해 정수부와 소수부를 합쳐 하나의 온도 값으로 만듭니다.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

테이블 코드는 오픈소스 프로젝트에서 가져와 수정했습니다. 새 데이터 들어올 때마다 자동 업데이트돼 분석에 유용합니다.

동시에 발열 온도(38℃ 이상)인지 체크해 넘으면 이메일로 교직원/교사에게 알림.

요약: 첫 채널(정수/소수 분리)은 백엔드용, 두 번째 채널(결합된 온도+사용자 ID)은 관리자용 보기 채널로 엑셀 스타일 테이블 제공.

1. 아두이노 나노 연결 설정

아두이노 나노 모듈 연결도 (나노와 우노 핀아웃 동일):

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
RFID - RC522
SDA D10
SCK D13
MOSI D11
MISO D12
IRQ 미연결
GND GND
RST D9
3.3V 3.3V
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
LCD
SDA A4
SCL A5
GND GND
5V 5V
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
거리 센서
5V 5V
GND GND
Input A0
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
부저
GND GND
Output D6
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
IR 온도 센서
SDA A4
SCL A5
GND GND
5V 5V
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
LED
평평한 면(캐소드) GND
평평하지 않은 면(애노드) D7

좋습니다! 아두이노 연결 완료.

2. 라즈베리파이 설정

라즈베리파이 3에 주로 두 가지 설치 필요:

1. 라즈비안 OS

설치는 직관적: 이미지 파일을 SD카드에 플래싱(쓰기) 후 라즈베리파이 3에 꽂기. 단계별 튜토리얼 원하면 balenaEtcher 소프트웨어로 라즈비안 이미지(데스크톱 및 추천 소프트웨어 포함 버전 권장) 플래싱.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

HDMI로 모니터 연결해 초기 설정. Preferences → Raspberry Pi Configuration에서 SSH, VNC 등 인터페이스 활성화(이더넷/와이파이로 원격 접속 가능).

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

(선택) 터미널에서 dhcpcd.conf 편집(sudo nano /etc/dhcpcd.conf)해 고정 IP 설정:

interface eth0
static ip_address=192.168.0.11/24

이더넷 케이블로 항상 같은 주소(192.168.0.11)로 접속 가능. 와이파이 연결 시 wlan0 IP로도 어디서든 접속 가능(같은 와이파이망). 우상단 와이파이 아이콘 마우스 오버로 wlan0 IP 확인.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

3. MySQL 데이터베이스 설정

약간 까다로울 수 있으니 주의 깊게 따라하세요. 특히 MySQL root 사용자 설정 부분은 실수 바로잡기 어렵습니다.

  1. 시스템 업데이트: sudo apt update && sudo apt upgrade
  2. Apache2 설치: sudo apt install apache2 (웹 서버용)
  3. PHP 설치: sudo apt install php php-mbstring
  4. 브라우저에서 라즈베리파이 IP 또는 localhost 접속해 Apache 인덱스 페이지 확인
  5. 데이터베이스 설치: sudo apt install mariadb-server php-mysql
  6. 중요: 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;
    
  7. root 로그인 테스트: mysql --user=root --password=yourmysqlpassword
  8. phpMyAdmin 설치: sudo apt install phpmyadmin 후 sudo phpenmod mysqli && sudo /etc/init.d/apache2 restart

축하! https://your_raspberrypi_ip/phpmyadmin으로 데이터베이스 접속 가능.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

4. SiPy 익스팬션 보드 2.0 설정 및 소프트웨어 가이드

SiPy 모듈을 익스팬션 보드에 장착(리셋 버튼이 USB 커넥터 쪽 향하게, 핀 안 보일 때까지 단단히 꽂기).

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

출처: Pycom 문서

SiPy 펌웨어 업데이트 필요(프로그램 업로드/실행 및 시그폭스 Device ID, PAC 번호 얻기 위함). OS별 펌웨어 업데이터 다운로드: Windows, macOS(10.11+), Linux(dialog, python-serial 패키지 필요).

업데이터 최초 실행 시 다음 화면은 한 번만 나옴: 올바른 시그폭스 리전(Region), 보드 선택 필수.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

지시 사항 정확히 따르세요. 잘못하면 Device ID와 PAC가 모두 'F'로 나옵니다(b 'FFFFFFFF', b 'FFFFFFFFFFFFFFFF').

펌웨어 업데이트 후 Visual Studio Code 설치, Pymakr 확장과 Node.js 설치 후 프로그램 업로드/실행 가능.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

새 폴더 생성(Ctrl+K+O) 후 파일 저장 위치로 지정. 새 파일(Ctrl+N) 생성 후 파이썬 파일로 저장(폴더 안에). 파일명은 자유지만 SiPy 업로드 시 main이어야 함.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

주의: while 1 무한 루프 업로드 시 SiPy 플래시에서 main.py 삭제 전까진 접근 불가. 실행 버튼(하단)으로 업로드 없이 실행 가능, 옆 업로드 버튼으로 현재 폴더 전체 업로드.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

실수로 무한 루프 올렸어도 FileZilla로 FTP 접속해 삭제 가능. FileZilla 무료 버전 다운로드/설치.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

사이트 매니저(Ctrl+S)에서 새 사이트 추가. 암호화: Only use plain FTP (insecure), 전송 설정: Passive, 최대 동시 연결 1.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

호스트(주소), 사용자, 비밀번호는 VS Code에서 All Commands → Global Settings로 확인. 프로젝트 설정에서 변경 가능.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

SiPy 모듈 SSID는 All Commands → Get WiFi AP SSID로 확인. 각 모듈마다 고유, 비밀번호는 동일하고 변경 불가: www.pycom.io.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

참고: 데스크톱 사용자는 와이파이 어댑터 필요.

FileZilla로 SiPy 플래시 접속: SiPy SSID에 연결 후 사이트 매니저에서 사이트 연결, 비밀번호 입력. flash 폴더 열기, main.py만 삭제. SiPy 재시작 후 프로그램 다시 실행/업로드 가능.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

참고: 실수 방지를 위해 flash 폴더를 OS에 복사해두세요.

5. 시그폭스 백엔드 등록

VS Code에서 Pycom 익스팬션 보드 연결 시 자동 감지. 터미널(Ctrl+~)나 파일에 아래 코드 붙여넣고 실행해 Device ID, PAC 획득.

from network import Sigfox
import binascii
sigfox = Sigfox(mode=Sigfox.SIGFOX, rcz=Sigfox.RCZ*) // *에 리전 번호
print(binascii.hexlify(sigfox.id()))
print(binascii.hexlify(sigfox.pac()))

터미널/파일 실행 결과로 ID, PAC 확인.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

시그폭스 백엔드 첫 페이지: 시그폭스 회사 기반 국가 선택(디바이스 사용 국가, 존마다 설정 다름).

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

다음 페이지에서 획득한 Device ID, PAC 입력 후 나머지 정보 기입.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

시그폭스 계정 생성/로그인 후 디바이스 등록. 새 계정이면 이메일로 비밀번호 설정 링크 발송.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

백엔드 계정 설정 완료 후 안테나 연결하고 테스트 데이터 전송:

from network import Sigfox
import socket
sigfox = Sigfox(mode=Sigfox.SIGFOX, rcz=Sigfox.RCZ*)
s = socket.socket(socket.AF_SIGFOX, socket.SOCK_RAW)
s.setblocking(True)
s.setsockopt(socket.SOL_SIGFOX, socket.SO_RX, False)
s.send(bytes([1,2,3,4,5,6,7,8,9,10,11,12]))

6. 클라우드 설정

IFTTT 이메일 알림 설정: IFTTT 웹사이트 가입/로그인 후 프로필(우상단 Explore 왼쪽) → Create.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

This 클릭 → Webhooks 검색/선택.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

Receive a web request 선택 → 이벤트 이름 입력(예: fever) → Create trigger.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

That 클릭 → email 검색/선택 → Send me an email 선택.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

메시지 정보 입력. 이벤트 트리거 데이터는 Ingredients로 전달. 예: {{EventName}}로 이벤트 이름 포함. Body에 최소 {{Value1}}, {{Value2}} 포함 필수. Create action으로 앱릿 완성. Value1,2,3은 MATLAB Analysis에서 파생되며 필요에 따라 수정 가능.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

ThingSpeak는 쉽게 설정/학습 가능한 오픈소스 IoT 플랫폼.

채널 2개 생성: (SIGFOX) TEMPERATURE PRIVATE VIEWING, (SIGFOX) TEMPERATURE PUBLIC VIEWING.

프라이빗 채널: 시그폭스 백엔드에서 바이트로 데이터 수신(유비닷츠가 문자열 디코딩 잘 안돼 바이트 사용). 정수부/소수부 분리 전송. 이 채널은 지저분한 값 보관용.

퍼블릭 채널: MATLAB Analysis로 두 값을 합쳐 하나의 온도 값으로 변환해 전송. 사용자 ID도 전송. MATLAB 스크립트는 ThingSpeak REACT로 데이터 삽입 시 트리거.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

REACT 설정: Apps → React → New React. 조건 유형: String, 테스트 빈도: On Data Insertion, 조건: 프라이빗 채널 Field 3(사용자 ID) ≠ 0, 액션: MATLAB Analysis(온도 계산 코드), 옵션: Run action only the first time condition is met.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한
학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

테이블 플러그인은 프라이빗 뷰에서만 보임(관리자용이므로 문제 없음).

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

Webhooks 정보: 프로필 로고 → My Services → Webhooks → Documentation(우상단) → 키와 요청 포맷 확인. 이벤트 이름은 fever.

https://maker.ifttt.com/trigger/{event}/with/key/(example)
https://maker.ifttt.com/trigger/fever/with/key/(example)

브라우저에 URL 붙여넣거나 앱릿 생성 시 Test 버튼으로 테스트 가능.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

모든 설정 완료 후 ThingSpeak React 설정 마치면 아래 같은 이메일 수신.

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

기여자

코드

[C] 아두이노 나노
/* 90% Aden 작성(https://www.astero.me), 10% 오픈소스 라이브러리(RFID, 온도 모듈 등) */
/* Initial Author: ryand1011 (https://github.com/ryand1011) */
/* MFRC522 RFID 라이브러리 예제 기반 */
/* MLX90614 온도 센서 라이브러리 예제 기반 (Adafruit) */
#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_sensePin A0

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

boolean tapped = true;
boolean confirmation = false;

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

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 {
    String card_UID = "";
    if (!mfrc522.PICC_IsNewCardPresent()) return;
    if (!mfrc522.PICC_ReadCardSerial()) return;
    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);
      String sMeasTemp = "";
      int dist_senseValue = analogRead(dist_sensePin);
      byte temp_Hbyte = 0;
      byte temp_Lbyte = 0;
      float meas_temp = 0.0;
      delay(2000);
      while ((dist_senseValue < 170) || (dist_senseValue > 200)) {
        dist_senseValue = analogRead(dist_sensePin);
        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_Hbyte = floor(meas_temp);
      temp_Lbyte = (meas_temp - temp_Hbyte) * 100;
      sMeasTemp += userID;
      sMeasTemp += ",";
      sMeasTemp += temp_Hbyte;
      sMeasTemp += ",";
      sMeasTemp += temp_Lbyte;
      Serial.println("TEMP");
      Serial.println(meas_temp);
      if ((meas_temp >= 28) && (meas_temp <= 42)) {
        unoSerial.print(sMeasTemp);
        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();
  }
}
[PYTHON] 라즈베리파이
''' Aden 작성; Hackster.io 시그폭스 대회용. https://www.astero.me '''
import mysql.connector
import serial
import os
import time

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

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)

print("Confirming USB Serial Port now, please wait")
connected = False
for x in range(2):
    time.sleep(2)
    ser.write("RAPI")
    if connected == False:
        serialConfirmation = ser.readline().strip() == "ARDUINO"
        print(serialConfirmation)
        if serialConfirmation == False:
            comPort = 'ttyUSB1'
            connected = True
        else:
            comPort = 'ttyUSB0'
            connected = True
    print(comPort)
ser = serial.Serial('/dev/' + comPort, baudRate)
print("COM PORT confirmed, using " + comPort)

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

if os.stat("count.txt").st_size == 0:
    print("Count has not been set, setting to 1 now.")
    count = 1
else:
    for countNumber in countFile:
        count = int(countNumber)
    print("Count has been restored from previous session: " + str(count))

try:
    print("Creating " + databaseName + " database now..")
    cursor.execute("CREATE DATABASE " + databaseName)
    print("Database has been sucessfully created.")
except mysql.connector.errors.DatabaseError:
    print(databaseName + " database is already created.")
    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))")

while True:
    cursor = queryConnection()
    cardID = str(ser.readline().strip())
    cursor.execute("SELECT * FROM userInfo WHERE cardID = '" + cardID + "'")
    items = cursor.fetchone()
    if items != None:
        print(cardID)
        userID = str(items[2])
        userDetails = str(items[3] + ", " + items[2])
        currentDate = str(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()))[0:10]
        currentTime = str(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()))[11:]
        print(items)
        ser.write(b'' + userDetails)
        countFile.close()
        countFile = open("count.txt", 'w')
        tempSignal = False
        while tempSignal == False:
            print("Getting Temperature")
            tempSignal = ser.readline().strip() == "TEMP"
            tempData = float(ser.readline().strip())
            print(tempData)
            if tempData >= 28 and tempData <= 42:
                cursor.execute("INSERT INTO `tempData`(`id`, `userID`, `dateMeas`, `timeMeas`, `tempMeasure`) VALUES (" + str(count) + ",'" + userID + "','" + currentDate + "','" + currentTime + "','" + str(tempData) + "')")
                conn.commit()
                count = count + 1
                countFile.write(str(count))
            else:
                ser.write(b'' + "0, 0")
    else:
        ser.write(b'' + ", 0")
        print("Nothing found")
    readySignal = ser.readline().strip() == "STANDBY"
    while readySignal == True:
        ser.write(b'' + "READY")
        print("sending")
        receivedSignal = ser.readline().strip() == "RECEIVED"
        if receivedSignal == True:
            readySignal = False
            print("received")
    cursor.close()
    conn.close()
[MicroPython] 시그폭스 (Pycom)
''' 100% Reginald 작성 '''
from machine import UART
from network import Sigfox
import binascii
import socket
import time
import pycom
import 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 != None:
            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]
            print(bData)
            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] MATLAB 스크립트
%% Aden 작성; Hackster.io 시그폭스 대회용. https://www.astero.me
readChannelID = 870479;
webhookTrigger = 'https://maker.ifttt.com/trigger/student_fever/with/key/h10MdSGwjSPtZQ43wH-AgoiKI0pwaljBNnGUEu4Yecn';
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);
display(wholeNumber, 'BEFORE')
analyzedData = wholeNumber + decimalNumber;
display(analyzedData, 'AFTER')
display(userID, 'USERID')
thingSpeakWrite(writeChannelID, 'Fields', [1,2], 'Values', {analyzedData, userID}, 'WriteKey', writeAPIKey)
if analyzedData >= 38
    webwrite(webhookTrigger, 'value1', analyzedData, 'value2', userID);
end

회로도

전체 연결 구성

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

아두이노 거리 센서 연결

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

온도 센서 연결

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

LED 연결

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

RFID 연결

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

LCD 연결

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

부저 연결

학교용 스마트 체온 모니터링 시스템: 정확하고 실시간이며 안전한

제조공정

  1. 라즈베리 파이와 DS18B20을 이용한 전문적인 온도 모니터링
  2. 라즈베리 파이로 서버실 정확한 온도 모니터링하기
  3. DIY 홈브루 온도 제어: 아두이노로 모니터링 및 조절하기
  4. K30 CO2 센서: 실시간 실내 공기질 모니터링
  5. 스마트 블라인드: 아두이노와 태양광으로 자동 조명 제어
  6. 비접촉 체온 측정 게이트: 아두이노 MKR1000으로 구현하는 자동 발열 검사 시스템
  7. 아두이노 우노 & WiFi 실드로 웹에서 실시간 온도 모니터링 - 시리얼 통신 활용
  8. 아두이노용 효율적인 8비트 IO 포트 라이브러리 – 디지털 제어 확장
  9. 헬스 밴드: 노인을 위한 신뢰할 수 있는 스마트 웨어러블 어시스턴트
  10. 스마트 농업: 미래 농업을 위한 IoT 기반 종합 모니터링