IoT : smart house sweet home

Sirapassorn Junpong
Super AI Engineer
Published in
5 min readFeb 2, 2021

Smart house sweet home เริ่มต้นขึ้นมายังไง?

มันเป็นโปรเจคที่เริ่มจากการที่ต้องลงเรียนในวิชา internet of things ของที่มหาวิทยาลัย ทำให้มีความสนใจในด้านนี้อย่างมาก จึงทำการศึกษาหาข้อมูลเพิ่มเติม นั่นคือจุดเริ่มต้นของโปรเจค smart house sweet home ซึ่งเป็นการผสมผสานระหว่าง Artificial Intelligence และ IoT อย่างลงตัว

Pain Point ปัญหาที่ทำให้เกิด project นี้ขึ้นมาคืออะไรล่ะ?

  • เมื่อเกิดโรคระบาด covid-19 ทำให้ต้องมีการระวังตัวมากขึ้นในการจับสิ่งของต่างๆ อีกสิ่งหนึ่งที่เรามักจะมองข้ามไป แต่สัมผัสเป็นประจำในทุกวันนั่นก็คือ กลอนประตู สวิตช์เปิดปิดไฟต่างๆ
  • Project นี้จึงจะเป็นตัวช่วยสำคัญที่จะช่วยควบคุมการล็อค ไม่ล็อคของกลอนประตูโดยอัตโนมัติ และแสดงผลในรูปของ dashboard เพื่อสังเกตุและควบคุมสถานะของประตู รวมถึงประวัติการใช้งานก็จะถูกบันทึกเอาไว้ และประโยชน์อีกประการหนึ่งคือเป็นการรักษาความปลอดภัยภายในบ้านอีกด้วย

Goal ของ project คืออะไร?

เป้าหมายของเราคือใช้กล้องหรือ face recognition ในการตรวจจับหน้าคนเพื่อปลดล็อคกลอนประตู รวมถึงเปิดไฟต้อนรับเจ้าของบ้านแบบอัตโนมัติอีกด้วย จากนั้นระบบก็จะจัดเก็บข้อมูล data ไว้แล้วแสดงผลออกมาในรูปของ dashboard

Feature ที่ใช้มีอะไรบ้าง?

  • Feature 1: Facial Recognition และ Door control

ใน feature นี้เราจะใช้ camera module และ facial recognition software เพื่อตรวจจับใบหน้าของเจ้าของบ้าน หากใช่ใบหน้าของเจ้าของบ้านจริงๆ กลอนประตูก็จะปลดล็อคอัตโนมัติ

  • Feature 2: Data collection และ Monitoring

Feature นี้เราจะจัดเก็บ data แล้วแสดงผลในรูป dashboard โดยการใช้ NETPIE และ NODERED

  • Feature 3: Light control

เราจะใช้ light intensity sensor ไฟจะสว่างขึ้น เมื่อประตูบ้านเปิดในตอนกลางคืน เพื่อเพิ่มประสิทธิภาพของกล้องที่จะจับใบหน้าของเจ้าของบ้าน รวมไปถึงเพื่อความปลอดภัยอีกด้วย

