ผู้เขียนบทความ : 090 นายสุรเชษฐ์ ลิ้มศิริรัศมี COE#15
คณะวิศวกรรมศาสตร์ : สาขาวิศวกรรมคอมพิวเตอร์
วิชา : 04-513-201 การโปรเเกรมคอมพิวเตอร์ชั้นสูง 1/2566
1.ความเป็นมา
ปัจจุบันนี้ประเทศไทยมีการพัฒนาความเจริญก้าวหน้าในการเป็นธุระกิจรับซื้อของเก่ามากขึ้นทำให้เกิดการใช้เเรงงานคนในการคัดเเยกโลหะ การที่มีเครื่องแยกโหละทำให้เกิดความสะดวกสบายมากขึ้นเพื่อลดการเกิดข้อผิดพลาดในกระบวนรีไซเคิล
จากการศึกษาและสำรวจพบปัญหาการเกิดโหละผสมโดยวิธีการส่วนใหญ่จะใช้ผู้คนในการคัดแยก เพื่อแก้ปัญหาดังกล่าวผู้ประดิษฐ์จึงได้จัดทำ เครื่องแยกโหละอัตโนมัติขึ้น
2.วัตถุประสงค์
1. เพื่อศึกษาเเละสร้างระบบเครื่องเเยกโหละ
2.เพื่อนำเซ็นเซอร์มาประยุกต์ใช้ในทางอุตสาหกรรม
3.เพื่อพัตนาการคัดเเยกโหละ
3.ขอบเขต
1.สามารถแยกโลหะ
2.สามารถแยกขยะได้
3.สามารถเเจ้งเตือนทางไลน์ได้
4.ประโยชน์ที่คาดว่าจะได้รับ
1.ลดการใช้เเรงงานคน
2.ลดการเกิดข้อผิดพลาดในกระบวนการคัดเเยก
3.ช่วยในกระบวนการรีไซเคิล
5.ความรู้ที่เกี่ยวข้อง
1.Proximity sensor ใช้ในการตรวจจับโหละ เป็นอุปกรณ์อิเล็กทรอนิกส์ที่สามารถตรวจจับวัตถุได้โดยไม่ต้องสัมผัสกับวัตถุโดยตรงทำให้ไม่เกิดรอยหรือการชำรุดเสียหายของชิ้นงาน ซึ่งจะอาศัยหลักการทำงานจากสนามไฟฟ้าและสนามแม่เหล็กบริเวณด้านหน้าของอุปกรณ์ เมื่อเซ็นเซอร์อยู่ใกล้กับวัตถุเป้าหมายมันจะส่งสัญญาณควบคุมออกมา
2.Servo motor ใช้ในการคัดเเยก สามารถควบคุมให้หมุดได้ตามองศาที่ต้องการ
3.Esp32 เป็นชิปไมโครคอนโทรลเลอร์ที่มาพร้อม WiFi มาตรฐาน 802.11 b/g/n และบลูทูธเวอร์ชั่น 4.2 ใช้ในการรับข้อมูลเเละประมวลผลตาม
4. Reflective Photoelectric Sensor อุปกรณ์ส่งสัญญาณเเสงจะถูกติดตั้งอยู่ฝั่งเดียวกับอุปกรณ์รับสัญญาณ โดยฝั่งตรงข้ามจะเป็นแผ่นสะท้อน(Reflector)ตัวเซ็นเซอร์จะทำการตรวจจับลำเเสงที่ส่งกลับมาจากเเผ่นสะท้อนหากมีสิ่งใดมาขวางระหว่างกลางก็จะมีการส่งสัญญาณให้อุปกรณ์ที่ทำงานร่วมกับรับรู้เหมาะสำหรับการติดตั้งในพื้นที่จำกัด สามารถตรวจจับวัตถุได้ในระยะไกล
5. โมดูลเซ็นเซอร์ตรวจจับวัตถุ ใช้ในการตรวจจับวัตถุ
6.ภาพรวมการทำงานของอุปกรณ์
6.1 โครงงานนี้ได้ออกแบบระบบคัดแยกโลหะ ที่ติดตั้งตัว Proximity sensor เพื่อสามารถตรวจจับโลหะและส่งค่าไปยังบอร์ด esp32 เพื่อแสดงค่าโลหะ ติดตั้ง Reflective Photoelectric Sensor เพื่อใช้ตรวจจับวัตถุโดยใช้หลักการสะท้อนของแสงเมื่อไปชนกับวัตถุและส่งค่าไปยังบอร์ด esp32 เพื่อตรวจจับวัตถุ โดยบอร์ด esp32 จะสั่งให้ Servo Motor ทำงาน และแสดงค่าการทำงานผ่านจอ LCD เมื่อวัตถุเติมแล้วโมดูลเซ็นเซอร์ตรวจจับวัตถุจะทำการส่งค่าไปยังบอร์ด esp32 แล้วส่งค่าไปทาง Line Notify เพื่อแจ้งเตือน
7.ทำการออกเเบบ PCD เป็นซอฟต์แวร์ทางด้านวิศวกรรมอิเล็กทรอนิกส์ ที่ใช้ในการ ออกแบบแผ่น PCB แผงวงจรอิเล็กทรอนิกส์ แบบครบวงจร การออกแบบแผ่น PCB กับเครื่องคอมพิวเตอร์ ช่วยลดเวลาในการทำงานของฝ่ายออกแบบ PCB และฝ่ายเครื่องกลได้เป็นอย่างดี
7.1ทำบอร์ด PCD เเละทดสอบการวงจรต่างๆ
7.2 ทำการออกเเบบโครงสร้างชิ้นงาน
8.วิธีการทำการเเจ้งเตือนผ่านไลน์
8.1ทำการขอLine Token ใน https://notify-bot.line.me/th/
8.2 นำรหัส Line Token นำไปใส่ในCode
#define LINE_TOKEN_PIR "uxTj7Ve94HUEVxPa8rJ1XlJ5OC3tzfByFakzCksuwRG"
9.ใช้การเขียนโปรเเกรมเเบบ OOP ในการให้ข้อมูล
9.1การสร้างClass Line Notify
การเข้าเรียกใช้ลิงค์ในการขออนุญาติLine
class LineNotifier {
public:
LineNotifier(const String& token) : LINE_TOKEN(token) {}
void notify(const String& message) {
WiFiClientSecure client;
if (!client.connect("notify-api.line.me", 443)) {
Serial.println("Connection failed");
delay(2000);
return;
}
String req = "POST /api/notify HTTP/1.1\r\n";
req += "Host: notify-api.line.me\r\n";
req += "Authorization: Bearer " + LINE_TOKEN + "\r\n";
req += "Cache-Control: no-cache\r\n";
req += "User-Agent: ESP8266\r\n";
req += "Content-Type: application/x-www-form-urlencoded\r\n";
req += "Content-Length: " + String(String("message=" + message).length()) + "\r\n";
req += "\r\n";
req += "message=" + message;
client.print(req);
delay(20);
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") {
break;
}
}
}
private:
const String LINE_TOKEN;
};
9.2 การสร้าง Class SensorController
คือการจัดการเซนเซอร์ต่างๆ เพื่อให้สามารถใช้งานได้
class SensorController {
public:
SensorController(int analogPin, int ironPin, int pirPin)
: analogPin(analogPin), ironPin(ironPin), pirPin(pirPin) {}
void setup() {
pinMode(analogPin, INPUT);
pinMode(ironPin, INPUT);
pinMode(pirPin, INPUT);
}
int readAnalogValue() {
digitalRead(analogPin);
}
int readIronValue() {
digitalRead(ironPin);
}
bool motionDetected() {
return digitalRead(pirPin) == LOW;
}
private:
const int analogPin;
const int ironPin;
const int pirPin;
};
9.3 การเรียกใช้คำสั่งต่างๆการLoopของโปรเเกรม
LCDController lcdController;
ServoController servoController;
LineNotifier lineNotifier(LINE_TOKEN_PIR);
SensorController sensorController(34, 26, 16);
int ironCount = 0;
int garbageCount = 0;
void setup() {
Serial.begin(9600);
Serial.println();
lcdController.begin();
servoController.moveServo(80);
Serial.println("Connecting to WiFi...");
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println();
Serial.print("Connected to WiFi: ");
Serial.println(WiFi.localIP());
delay(5000);
Serial.println("PIR Sensor Ready!!");
}
void loop() {
int val = sensorController.readAnalogValue();
int sad = sensorController.readIronValue();
if (val == 1 && sad == 0) {
servoController.moveServo(10);
Serial.println("Iron");
ironCount++;
lcdController.updateIronCount(ironCount);
delay(2000);
} else if (val == 1 && sad == 1) {
servoController.moveServo(150);
Serial.println("Garbage");
garbageCount++;
lcdController.updateGarbageCount(garbageCount);
delay(2000);
}
if (WiFi.status() == WL_CONNECTED) {
if (sensorController.motionDetected()) {
Serial.println("Detected !");
lineNotifier.notify("แจ้งเตือน: มีการเคลื่อนไหว");
delay(1000);
}
}
}
6.ผลการดำเนินการ
6.1 การทำงานของระบบ
6.2 เมื่อมีวัตถุเข้ามาจะทำการตรวจสอบว่าใช่โหละหรือไม่
ถ้าใช่โลหะจะทำงานปัดไปทางขวาทางไม่ใช่จะปัดไปทางซ้าย
6.3 เมื่อวัตถุเต็มจะมีการเเจ้งเตือนผ่านไลน์
ผลการทดลองที่ได้
6.4 Codeในการทำงานทั้งหมด
#include <WiFi.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFiClientSecure.h>
#include <ESP32Servo.h>
#define WIFI_SSID "Surachet"
#define WIFI_PASSWORD "game2222"
#define LINE_TOKEN_PIR "uxTj7Ve94HUEVxPa8rJ1XlJ5OC3tzfByFakzCksuwRG"
class LCDController {
public:
LCDController() : LCD(0x27, 20, 4) {}
void begin() {
LCD.begin();
LCD.setCursor(4, 0);
LCD.print("Surachet");
}
void updateIronCount(int count) {
LCD.setCursor(6, 1);
LCD.print(count);
}
void updateGarbageCount(int count) {
LCD.setCursor(9, 2);
LCD.print(count);
}
private:
LiquidCrystal_I2C LCD;
};
class ServoController {
public:
ServoController() {
myservo.attach(5);
}
void moveServo(int angle) {
myservo.write(angle);
}
private:
Servo myservo;
};
class LineNotifier {
public:
LineNotifier(const String& token) : LINE_TOKEN(token) {}
void notify(const String& message) {
WiFiClientSecure client;
if (!client.connect("notify-api.line.me", 443)) {
Serial.println("Connection failed");
delay(2000);
return;
}
String req = "POST /api/notify HTTP/1.1\r\n";
req += "Host: notify-api.line.me\r\n";
req += "Authorization: Bearer " + LINE_TOKEN + "\r\n";
req += "Cache-Control: no-cache\r\n";
req += "User-Agent: ESP8266\r\n";
req += "Content-Type: application/x-www-form-urlencoded\r\n";
req += "Content-Length: " + String(String("message=" + message).length()) + "\r\n";
req += "\r\n";
req += "message=" + message;
client.print(req);
delay(20);
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") {
break;
}
}
}
private:
const String LINE_TOKEN;
};
class SensorController {
public:
SensorController(int analogPin, int ironPin, int pirPin)
: analogPin(analogPin), ironPin(ironPin), pirPin(pirPin) {}
void setup() {
pinMode(analogPin, INPUT);
pinMode(ironPin, INPUT);
pinMode(pirPin, INPUT);
}
int readAnalogValue() {
digitalRead(analogPin);
}
int readIronValue() {
digitalRead(ironPin);
}
bool motionDetected() {
return digitalRead(pirPin) == LOW;
}
private:
const int analogPin;
const int ironPin;
const int pirPin;
};
LCDController lcdController;
ServoController servoController;
LineNotifier lineNotifier(LINE_TOKEN_PIR);
SensorController sensorController(34, 26, 16);
int ironCount = 0;
int garbageCount = 0;
void setup() {
Serial.begin(9600);
Serial.println();
lcdController.begin();
servoController.moveServo(80);
Serial.println("Connecting to WiFi...");
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println();
Serial.print("Connected to WiFi: ");
Serial.println(WiFi.localIP());
delay(5000);
Serial.println("PIR Sensor Ready!!");
}
void loop() {
int val = sensorController.readAnalogValue();
int sad = sensorController.readIronValue();
if (val == 1 && sad == 0) {
servoController.moveServo(10);
Serial.println("Iron");
ironCount++;
lcdController.updateIronCount(ironCount);
delay(2000);
} else if (val == 1 && sad == 1) {
servoController.moveServo(150);
Serial.println("Garbage");
garbageCount++;
lcdController.updateGarbageCount(garbageCount);
delay(2000);
}
if (WiFi.status() == WL_CONNECTED) {
if (sensorController.motionDetected()) {
Serial.println("Detected !");
lineNotifier.notify("แจ้งเตือน: มีการเคลื่อนไหว");
delay(1000);
}
}
}
7.สรุปผลเเละข้อเสนอเเนะ
1.สรุปผลจากผลการทดลอง เครื่องคัดแยกโลหะ มีประสิทธิภาพ ตรงตามเงื่อนไขตามที่ทดลอง ได้แก่
1).การคัดแยกโลหะ
2).ยังเกิดข้อผิดพลาดในตัวเซ็นเซอร์โลหะเล็กน้อย
3).การคัดแยกขยะที่มีประสิทธิภาพสูง
4).การแจ้งเตือนผ่านไลน์เมื่อวัตถุโลหะเต็มได้
2.ข้อเสนอเเนะ
2.1 เซนเซอร์เป็นเซนเซอร์ตัวจับเเม่เหล็กทำให้เกิดการตัวจับยากขึ้น
8.ข้อมูลอ้างอิง
[1] คณสรณ์ ผิวบาง, ศรัณยู พรหมยุทธนา, และการตรัตน์ ขำดำ. (2562). เครื่องคัดแยกขวดอัตโนมัติ.
[สืบค้นวันที่ 2 กันยายน 2566] จากhttp://mecha.sut.ac.th/project_file/project_00030.pdf
[2] Cyber Tice. (2562). สอนใช้งาน Node MCU ESP8266แจ้งเตือนผ่าน LINE Notify.
[สืบค้นวันที่ 20 กันยายน 2566] จากhttps://www.cybertice.com/article
[3] เริ่มต้นการเขียนโปรแกรมด้วยภาษาC++ ยุทธนา ลีลาศวัฒนกุล. (2547). เริ่มต้นการเขียนโปรแกรมด้วยภาษาC++.กรุงเทพมหานคร:หจก.ไทยเจริญการพิมพ์