4 มิถุนายน 2567
งานที่ได้รับมอบหมายคือการใช้ Arduino OPTA ให้สามารถทำงานร่วมกับ MQTT โดยใช้เซ็นเซอร์ตรวจจับอุณหภูมิ และ ตรวจจับแสงร่วมด้วย โดยในวันแรกเริ่มจากการศึกษาหาข้อมูลเกี่ยวกับ MQTT และ Arduino OPTA
งานที่ได้ทำในวันนี้
- ทดลองเล่น Arduino OPTA กับโปรแกรม Arduino PLC IDE ให้สามารถเชื่อมต่อและส่งข้อมูลหากันได้
link : https://youtu.be/jSVzVAaLURM?si=CXrpVnToBDBU6ikI
5 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- หาข้อมูลทำงานของการใช้ Arduino OPTA กับการทำงานร่วมกับ MQTT
- ศึกษาข้อมูลเกี่ยวกับ MQTT
- หาข้อมูลเซ็นเซอร์ที่ใช้ควบคุมแสง และอุณหภูมิและความชื้น โดยเลือกที่การสื่อสารแบบ I2C หรือ RS485
ข้อมูลเซ็นเซอร์
https://docs.google.com/document/d/1oI1ew-Da6GK_8S-1gyNs-q1flLhN9S3CtBR6bTGYz4M/edit?usp=sharing
ที่มา
link : https://aws.amazon.com/th/what-is/mqtt/
link : https://youtu.be/Gu9txMng_nQ?si=mHZXic-37guzO5vT
6 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- ศึกษาการใช้งาน MQTT และทดลองเชื่อมต่อกับการทำงานร่วมกับ MQTT โดยให้ส่งข้อความไปแสดงใน HiveMQ โดยใช้โปรแกรม Arduino IDE และควบคุมไฟ LED
- หาเซ็นเซอร์ที่ใช้ควบคุมแสง อุณหภูมิและความชื้น โดยใช้ Arduino wifi rev 2 ในการทดลอง
โค้ดการทดลอง
โค้ดนี้เป็นการทดลองโดยใช้ Arduino wifi rev 2 เชื่อต่อกับ HiveMQ และรับค่าแสงจากเซ็นเซอร์ LDR เข้ามาควบคุมการเปิด/ปิดไฟ LED
หมายเหตุ :โค้ดนี้ยังไม่รวมการรับค่าอุณหภูมิและความชื้น
Library ที่ใช้
- WiFiNINA
- PubSubClient
- ArduinoJson
#include <SPI.h>
#include <WiFiNINA.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#define LED_PIN 4
#define LDR_PIN A0
// Wi-Fi Credentials
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
// MQTT Broker Details
String device_id = "Device0001";
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
const char* mqtt_user = "Device0001";
const char* mqtt_password = "Device0001";
const char* mqtt_clientId = "Device_Device0001";
const char* topic_publish = "JPLearning_SensorData";
const char* topic_subscribe = "JPLearning_CommandRequest";
WiFiClient wifiClient;
PubSubClient mqtt_client(wifiClient);
// Data Sending Time
unsigned long CurrentMillis, PreviousMillis, DataSendingTime = (unsigned long) 1000 * 10;
// Variable
byte lightStatus;
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
Serial.println("\n\nWelcome to JP Learning\n");
// Start the Wi-Fi connection
setup_wifi();
// Connect to MQTT broker
mqtt_client.setServer(mqtt_server, mqtt_port);
mqtt_client.setCallback(callback);
mqtt_connect();
}
void loop() {
// MQTT handling
if (!mqtt_client.loop()) {
mqtt_connect();
}
// LDR value handling and MQTT publishing
int LDR_Value = analogRead(LDR_PIN);
if (LDR_Value == 0) {
Serial.println("\n\nFailed to read from LDR sensor!");
} else {
Serial.println("\n\nLDR Value: " + String(LDR_Value));
Serial.println("Light: " + String(lightStatus) + " " + String(lightStatus == 1 ? "ON" : "OFF"));
// Devices State Sync Request
CurrentMillis = millis();
if (CurrentMillis - PreviousMillis > DataSendingTime) {
PreviousMillis = CurrentMillis;
// Publish LDR Data
String pkt = "{";
pkt += "\"device_id\": \"Device00001\", ";
pkt += "\"type\": \"Light\", ";
pkt += "\"value\": " + String(LDR_Value) + "";
pkt += "}";
mqtt_publish((char*) pkt.c_str());
}
}
}
void setup_wifi() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void mqtt_connect() {
while (!mqtt_client.connected()) {
Serial.println("Attempting MQTT connection...");
if (mqtt_client.connect(mqtt_clientId, mqtt_user, mqtt_password)) {
Serial.println("MQTT Client Connected");
mqtt_publish((char*)("Hi from " + device_id).c_str());
mqtt_subscribe(topic_subscribe);
} else {
Serial.print("failed, rc=");
Serial.print(mqtt_client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void mqtt_publish(char * data) {
mqtt_connect();
if (mqtt_client.publish(topic_publish, data)) {
Serial.println("Publish \"" + String(data) + "\" ok");
} else {
Serial.println("Publish \"" + String(data) + "\" failed");
}
}
void mqtt_subscribe(const char * topic) {
if (mqtt_client.subscribe(topic)) {
Serial.println("Subscribe \"" + String(topic) + "\" ok");
} else {
Serial.println("Subscribe \"" + String(topic) + "\" failed");
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String command;
Serial.print("\n\nMessage arrived [");
Serial.print(topic);
Serial.println("] ");
for (int i = 0; i < length; i++)
command += (char)payload[i];
if (command.length() > 0)
Serial.println("Command receive is : " + command);
DynamicJsonDocument doc(1024);
deserializeJson(doc, command);
JsonObject obj = doc.as<JsonObject>();
String id = obj["device_id"];
String type = obj["type"];
String value = obj["value"];
Serial.println("\nCommand device_id is : " + id);
Serial.println("Command type is : " + type);
Serial.println("Command value is : " + value);
if (id == device_id && type == "Light") {
if (value == "1") {
lightStatus = 1;
digitalWrite(LED_PIN, HIGH);
Serial.println("\nLED ON by Application");
mqtt_publish((char*) command.c_str());
} else {
lightStatus = 0;
digitalWrite(LED_PIN, LOW);
Serial.println("\nLED OFF by Application");
mqtt_publish((char*) command.c_str());
}
}
}
ปัญหาที่พบระหว่างการทำงาน
- ในระหว่างทำมีการลองเปลี่ยนข้อมูลหัวข้อ Topic เกิดข้อผิดพลาดของโค้ดคือข้อมูลไม่ส่งไปหา Topic ใหม่
7 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- เข้าไปช่วยตรวจรับ Hololens โดยตรวจสอบว่าเครื่องมีหนิหหรือใช้งานผิดปกติหรือไม่
10 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- ค้นคว้าการทำงานของ OPTA
- ทดลองนำ Arduino OPTA เชื่อต่อกับ MQTT
Arduino OPTA
Arduino Opta เป็นอุปกรณ์ PLC ขนาดเล็กที่ปลอดภัยและสามารถใช้งานง่ายพร้อมด้วยความสามารถ IoT ระดับอุตสาหกรรม ออกแบบร่วมกับ Finder ผู้ผลิตอุปกรณ์อัตโนมัติทางอุตสาหกรรมและอาคารชั้นนำ
Arduino Opta มี 3 รุ่น ได้แก่
- Arduino Opta Lite มีอินเตอร์เฟสผ่านทาง USB Type-C, Ethernet
- Arduino Opta RS485 มีอินเตอร์เฟสผ่านทาง USB Type-C, Ethernet, RS-485 แบบ Half Duplex
- Arduino Opta WiFi มีอินเตอร์เฟสผ่านทาง USB Type-C, Ethernet, RS-485 แบบ Half Duplex, Wi-Fi + BLE
คุณสมบัติของ Arduino Opta:
- MCU – ไมโครคอนโทรลเลอร์ STMicroelectronics STM32H747XI พร้อม Arm Cortex-M7 1 คอร์ สูงสุด 480 MHz, Arm Cortex-M4 1 คอร์ สูงสุด 240 MHz, flash ขนาด 2MB , SRAM ขนาด 1MB (ตามที่พบในบอร์ด Portenta H7 ทั้งหมด)
- พื้นที่เก็บข้อมูล – Flash QSPI ขนาด 16MB
- I/O
- 8x อินพุตดิจิตอล/อนาล็อก (0-10V)
- 4x เอาต์พุตหน้าสัมผัสรีเลย์ปกติเปิด (NO relay), พิกัด 10 A
- การเชื่อมต่ออินเทอร์เฟซ
- พอร์ต Ethernet RJ45 สำหรับ LAN หรือ MODBUS TCP/IP
- พอร์ตเสริม RS485 สำหรับการเชื่อมต่อ MODUS RTU
- โมดูลรวมเสริม WiFi & BLE
- USB – พอร์ต USB 2.0 Type-C 1 ช่อง, การเขียนโปรแกรมหรือการบันทึกข้อมูล (ผ่าน memory stick)
- ความปลอดภัย – ATECC608B secure element
- อื่นๆ – ปุ่ม RTC, ปุ่มรีเซ็ตและปุ่มผู้ใช้, ไฟ LED แสดงสถานะต่างๆ สำหรับ I/O และอีเธอร์เน็ต
- การจ่ายแรงดัน – อินพุต 12…24 V DC
- ขนาด – ประมาณ 90 x 85 x 69 มม. (ติดตั้งรางปีกนก DIN Rail)
- น้ำหนัก – 210 กรัม
- Ingress Protection (มาตรฐานการป้องกัน) IP20
พอร์ตการเชื่อมต่อ
ปัญหาที่พบระหว่างการทำงาน
- ในครั้งแรก Arduino OPTA เชื่อ Broker MQTT มีปัญหาที่การเชื่อต่อ failed เนื่องจากการใช้ไลบรารีหรือโค้ดบางส่วนที่ต้องปรับให้ทำงานกับ Arduino OPTA ได้
ที่มา
link :https://docs.arduino.cc/hardware/opta
11 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- ทดลองใช้ Arduino OPTA ร่วมกับ HiveMQ และ MQTTX
โค้ดการทดลอง
โค้ดนี้เป็นทดลองใช้ Arduino OPTA ร่วมกับ HiveMQ โดยรับค่าแสงจากเซ็นเซอร์ LDR เข้ามาควบคุมการเปิด/ปิดไฟ LED ซึ่งจะแสดงสถานะการเชื่อมต่อ Wi-Fi และ MQTT การอ่านค่า LDR และการควบคุม LED ผ่านคำสั่ง MQTT รวมถึงการส่งข้อมูล LDR ไปยัง MQTT broker ทุก ๆ 10 วินาที
หมายเหตุ :โค้ดนี้ยังไม่รวมการรับค่าอุณหภูมิและความชื้น
Library ที่ใช้
- WiFi
- PubSubClient
- ArduinoJson
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#define LED_Pin LED_D0
#define LDR_Pin A0
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;
String device_id = "LDR_SENSOR_1"; // ชื่ออุปกรณ์ที่ต้องการตั้ง
const char* mqtt_server = "mqtt-dashboard.com";
const int mqtt_port = 1883;
const char* mqtt_user = "Nattanit"; // ชื่อ User ที่ต้องการตั้ง
const char* mqtt_password = "Nattanit"; // Password ที่ User ต้องการตั้ง
const char* mqtt_clientId = "clientId-gaGnJtBAzp";
const char* topic_publish = "M2MQTT_Unity/test12"; // Publisher: ส่งข้อมูลไปยัง MQTT Broker
const char* topic_subscribe = "M2MQTT_Unity/test2"; // Subscriber: รับข้อมูลจาก MQTT Broker
WiFiClient wifiClient;
PubSubClient mqtt_client(wifiClient);
// Data Sending Time
unsigned long CurrentMillis, PreviousMillis, DataSendingTime = (unsigned long) 1000 * 10;
// Variable
byte lightStatus;
void setup() {
Serial.begin(115200);
pinMode(LED_Pin, OUTPUT);
Serial.println("\n\nWelcome to OPTA\n");
// Start the Wi-Fi connection
setup_wifi();
// Connect to MQTT broker
mqtt_client.setServer(mqtt_server, mqtt_port);
mqtt_client.setCallback(callback);
mqtt_connect();
// Subscribe ไปยัง topic ที่ต้องการรับค่าควบคุม LED
mqtt_subscribe(topic_subscribe);
}
void loop() {
// MQTT handling
if (!mqtt_client.loop()) {
mqtt_connect();
}
mqtt_client.loop();
// LDR value handling and MQTT publishing
int LDR_Value = analogRead(LDR_Pin);
if (LDR_Value == 0) {
Serial.println("\n\nFailed to read from LDR sensor!");
} else {
Serial.println("\n\nLDR Value: " + String(LDR_Value));
Serial.println("Light: " + String(lightStatus) + " " + String(lightStatus == 1 ? "ON" : "OFF"));
delay(1000);
// Devices State Sync Request
CurrentMillis = millis();
if (CurrentMillis - PreviousMillis > DataSendingTime) {
PreviousMillis = CurrentMillis;
// Publish LDR Data
String pkt = "{";
pkt += "\"device_id\": \"LDR_SENSOR_1\", ";
pkt += "\"type\": \"Light\", ";
pkt += "\"value\": " + String(LDR_Value) + "";
pkt += "}";
mqtt_publish((char*) pkt.c_str());
}
}
}
void setup_wifi() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void mqtt_connect() {
while (!mqtt_client.connected()) {
Serial.println("Attempting MQTT connection...");
if (mqtt_client.connect(mqtt_clientId, mqtt_user, mqtt_password)) {
Serial.println("MQTT Client Connected");
mqtt_publish((char*)("Hi from " + device_id).c_str());
mqtt_subscribe(topic_subscribe);
} else {
Serial.print("failed, rc=");
Serial.print(mqtt_client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void mqtt_publish(char * data) {
mqtt_connect();
if (mqtt_client.publish(topic_publish, data)) {
Serial.println("Publish \"" + String(data) + "\" ok");
} else {
Serial.println("Publish \"" + String(data) + "\" failed");
}
}
void mqtt_subscribe(const char * topic) {
if (mqtt_client.subscribe(topic)) {
Serial.println("Subscribe \"" + String(topic) + "\" ok");
} else {
Serial.println("Subscribe \"" + String(topic) + "\" failed");
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String command;
Serial.print("\n\nMessage arrived [");
Serial.print(topic);
Serial.println("] ");
for (int i = 0; i < length; i++) {
command += (char)payload[i];
}
if (command.length() > 0) {
Serial.println("Command received is : " + command);
}
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, command);
if (error) {
Serial.print("Failed to parse JSON: ");
Serial.println(error.c_str());
return;
}
JsonObject obj = doc.as<JsonObject>();
String id = obj["device_id"];
String type = obj["type"];
String value = obj["value"];
Serial.println("\nCommand device_id is : " + id);
Serial.println("Command type is : " + type);
Serial.println("Command value is : " + value);
if (id == device_id && type == "Light") {
if (value == "1") {
lightStatus = 1;
digitalWrite(LED_Pin, HIGH);
Serial.println("\nLED ON by Application");
mqtt_publish((char*) command.c_str());
} else {
lightStatus = 0;
digitalWrite(LED_Pin, LOW);
Serial.println("\nLED OFF by Application");
mqtt_publish((char*) command.c_str());
}
}
}
ปัญหาที่พบระหว่างการทำงาน
- ในการทำงานช่วงแรกๆปัญหา Arduino OPTA ไม่อ่านค่า LDR หรือ่านค่าเป็น 0 หรือเป็นค่า error
12 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- ทดลองการใช้ Arduino OPTA ต่อจากเมื่อวานให้เสร็จสมบรูณ์
- ทดลองใช้ Arduino OPTA ร่วมกับ HiveMQ และ MQTTX ร่วมกับการส่งข้อมูลจาก Unity เข้ามาควบคุมไฟ LED ให้สามารถเปิดปิดได้
- ศึกษาว่า QoS คืออะไร
MQTT มีสามระดับของ QoS เพื่อจัดการกับการส่งข้อความ :
- QoS 0: ส่งข้อความเพียงครั้งเดียว โดยไม่รับประกันการส่งถึง
- QoS 1: ส่งข้อความอย่างน้อยหนึ่งครั้ง โดยมีการรับประกันการส่ง
- QoS 2: ส่งข้อความเพียงครั้งเดียว โดยมีการรับประกันการส่งและการจัดการการส่งซ้ำ
ปัญหาที่พบ
- อ่านค่าจาก LDR ได้ จะพบว่าอ่านค่าได้น้อยกว่าจากการอ่านค่าใน Arduion WiFi rev 2
สิ่งที่ได้เรียนรู้
- หลังจากทดลองให้ Arduino OPTA อ่านค่า LDR ได้ ก็จะพบว่าค่าที่อ่านได้นั้นมีค่าน้อยกว่าการอ่านค่าใน Arduion WiFi rev 2 เกิดจากการที่เราจ่ายไฟให้กับ LDR เป็นไฟ 5 V เหมือนตอนที่ทดลองกับ Arduion WiFi rev 2 ทำให้กระแสไหลน้อย ดังนั้นจึงแก้จากการเพิ่มกระแสเข้าไปให้ LDR เป็น 12 V โดยตอนทดลองใช้ไฟร่วมกับ Arduino OPTA เลย
13 มิถุนายน 2567
งานที่ได้ทำในวันนนี้
- ทดลองใช้ Arduino OPTA กับเซ็นเซอร์ BH1750FVI ที่เป็นการสื่อสารแบบ I2C และเซ็นเซอร์ XY-MD02 ที่เป็นการสื่อสารแบบ RS485
ปัญหาที่พบ
- Arduino OPTA ไม่มีช่องรับสัญญาณแบบ I2C ทำให้ไม่สามรถใช้งานเซ็นเซอร์ BH1750FVI ได้ โดยค้นหาช่องการเชื่อต่อทั้งจากใน Google
สิ่งที่ได้เรียนรู้
- จากที่โดยค้นหาช่องการเชื่อต่อ I2C ทั้งจากใน Google ,YouTube และ Document ของ Arduino OPTA ไม่พบช่องสัญญาณ I2C หรือ ใน Arduino OPTA มีช่อง Port for communication and connection of auxiliary modules ที่เป็นช่องแยกมีคนเคยทำไว้ แต่หลักๆแล้วช่องนี้ไม่ได้ออกแบบมาเพื่อเชื่อต่อ I2C โดยเฉพาะ
14 – 19 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- ทดลองใช้ Arduino OPTA กับเซ็นเซอร์ XY-MD02 ที่เป็นการสื่อสารแบบ RS485
- ทดลองใช้ Arduino WiFi Rev2 กับเซ็นเซอร์ XY-MD02 ที่เป็นการสื่อสารแบบ RS485
ปัญหาที่พบ
- Arduino OPTA ไม่สามารถส่งค่าสื่อสารกับเซ็นเซอร์ได้ โดยเมื่อส่งค่าไปเรียกค่าอุณหภูมิและความชื้นแล้ว เซ็นเซอร์ไม่ตอบค่ากลับมา
สิ่งที่ได้เรียนรู้
- การเชื่อต่อ RS485 สาย Arduino OPTA กับ เซนเซอร์ XY-MD02 ใน Arduion OPTA จะมี Port การเชื่อมต่อ RS485 แบบ A(-) และ B(+) และในเซ็นเซอร์ XY-MD02 จะมี Port การเชื่อมต่อ RS485 แบบ A(+) และ B(-) ซึ่งในงานนี้ที่เราจะใช้งานให้ยึด Port ที่เป็น A ,B เป็นหลักไปเลย เช่น ต่อสาย A(-) ของ Arduino OPTA เข้ากับ ช่อง A(+) ของเซ็นเซอร์ XY-MD02
- การอ่าน data sheet ของเซ็นเซอร์ XY-MD02
- Funciotn ต่างๆที่มีไว้ควบคุมการเขียนใน register ของ RS485
- วิธีการที่เซ็นเซอร์อ่านค่าเมื่อได้รับการส่งค่า
เมื่อส่งค่าไปถามใน register Starting Address Hi และ Starting Address Li ข้อมูลจะตอบกลับมาเป็นจำนวน 2 Bytes ซึ่งค่าอุหภูมิในช่องแรกที่ตอบกลับมา(ไฮไลต์สีเหลือง) ให้นำมาต่อกับช่องที่ 2(ไฮไลต์สีฟ้า) แล้วเปลี่ยนค่าจาก Hex เป็น decimal
ที่มา
link :https://iot-kmutnb.github.io/blogs/sensors/xy-md02
20 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- รวมโค้ดส่วนต่างๆ ของ Arduino WiFi Rev 2 ที่ได้ทดลองกับเซ็นเซอร์และการส่งค่าเข้าด้วยกัน ให้ทำงานกับ MQTT และ Unity ให้เป็นระบบที่ทำงานร่วมกันได้
#include <SPI.h>
#include <WiFiNINA.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <BH1750.h>
#include <SoftwareSerial.h>
#include <ModbusMaster.h>
#include "arduino_secrets.h"
// MQTT Setup
const char* mqtt_server = "0.tcp.ap.ngrok.io";
const int mqtt_port = 12537;
const char* mqtt_user = "Nattanit";
const char* mqtt_password = "1234";
const char* mqtt_clientId = "clientId-gaGnJtBAzp";
const char* topic_publish_light = "M2MQTT_Unity/sensor/BH1750FVI";
const char* topic_subscribe = "M2MQTT_Unity/LED";
const char* topic_temperature_humidity = "M2MQTT_Unity/sensor/xy_md02";
// Device Setup
String device_id = "Sensors";
WiFiClient wifiClient;
PubSubClient mqtt_client(wifiClient);
// BH1750 Setup
#define LED_Pin 13
BH1750 lightMeter;
// XY-MD02 Setup
SoftwareSerial mySerial(2, 3); // RX, TX
#define MAX485_DE 4
#define MAX485_RE_NEG 5
ModbusMaster node;
// Data Sending Time
unsigned long CurrentMillis, PreviousMillis, DataSendingTime = 10000; // 10 seconds
// Variable
byte lightStatus;
void preTransmission() {
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);
}
void postTransmission() {
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
}
void setup() {
Serial.begin(115200);
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
pinMode(LED_Pin, OUTPUT); // Ensure LED pin is set as OUTPUT
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
Serial.println("\n\nWelcome to All_Sensors\n");
// Start the Wi-Fi connection
setup_wifi();
// Connect to MQTT broker
mqtt_client.setServer(mqtt_server, mqtt_port);
mqtt_client.setCallback(callback);
mqtt_connect();
// Initialize the BH1750 sensor
Wire.begin();
if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) {
Serial.println(F("BH1750 Advanced begin"));
} else {
Serial.println(F("Error initializing BH1750"));
}
// Initialize the ModbusMaster for XY-MD02
mySerial.begin(9600);
node.begin(1, mySerial);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void loop() {
// MQTT handling
if (!mqtt_client.loop()) {
mqtt_connect();
}
// Read LDR value and publish via MQTT
float lux = lightMeter.readLightLevel();
if (lux < 0) {
Serial.println("\n\nFailed to read from BH1750 sensor!");
} else {
Serial.println("\n\nBH1750 Lux Value: " + String(lux, 2)); // Two decimal places
Serial.println("Light: " + String(lightStatus) + " " + String(lightStatus == 1 ? "ON" : "OFF"));
// Publish BH1750 data
StaticJsonDocument<200> doc;
doc["device_id"] = device_id;
doc["type"] = "Light";
doc["sensor"] = "BH1750FVI";
doc["value"] = String(lux, 2); // Two decimal places
char jsonBuffer[512];
serializeJson(doc, jsonBuffer);
mqtt_publish(topic_publish_light, jsonBuffer);
Serial.println();
}
// Read XY-MD02 data and publish via MQTT
uint8_t result = node.readInputRegisters(1, 2);
if (result == node.ku8MBSuccess) {
float temp = node.getResponseBuffer(0) / 10.0f;
float humi = node.getResponseBuffer(1) / 10.0f;
Serial.print("Temp: ");
Serial.println(String(temp, 2)); // Two decimal places
Serial.print("Humi: ");
Serial.println(humi);
// Publish Temperature and Humidity data
StaticJsonDocument<200> doc;
doc["device_id"] = device_id;
doc["type"] = "XY-MD02";
doc["temperature"] = String(temp, 2); // Two decimal places
doc["humidity"] = humi;
char buffer[512];
serializeJson(doc, buffer);
mqtt_publish(topic_temperature_humidity, buffer);
}
delay(3000); // Delay before next iteration
}
void setup_wifi() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(SECRET_SSID);
WiFi.begin(SECRET_SSID, SECRET_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void mqtt_connect() {
while (!mqtt_client.connected()) {
Serial.println("Attempting MQTT connection...");
if (mqtt_client.connect(mqtt_clientId, mqtt_user, mqtt_password)) {
Serial.println("MQTT Client Connected");
mqtt_publish(topic_publish_light, (char*)("Hi from " + device_id).c_str());
mqtt_subscribe(topic_subscribe);
} else {
Serial.print("failed, rc=");
Serial.print(mqtt_client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void mqtt_publish(const char * topic, char * data) {
mqtt_connect();
if (mqtt_client.publish(topic, data)) {
Serial.println("Publish \"" + String(data) + "\" to topic \"" + String(topic) + "\" ok");
} else {
Serial.println("Publish \"" + String(data) + "\" to topic \"" + String(topic) + "\" failed");
}
}
void mqtt_subscribe(const char * topic) {
if (mqtt_client.subscribe(topic)) {
Serial.println("Subscribe \"" + String(topic) + "\" ok");
} else {
Serial.println("Subscribe \"" + String(topic) + "\" failed");
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String command;
Serial.print("\n\nMessage arrived [");
Serial.print(topic);
Serial.println("] ");
for (int i = 0; i < length; i++) {
command += (char)payload[i];
}
if (command.length() > 0) {
Serial.println("Command received is : " + command);
}
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, command);
if (error) {
Serial.print("Failed to parse JSON: ");
Serial.println(error.c_str());
return;
}
JsonObject obj = doc.as<JsonObject>();
String id = obj["device_id"];
String type = obj["type"];
String value = obj["value"];
Serial.println("\nCommand device_id is : " + id);
Serial.println("Command type is : " + type);
Serial.println("Command value is : " + value);
if (id == device_id && type == "LED") {
if (value == "1") {
lightStatus = 1;
digitalWrite(LED_Pin, HIGH);
Serial.println("\nLED ON by Application");
mqtt_publish(topic_publish_light, (char*) command.c_str());
} else if (value == "0") {
lightStatus = 0;
digitalWrite(LED_Pin, LOW);
Serial.println("\nLED OFF by Application");
mqtt_publish(topic_publish_light, (char*) command.c_str());
} else {
Serial.println("\nInvalid value received for LED control.");
}
}
}
ปัญหาที่พบ
- ระหว่างการรวมโค้ดเมื่อทำงานรวมกันแล้วมี Error
21 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- ทดลองใช้ Arduino OPTA ซ็นเซอร์ BH1750FVI และ เซ็นเซอร์ XY-MD02 ที่ทำงานเสร็จสมบูรณ์
- ทดสอบและแก้ไขโค้ดให้สมบูรณ์และใช้งานกับ Unity ได้ดีมากขึ้น
โค้ดการทดลอง
โค้ดการทำงานของ Arduino WiFi Rve 2 โดยรับค่าแสงจากเซ็นเซอร์ BH1750FVI และรับค่าอุณหภูมิจากเซ็นเซอร์ XY-MD02 ซึ่งจะส่งข้อมูลผ่าน MQTT ไปหายัง Unity ที่ทำงานเสร็จสมบูรณ์ และสามารถควบคุมการเปิด/ปิดไฟได้
#include <SPI.h>
#include <WiFiNINA.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <BH1750.h>
#include <SoftwareSerial.h>
#include <ModbusMaster.h>
#include "arduino_secrets.h"
// MQTT Setup
const char* mqtt_server = "0.tcp.ap.ngrok.io";
const int mqtt_port = 12655;
const char* mqtt_user = "Nattanit";
const char* mqtt_password = "1234";
const char* mqtt_clientId = "clientId-gaGnJtBAzp";
const char* topic_publish_light = "M2MQTT_Unity/sensor/BH1750FVI";
const char* topic_subscribe = "M2MQTT_Unity/LED";
const char* topic_temperature_humidity = "M2MQTT_Unity/sensor/xy_md02";
// Device Setup
String device_id = "Sensors";
WiFiClient wifiClient;
PubSubClient mqtt_client(wifiClient);
// BH1750 Setup
#define LED_Pin 13
BH1750 lightMeter;
// XY-MD02 Setup
SoftwareSerial mySerial(2, 3); // RX, TX
#define MAX485_DE 4
#define MAX485_RE_NEG 5
ModbusMaster node;
// Data Sending Time
unsigned long CurrentMillis, PreviousMillis, DataSendingTime = 10000; // 10 seconds
// Variable
byte lightStatus;
void preTransmission() {
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);
}
void postTransmission() {
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
}
void setup() {
Serial.begin(115200);
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
pinMode(LED_Pin, OUTPUT); // Ensure LED pin is set as OUTPUT
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
Serial.println("\n\nWelcome to All_Sensors\n");
// Start the Wi-Fi connection
setup_wifi();
// Connect to MQTT broker
mqtt_client.setServer(mqtt_server, mqtt_port);
mqtt_client.setCallback(callback);
mqtt_connect();
// Initialize the BH1750 sensor
Wire.begin();
if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) {
Serial.println(F("BH1750 Advanced begin"));
} else {
Serial.println(F("Error initializing BH1750"));
}
// Initialize the ModbusMaster for XY-MD02
mySerial.begin(9600);
node.begin(1, mySerial);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void loop() {
// MQTT handling
if (!mqtt_client.loop()) {
mqtt_connect();
}
// Read LDR value and publish via MQTT
float lux = lightMeter.readLightLevel();
if (lux < 0) {
Serial.println("\n\nFailed to read from BH1750 sensor!");
} else {
Serial.println("\n\nBH1750 Lux Value: " + String(lux, 2)); // Two decimal places
Serial.println("Light: " + String(lightStatus) + " " + String(lightStatus == 1 ? "ON" : "OFF"));
// Publish BH1750 data
StaticJsonDocument<200> doc;
doc["device_id"] = device_id;
doc["type"] = "Light";
doc["sensor"] = "BH1750FVI";
doc["value"] = String(lux, 2); // Two decimal places
char jsonBuffer[512];
serializeJson(doc, jsonBuffer);
mqtt_publish(topic_publish_light, jsonBuffer);
Serial.println();
}
// Read XY-MD02 data and publish via MQTT
uint8_t result = node.readInputRegisters(1, 2);
if (result == node.ku8MBSuccess) {
float temp = node.getResponseBuffer(0) / 10.0f;
float humi = node.getResponseBuffer(1) / 10.0f;
Serial.print("Temp: ");
Serial.println(String(temp, 2)); // Two decimal places
Serial.print("Humi: ");
Serial.println(humi);
// Publish Temperature and Humidity data
StaticJsonDocument<200> doc;
doc["device_id"] = device_id;
doc["type"] = "XY-MD02";
doc["temperature"] = String(temp, 2); // Two decimal places
doc["humidity"] = humi;
char buffer[512];
serializeJson(doc, buffer);
mqtt_publish(topic_temperature_humidity, buffer);
}
delay(3000); // Delay before next iteration
}
void setup_wifi() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(SECRET_SSID);
WiFi.begin(SECRET_SSID, SECRET_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void mqtt_connect() {
while (!mqtt_client.connected()) {
Serial.println("Attempting MQTT connection...");
if (mqtt_client.connect(mqtt_clientId, mqtt_user, mqtt_password)) {
Serial.println("MQTT Client Connected");
mqtt_publish(topic_publish_light, (char*)("Hi from " + device_id).c_str());
mqtt_subscribe(topic_subscribe);
} else {
Serial.print("failed, rc=");
Serial.print(mqtt_client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void mqtt_publish(const char * topic, char * data) {
mqtt_connect();
if (mqtt_client.publish(topic, data)) {
Serial.println("Publish \"" + String(data) + "\" to topic \"" + String(topic) + "\" ok");
} else {
Serial.println("Publish \"" + String(data) + "\" to topic \"" + String(topic) + "\" failed");
}
}
void mqtt_subscribe(const char * topic) {
if (mqtt_client.subscribe(topic)) {
Serial.println("Subscribe \"" + String(topic) + "\" ok");
} else {
Serial.println("Subscribe \"" + String(topic) + "\" failed");
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String command;
Serial.print("\n\nMessage arrived [");
Serial.print(topic);
Serial.println("] ");
for (int i = 0; i < length; i++) {
command += (char)payload[i];
}
if (command.length() > 0) {
Serial.println("Command received is: " + command);
}
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, command);
if (error) {
Serial.print("Failed to parse JSON: ");
Serial.println(error.c_str());
return;
}
JsonObject obj = doc.as<JsonObject>();
String id = obj["device_id"];
String type = obj["type"];
String value = obj["value"];
Serial.println("\nCommand device_id is: " + id);
Serial.println("Command type is: " + type);
Serial.println("Command value is: " + value);
if (id == device_id && type == "LED") {
if (value == "1") {
lightStatus = 1;
digitalWrite(LED_Pin, HIGH);
Serial.println("\nLED ON by Application");
} else if (value == "0") {
lightStatus = 0;
digitalWrite(LED_Pin, LOW);
Serial.println("\nLED OFF by Application");
} else {
Serial.println("\nInvalid value received for LED control.");
}
}
}
ไฟล์ arduino_secrets.h
#define SECRET_SSID " your_SSID" //ชื่อ WiFi
#define SECRET_PASS " your_PASSWORD" //ญฟหหไนำก WiFi
ตัวอย่างโค้ดและวงจร
link : https://www.allnewstep.com/product/3344/bh1750fvi-arduino-sensor-เซ็นเซอร์วัดความเข้มแสง
24 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- ในช่วงเช้าทำการศึกษาเกี่ยวกับ RS485 และเตรียมตัวสำหรับการนำเสนองานให้กับอาจาร์ยจากคณะมันติมีเดียที่เข้ามาเยี่ยมชม
- นำเสนองานจากโปรเจ็คที่ได้รับมอบหมายการทำงานของ Arduino Opta ร่วมกับ MQTT
25 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- เขียนโค้ด RS485 และการใช้ modbus pull ในการดูค่าและกำหนด Slave Id ของเซ็นเซอร์ XY-MD02
สิ่งที่ได้เรียนรู้
- การใช้งานโปรแกรม modbus pull
- การกำหนดค่า Slave Id ของเซ็นเซอร์ XY-MD02
- การเขียนโค้ดไปอ่านค่า register เซ็นเซอร์ XY-MD02
26 -27 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- ออกบูธนำเสนองาน ณ งาน Academic Support fair 2024 ให้กับผู้เข้าเยี่ยมชมนิทัศการ
- นำเสนองานให้กับผอ.โรงเรียนดรุณสิกขาลัย และผู้บริหารสยามพิวรรธน์
28 มิถุนายน 2567
งานที่ได้ทำในวันนี้
- รวบรวมโค้ดต่างๆของ Arduion OPTA ทั้งเซ็นเซอร์แสง LDR เข้ากับเซ็นเซอร์ XY-MD02 ที่สื่อสารแบบ RS485 ที่เสร็จสมบรูณ์แล้ว
โค้ดการทดลอง
โค้ดนี้เป็นโค้ดการทำงานของ Arduino OPTA ที่รับค่าแสงจากเซ็นเซอร์ LDR และค่าอุณหภูมิและความชื้นจากบเซ็นเซอร์ XY-MD02 ที่สื่อสารแบบ RS485 โดยจะส่งข่อมูลไปที่ MQTT ละสามารถเปิด/ปิดไป LED ได้จาก Unity ที่เสร็จสมบรูณ์แล้ว
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include "arduino_secrets.h"
#include <ArduinoModbus.h>
#include <ArduinoRS485.h>
int LED_Pin = D2;
#define LDR_Pin A0
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;
String device_id = "SENSORS";
const char* mqtt_server = "0.tcp.ap.ngrok.io";
const int mqtt_port = 17493;
const char* mqtt_user = "Nattanit";
const char* mqtt_password = "1234";
const char* mqtt_clientId = "clientId-UJ4PTJOEzd";
const char* topic_publish = "M2MQTT_Unity/sensor/LDR";
const char* topic_subscribe = "M2MQTT_Unity/LED";
const char* topic_temperature = "M2MQTT_Unity/sensor/temperature";
const char* topic_humidity = "M2MQTT_Unity/sensor/humidity";
WiFiClient wifiClient;
PubSubClient mqtt_client(wifiClient);
constexpr auto baudrate { 9600 };
constexpr auto bitduration { 1.f / baudrate };
constexpr auto preDelayBR { bitduration * 9.6f * 3.5f * 1e6 };
constexpr auto postDelayBR { bitduration * 9.6f * 3.5f * 1e6 };
unsigned long CurrentMillis, PreviousMillis, DataSendingTime = 1000;
byte lightStatus;
void setup() {
Serial.begin(115200);
pinMode(LED_Pin, OUTPUT);
Serial.println("\n\nWelcome to OPTA\n");
setup_wifi();
mqtt_client.setServer(mqtt_server, mqtt_port);
mqtt_client.setCallback(callback);
mqtt_connect();
mqtt_subscribe(topic_subscribe);
RS485.setDelays(preDelayBR, postDelayBR);
if (!ModbusRTUClient.begin(baudrate, SERIAL_8E1)) {
Serial.println("Failed to start Modbus RTU Client!");
while (1);
}
}
void loop() {
if (!mqtt_client.loop()) {
mqtt_connect();
}
mqtt_client.loop();
int LDR_Value = analogRead(LDR_Pin);
if (LDR_Value == 0) {
Serial.println("\n\nFailed to read from LDR sensor!");
} else {
Serial.println("\n\nLDR Value: " + String(LDR_Value));
Serial.println("Light: " + String(lightStatus) + " " + String(lightStatus == 1 ? "ON" : "OFF"));
delay(3000);
CurrentMillis = millis();
if (CurrentMillis - PreviousMillis > DataSendingTime) {
PreviousMillis = CurrentMillis;
String pkt = "{";
pkt += "\"device_id\": \"SENSORS\", ";
pkt += "\"type\": \"Light\", ";
pkt += "\"value\": " + String(LDR_Value) + "";
pkt += "}";
mqtt_publish((char*) pkt.c_str());
Serial.println();
readInputRegisterValues();
}
}
}
void setup_wifi() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void mqtt_connect() {
while (!mqtt_client.connected()) {
Serial.println("Attempting MQTT connection...");
if (mqtt_client.connect(mqtt_clientId, mqtt_user, mqtt_password)) {
Serial.println("MQTT Client Connected");
mqtt_publish((char*)("Hi from " + device_id).c_str());
mqtt_subscribe(topic_subscribe);
} else {
Serial.print("failed, rc=");
Serial.print(mqtt_client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void mqtt_publish(char * data) {
mqtt_connect();
if (mqtt_client.publish(topic_publish, data)) {
Serial.println("Publish \"" + String(data) + "\" ok");
} else {
Serial.println("Publish \"" + String(data) + "\" failed");
}
}
void mqtt_publish_temperature(float temperature) {
char buf[8]; // เก็บข้อมูลที่ได้จากการแปลง
// แปลงค่า float เป็น string ที่มี 2 ตำแหน่งทศนิยม
String temperatureString = String(temperature, 2);
DynamicJsonDocument doc(128);
doc["device_id"] = "SENSORS";
doc["type"] = "Temperature";
doc["value"] = temperatureString;
char jsonBuffer[128];
serializeJson(doc, jsonBuffer);
mqtt_connect();
if (mqtt_client.publish(topic_temperature, jsonBuffer)) {
Serial.println("Publish \"" + String(jsonBuffer) + "\" ok");
} else {
Serial.println("Publish \"" + String(jsonBuffer) + "\" failed");
}
}
void mqtt_publish_humidity(float humidity) {
char buf[8]; // เก็บข้อมูลที่ได้จากการแปลง
// แปลงค่า float เป็น string ที่มี 2 ตำแหน่งทศนิยม
String humidityString = String(humidity, 2);
DynamicJsonDocument doc(128);
doc["device_id"] = "SENSORS";
doc["type"] = "Humidity";
doc["value"] = humidityString;
char jsonBuffer[128];
serializeJson(doc, jsonBuffer);
mqtt_connect();
if (mqtt_client.publish(topic_humidity, jsonBuffer)) {
Serial.println("Publish \"" + String(jsonBuffer) + "\" ok");
} else {
Serial.println("Publish \"" + String(jsonBuffer) + "\" failed");
}
}
void mqtt_subscribe(const char * topic) {
if (mqtt_client.subscribe(topic)) {
Serial.println("Subscribe \"" + String(topic) + "\" ok");
} else {
Serial.println("Subscribe \"" + String(topic) + "\" failed");
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String command;
Serial.print("\n\nMessage arrived [");
Serial.print(topic);
Serial.println("] ");
for (int i = 0; i < length; i++) {
command += (char)payload[i];
}
if (command.length() > 0) {
Serial.println("Command received is : " + command);
}
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, command);
if (error) {
Serial.print("Failed to parse JSON: ");
Serial.println(error.c_str());
return;
}
JsonObject obj = doc.as<JsonObject>();
String id = obj["device_id"];
String type = obj["type"];
String value = obj["value"];
Serial.println("\nCommand device_id is : " + id);
Serial.println("Command type is : " + type);
Serial.println("Command value is : " + value);
if (id == device_id && type == "LED") {
if (value == "1") {
lightStatus = 1;
digitalWrite(LED_Pin, HIGH);
} else {
lightStatus = 0;
digitalWrite(LED_Pin, LOW);
}
}
}
void readInputRegisterValues() {
DynamicJsonDocument doc(1024);
if (!ModbusRTUClient.requestFrom(2, INPUT_REGISTERS , 0x01, 1)) {
Serial.print("Read temperature failed! ");
Serial.println(ModbusRTUClient.lastError());
} else {
int16_t temperature_raw = ModbusRTUClient.read();
float temperature = temperature_raw / 10.0;
Serial.print("Temperature: ");
Serial.print(temperature, 2);
Serial.println(" °C\t");
doc["temperature"] = temperature;
char jsonBuffer[128];
serializeJson(doc, jsonBuffer);
mqtt_publish_temperature(temperature);
while (ModbusRTUClient.available()) {
Serial.print(ModbusRTUClient.read());
Serial.print(' ');
}
Serial.println();
}
if (!ModbusRTUClient.requestFrom(2, INPUT_REGISTERS , 0x02, 1)) {
Serial.print("Read humidity failed! ");
Serial.println(ModbusRTUClient.lastError());
} else {
uint16_t humidity_raw = ModbusRTUClient.read();
float humidity = humidity_raw / 10.0;
Serial.print("Humidity: ");
Serial.print(humidity, 2);
Serial.println(" %");
doc["humidity"] = humidity;
char jsonBuffer[128];
serializeJson(doc, jsonBuffer);
mqtt_publish_humidity(humidity);
while (ModbusRTUClient.available()) {
Serial.print(ModbusRTUClient.read());
Serial.print(' ');
}
Serial.println();
}
}
ไฟล์ arduino_secrets.h
#define SECRET_SSID " your_SSID" //ชื่อ WiFi
#define SECRET_PASS " your_PASSWORD" //รหัส WiFi
สิ่งที่ได้เรียนรู้
- การเขียนโค้ดควบคุมเซ็นเซอร์ XY-MD02 โดยใช้การสื่อสารแบบ RS485 อ่านทั้งค่าอุณหภูมิและความชื้น
1 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ช่วงเช้าจัดทำรูปเล่มรายงาน
- ช่วงบ่ายทดลองใช้แขนกล โดยควบคุมให้หยิบขวดน้ำจากจุดที่ 1 ไปยังจุดที่ 2 และนำกลับมาวางไว้ที่จุดที่ 1 และทำซ้ำไปเรื่อยๆ
สิ่งที่ได้เรียนรู้
- การใช้งานแขนกล
- วิธีการควบคุม อุปกรณ์หรือเครื่องมือต่างๆที่สามารถทำได้
- ได้ทดลองเขียนโปรแกรมควบคุมแขนกล
2 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- จัดทำรูปเล่มรายงาน
สิ่งที่ได้เรียนรู้
- การใช้งานเครื่องมือใน Word ที่โปรมากขึ้น
- วิธีการจัดเรียนหน้า การใส่หัวข้อ
3 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ช่วงเช้าทำรูปเล่มรายงาน
- ช่วงบ่ายทดลองเล่น HoloLens โดยทดลองเล่นการหยิบจับ 3D เคลื่อนไหวไปมา ย่อ ขยาย
สิ่งที่ได้เรียนรู้
- การใช้งาน HoloLens วิธีการควบคุม การใช้งานเบื้องต้น
- ได้ทดลอง HoloLens มีลักษณะอย่างไร ทำงานอย่างไร
4 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- จัดทำรูปเล่มรายงาน
5 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- จัดทำรูปเล่ม
8 กรกฎาคม 2567
งานที่ทำในวันนี้
- จัดระบบสายไฟที่ต่อกับ Arduino OPTA ที่ใช้ในงานวัด AR ให้เป็นระเบียบมากขึ้น และลกอุปกรณ์ที่ไม่จำเป็นออก
- ทดลองให้ Unity ที่ใข้ Tools MRTK3 ในการควบคุม การเปิด/ปิดไฟกับ Arduino OPTA ที่สื่อสารกันผ่าน MQTT
สิ่งที่ได้เรียนรู้
- การลดรูปแบบวงจรให้น้อยลง
- การเขียนโค้ดให้ทำงานร่วมกับ Unity ผ่าน MQTT
9 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ทดลองใช้ Arduino OPTA ควบคุมรถผ่าน MQTT ให้สามารถสั่งการได้จาก Hololens
- ศึกษาอุปกรณ์ที่ใช้ติดตั้งรถ
- ทดลองเขียนโค้ดควบคุมมอเตอร์
ปัญหาที่พบ
- ติดปัญหาล้อหมุนช้า เนื่องจากมีล้อบางอันของรถหลวม และไม่เท่ากัน
สิ่งที่ได้เรียนรู้
- การเขียนโค้ดควบคุมมอเตอร์ผ่าน MQTT
- ศึกษาหาข้อมูลของอุปกรณ์ต่างที่ใช้ในการควบคุมรถ
10 กรกฎาคม 2567
งานที่ทำในวันนี้
- ทดลองเขียนโค้ดควบคุมรถต่อ โดยวันนี้ทั้งสองล้อสามารถทำงานได้แล้ว
- สามารถสั่งการจาก MQTT ได้
- หาโมดูลที่จะนำมาประกอบกับ Arduino OPTA กับ เซ็นเซอร์แสง และอุณหภมิ ที่ใช้รับค่าจาก Unity เพื่อไปแสดงข้อมูลของวัด
ปัญหาที่พบ
- ไม่เจอโมดูลที่สามารถใช้กับขนาด LED ที่ต้องการ
สิ่งที่ได้เรียนรู้
- การเขียนโปรแกรมให้สามารถควบคุมมอเตอร์ และทำงารร่วมกับ MQTT
11 กรกฎาคม 2567
งานที่ทำในวันนี้
- ทำการทดลองต่อ โดยทำการเขียนโค้ดควบคุมมอเตอร์ให้ไปข้างหน้า ซ้าย ขวา และถอยหลัง
- ทำการทดลองให้ Arduino OPTA เชื่อมต่อเชื่อต่อกับกับ MQTT แบบ Web Socket Secure
ปัญหาที่พบ
- ยังไม่สามารถวิ่งถอยหลังได้ ทำให้ต้องหาข้อมูลว่าต้องใช้อุปกรณ์อะไรมาช่วยเสริมให้รถสามารถวิ่งถอยหลังได้
- ยังไม่เจอโมดูลที่สามารถใช้กับขนาด LED ที่ต้องการ
- ไม่สามารถเชื่อต่อ Arduino OPTA เข้าเก็บ Web Socket Secure เนื่องจากไม่มีไลบรารีมาลองรับ
สิ่งที่ได้เรียนรู้
- การเขียนโปรแกรมควบคุมมอเตอร์ให้ขยับซ้าย ขวา
- ได้ทดลองเขียนโปรแกรมให้ Arduino OPTA ใช้งานกับ Web Socket Secure
12 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ทดลองใช้ Arduino OPTA ควบคุมรถผ่าน MQTT ให้สามารถสั่งการได้จาก hololens โดยเพิ่ม Motor Drive Module L298N เข้าไปเพื่อให้สามารถทำให้ตัวรถวิ่งถอยหลังได้
- ปรับแก้ไขโค้ดเพื่อให้สามารถทำงานได้
สิ่งที่ได้เรียนรู้
- การใช้งาน Motor Drive Module L298N
15 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ศึกษาการใช้ 3D Printer
- ค้นหาโมเดลรางสแตนเรท
- ทดลองปริ้น DIN Rail stand เพื่อที่จะนำมาประกอบกับสแตนเลสสำหรับเป็นรางให้ Arduino OPTA ในงานและเซ็นเซอร์สำหรับงานวัด AR
- ทดลองใช้ Unity ให้สามารถอัปโหลดลง Hololens
ปัญหาที่พบ
- เมื่อลองทำ Unity ตามคริป บางอย่างใน Unity ไม่เหมือนกับคริปที่กำลังทดลองทำ ทำให้ต้องทดลองเวอร์ชั่นต่างๆใหม่
สิ่งที่ได้เรียนรู้
- การใช้เครื่อง 3D Printer
- การใช้โปรแกรม UltiMaker Cura
- การใช้งาน Unity การตั้งค่าต่างๆที่เอาไว้ใช้สำหรับการใช้งานกับ HoloLens
- การเลือกใช้งานของพลาสติกชนิดต่างๆ
16 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ค้นหาโมเดลที่ใช้สำหรับการทำเป็นกรอบไว้ใส่ไฟ LED ที่ใช้เปิดปิดไฟของงานวัด AR Temple
- ค้นหาโมเดลที่ใช้ยึดเครื่องปริ้น 3D
- ทดลองใช้ Unity ให้สามารถอัปโหลดลง HoloLens ต่อ
ปัญหาที่พบ
- ไม่เจอโมดูลที่สามารถใช้กับขนาด LED ที่ต้องการ
- เมื่อลองลง Unity ใหม่แล้ว พบปัญหากับ Visual Studio 2022 ติดปัญหาปุ่มที่ใช้สำหรับการเชื่อต่อเข้ากับ HoloLens ไม่มีเหมือนในคลิป ทำให้ต้องลองลงหลายๆเวอร์ชั่น
สิ่งที่ได้เรียนรู้
- การใช้งาน Unity
- การอัปโหลดและการตั้งค่าต่างๆใน Unity ที่ใช้เชื่อมต่อกับ HoloLens
- การตั้งค่าต่างๆใน Visual Studio 2022 ที่ใช้เชื่อมต่อกับ HoloLens
17 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ออกแบบตัวจับสำหรับการยึดหลอดไฟ LED เข้ากับราง
- หาโมเดลสำหรับการยึดตัวจับ LED เข้ากับรางสแตรนเรท
- ทดลองควบคุม รถ ที่ควบคุมจาก Arduino OPTA จาก MQTT และควบคุมการเคลื่อนไหวจาก HoloLens
สิ่งที่ได้เรียนรู้
- การออกแบบโมเดล 3D ที่ใช้สำหรับยึด LED
18 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ออกแบบตัวจับสำหรับการยึดหลอดไฟ LED เข้ากับราง
- หาโมเดลสำหรับการยึดตัวจับ LED เข้ากับราง
ปัญหาที่พบ
- เมื่อออกแบบตัวยึด LED มาแล้ว คำนวญด้านการใส่ผิดทำให้ต้องหาโมเดลที่ใช้ยึดเข้ากับรางใหม่
- โมเดลที่หาได้ส่วนใหญ่มีขนาดใหญ่เกินไป และไม่สามารถแก้ไขขนาดได้
สิ่งที่ได้เรียนรู้
- การออกแบบที่ต้องใช้การความคิดที่ถี่ถ้วนมากขึ้น
19 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ปรับแก้โมเดลตัวยึด LED และ โมเดลสำหรับการยึดเข้ากับราง
- ทดลองประกอบโมเดล (เสร็จเรียบร้อย)
สิ่งที่ได้เรียนรู้
- การออกแบบโมเดลต่างๆ
22 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ทดลองให้ Arduino OPTA เชื่อมต่อกับ MQTT แบบ Web Socket Secure
- ทดลองการเขียนไลบรารีเพื่อให้ใช้งานกับ Web Socket Secure
ปัญหาที่พบ
- เมื่อทดลองให้ Arduino OPTA เชื่อมต่อกับ Web Socket Secure ไม่สามารถเชื่อมต่อได้ หรือเมื่อเชื่อมต่อได้ ไม่สามารถเข้าถึง Broker ได้
- เมื่อลองเขียนไลบรารียังไม่สามารถใช้งานได้ เนื่องจากขาดองค์ประกอบหลายอย่าง
สิ่งที่ได้เรียนรู้
- การใช้ mosquitto ในการเชื่อมต่อกับ MQTT
23 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ทดลองให้ Arduino OPTA เชื่อต่อกับ MQTT แบบ Web Socket ก่อนที่จะไปทำแบบ Web Socket Secure
- ทดลองให้ Arduino OPTA การควบคุมผ่าน Hololens โดยสื่อสารกันผ่าน MQTT
ปัญหาที่พบ
- Arduino OPTA ยังไม่สามารถเชื่อมต่อแบบ Web Socket ได้ เนื่องจากการไม่สามารถเรียกใช้บรารี่ websocket client เพราะ Arduino OPTA ไม่รองรับ
- เมื่อลงให้ Hololens ควบคุม Arduino OPTA แล้วพบว่าไม่สามารถถอยหลังได้ เนื่องจากสายที่เชื่อมต่อจากมอเตอร์ขาด
สิ่งที่ได้เรียนรู้
- ข้อมูลที่ไลบรารี websocket client ใช้ในการเขียนกับ ESP32
25 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ซ่อมสายจากมอเตอร์ที่ขาด
- ทดลองใช้ ESP32 ในการเชื่อต่อกับ Web Socket และ Web Socket Secure
- ทดลองใช้ Arduino OPTA กับ HoloLens ในการควบคุมรถผ่าน MQTT
ปัญหาที่พบ
- เมื่ออัปโหลดโค้ดไปแล้วไม่สามารถเชื่อต่อกับ Broker ของ MQTT ที่เชื่อมต่อผ่าน Port 8080 และProt 443ได้
สิ่งที่ได้เรียนรู้
- การเขียนโปรแกรม ESP32 เพื่อเชื่อต่อกับ Web Socket และ Web Socket Secure
26 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- ทดลองเขียน Arduino OPTA กับ Web Socket และ Web Socket Secure
ปัญหาที่พบ
- Arduino OPTA ติดปัญหาการเข้าถึงไลบรารีที่ใช้เชื่อต่อกับ Web Socket และ Web Socket Secure
- เมื่ออัปโหลดโค้ดไปแล้วไม่สามารถเชื่อต่อกับ Broker ของ MQTT ที่เชื่อมต่อผ่าน Port 8080 และProt 443ได้
สิ่งที่ได้เรียนรู้
- Arduino OPTA สามารถสื่อสารได้แค่แบบ TCP
30 กรกฎษคม 2567
สิ่งที่ได้ทำในวันนี้
- จัดทำสไลด์สำหรับพรีเซ็นสรุปฝึกงาน
- แก้ไขโค้ดรถให้สมบรูณ์
- ทดลองการทำงานของระบบวัด AR
โค้ดการทดลอง
โค้ดนี้เป็นการใช้ Arduino OPTA ในการรับคำสั่งจาก HoloLens ในการควบคุมการเคลื่อนที่ของรถ โดยใช้การสื่อสารผ่าน MQTT
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include "arduino_secrets.h"
const int LEFT_MOTOR_IN1 = D0; // Left Motor Input 1
const int LEFT_MOTOR_IN2 = D1; // Left Motor Input 2
const int RIGHT_MOTOR_IN3 = D2; // Right Motor Input 3
const int RIGHT_MOTOR_IN4 = D3; // Right Motor Input 4
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;
String device_id = "MOTORS";
const char* mqtt_server = "0.tcp.ap.ngrok.io";
const int mqtt_port = 15683;
const char* mqtt_user = "Unity";
const char* mqtt_password = "1234";
const char* mqtt_clientId = " "; // Unique MQTT client ID
const char* topic_subscribe = "M2MQTT_Unity/robot/control";
WiFiClient wifiClient;
PubSubClient mqtt_client(wifiClient);
void setup() {
Serial.begin(115200);
pinMode(LEFT_MOTOR_IN1, OUTPUT);
pinMode(LEFT_MOTOR_IN2, OUTPUT);
pinMode(RIGHT_MOTOR_IN3, OUTPUT);
pinMode(RIGHT_MOTOR_IN4, OUTPUT);
Serial.println("\n\nWelcome to OPTA\n");
setup_wifi();
mqtt_client.setServer(mqtt_server, mqtt_port);
mqtt_client.setCallback(callback);
mqtt_connect();
mqtt_subscribe(topic_subscribe);
}
void loop() {
if (!mqtt_client.connected()) {
mqtt_connect();
}
mqtt_client.loop();
}
void setup_wifi() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void mqtt_connect() {
while (!mqtt_client.connected()) {
Serial.println("Attempting MQTT connection...");
if (mqtt_client.connect(mqtt_clientId, mqtt_user, mqtt_password)) {
Serial.println("MQTT Client Connected");
mqtt_subscribe(topic_subscribe);
} else {
Serial.print("failed, rc=");
Serial.print(mqtt_client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void mqtt_subscribe(const char* topic) {
if (mqtt_client.subscribe(topic)) {
Serial.println("Subscribe \"" + String(topic) + "\" ok");
} else {
Serial.println("Subscribe \"" + String(topic) + "\" failed");
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String command;
Serial.print("\n\nMessage arrived [");
Serial.print(topic);
Serial.println("] ");
for (int i = 0; i < length; i++) {
command += (char)payload[i];
}
if (command.length() > 0) {
Serial.println("Command received is : " + command);
}
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, command);
if (error) {
Serial.print("Failed to parse JSON: ");
Serial.println(error.c_str());
return;
}
String id = doc["device_id"];
String type = doc["type"];
String value = doc["value"];
Serial.println("\nCommand device_id is : " + id);
Serial.println("Command type is : " + type);
Serial.println("Command value is : " + value);
if (id == device_id && type == "CONTROL" && value == "stop") {
stopMoving();
return;
}
if (id == device_id && type == "CONTROL") {
if (value == "left") {
moveLeft();
} else if (value == "right") {
moveRight();
} else if (value == "forward") {
moveForward();
} else if (value == "backward") {
moveBackward();
}
}
}
void moveRight() {
digitalWrite(LEFT_MOTOR_IN1, LOW); // Stop left motor
digitalWrite(LEFT_MOTOR_IN2, LOW); // Stop left motor
digitalWrite(RIGHT_MOTOR_IN3, HIGH); // Right motor forward
digitalWrite(RIGHT_MOTOR_IN4, LOW); // Right motor forward
delay(500); // Replace with millis() for non-blocking delay
stopMoving();
}
void moveLeft() {
digitalWrite(LEFT_MOTOR_IN1, HIGH); // Left motor forward
digitalWrite(LEFT_MOTOR_IN2, LOW); // Left motor forward
digitalWrite(RIGHT_MOTOR_IN3, LOW); // Stop right motor
digitalWrite(RIGHT_MOTOR_IN4, LOW); // Stop right motor
delay(500); // Replace with millis() for non-blocking delay
stopMoving();
}
void moveForward() {
digitalWrite(LEFT_MOTOR_IN1, HIGH);
digitalWrite(LEFT_MOTOR_IN2, LOW);
digitalWrite(RIGHT_MOTOR_IN3, HIGH);
digitalWrite(RIGHT_MOTOR_IN4, LOW);
delay(500); // Replace with millis() for non-blocking delay
stopMoving();
}
void moveBackward() {
digitalWrite(LEFT_MOTOR_IN1, LOW);
digitalWrite(LEFT_MOTOR_IN2, HIGH);
digitalWrite(RIGHT_MOTOR_IN3, LOW);
digitalWrite(RIGHT_MOTOR_IN4, HIGH);
delay(500); // Replace with millis() for non-blocking delay
stopMoving();
}
void stopMoving() {
digitalWrite(LEFT_MOTOR_IN1, LOW);
digitalWrite(LEFT_MOTOR_IN2, LOW);
digitalWrite(RIGHT_MOTOR_IN3, LOW);
digitalWrite(RIGHT_MOTOR_IN4, LOW);
}
ไฟล์ arduino_secrets.h
#define SECRET_SSID " your_SSID" //ชื่อ WiFi
#define SECRET_PASS " your_PASSWORD" //รหัส WiFi
ปัญหาที่พบ
- รถมีการวิ่งสลับซ้าย ขวา เมื่อกดปุ่มซ้ายรถวิ่งไปทางขวา เนื่องจากโค้ดกำหนดให้เมื่อกดซ้ายมอเตอร์ด้านซ้ายทำงาน เมื่อกดปุ่มขวารถวิ่งไปทางซ้าย เนื่องจากโค้ดกำหนดให้เมื่อกดขวามอเตอร์ด้านขวาทำงาน
สิ่งที่ได้เรียนรู้
- การขวบคุมมอเตอร์ในการวิ่งซ้าย ขวา
31 กรกฎาคม 2567
งานที่ได้ทำในวันนี้
- เขียนบล็อกและจะตกแต่งบล็อก
- ถ่ายวีดีโอการทดลอง
- แก้ไขสไลด์
- นำเสนองาน