modbus --- بروتوكول Modbus RTU للتابع (slave)

توفّر هذه الوحدة تنفيذًا بلغة Python خالصة لتابع (slave) Modbus RTU يتواصل عبر UART. تحتفظ بمصفوفة سجلات احتفاظ داخلية وتستجيب لرموز دوال Modbus القياسية 0x03 (قراءة سجلات الاحتفاظ) و 0x06 (كتابة سجل مفرد) و 0x10 (كتابة سجلات متعددة). يُحسب CRC-16 (متعددة حدود Modbus) باستخدام جدول بحث.

على سبيل المثال:

from machine import UART
from modbus import ModbusRTU

uart = UART(1, 115200, timeout=10, timeout_char=10)
modbus = ModbusRTU(uart, slave_id=0x01, register_num=30)

while True:
    if modbus.any():
        modbus.handle(debug=False)

class ModbusRTU

تابع (slave) Modbus RTU يقرأ الطلبات من UART، ويحدّث مصفوفة سجلاته الداخلية، ويكتب الاستجابة المقابلة مرة أخرى إلى UART.

class modbus.ModbusRTU(uart: machine.UART, slave_id: int = 0x01, register_num: int = 30)

ينشئ تابع ModbusRTU (slave).

  • uart هو نسخة UART (مثل machine.UART أو pyb.UART) تُستخدم لإرسال واستقبال إطارات Modbus. يجب تهيئة UART بمعدل الباود والتماثل والمهل المناسبة قبل تمريره.

  • slave_id هو عنوان تابع Modbus (1-247) الذي ستستجيب له هذه النسخة. تُتجاهل الإطارات الموجَّهة إلى معرّفات توابع أخرى.

  • register_num هو عدد سجلات الاحتفاظ ذات 16 بت التي تدعم هذا التابع. تُخزَّن السجلات في القائمة REGISTER وتُهيَّأ إلى صفر.

SLAVE_ID: int

عنوان تابع Modbus الذي ستستجيب له هذه النسخة. يُضبط من وسيط المُنشئ slave_id.

uart: machine.UART

نسخة UART الممرَّرة إلى المُنشئ، تُستخدم لجميع عمليات الإدخال/الإخراج.

register_num: int

عدد سجلات الاحتفاظ ذات 16 بت، يُضبط من وسيط المُنشئ register_num.

REGISTER: list[int]

قائمة بطول register_num تحتفظ بقيم السجلات الحالية ذات 16 بت. تحدّث عمليات القراءة والكتابة المنفَّذة عبر طلبات Modbus الواردة هذه القائمة. يمكن لشيفرة التطبيق القراءة من هذه القائمة أو الكتابة إليها مباشرة لتبادل البيانات مع رئيس (master) Modbus.

CRC16_TABLE: list[int]

جدول بحث محسوب مسبقًا من 256 مدخلًا لمتعددة حدود Modbus CRC-16، يُستخدم بواسطة crc16().

any() int

يُرجع عدد البايتات المتاحة حاليًا في مخزن الاستقبال المؤقت لـ UART الأساسي (يفوّض إلى uart.any()). استخدم هذا للتحقق من وجود طلب وارد قبل استدعاء handle().

clear() None

يعيد تعيين كل مدخل في REGISTER إلى 0.

crc16(data: bytes | bytearray) bytes

يحسب Modbus CRC-16 للبيانات data باستخدام CRC16_TABLE ويُرجعه ككائن bytes من بايتين بترتيب الصغير-أولًا (little-endian) مناسب للإلحاق بإطار Modbus.

  • data هو bytes/bytearray (أو أي عنصر قابل للتكرار من الأعداد الصحيحة) يحتوي على البايتات المراد حساب اختبار المجموع لها.

handle(debug: bool = False) None

يقرأ طلب Modbus مفردًا من UART، ويحدّث مصفوفة السجلات الداخلية حسب الحاجة، ويكتب الاستجابة المقابلة مرة أخرى إلى UART.

رموز الدوال المدعومة:

  • 0x03 قراءة سجلات الاحتفاظ --- يستجيب بالمدى المطلوب من قيم السجلات.

  • 0x06 كتابة سجل مفرد --- يكتب سجلًا واحدًا ويردّد العنوان والقيمة.

  • 0x10 كتابة سجلات متعددة --- يكتب مدى متصلًا من السجلات ويستجيب بعنوان البداية والعدد.

تُرجع استجابات استثناء Modbus في الحالات التالية:

  • دالة غير مشروعة (0x01) --- رمز دالة غير مدعوم.

  • عنوان بيانات غير مشروع (0x02) --- فهرس السجل خارج المدى.

  • قيمة بيانات غير مشروعة (0x03) --- عدد البايتات لا يطابق العدد المعلن للسجلات.

تُسقَط بصمت الإطارات التي لا يطابق CRC الخاص بها أو التي لا يطابق عنوان تابعها SLAVE_ID.

  • debug إذا كان True، يطبع الطلب الخام، ورمز الدالة المحلَّل، والاستجابة المولَّدة، وأي تفاصيل أخطاء إلى REPL. القيمة الافتراضية False.