1. การสื่อสารข้อมูลที่ตรวจสอบความถูกต้องและแม่นยำด้วย CRC
  2. ความสำคัญของ CRC กับการสื่อสารข้อมูล
  3. หลักการทำงานของ CRC
  4. ตัวอย่างการใช้ Python และ pyserial ในการสื่อสารผ่าน RS-232 และ RS-485
  5. การประยุกต์ใช้ CRC ใน Python
  6. การทดสอบการสื่อสาร 100 ครั้ง
  7. การตั้งบัฟเฟอร์เพื่อการจัดการข้อมูล
  8. ตัวอย่างการคำนวณ CRC สำหรับ MODBUS
  9. การสื่อสารผ่านโปรโตคอล MQTT ด้วยการตรวจสอบ CRC
  10. การใช้งาน CRC ในโปรโตคอล MQTT
    • ฝั่งผู้ส่ง (Broker)
    • ฝั่งผู้รับ (Subscriber)
  11. การใช้งาน CRC ใน Arduino
  12. สรุป

 

การสื่อสารข้อมูลที่มุ่งเน้นการตรวจสอบความถูกต้องและแม่นยำมีความสำคัญอย่างยิ่งในระบบอิเล็กทรอนิกส์และไมโครคอนโทรลเลอร์ (MCU) โดยใช้เทคนิค CRC (Cyclic Redundancy Check) เพื่อป้องกันข้อผิดพลาดที่อาจเกิดขึ้นระหว่างการสื่อสาร วิธีการนี้ช่วยให้มั่นใจว่าข้อมูลที่ส่งไปยัง MCU และข้อมูลที่รับกลับมามีความถูกต้อง

ความสำคัญของ CRC กับ การสื่อสารข้อมูล

การสื่อสารข้อมูลที่เชื่อถือได้ในระบบอิเล็กทรอนิกส์เป็นสิ่งจำเป็น CRC เป็นเทคนิคที่ใช้ตรวจสอบความถูกต้องของข้อมูลที่รับส่งเพื่อป้องกันข้อผิดพลาดที่อาจเกิดขึ้น

หลักการทำงานของ CRC

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

ตัวอย่างการใช้ Python และ pyserial ในการสื่อสารผ่าน RS-232 และ RS-485

เพื่อให้มั่นใจว่าการรับส่งข้อมูลถูกต้องและครบถ้วน คุณสามารถใช้ Python และไลบรารี pyserial สำหรับการสื่อสารกับ Inverter ต่อไปนี้คือตัวอย่างโค้ด :

python

import serial
import time

# กำหนดพอร์ตอนุกรมและ baudrate
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)

def send_command(command):
    ser.write(command)
    time.sleep(0.1)

def read_response(expected_length):
    buffer = bytearray()
    while True:
        if ser.in_waiting:
            buffer.extend(ser.read(ser.in_waiting))
        if len(buffer) >= expected_length:
            break
        time.sleep(0.01)
    return buffer

if __name__ == '__main__':
    # ตัวอย่างคำสั่งสำหรับ Inverter
    command = b'\x01\x03\x00\x00\x00\x10\x14\x0B'  # ตรวจสอบคำสั่งให้ถูกต้องตามโปรโตคอลของ Inverter
    expected_length = 37  # กำหนดความยาวข้อมูลที่คาดว่าจะได้รับ

    send_command(command)
    response = read_response(expected_length)
   
    if response:
        print(f'Received data: {response}')
    else:
        print('No data received')

    ser.close()

การประยุกต์ใช้ CRC ใน Python

การใช้ Python และไลบรารี pyserial เราสามารถสร้างฟังก์ชันสำหรับคำนวณและตรวจสอบค่า CRC เพื่อรับรองความถูกต้องของข้อมูล ตัวอย่างโค้ดต่อไปนี้แสดงวิธีการเพิ่มค่า CRC ไปยังข้อมูลที่ส่ง และตรวจสอบค่า CRC ของข้อมูลที่รับกลับมา:

