ตารางคำสั่งเฉพาะ
Note
หน้านี้ใช้กับกล่องเสียงที่เป็นค่าตั้งต้นจากโรงงาน ซึ่งพูดภาษาเฉพาะของผู้ผลิต ไม่ใช่ Modbus
ตัวที่ทางร้านจำหน่ายเป็น Modbus ดูหน้านั้นแทน หน้านี้มีไว้เผื่อเครื่องที่ได้มาจากที่อื่น หรือตอนที่หน้า Modbus ยิงแล้วเงียบ
ตั้งค่าพอร์ต
ค่า |
|
|---|---|
ความเร็ว |
9600 |
ข้อมูล · หยุด · พาริตี้ |
8 · 1 · ไม่มี |
ใช้ได้กับ |
RS232 และ RS485 |
โครงเฟรม
ยาว 7 ไบต์เสมอ ทั้งขาส่งและขาตอบ
0 1 2 3 4 5 6
┌────┬──────┬────────┬───────┬───────┬─────┬────┐
│ 01 │ 51 │โฟลเดอร์│ 00 │ความดัง│ XOR │ 02 │
└────┴──────┴────────┴───────┴───────┴─────┴────┘
│ │ │ │ │ │ │
│ │ │ │ │ │ └── ไบต์ปิดท้าย ตายตัว
│ │ │ │ │ └──────── XOR ของไบต์ 0 ถึง 4
│ │ │ │ └─────────────── 00 ถึง 1C คือ 0-28
│ │ │ └─────────────────────── ไม่ได้ใช้ ใส่ 00
│ │ └──────────────────────────────── 00 ถึง FF คือ 0-255
│ └───────────────────────────────────────── 51 สั่ง · 52 คำตอบ
└─────────────────────────────────────────────── ไบต์เริ่ม ตายตัว
Important
ส่งโฟลเดอร์กับความดังไปพร้อมกันในเฟรมเดียวจบ
ต่างจาก Modbus ที่ต้องส่งสองเฟรม แบบนี้สั้นกว่าและเร็วกว่า
Warning
🔴 ไม่มีคำสั่งอ่านค่ากลับ
โปรโตคอลนี้สั่งได้อย่างเดียว อ่านไม่ได้ จะรู้ว่าลำโพงตั้งไว้เท่าไร ต้องจำเองในโปรแกรม
ถ้าโปรแกรมรีสตาร์ท จะไม่มีทางรู้ว่าลำโพงกำลังเล่นอะไรอยู่ — ให้สั่งหยุดทันทีที่เริ่มโปรแกรม เพื่อกลับสู่สถานะที่รู้แน่นอน
XOR
เอาไบต์ที่ 0 ถึง 4 มา XOR กันทั้งหมด ได้ไบต์เดียว
def xor8(data):
v = 0
for b in data:
v ^= b
return v
def frame(folder, volume):
body = [0x01, 0x51, folder & 0xFF, 0x00, volume & 0xFF]
return bytes(body + [xor8(body), 0x02])
Tip
XOR ตรวจได้อ่อนกว่า CRC16 มาก — สลับตำแหน่งสองไบต์แล้ว XOR ยังเท่าเดิม จับไม่ได้
บนสายที่ยาวหรือมีสัญญาณรบกวน Modbus จึงน่าเชื่อถือกว่า ถ้าเลือกได้ให้สั่งซื้อแบบ Modbus
ตัวอย่างเฟรม
ทุกเฟรมข้างล่างนี้คำนวณด้วยโปรแกรม ไม่ได้พิมพ์มือ สองอันแรกตรงกับตัวอย่างในคู่มือทุกไบต์
ทำอะไร |
ส่ง |
ลำโพงตอบ |
|---|---|---|
เล่น |
|
|
เล่น |
|
|
หยุด |
|
|
🔴 กับดักเสียงสะท้อน
Danger
คำสั่งกับคำตอบต่างกันแค่ไบต์เดียว — 51 กับ 52
สาย RS485 บางเส้นสะท้อนสิ่งที่เราส่งกลับมาเอง ถ้าโค้ดเช็กแค่ว่า "มีอะไรกลับมาไหม" จะนึกว่าลำโพงตอบแล้ว ทั้งที่ลำโพงอาจไม่ได้ต่ออยู่ด้วยซ้ำ
ต้องเช็กว่าไบต์ที่สองเป็น 52 ถ้าได้ 51 แปลว่าเป็นเสียงสะท้อน
ไม่ใช่คำตอบ
def is_real_reply(frame, sent_folder):
if len(frame) != 7:
return False
if frame[1] != 0x52: # 51 คือคำสั่งเราเอง สะท้อนกลับมา
return False
if frame[2] != sent_folder: # ต้องเป็นโฟลเดอร์ที่เราสั่งไป
return False
return frame[5] == xor8(frame[:5])
ตรวจโค้ดก่อนต่อของจริง
พิมพ์เฟรมที่โปรแกรมสร้างออกมาเทียบกับตารางข้างบนก่อนเสียบของจริง
Warning
เลือกภาษาผิดจะเงียบสนิท ไม่มีข้อความผิดพลาด
ถ้ายิงเฟรมจากหน้านี้แล้วไม่มีอะไรตอบ ให้ลองแบบ Modbusดู ก่อนจะไปไล่หาปัญหาที่สายไฟ