ต่อใช้งาน Arduino กับเซ็นเซอร์วัดการสั่นสะเทือน SN-3003-WZ-N01 ผ่าน RS485
ต่อใช้งาน Arduino กับเซ็นเซอร์วัดการสั่นสะเทือน SN-3003-WZ-N01 ผ่าน RS485
บทความนี้เหมาะกับคนที่กำลังหาเซ็นเซอร์วัดการสั่นสะเทือนไปติดตั้งที่เครื่องจักรจริง โดยเฉพาะงาน Predictive Maintenance หรือการบำรุงรักษาเชิงพยากรณ์ ที่ต้องการเฝ้าติดตามสุขภาพของมอเตอร์ ปั๊มน้ำขนาดใหญ่ หรือโครงสร้างอาคาร
เซ็นเซอร์ SN-3003-WZ-N01 ตัวนี้วัดการสั่นสะเทือนแบบ 3 แกน X Y Z ครอบคลุมความถี่ 10-1600Hz ส่งข้อมูลผ่านพอร์ต RS485 ด้วยโปรโตคอล Modbus RTU ตัวหัวดูดแม่เหล็กทำให้ติดตั้งเข้ากับตัวเครื่องจักรได้ทันทีโดยไม่ต้องเจาะ นี่คือจุดที่ทำให้มันแตกต่างจากเซ็นเซอร์วัดการสั่นสะเทือนแบบธรรมดาที่ขายในไทย
อุปกรณ์ที่ต้องเตรียม
| อุปกรณ์ | จำนวน | หมายเหตุ |
|---|---|---|
| Arduino UNO R3 | 1 ชุด | พร้อมสาย USB |
| MAX485 Module | 1 ชุด | ตัวแปลง TTL เป็น RS485 |
| หัวแจ็ง 2.1×5.5mm | 1 ชุด | ต่อ DC Jack |
| อะแดปเตอร์ 12V 5A | 1 ชุด | จ่ายไฟให้เซ็นเซอร์ |
| อะแดปเตอร์ 9V 2A | 1 ชุด | จ่ายไฟให้ Arduino |
| สายจัมเปอร์ ผู้-ผู้ | 20 เส้น | |
| สายจัมเปอร์ ผู้-เมีย | 20 เส้น | |
| สายจัมเปอร์ เมีย-เมีย | 10 เส้น | |
| OLED 128×64 I2C | 1 จอ | แสดงผลค่าที่อ่านได้ |
| บอร์ดทดลอง MB-102 | 1 แผ่น | ช่วยจัดวงจร |
วงจรการต่อสาย
ส่วนที่ 1: Arduino กับ MAX485
Arduino UNO R3 → MAX485 Module
────────────────────────────────
5V → VCC
GND → GND
D2 (RX) → RO (Receiver Output)
D3 (TX) → DI (Driver Input)
D7 → DE (Driver Enable)
D8 → RE (Receiver Enable)
ส่วนที่ 2: SN-3003-WZ-N01 กับ MAX485
SN-3003-WZ-N01 → MAX485 Module
──────────────────────────────
สายสีน้ำเงิน (B) → B
สายสีเหลือง (A) → A
หมายเหตุ สีสาย A กับ B อาจต่างกันตามผู้ผลิต ถ้าอ่านค่าไม่ได้ให้ลองสลับ A กับ B ดู
ส่วนที่ 3: จ่ายไฟให้เซ็นเซอร์
SN-3003-WZ-N01 → แหล่งจ่ายไฟ 12V DC
──────────────────────────────
สายสีน้ำตาล → ไฟบวก (+)
สายสีดำ → ไฟลบ (-)
ส่วนที่ 4: OLED Display
Arduino UNO R3 → OLED 128×64 I2C
────────────────────────────────
5V → VCC
GND → GND
A4 → SDA
A5 → SCL
ข้อสำคัญ ต้องต่อ GND ร่วมกันทั้งหมด ทั้ง Arduino, MAX485 และแหล่งจ่ายไฟ 12V ไม่งั้นสัญญาณ RS485 จะอ่านค่าผิด
ติดตั้ง Library ที่จำเป็น
โปรเจคนี้ต้องใช้ Library สำหรับ OLED กับ SoftwareSerial ของผู้เขียนบทความต้นฉบับ ดาวน์โหลดได้จาก MediaFire แล้วแตกไฟล์ไปไว้ที่โฟลเดอร์ libraries ของ Arduino IDE
This PC > Documents > Arduino > libraries
ถ้ายังไม่เคยลง Library ดูวิธีละเอียดได้จากบทความ “สอนใช้งาน Arduino ติดตั้ง Library ในโปรแกรม Arduino IDE เชื่อมต่อกับ Sensor ต่างๆ”
โครงสร้างข้อมูล Modbus RTU สำหรับ SN-3003-WZ-N01
เซ็นเซอร์รุ่นนี้สื่อสารด้วย Modbus RTU บน RS485 โดยมี Register Map ดังนี้ (ตัวอย่างที่อ้างอิงจาก spec ของเซ็นเซอร์ประเภทนี้)
| Register | ข้อมูล |
|---|---|
| 0x0000 | อุณหภูมิ (Temperature) |
| 0x0001 | ความเร็วแกน X (Velocity X) |
| 0x0002 | ความเร็วแกน Y (Velocity Y) |
| 0x0003 | ความเร็วแกน Z (Velocity Z) |
| 0x0004 | ความเร่งแกน X (Acceleration X) |
| 0x0005 | ความเร่งแกน Y (Acceleration Y) |
| 0x0006 | ความเร่งแกน Z (Acceleration Z) |
โค้ดสำหรับอ่านค่าการสั่นสะเทือน
#include <SoftwareSerial.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ============================================
// ตั้งค่า SoftwareSerial สำหรับ RS485
// ============================================
#define RS485_TX_PIN 3
#define RS485_RX_PIN 2
#define RS485_DE_PIN 7 // Driver Enable
#define RS485_RE_PIN 8 // Receiver Enable
// ============================================
// ตั้งค่า Modbus
// ============================================
#define SENSOR_ADDR 0x01
#define BAUD_RATE 9600
// ============================================
// ตั้งค่า OLED
// ============================================
#define OLED_ADDR 0x3C
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
SoftwareSerial rs485(RS485_RX_PIN, RS485_TX_PIN);
// ============================================
// ฟังก์ชันส่งคำสั่ง Modbus RTU
// ============================================
void sendModbusRequest(byte functionCode, unsigned int startReg, int qty) {
// ปิด Driver Enable ก่อนส่ง
digitalWrite(RS485_DE_PIN, HIGH);
digitalWrite(RS485_RE_PIN, HIGH);
byte data[8];
data[0] = SENSOR_ADDR;
data[1] = functionCode;
data[2] = highByte(startReg);
data[3] = lowByte(startReg);
data[4] = highByte(qty);
data[5] = lowByte(qty);
// คำนวณ CRC16
unsigned int crc = calcCRC(data, 6);
data[6] = lowByte(crc);
data[7] = highByte(crc);
delayMicroseconds(50);
rs485.write(data, 8);
rs485.flush();
// สลับเป็นโหมดรับ
digitalWrite(RS485_DE_PIN, LOW);
digitalWrite(RS485_RE_PIN, LOW);
}
// ============================================
// ฟังก์ชันอ่านค่าจาก Sensor
// ============================================
bool readModbusResponse(float &temp, float &velX, float &velY, float &velZ,
float &accX, float &accY, float &accZ) {
if (rs485.available() < 21) {
return false;
}
byte response[21];
int len = 0;
unsigned long start = millis();
while (rs485.available() && len < 21) {
response[len++] = rs485.read();
if (millis() - start > 1000) break;
}
if (len < 21) return false;
// ตรวจสอบ CRC
unsigned int crcCalc = calcCRC(response, len - 2);
unsigned int crcRecv = word(response[len - 1], response[len - 2]);
if (crcCalc != crcRecv) {
Serial.println("CRC Error");
return false;
}
// ถอดค่าจาก Register (ขึ้นกับ Data Type ของ Sensor)
// ค่าตัวอย่าง - แปลง raw data เป็น engineering value
// ปรับค่าตัวคูณ (multiplier) ตาม spec ของเซ็นเซอร์จริง
temp = (int16_t)word(response[3], response[4]) / 10.0;
velX = (int16_t)word(response[5], response[6]) / 100.0;
velY = (int16_t)word(response[7], response[8]) / 100.0;
velZ = (int16_t)word(response[9], response[10]) / 100.0;
accX = (int16_t)word(response[11], response[12]) / 1000.0;
accY = (int16_t)word(response[13], response[14]) / 1000.0;
accZ = (int16_t)word(response[15], response[16]) / 1000.0;
return true;
}
// ============================================
// ฟังก์ชันคำนวณ CRC16 Modbus
// ============================================
unsigned int calcCRC(byte *data, int length) {
unsigned int crc = 0xFFFF;
for (int i = 0; i < length; i++) {
crc ^= data[i];
for (int j = 0; j < 8; j++) {
if (crc & 0x0001) {
crc = (crc >> 1) ^ 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
// ============================================
// ฟังก์ชันแสดงผลบน OLED
// ============================================
void displayData(float temp, float velX, float velY, float velZ,
float accX, float accY, float accZ) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("=== Vibration Sensor ===");
display.print("Temp: "); display.print(temp, 1); display.println(" C");
display.print("Vel X:"); display.print(velX, 2); display.println(" mm/s");
display.print("Vel Y:"); display.print(velY, 2); display.println(" mm/s");
display.print("Vel Z:"); display.print(velZ, 2); display.println(" mm/s");
display.print("Acc X:"); display.print(accX, 3); display.println(" g");
display.print("Acc Y:"); display.print(accY, 3); display.println(" g");
display.print("Acc Z:"); display.print(accZ, 3); display.println(" g");
display.display();
}
// ============================================
// Setup
// ============================================
void setup() {
Serial.begin(9600);
rs485.begin(BAUD_RATE);
pinMode(RS485_DE_PIN, OUTPUT);
pinMode(RS485_RE_PIN, OUTPUT);
digitalWrite(RS485_DE_PIN, LOW);
digitalWrite(RS485_RE_PIN, LOW);
// OLED init
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Waiting sensor...");
display.display();
Serial.println("Modbus RS485 Vibration Sensor Ready");
}
// ============================================
// Loop
// ============================================
void loop() {
float temp, velX, velY, velZ, accX, accY, accZ;
// Function Code 0x04: Read Input Registers
sendModbusRequest(0x04, 0x0000, 7);
if (readModbusResponse(temp, velX, velY, velZ, accX, accY, accZ)) {
// แสดงผลบน Serial Monitor
Serial.print("Temp: "); Serial.print(temp, 1);
Serial.print(" Vel(X,Y,Z): ");
Serial.print(velX, 2); Serial.print(", ");
Serial.print(velY, 2); Serial.print(", ");
Serial.print(velZ, 2);
Serial.print(" Acc(X,Y,Z): ");
Serial.print(accX, 3); Serial.print(", ");
Serial.print(accY, 3); Serial.print(", ");
Serial.print(accZ, 3);
Serial.println();
// แสดงผลบน OLED
displayData(temp, velX, velY, velZ, accX, accY, accZ);
}
delay(500);
}
จุดที่ต้องปรับตาม Spec จริง
- ค่าตัวคูณ (Scaling Factor) ค่าที่แปลงในโค้ดข้างต้นใช้
/100.0สำหรับ Velocity และ/1000.0สำหรับ Acceleration แต่ค่าจริงอาจต่างกัน ต้องเทียบกับคู่มือเซ็นเซอร์ - จำนวน Byte ที่ตอบกลับ โค้ดนี้รอ 21 bytes แต่ถ้าเซ็นเซอร์ตอบกลับค่าต่างกัน ให้ปรับเงื่อนไข
rs485.available() < 21และการถอดค่าให้ตรง - Register Address ที่อยู่ Register ที่ให้ไว้เป็นตัวอย่าง ควรตรวจสอบจาก Data Sheet ของรุ่นที่ซื้อ
วิธี Upload และดูผลลัพธ์
- คัดลอกโค้ดไปวางใน Arduino IDE
- เลือก Board: Tools → Board → Arduino UNO
- เลือก Port: Tools → Port → COM ที่เชื่อมต่อ
- กด Upload จากเมนู Sketch
- เปิด Serial Monitor ตั้ง Baud Rate เป็น 9600
- สังเกตค่าอุณหภูมิ ความเร็ว และความเร่ง 3 แกน แสดงทั้งบน Serial Monitor และจอ OLED
ทดสอบเซ็นเซอร์ด้วยลมร้อน
วิธีง่ายที่สุดในการตรวจสอบว่าเซ็นเซอร์ทำงานถูกต้อง คือใช้ไดร์เป่าผมเป่าลมร้อนไปที่หัวแม่เหล็กของเซ็นเซอร์ โดยวางไดร์เป่าผมให้สัมผัสพื้น จากนั้นสังเกตว่า
- ค่า อุณหภูมิ ที่เซ็นเซอร์วัดได้เพิ่มขึ้น
- ค่า ความเร็ว และ ความเร่ง 3 แกน เปลี่ยนไปตามแรงสั่นสะเทือนที่เกิดขึ้นจากลมร้อน
ถ้าค่าเปลี่ยนแปรตามแรงสั่น แสดงว่าวงจรและโค้ดทำงานถูกต้อง ถ้าไม่เปลี่ยนให้ตรวจสอบการต่อสาย A B หรือลองสลับดู
ความถี่ที่ควรรู้
การสั่นสะเทือนของเครื่องจักรส่วนใหญ่จะอยู่ในช่วง 10-1600Hz ซึ่งเป็นย่านที่ SN-3003-WZ-N01 ครอบคลุม ถ้าต้องการวิเคราะห์เชิงลึก เช่น ดูว่าความถี่ใดเกิดขึ้นเป็นพิเศษ (Fault Frequency) อาจต้องใช้ FFT หรือเก็บข้อมูลไปวิเคราะห์เพิ่มเติมด้วย Python หรือ MATLAB
วิดีโออ้างอิง
อยากทำโปรเจคแบบนี้?
รับทำโปรเจค Arduino / IoT จบงานไว ส่งงานครบ พร้อมสอน
หากต้องการ รับทำโปรเจคอาดูโน่ หรือระบบ IoT แบบเร่งด่วน สามารถดูรายละเอียดบริการได้ที่หน้าแรก
จ้างทำโปรเจคเลย