مدونة د.خلدون عرفة للروبوتيك
بروتوكولات نقل البيانات
في عالم الأنظمة المدمجة والروبوتات الحديثة، تعتبر القدرة على التواصل بين المتحكمات والمكونات الذكية هي قلب كل مشروع ناجح. من الحساسات الدقيقة إلى الشاشات عالية السرعة، ومن وحدات البلوتوث إلى الذاكرة الخارجية، كل جهاز يعتمد على بروتوكول اتصال فعال لضمان نقل البيانات بسرعة ودقة وموثوقية فالبروتوكولات الأكثر استخدامًا في هذا المجال هي UART, I²C و SPIفالبساطة والموثوقية لمسافات طويلة UART و الأسلاك القليلة وإمكانية توصيل عدة أجهزة I²C و السرعة العالية والدقة المثلى لنقل البيانات الكبيرة SPI.
بروتوكول I2C
I2C (Inter-Integrated Circuit) هو بروتوكول تسلسلي (Serial Communication Protocol) اخترعته شركة Philips سنة 1982 فكرته تعتمد على خطين فقط:
SCL (Serial Clock Line): خط الساعة، يحدد توقيت نقل البيانات.SDA (Serial Data Line): خط البيانات، يتم عبره تبادل البتات.
المميزات العميقة والنادرة في I2C
- نظام Multi-Master: ليس "ماستر واحد وبقية عبيد"، I2C يسمح بوجود أكثر من Master بنفس الوقت. إذا كان الأرسال مع بعض، البروتوكول فيه آلية Arbitration (تحكيم) تقوم بتحديد أي ماستر له الأولوية بدون تضارب . هذه الميزة نادرة و تدع I2C مناسب للأنظمة المعقدة.
- الـ Clock Stretching: الأجهزة البطيئة ممكن توقف الماستر عن طريق إبقاء خط الساعة منخفض، هذه التقنية تقوم بالمحافظة على التزامن وبتمنع فقدان البيانات، وليس كل بروتوكول يدعم هذه المرونة.
- Address Resolution Protocol (ARP): من الأشياء الأقل شهرة إن I2C عنده بروتوكول فرعي لإدارة العناوين التلقائية. يعني بعض الأجهزة تقوم "تفاوض" على العنوان إذا وجد فيه تضارب عناوين.
- استخدامه في مجالات حساسة:
في الشاشات (Display Data Channel – DDC)، بروتوكول I2C هو اللي بيخلي الكمبيوتر يتعرف على نوع الشاشة ودقتها تلقائياً.
المميزات العميقة والنادرة في I2C
- Start Condition: الماستر يسحب خط SDA لأسفل بينما SCL عالي → إشارة بدء.
- Address Frame: الماستر يرسل عنوان الجهاز (7 أو 10 بت).
- Read/Write Bit: يحدد إذا الماستر بده يقرأ أو يكتب.
- ACK/NACK: الجهاز العبد يرد بإشارة تأكيد أو رفض.
- Data Transfer: يتم تبادل البيانات بتات بتات.
- Stop Condition: الماستر يرفع SDA بينما SCL عالي → إشارة انتهاء.
العيوب :
- أبطأ من SPI لما تحتاج نقل بيانات ضخمة جداً.
- طول الأسلاك محدود (عادة أقل من مترين بسرعات عالية).
- احتمالية حدوث تضارب إذا ما تم إدارة العناوين بشكل صحيح.
- أعماق بروتوكول I2C
بروتوكولات مبنية على I2C
- SMBus (System Management Bus): مستخدم بالـ PC لمراقبة البطارية، الحرارة، الفولتية.
- PMBus (Power Management Bus): للتحكم بمصادر الطاقة الذكية.
- DDC (Display Data Channel): بين الشاشة وكرت الشاشة عشان يعرف الـ EDID (الدقة، معدل التحديث).
- TWI (Two Wire Interface): نفس I2C لكن بمسميات مختلفة (مثلاً في AVR).
المزامنة والـ Clock Stretching بعمق
بعض الـ Master ما بيدعموها (مثلاً في بعض المتحكمات الرخيصة)، وهذا يسبب مشاكل توافق.
الأجهزة المتقدمة (زي الـ Raspberry Pi) تدعم Clock Stretching لكن بسرعات محددة.
الأمان والمشاكل الواقعية
Noise Sensitivity: بما إنه خط واحد مش تفاضلي مثل CAN، ممكن يتأثر بالتشويش (EMI). لذلك يستخدم بكثافة داخل البوردات، مش بالكابلات الطويلة.
Bus Lockup: إذا Device عمل Hold دائم على SDA → الباص كله يتجمد.
الحل: Reset الـ Slave.
أو فصل SDA/SCL لحظياً عبر MOSFET Switch
تطبيقات متقدمة نادرة
- Memories: EEPROM و RTC (ساعة حقيقية) كلها مبنية على I2C.
- Multi-Sensor Fusion: الروبوتات بتوصل IMU، Magnetometer، Barometer بنفس الباص وتقرأ الكل بشكل متزامن.
- Configuration Chains: المعالجات الحديثة بتبرمج شرائح أخرى (مثل Power Regulators) عبر I2C مع بداية التشغيل.
اتجاهات حديثة
- أسرع (حتى 12.5 Mbps).
- أقل استهلاك طاقة.
- متوافق مع الأجهزة القديمة.
- يحل مشاكل Arbitration و Addressing
تجربة عملية بسيطة:
#include <Wire.h>
#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp;
void setup() {
Serial.begin(9600);
Wire.begin();
if (!bmp.begin()) {
Serial.println("Could not find BMP280 sensor!");
while(1);
}
}
void loop() {
Serial.print("Temperature = ");
Serial.print(bmp.readTemperature());
Serial.print(" *C | Pressure = ");
Serial.println(bmp.readPressure());
delay(1000);
}
استخدم هذا الكود في Adruino لتجربة بروتوكول I2C.
ستحتاج الى:
- حساس حرارة/ضغط (مثل BMP280 – يدعم I²C و SPI)
- شاشة OLED صغيرة (I²C أو SPI)
- أسلاك توصيل (Jumper Wires)
- مقاومات Pull-up (2.2kΩ – 10kΩ) لو استخدمنا I²C على Arduino
التوصيل:
BMP280 أو OLED:
SDA → A4 (Arduino) / GPIO 2 (Raspberry Pi)
SCL → A5 (Arduino) / GPIO 3 (Raspberry Pi)
VCC → 3.3V / 5V
GND → GND
استخدم مقاومات Pull-up على SDA و SCL إذا لزم الأمر
ملاحظة عملية:
يمكن توصيل OLED بنفس SDA/SCL لعرض البيانات مباشرة.
يمكن تجربة عدة أجهزة على نفس الخطين لمشاهدة عمل I²C Multi-Device.
بروتوكول UART
TX: لنقل البيانات من المرسل إلى المستقبل.
RX: لاستقبال البيانات من المرسل الآخر.
هيكل الفريم Frame Structure
كل بايت بينقل ضمن "فريم":
- Start Bit (دائماً 0) → إشارة بداية.
- Data Bits (5–9 عادة) → محتوى البيانات.
- Parity Bit (اختياري) → لاكتشاف الأخطاء.
- Stop Bit(s) (عادة 1 أو 2) → إنهاء الفريم.
السرعة والتزامن
الانحراف (Baud Rate Error) لازم يكون < ±2% تقريباً، وإلا بيصير Loss للبيانات.
بعض الـ UART تدعم Auto-Baud Detection: بتتعلم السرعة من أول بايت مستلم.
المميزات العميقة
يشتغل لمسافات أطول من I²C (مع RS-232 أو RS-485 ممكن يتجاوز مئات الأمتار).
يدعم Full-Duplex حقيقي، مو مثل I²C اللي Half-Duplex.
القيود
ما في Addressing داخلي: على عكس I²C.
غير مناسب لعدد كبير من الأجهزة بدون وسيط.
تطبيقات عملية واقعية
- Debugging: أغلب الميكروكنترولرات (Arduino, STM32, Raspberry Pi) تستخدم UART لعرض Logs.
- GPS Modules: تستعمل UART لإرسال البيانات (NMEA Sentences).
- Modems: قديمًا (AT Commands).
- Bluetooth HC-05 / ESP8266: واجهتها الأساسية UART.
مستويات أعمق (Industrial UART)
LIN Bus: في السيارات، مبني فوق UART لكنه يضيف Addressing وتوقيت مضبوط.
المقارنة مع I²C و UART
I²C → جهازين وأكثر، لكن مسافة قصيرة.
الفلسفة وراء UART
الهدف: تحويل البتات من متوازي (داخل المعالج) إلى تسلسلي (على خط واحد) والعكس.
لذلك، الـ UART موجود تقريبًا بكل معالج ومتحكم، وغالبًا يكون "بوابة العالم الخارجي" للمطورين.
الميزات العملية
- Full-Duplex حقيقي: إرسال واستقبال بنفس الوقت.
- Latency قليل: ما في Arbitration أو Addressing مثل I²C.
- مناسب للـ Debugging: أي متحكم عنده UART → بسهولة بتشبكه على Serial Monitor.
العيوب
- لا يوجد Addressing داخلي → يجب إضافة بروتوكول أعلى (مثلاً MODBUS).
- يدعم جهازين فقط (Point-to-Point) إلا إذا استخدمت RS-485 أو Multiplexer.
- حساس جدًا لعدم تطابق البود ريت أو التشويش.
تطبيقات متقدمة
- GPS Modules: تبعث جمل NMEA عبر UART.
- Bluetooth HC-05/HC-06: التواصل الأساسي UART.
- ESP8266/ESP32: في البداية بيتبرمجوا عبر UART.
- Modbus RTU (صناعي): بروتوكول صناعي مبني على UART/RS-485.
- Bootloaders: معظم الميكروكنترولرات تنزل برامجها عبر UART.
تجربة عملية بسيطة:
void setup() {
Serial.begin(9600); // ضبط سرعة البود
}
void loop() {
Serial.println("Hello UART!");
delay(1000);
}
ستحتاج الى:
- أسلاك توصيل (Jumper Wires)
Arduino TX → USB → Computer (Serial Monitor)
Arduino RX → إذا أردنا جهاز آخر للتبادل
ملاحظة عملية:
استخدمي Serial Monitor على Arduino IDE لمشاهدة البيانات.
يمكن ربط Arduino بـ GPS Module أو Bluetooth Module عبر نفس UART لقراءة بيانات فعلية.
بروتوكول SPI
اخترعته شركة Motorola في الثمانينات، واليوم هو العمود الفقري للتواصل بين المتحكمات والذاكرات، الشاشات، الـ ADC/DAC، وحتى أجهزة الاستشعار عالية الدقة.
ما هو SPI؟
Synchronous: فيه خط ساعة Clock يحدد التوقيت.
يعتمد على مبدأ Master–Slave: جهاز واحد Master يتحكم بالساعة، وبقية الأجهزة Slaves.
خطوط SPI الرئيسية
- MOSI (Master Out Slave In): بيانات من الماستر للعبد.
- MISO (Master In Slave Out): بيانات من العبد للماستر.
- SCLK (Serial Clock): خط الساعة من الماستر.
- SS/CS (Slave Select / Chip Select): خط اختيار العبد (Active Low).
- في نظام فيه عدة أجهزة، كل Slave يحتاج خط CS خاص به.
بنية الإطار (Frame Format)
بايت 8 بت (أحيانًا 16 أو 32).
البيانات تُرسل بت بت، متزامنة مع نبضات الساعة.
النقل يتم Full-Duplex: بنفس الوقت اللي الماستر يرسل فيه بت، يستقبل بت من الـ Slave.
السرعة (Speed)
ممكن يوصل لعشرات الـ MHz (10–100+ MHz حسب العتاد).
لذلك يُستخدم مع الذاكرات (Flash, EEPROM)، شاشات TFT، وحساسات دقيقة.
المميزات العميقة لـ SPI
سرعة عالية: مثالي للبيانات الضخمة (صور، تسجيلات).
بنية بسيطة: ما يحتاج Addressing مثل I²C.
مرونة: يدعم أي طول بيانات (8، 16، 32، حتى Streams).
العيوب
لا يوجد Addressing داخلي: كل جهاز محتاج خط CS مستقل.
مسافة قصيرة: مثل I²C، عادة أقل من 1–2 متر بسرعات عالية.
لا يوجد آلية كشف أخطاء مدمجة (لا Parity ولا ACK/NACK).
تطبيقات عملية
- الذاكرة (Memory): EEPROM, Flash, SD Cards كلها تشتغل على SPI.
- الشاشات: OLED, LCD, TFT.
- الـ ADC/DAC: للتحويل السريع بين Analog ↔️ Digital.
- الحساسات عالية الدقة: مثل Gyroscopes, Accelerometers, Temperature Sensors.
- المودمات والـ RF Modules: مثل nRF24L01, LoRa.
الأعماق الفيزيائية
إشارات SPI عادة Push-Pull، يعني الماستر يقدر يرفع ويخفض الجهد.
ما يحتاج Pull-up Resistors مثل I²C.
الاستهلاك أعلى مع السرعات العالية (لأن كل تغيير على الساعة يستهلك شحن/تفريغ).
التداخل (Crosstalk) ممكن يسبب مشاكل بسرعات >20 MHz، لذلك لازم نستخدم مسارات قصيرة + Ground Planes.
توسعات SPI
QSPI (Quad SPI): يستخدم 4 خطوط بيانات بدل MOSI/MISO → زيادة السرعة بشكل ضخم (حتى 100+ MB/s).
Dual SPI: مثل QSPI لكن بخطين.
مقارنة عميقة مع I²C و UART
| الميزة | UART | I²C | SPI |
| عدد الخطوط | 2 (TX,RX) | 2 (SDA,SCL) | 4+ (MOSI, MISO, SCLK, CS) |
| عدد الأجهزة | جهازين فقط | 100+ (Addressing) | عدة أجهزة لكن يحتاج CS لكل واحد |
| السرعة | حتى 1 Mbps | حتى 3.4 Mbps (HS Mode) | حتى 100+ Mbps |
| المزامنة | Asynchronous | Synchronous (Clock) | Synchronous (Clock) |
| Full-Duplex | نعم | لا (Half-Duplex) | نعم |
| آلية كشف الأخطاء | بت المساواة (Optional Parity Bit) | Bit-level + Ack/Nack | لا يوجد مدمج (يعتمد على بروتوكولات أعلى) |
| أفضل استخدام | اتصال بسيط بين جهازين (مثلا pc - متحكم) | شبكات من عدة مستشعرات وأجهزة ببطء نسبي | نقل بيانات سريع بين متحكم واجهزة طرفية |
| نوع الاتصال | نقطة-الى-نقطة (point-to-point) | متعدد النقاط (Multi-Master, Multi-Slave) | Master-Slave |
نصائح عملية للمهندسين
- لاختيار البروتوكول المناسب:
بيانات سريعة أو كبيرة الحجم → SPI.
مسافات طويلة أو Debugging → UART.
- التوصيل الفيزيائي:
I²C: Pull-up Resistors مهمة، الانتباه لـ Capacitance.
SPI: لكل Slave CS خاص، واستخدم مسارات قصيرة للسرعات العالية.
- إدارة الأخطاء:
I²C: ACK/NACK + Arbitration + Clock Stretching.
SPI: عادة بدون كشف أخطاء، يمكن إضافة CRC على طبقة البروتوكول العلوي
كل بروتوكول له مجاله:
UART: بساطة وموثوقية لمسافات طويلة.
I²C: مرونة بعدد الأجهزة وقلة الأسلاك.
SPI: سرعة ودقة عالية لنقل البيانات الثقيلة.
تجربة عملية بسيطة:
#include <SPI.h>
#include <Adafruit_BMP280.h>
#define BMP_CS 10
Adafruit_BMP280 bmp(BMP_CS); // SPI mode
void setup() {
Serial.begin(9600);
if (!bmp.begin()) {
Serial.println("BMP280 SPI not detected!");
while(1);
}
}
void loop() {
Serial.print("Temperature = ");
Serial.print(bmp.readTemperature());
Serial.print(" *C | Pressure = ");
Serial.println(bmp.readPressure());
delay(1000);
}
استخدم هذا الكود في Arduino لتجربة بروتوكول SPI.
ستحتاج الى:
- حساس حرارة/ضغط (مثل BMP280 – يدعم I²C و SPI)
- شاشة OLED صغيرة (I²C أو SPI)
- أسلاك توصيل (Jumper Wires)
- مقاومات Pull-up (2.2kΩ – 10kΩ) لو استخدمنا I²C على Arduino
التوصيل:
SCK → SCLK Arduino
SDI → MOSI Arduino
SDO → MISO Arduino
CS → أي Pin Digital (مثلاً D10)
VCC & GND كما سابقاً
ملاحظة عملية:
SPI أسرع من I²C → يمكن قراءة بيانات الحساس بسرعة أعلى.
إذا وصلنا أكثر من SPI Slave، لكل واحد نستخدم CS مختلف.
https://www.facebook.com/groups/arabicyoungtalentrobotics/
https://www.youtube.com/@YoungTalentRobotics
حول المقالة
-
متوسط
عندما تشترك في المدونة سنرسل لك بريدا إلكترونيا عندما تكون هناك مقالات جديدة على الموقع حتى لا تفوتها.
تعليقات