python

import serial
import time

# กำหนดพอร์ตอนุกรมและ baudrate
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)

def calculate_crc(data):
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for _ in range(8):
            if crc & 1:
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc

def append_crc(data):
    crc = calculate_crc(data)
    return data + bytes([crc & 0xFF, (crc >> 8) & 0xFF])

def check_crc(response):
    received_crc = (response[-1] << 8) | response[-2]
    calculated_crc = calculate_crc(response[:-2])
    return received_crc == calculated_crc

def send_command_with_crc(command):
    command_with_crc = append_crc(command)
    ser.write(command_with_crc)

def read_response(expected_length):
    buffer = bytearray()
    while len(buffer) < expected_length + 2:
        if ser.in_waiting:
            buffer.extend(ser.read(ser.in_waiting))
        time.sleep(0.01)
    return buffer

if __name__ == '__main__':
    command = b'COMMAND'  # คำสั่งที่ต้องการทดสอบ
    success_count = 0
    total_tests = 100

    for _ in range(total_tests):
        send_command_with_crc(command)
        response = read_response(len(command))
        if check_crc(response):
            if response[:-2] == command:
                success_count += 1

    print(f'Successful transmissions: {success_count}/{total_tests}')
    ser.close()

 

สรุป

การใช้ CRC ในการสื่อสารข้อมูลช่วยเพิ่มความน่าเชื่อถือและความถูกต้องของข้อมูลที่รับส่งผ่านพอร์ตอนุกรม โดยเฉพาะในระบบที่ต้องการความมั่นใจในความถูกต้องของข้อมูลที่ส่งและรับ

การใช้ CRC ในการสื่อสารข้อมูลผ่านพอร์ตอนุกรม

การใช้ CRC ในการตรวจสอบความถูกต้องของข้อมูลเป็นวิธีที่มีประสิทธิภาพในการเพิ่มความน่าเชื่อถือของระบบสื่อสาร โดยเฉพาะอย่างยิ่งในการสื่อสารผ่านพอร์ตอนุกรม (Serial Port) ที่มีการใช้งานอย่างแพร่หลายในระบบอิเล็กทรอนิกส์และไมโครคอนโทรลเลอร์ (MCU)

ความสำคัญของการตรวจสอบความถูกต้องในข้อมูลการสื่อสาร

การสื่อสารข้อมูลที่มีความถูกต้องและแม่นยำเป็นสิ่งจำเป็นสำหรับระบบอิเล็กทรอนิกส์และไมโครคอนโทรลเลอร์ โดยเฉพาะเมื่อมีข้อกำหนดในการส่งและรับข้อมูลที่ต้องไม่มีข้อผิดพลาด การใช้ CRC ช่วยเพิ่มความมั่นใจในการสื่อสารข้อมูล ลดโอกาสเกิดข้อผิดพลาด และ ทำให้ระบบมีความน่าเชื่อถือมากขึ้น

ตัวอย่างการใช้ CRC ใน Python

การใช้ CRC ในการสื่อสารผ่านพอร์ตอนุกรมในภาษา Python สามารถทำได้โดยการคำนวณค่า CRC ของข้อมูล เพิ่มค่า CRC ไปยังข้อมูลที่ส่ง และตรวจสอบค่า CRC ของข้อมูลที่รับกลับมา ต่อไปนี้คือตัวอย่างโค้ดที่แสดงให้เห็นถึงวิธีการคำนวณและตรวจสอบค่า CRC:

python

import serial
import time

# กำหนดพอร์ตอนุกรมและ baudrate
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)

def calculate_crc(data):
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for _ in range(8):
            if crc & 1:
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc

def append_crc(data):
    crc = calculate_crc(data)
    return data + bytes([crc & 0xFF, (crc >> 8) & 0xFF])