Hardware lists หรืออุปกรณ์ที่ใช้มีอะไรบ้าง?

  1. NUCLEO-F401RE Board
  2. Raspberry Pi 4 Board
  3. Ultrasonic Sensor Module (HC-SR04) 5V (https://www.arduitronics.com/product/20/ultrasonic-sensor-module-hc-sr04-5v)
  4. SG90 Servo Motor 0–180 degree (https://www.myarduino.net/product/29/sg90-servo-motor-0-180-%E0%B8%AD%E0%B8%87%E0%B8%A8%E0%B8%B2?gclid=Cj0KCQiAhZT9BRDmARIsAN2E-J1lVgnmgNptIYqP1E1WX6cgvNk7LTzRfZyeASrIBbHjhYJ-1-DcKXsaAsLBEALw_wcB)
  5. Infrared Obstacle Avoidance Sensor Module (https://www.arduino4.com/product/93/infrared-obstacle-avoidance-sensor-module)
  6. Light intensity sensor (https://www.myarduino.net/product/712/%E0%B9%82%E0%B8%A1%E0%B8%94%E0%B8%B9%E0%B8%A5-%E0%B8%A7%E0%B8%B1%E0%B8%94%E0%B8%84%E0%B8%A7%E0%B8%B2%E0%B8%A1%E0%B9%80%E0%B8%82%E0%B9%89%E0%B8%A1%E0%B9%81%E0%B8%AA%E0%B8%87-gy-30-bh1750fvi-digital-light-intensity-light-module)
  7. Power supply
  8. Electric wires

Block diagram ของงานนี้เป็นอย่างไร?

Key Performance Index และ Pass/Fail Criteria ตัววัดผลมีอะไรบ้าง?

  • KPI1: โปรแกรมสามารถ detect ใบหน้าคนได้สำเร็จด้วย accuracy ที่มากกว่าหรือเท่ากับ 80%
  • KPI2: สามารถควบคุมการเปิดปิดของกลอนประตูได้สำเร็จเมื่อได้รับคำสั่งมาด้วย accuracy ที่มากกว่าหรือเท่ากับ 80%
  • KPI3: NETPIE dashboard สามารถแสดงได้อย่างประสบความสำเร็จด้วย accuracy ที่มากกว่าหรือเท่ากับ 80%

หลังจากที่กำหนด goal, hardware lists และ KPIวัดผลโปรเจคของเราเสร็จแล้ว ลำดับถัดไปก็มาเริ่มทำโปรเจคกันเลย!

งานนี้เราพยายามใช้งานระบบของ NUCLEO-F401RE, sensor ต่างๆ แล้วก็ raspberry pi มาทำงานด้วยกัน ในงานนี้ เราอยากจะใช้ NUCLEO-F401RE มาทำงานเข้ากับ sensor เป็นตัวบังคับแล้วค่อยส่งข้อมูลต่างๆ ไปให้ raspberry pi ประมวลผลและ เชื่อมต่อแสดงข้อมูลออกมาโดยใช้ NETPIE IOT platform

  1. เรามาเริ่มส่วนแรกกันเลย โดยเราจะเริ่มทำการเชื่อมต่อ บอร์ด nucleo กับ sensor ของเรา ในครั้งนี้เราจะใช้ platform ที่ชื่อว่า Mbed ในการสั่งการควมคุมบอร์ด โดยข้อดีของ Mbed ก็คือ ทางเว็ปไซต์จะมี library ของแต่ละบอร์ดให้พร้อมหมดแล้ว ทำให้การเรียกใช้ง่ายขึ้นเยอะมาก แค่ไปดูตัวอย่างจากแต่ละ library แล้วก็เรียกใช้ได้เลย

2. เราก็จะทำการเขียนโค้ดให้ sensor ทุกตัวมันใช้งานด้วยกันได้ในระบบ ประตูของเราก็คือเราต้องการ ใช้ ultrasonic sensor เพื่อดูว่าจะมีคนเดินเข้ามาในประตูรึป่าว แล้วเราค่อยถ่ายรูปแล้วส่งไปให้ raspberry pi ทำการวิเคราะห์ รูปโดยใช้ face recognition เพื่อดูว่าคนที่เดินเข้ามาเนี่ยใช่เจ้าของบ้านรึป่าว ถ้าระบบเห็นว่าคนนี้ถูกต้อง servo จะเปิดประตูให้แล้วก็ใช้ avoidance sensor ดูอีกว่าประตูปิดรึยังถ้าประตูปิดแล้ว avoidance sensor จะไปสั่งให้ประตูlock แต่ถ้ายังประตูก็จะเปิดแบบนั้นแหละเพราะว่ายังมีคนอยู่

  • Ultrasonic Sensor

เป็นเซนเซอร์ที่ช่วยในเรื่องของตรวจจับวัตถุต่างๆ ใช้ตรวจจับเมื่อกล้อง detect หน้าเจ้าของบ้านได้สำเร็จ และพอเมื่อเจ้าของบ้านเดินผ่านเซนเซอร์ตัวนี้ก็จะ detect ส่งค่าไปยัง servo motor ให้เปิดประตู

  • Servo Motor

ใช้เพื่อเป็นมอเตอร์ที่ใช้ควบคุมการหมุน การเคลื่อนที่ของประตู จะทำงานร่วมกับ ultrasonic sensor

  • Infrared Obstacle Avoidance Sensor Module

ใช้เพื่อตรวจจับวัตถุกีดขวาง สามารถนำมาใช้ตรวจจับวัตถุที่อยู่ตรงหน้าได้

  • Light intensity sensor

ใช้เพื่อวัดความเข้มแสง

ตัวอย่าง code ของ ultrasonic sensor, servo motor และ Infrared Obstacle Avoidance Sensor Module :

/* mbed Microcontroller Library* Copyright (c) 2019 ARM Limited* SPDX-License-Identifier: Apache-2.0*/#include "mbed.h"#include "platform/mbed_thread.h"#include "SRF05.h"#include "Servo.h"Servo myservo(PC_7);DigitalOut led3(D2); //status ledint led4;DigitalIn ir1(D8); //status ledDigitalIn p_light(A0);DigitalOut p_led(D3);int light_value = 0;void checkAvoid() //check avoidance{if(ir1 != 0){led3 = 0;}else{led3 = 0;for(int i=100; i>0; i--) {myservo = i/100.0;wait(0.01);}printf("Servo =%.1f\r\n", myservo.read());led4 = 0;}}int main(){DigitalOut led(LED1);// Initialise the digital pin LED1 as an outputmyservo = 0;p_led = 0;while (true) {light_value = p_light.read();if (light_value==1) { // light_value=1 is too darkp_led = 1;}else {p_led = 0;}led = 1;SRF05 srf(PB_5, PA_8); // Trigger, Echoif(srf.read() <= 10){printf("Distance =%.1f\r\n", srf.read());if(led == 1 && p_led == 1){for(int i=0; i<100; i++) {myservo = i/100.0;wait(0.01);}printf("Servo =%.1f\r\n", myservo.read());wait(2);led4 = 1;while(led4 == 1){printf("Avoid =%d\r\n", ir1.read());checkAvoid();wait(0.5);}}else{led4 = 0;}}thread_sleep_for(500);}return 0;}

ตัวอย่าง code ของ light intensity sensor :

/* mbed Microcontroller Library* Copyright (c) 2019 ARM Limited* SPDX-License-Identifier: Apache-2.0*/#include "mbed.h"Serial pc(PA_2, PA_3, pc);DigitalIn p_light(A0);DigitalOut p_led1(D3);int main(){int light_value = 0;p_led1 = 0;while (true) {light_value = p_light.read();if (light_value ==1) {p_led1=1;pc.printf(“Hello!\n”);}else {p_led1=0;}}}

3. ลำดับถัดไปคือ การส่งข้อมูลระหว่าง NUCLEO-F401RE กับ raspberry pi

เอาละทีนี้เราก็เริ่มทำงานไปได้ถึงจุดนึงแล้ว แต่ที่ยังงงๆอยู่คือแล้วเราจะส่งข้อมูลจาก บอร์ด nucleo ไปให้ raspberry pi ได้ยังไงละ?

คำตอบก็คือเราสามารถใช้ port serial ของบอร์ดเพื่อการส่งการอ่านค่าได้ยังไงละ ทีนี้เราก็ไปแก้โค้ดใน Mbed นิดหน่อยให้มันไปโชว์ค่าข้อมูลใน serial 9600 แล้วให้ raspberry pi ไปอ่านค่าจาก port นั้น ในที่นี้เราสามารถใช้เครื่องมือตัวนึงที่ชื่อว่า Node-RED ซึ่งเป็นเครื่องมือช่วยทำงานกับ raspberry pi โดยใช้ node-js ได้ดีมาก โดยเจ้า Node-RED เนี่ยมันจะทำงานกับ event-driven application ได้ดีมาก เพราะมันเหมือนกับการวาด flow chart เลยทำให้ใช้ได้ง่ายมากเลย

ตัวอย่าง code :

ใช้ Node-RED

4. ส่งข้อมูลสถานะประตูไปแสดงผลใน dashboard ด้วย NETPIE

เอาละตอนนี้เรามีข้อมูลแล้ว เราสามารถทำการกรองข้อมูลต่างๆไปได้ และประมวลผลได้แล้วแต่เราจะโชว์ข้อมูลยังไงละ คำตอบก็คือเราสามารถใช้ NETPIE ในการเชื่อมต่อดึงข้อมูลจาก Node-RED มาได้โดยตรงเลยนี่เอง โดยที่นี้เราก็สามารถไปอ่านจาก docs ของทาง netpie ได้เลย

ตัวอย่างการแสดงผล :

5. การทำ face recognition

ตัวอย่าง code training :

import cv2import numpy as npfrom PIL import Imagefrom glob import globimport oscascade = "haarcascade_frontalface_default.xml"#รูปใน path data จะเรียงแบบ User_jump_1_.jpg, User_jump_2_.jpg, User_jump_3_.jpg, ... User_jump_30_.jpgpath = "data"recognizer = cv2.face.LBPHFaceRecognizer_create()detector = cv2.CascadeClassifier(cascade)imgPaths = [glob(os.path.join(path,"*.jpg"))]samples = []ids = []for imgPath in imgPaths:PIL_img = Image.open(imgPath).convert('L') # convert it to grayscaleimgArray = np.array(PIL_img,'uint8')id = int(os.path.split(imagePath)[-1].split("_")[1])faces = detector.detectMultiScale(imgArray)for (x,y,w,h) in faces:samples.append(imgArray[y:y+h,x:x+w])ids.append(id)faces,ids = getInfo(path)recognizer.train(faces, np.array(ids))recognizer.write('trainer.yml')

ตัวอย่าง code recognizer :

import cv2import numpy as npimport osimport RPi.GPIO as GPIOimport timerelay = 26GPIO.setwarnings(False)GPIO.setmode(GPIO.BCM)GPIO.setup(relay, GPIO.OUT)GPIO.output(relay ,1)recognizer = cv2.face.LBPHFaceRecognizer_create()recognizer.read('trainer.yml')cascade = "haarcascade_frontalface_default.xml"faceCascade = cv2.CascadeClassifier(cascadePath);id = 0names = ["Jump"]cam = cv2.VideoCapture(0)minW = 0.1*cam.get(3)minH = 0.1*cam.get(4)font = cv2.FONT_HERSHEY_SIMPLEXwhile True:ret, img =cam.read()img = cv2.flip(img, -1)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)faces = faceCascade.detectMultiScale( gray, scaleFactor = 1.2, minNeighbors = 5 )for(x,y,w,h) in faces:cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)id, confidence = recognizer.predict(gray[y:y+h,x:x+w])if (confidence <= 80):id = names[id]confidence = "  {0}%".format(round(100 - confidence))GPIO.output(relay, 0)cv2.putText(img, str(id), (x+5,y-5), font, 1, (255,255,255), 2)cv2.putText(img, str(confidence), (x+5,y+h-5), font, 1, (255,255,0), 1)else:id = "Not Allowed"confidence = "  {0}%".format(round(100 - confidence))GPIO.output(relay, 1)cv2.imshow('camera',img)k = cv2.waitKey(10) & 0xffif k == 27:breakcam.release()cv2.destroyAllWindows()

จบไปแล้ว สำหรับขั้นตอนทั้งหมด หากมีผิดพลาดตรงส่วนไหนต้องขออภัยส่วนนะคะ หวังว่าบทความนี้จะช่วยให้ผู้อ่านได้รับความรู้ไม่มากก็น้อย แล้วพบกันใหม่บทความหน้าค่า~

--

--