def check_crc(response):
    received_crc = (response[-1] << 8) | response[-2]
    calculated_crc = calculate_crc(response[:-2])
    return received_crc == calculated_crc

def send_command_with_crc(command):
    command_with_crc = append_crc(command)
    ser.write(command_with_crc)

def read_response(expected_length):
    buffer = bytearray()
    while len(buffer) < expected_length + 2:
        if ser.in_waiting:
            buffer.extend(ser.read(ser.in_waiting))
        time.sleep(0.01)
    return buffer

if __name__ == '__main__':
    command = b'COMMAND'  # คำสั่งที่ต้องการทดสอบ
    success_count = 0
    total_tests = 100

    for _ in range(total_tests):
        send_command_with_crc(command)
        response = read_response(len(command))
        if check_crc(response):
            if response[:-2] == command:
                success_count += 1

    print(f'Successful transmissions: {success_count}/{total_tests}')
    ser.close()

การทดสอบการสื่อสาร 100 ครั้ง

เพื่อให้มั่นใจว่าการสื่อสารมีความถูกต้องและเสถียร สามารถทำการทดสอบโดยการส่งคำสั่งไปยัง MCU และรับข้อมูลกลับมา 100 ครั้ง พร้อมตรวจสอบความถูกต้องของข้อมูลในแต่ละครั้ง วิธีนี้ช่วยให้คุณสามารถประเมินและปรับปรุงระบบสื่อสารของคุณได้อย่างมีประสิทธิภาพ

การตั้งบัฟเฟอร์เพื่อการจัดการข้อมูล

ในการสื่อสารผ่านพอร์ตอนุกรม การตั้งบัฟเฟอร์เป็นสิ่งสำคัญเพื่อจัดการข้อมูลที่รับเข้ามาและป้องกันการสูญหายของข้อมูล นอกจากนี้ การใช้การตรวจสอบค่าควบคุม (checksum) หรือการตรวจสอบความถูกต้องของข้อมูล (error checking) เช่น CRC สามารถช่วยให้มั่นใจได้ว่าข้อมูลที่รับส่งมีความถูกต้องและไม่มีข้อผิดพลาดในการสื่อสาร

ตัวอย่างการคำนวณ CRC สำหรับ MODBUS

การคำนวณ CRC สำหรับโปรโตคอล MODBUS ซึ่งใช้กันอย่างแพร่หลายใน Inverter หลายรุ่น:

python

การสื่อสารผ่านโปรโตคอล MQTT ด้วยการตรวจสอบ CRC

การตรวจสอบความถูกต้องของข้อมูลเมื่อใช้โปรโตคอล MQTT สามารถทำได้โดยใช้การยืนยันความถูกต้องของข้อมูล (data integrity) ที่จัดเตรียมโดย MQTT เอง แม้ว่า MQTT ไม่ได้มีการตรวจสอบ CRC ในตัว แต่คุณสามารถเพิ่มการตรวจสอบ CRC ในข้อมูลเพย์โหลด (payload) ก่อนที่จะส่งไปยังโบรกเกอร์ MQTT

ตัวอย่างโค้ดใน Python สำหรับ MQTT

Broker

python

import paho.mqtt.client as mqtt
import struct

def calculate_crc(data):
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for _ in range(8):
            if crc & 1:
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc

def on_connect(client, userdata, flags, rc):
    print("Connected with result code " + str(rc))
    payload = b'Hello, MQTT!'
    crc = calculate_crc(payload)
    payload_with_crc = payload + struct.pack('<H', crc)
    client.publish("test/topic", payload_with_crc)

client = mqtt.Client()
client.on_connect = on_connect
client.connect("mqtt.eclipse.org", 1883, 60)
client.loop_forever()

Subscriber

python

import paho.mqtt.client as mqtt
import struct

def calculate_crc(data):
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for _ in range(8):
            if crc & 1:
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc

def on_message(client, userdata, msg):
    payload = msg.payload
    received_crc = struct.unpack('<H', payload[-2:])[0]
    data = payload[:-2]
    calculated_crc = calculate_crc(data)
    if received_crc == calculated_crc:
        print("Received valid data:", data)
    else:
        print("Received data with invalid CRC")

client = mqtt.Client()
client.on_message = on_message
client.connect("mqtt.eclipse.org", 1883, 60)
client.subscribe("test/topic")
client.loop_forever()

สรุป

การใช้ CRC ในการสื่อสารข้อมูลผ่านพอร์ตอนุกรมและโปรโตคอล MQTT เป็นวิธีที่มีประสิทธิภาพในการตรวจสอบและรับรองความถูกต้องของข้อมูล ช่วยให้ระบบมีความน่าเชื่อถือและเสถียรมากขึ้น

การตรวจสอบความถูกต้องของข้อมูลในระบบอิเล็กทรอนิกส์และไมโครคอนโทรลเลอร์

การตรวจสอบความถูกต้องของข้อมูลที่ส่งและรับเป็นสิ่งสำคัญอย่างยิ่งในระบบอิเล็กทรอนิกส์และไมโครคอนโทรลเลอร์ (MCU) ไม่ว่าจะเป็นการสื่อสารผ่านพอร์ตอนุกรม (Serial Port) หรือโปรโตคอลการสื่อสารอื่นๆ การใช้เทคนิคต่างๆ เช่น CRC (Cyclic Redundancy Check) ช่วยเพิ่มความน่าเชื่อถือของข้อมูลและลดโอกาสเกิดข้อผิดพลาดได้

ตัวอย่างการใช้งาน CRC ในการสื่อสารข้อมูล

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

ตัวอย่างการคำนวณและตรวจสอบ CRC สำหรับการสื่อสารผ่านพอร์ตอนุกรม

python

 

import serial
import time

# กำหนดพอร์ตอนุกรมและ baudrate
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)

def calculate_crc(data):
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for _ in range(8):
            if crc & 1:
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc

def append_crc(data):
    crc = calculate_crc(data)
    return data + bytes([crc & 0xFF, (crc >> 8) & 0xFF])

def check_crc(response):
    received_crc = (response[-1] << 8) | response[-2]
    calculated_crc = calculate_crc(response[:-2])
    return received_crc == calculated_crc

def send_command_with_crc(command):
    command_with_crc = append_crc(command)
    ser.write(command_with_crc)

def read_response(expected_length):
    buffer = bytearray()
    while len(buffer) < expected_length + 2:
        if ser.in_waiting:
            buffer.extend(ser.read(ser.in_waiting))
        time.sleep(0.01)
    return buffer

if __name__ == '__main__':
    command = b'COMMAND'  # คำสั่งที่ต้องการทดสอบ
    success_count = 0
    total_tests = 100

    for _ in range(total_tests):
        send_command_with_crc(command)
        response = read_response(len(command))
        if check_crc(response):
            if response[:-2] == command:
                success_count += 1

    print(f'Successful transmissions: {success_count}/{total_tests}')
    ser.close()


การใช้งาน CRC ในโปรโตคอล MQTT

การตรวจสอบความถูกต้องของข้อมูลในโปรโตคอล MQTT สามารถทำได้โดยการเพิ่มการตรวจสอบ CRC ในข้อมูลเพย์โหลด (payload) ก่อนที่จะส่งไปยังโบรกเกอร์ MQTT โดยมีตัวอย่างโค้ดดังนี้:

ฝั่งผู้ส่ง (Broker)

python

 

import paho.mqtt.client as mqtt
import struct

def calculate_crc(data):
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for _ in range(8):
            if crc & 1:
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc

def on_connect(client, userdata, flags, rc):
    print("Connected with result code " + str(rc))
    payload = b'Hello, MQTT!'
    crc = calculate_crc(payload)
    payload_with_crc = payload + struct.pack('<H', crc)
    client.publish("test/topic", payload_with_crc)

client = mqtt.Client()
client.on_connect = on_connect
client.connect("mqtt.eclipse.org", 1883, 60)
client.loop_forever()


ฝั่งผู้รับ (Subscriber)

python

 

import paho.mqtt.client as mqtt
import struct

def calculate_crc(data):
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for _ in range(8):
            if crc & 1:
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc

def on_message(client, userdata, msg):
    payload = msg.payload
    received_crc = struct.unpack('<H', payload[-2:])[0]
    data = payload[:-2]
    calculated_crc = calculate_crc(data)
    if received_crc == calculated_crc:
        print("Received valid data:", data)
    else:
        print("Received data with invalid CRC")

client = mqtt.Client()
client.on_message = on_message
client.connect("mqtt.eclipse.org", 1883, 60)
client.subscribe("test/topic")
client.loop_forever()

 

การใช้งาน CRC ใน Arduino

สำหรับการสื่อสารระหว่าง Arduino และ Inverter หรืออุปกรณ์อื่นๆ การใช้ CRC ช่วยให้การสื่อสารมีความถูกต้องและเสถียรมากขึ้น โดยสามารถใช้งานได้ดังนี้:

ตัวอย่างโค้ดบน Arduino

cpp

#include <SoftwareSerial.h>

// กำหนดพอร์ตอนุกรม
SoftwareSerial mySerial(10, 11); // RX, TX

// ฟังก์ชันคำนวณ CRC
unsigned int calculateCRC(byte *array, int length) {
    unsigned int crc = 0xFFFF;
    for (int pos = 0; pos < length; pos++) {
        crc ^= (unsigned int)array[pos];
        for (int i = 8; i != 0; i--) {
            if ((crc & 0x0001) != 0) {
                crc >>= 1;
                crc ^= 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

// ฟังก์ชันส่งคำสั่งพร้อม CRC
void sendCommand(byte *command, int length) {
    unsigned int crc = calculateCRC(command, length);
    command[length] = crc & 0xFF;
    command[length + 1] = (crc >> 8) & 0xFF;
    mySerial.write(command, length + 2);
}

// ฟังก์ชันอ่านและตรวจสอบ CRC
bool checkCRC(byte *response, int length) {
    unsigned int receivedCRC = (response[length - 1] << 8) | response[length - 2];
    unsigned int calculatedCRC = calculateCRC(response, length - 2);
    return receivedCRC == calculatedCRC;
}

void setup() {
    Serial.begin(9600);
    mySerial.begin(9600);

    // คำสั่งตัวอย่างสำหรับ Inverter
    byte command[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x10};
    sendCommand(command, sizeof(command));

    delay(1000);
    byte response[37];
    int index = 0;

    // รับข้อมูล
    while (mySerial.available() && index < sizeof(response)) {
        response[index++] = mySerial.read();
    }

    // ตรวจสอบ CRC
    if (checkCRC(response, index)) {
        Serial.println("Received valid data:");
        for (int i = 0; i < index; i++) {
            Serial.print(response[i], HEX);
            Serial.print(" ");
        }
        Serial.println();
    } else {
        Serial.println("Received data with invalid CRC");
    }
}

void loop() {
    // ว่างเปล่า
}

สรุป

การตรวจสอบความถูกต้องของข้อมูลด้วย CRC เป็นวิธีที่มีประสิทธิภาพในการเพิ่มความน่าเชื่อถือและเสถียรภาพของการสื่อสารข้อมูลในระบบอิเล็กทรอนิกส์และไมโครคอนโทรลเลอร์ การใช้ CRC สามารถนำมาใช้ได้ในหลายโปรโตคอลการสื่อสาร เช่น พอร์ตอนุกรม (Serial Port), MQTT, และการสื่อสารกับอุปกรณ์อื่นๆ ผ่าน Arduino ซึ่งจะช่วยให้ระบบมีความมั่นใจในความถูกต้องของข้อมูลที่รับและส่ง