- ما هو بروتوكول الاتصال I2C؟
- كيف تعمل I2C Communication؟
- أين تستخدم اتصالات I2C؟
- I2C في اردوينو
- المكونات مطلوبة
- مخطط الرسم البياني
- شرح العمل
- برمجة I2C في اردوينو
- شرح برمجة ماستر اردوينو
- شرح برمجة الرقيق اردوينو
في برنامجنا التعليمي السابق تعلمنا عن اتصال SPI في Arduino. سنتعرف اليوم على بروتوكول اتصال تسلسلي آخر: I2C (دوائر متكاملة). بمقارنة I2C مع SPI ، فإن I2C يحتوي على سلكين فقط بينما يستخدم SPI أربعة ، ويمكن أن يكون لـ I2C متعدد رئيسي وعبد ، بينما يمكن أن يكون لـ SPI رئيس واحد وعبيد متعدد. لذلك هناك أكثر من متحكم واحد في المشروع يجب أن يكون متقنًا ثم يتم استخدام I2C. يستخدم اتصال I2C بشكل عام للتواصل مع الجيروسكوب ومقياس التسارع ومستشعرات الضغط الجوي وشاشات LED وما إلى ذلك.
في هذا البرنامج التعليمي الخاص بـ Arduino I2C ، سنستخدم اتصال I2C بين لوحين من اردوينو ونرسل (من 0 إلى 127) قيمًا لبعضهما البعض باستخدام مقياس الجهد. سيتم عرض القيم على شاشة LCD مقاس 16 × 2 متصلة بكل من Arduino. هنا سوف يعمل أحد الأردوينو بصفة السيد والآخر يعمل كعبد. لنبدأ بمقدمة حول اتصالات I2C.
ما هو بروتوكول الاتصال I2C؟
يشير المصطلح IIC إلى " الدوائر المتكاملة المشتركة ". يُشار إليه عادةً باسم I2C أو I تربيع C أو حتى على أنه بروتوكول واجهة بسلكين (TWI) في بعض الأماكن ، لكن كل هذا يعني نفس الشيء. I2C هو بروتوكول اتصال متزامن بمعنى أن كلا الجهازين اللذين يتشاركان المعلومات يجب أن يشتركان في إشارة ساعة مشتركة. يحتوي على سلكين فقط لمشاركة المعلومات ، أحدهما يستخدم لإشارة الديك والآخر يستخدم لإرسال واستقبال البيانات.
كيف تعمل I2C Communication؟
تم تقديم اتصال I2C لأول مرة بواسطة Phillips. كما ذكرنا سابقًا أنه يحتوي على سلكين ، سيتم توصيل هذين السلكين عبر جهازين. هنا جهاز واحد يسمى رئيسي والجهاز الآخر يسمى عبد. يجب أن يحدث الاتصال وسيحدث دائمًا بين اثنين من السيد والعبد. ميزة اتصال I2C هي أنه يمكن توصيل أكثر من عبد واحد بالسيد.
يتم الاتصال الكامل من خلال هذين السلكين وهما الساعة التسلسلية (SCL) والبيانات التسلسلية (SDA).
Serial Clock (SCL): يشارك إشارة الساعة التي تم إنشاؤها بواسطة السيد مع التابع
Serial Data (SDA): يرسل البيانات من وإلى السيد والعبد.
في أي وقت من الأوقات ، لن يتمكن سوى السيد من بدء الاتصال. نظرًا لوجود أكثر من عبد واحد في الحافلة ، يتعين على السيد أن يشير إلى كل عبد باستخدام عنوان مختلف. عند مخاطبته فقط العبد بهذا العنوان المعين سيرد بالمعلومات بينما يستمر الآخرون في الإقلاع. بهذه الطريقة يمكننا استخدام نفس الناقل للتواصل مع أجهزة متعددة.
لم يتم تحديد مستويات الجهد في I2C مسبقًا. اتصال I2C مرن ، يعني أن الجهاز الذي يعمل بجهد 5 فولت ، يمكنه استخدام 5 فولت لـ I2C ويمكن للأجهزة 3.3 فولت استخدام 3 فولت لاتصالات I2C. ولكن ماذا لو احتاج جهازان يعملان بجهد كهربائي مختلف إلى الاتصال باستخدام I2C؟ A 5V I2C حافلة لا يمكن ان تكون مرتبطة مع 3.3V الجهاز. في هذه الحالة ، تُستخدم محولات الجهد لمطابقة مستويات الجهد بين ناقلتي I2C.
هناك مجموعة من الشروط التي تؤطر الصفقة. يبدأ بدء الإرسال بحافة متساقطة من SDA ، والتي يتم تعريفها على أنها حالة "START" في الرسم البياني أدناه حيث يترك Master SCL مرتفعًا مع ضبط SDA منخفض.
كما هو موضح في الرسم البياني أعلاه ،
الحافة المتساقطة لـ SDA هي مشغل الأجهزة لحالة START. بعد ذلك ، تدخل جميع الأجهزة الموجودة على نفس الحافلة في وضع الاستماع.
بنفس الطريقة ، تعمل الحافة الصاعدة لـ SDA على إيقاف الإرسال الذي يظهر على أنه حالة "STOP" في الرسم البياني أعلاه ، حيث يترك السيد SCL مرتفعًا ويطلق أيضًا SDA للارتفاع. لذا فإن ارتفاع حافة SDA يوقف الإرسال.
تشير بت R / W إلى اتجاه إرسال البايتات التالية ، إذا كانت عالية ، فهذا يعني أن العبد سينقلها وإذا كانت منخفضة ، فهذا يعني أن السيد سوف يرسل.
يتم إرسال كل بت في كل دورة ساعة ، لذلك يستغرق الأمر 8 دورات على مدار الساعة لإرسال بايت. بعد إرسال كل بايت أو استلامه ، يتم الاحتفاظ بدورة الساعة التاسعة لـ ACK / NACK (معترف به / غير معترف به). يتم إنشاء بت ACK عن طريق إما تابع أو رئيسي حسب الحالة. لبت ACK، يتم تعيين SDA إلى الأقل قبل رئيسي أو الرقيق في 9 عشر دورة على مدار الساعة. لذلك فهو منخفض يعتبر ACK وإلا NACK.
أين تستخدم اتصالات I2C؟
يستخدم اتصال I2C فقط للاتصال قصير المدى. إنه بالتأكيد موثوق إلى حد ما لأنه يحتوي على نبض ساعة متزامن لجعله ذكيًا. يستخدم هذا البروتوكول بشكل أساسي للتواصل مع المستشعر أو الأجهزة الأخرى التي يتعين عليها إرسال المعلومات إلى السيد. يكون مفيدًا جدًا عندما يتعين على المتحكم الدقيق الاتصال بالعديد من الوحدات التابعة الأخرى باستخدام الحد الأدنى من الأسلاك فقط. إذا كنت تبحث عن اتصال بعيد المدى ، فعليك تجربة RS232 وإذا كنت تبحث عن اتصال أكثر موثوقية ، فعليك تجربة بروتوكول SPI.
I2C في اردوينو
توضح الصورة أدناه دبابيس I2C الموجودة في Arduino UNO.
خط I2C | دبوس في اردوينو |
SDA | A4 |
SCL | A5 |
قبل أن نبدأ في برمجة I2C باستخدام اثنين من Arduino. نحتاج إلى التعرف على مكتبة Wire المستخدمة في Arduino IDE.
في مكتبة
1. Wire.begin (العنوان):
الاستخدام: تستخدم هذه المكتبة لإجراء اتصالات مع أجهزة I2C. قم ببدء مكتبة Wire والانضمام إلى ناقل I2C بصفتك سيدًا أو تابعًا.
العنوان: عنوان الرقيق 7 بت اختياري وإذا لم يتم تحديد العنوان ، فإنه ينضم إلى الناقل باعتباره رئيسيًا مثل هذا.
2. Wire.read ():
الاستخدام: تُستخدم هذه الوظيفة لقراءة البايت الذي تم استلامه من الجهاز الرئيسي أو التابع ، إما أنه تم نقله من جهاز تابع إلى جهاز رئيسي بعد مكالمة لطلب من () أو تم نقله من سيد إلى تابع.
3. Wire.write ():
الاستخدام: تُستخدم هذه الوظيفة لكتابة البيانات إلى جهاز تابع أو رئيسي.
Slave to Master: يكتب Slave البيانات إلى سيد عند استخدام Wire.RequestFrom () في master.
Master to Slave: للإرسال من الجهاز الرئيسي إلى الجهاز التابع ، يتم استخدام Wire.write () بين المكالمات إلى Wire.beginTransmission () و Wire.endTransmission ().
يمكن كتابة Wire.write () على النحو التالي:
- Wire.write (القيمة)
القيمة: قيمة لإرسالها على هيئة بايت واحد.
- Wire.write (سلسلة):
سلسلة: سلسلة لإرسالها كسلسلة من البايت.
- Wire.write (البيانات ، الطول):
البيانات: مصفوفة من البيانات لإرسالها على هيئة بايت
الطول: عدد البايتات المطلوب إرسالها.
4. Wire.beginTransmission (العنوان):
الاستخدام: تُستخدم هذه الوظيفة لبدء الإرسال إلى جهاز I2C بعنوان الرقيق المحدد. بعد ذلك ، قم ببناء قائمة انتظار من البايتات للإرسال باستخدام وظيفة write () ثم إرسالها عن طريق استدعاء وظيفة endTransmission () . يتم إرسال عنوان 7 بت للجهاز.
5. Wire.endTransmission () ؛
الاستخدام: تُستخدم هذه الوظيفة لإنهاء إرسال إلى جهاز تابع بدأ بواسطة startTransmission () وتنقل وحدات البايت التي تم وضعها في قائمة الانتظار بواسطة Wire.write ().
6. Wire.onRequest () ؛
الاستخدام: يتم استدعاء هذه الوظيفة عندما يطلب المعلم البيانات باستخدام Wire.requestFrom () من الجهاز التابع. هنا يمكننا تضمين وظيفة Wire.write () لإرسال البيانات إلى السيد.
7. Wire.onReceive () ؛الاستخدام: يتم استدعاء هذه الوظيفة عندما يتلقى جهاز تابع بيانات من سيد. هنا يمكننا تضمين Wire.read () ؛ وظيفة لقراءة البيانات المرسلة من السيد.
8. Wire.request From (العنوان ، الكمية) ؛
الاستخدام: تُستخدم هذه الوظيفة في الرئيسي لطلب وحدات البايت من جهاز تابع. تُستخدم الوظيفة Wire.read () لقراءة البيانات المرسلة من الجهاز التابع.
العنوان: عنوان الجهاز المكون من 7 بتات لطلب وحدات البايت منه
الكمية: عدد البايت المطلوب طلبه
المكونات مطلوبة
- اردوينو أونو (2-Nos)
- وحدة عرض 16X2 LCD
- 10K مقياس الجهد (4-Nos)
- اللوح
- توصيل الأسلاك
مخطط الرسم البياني
شرح العمل
هنا لتوضيح اتصال I2C في Arduino ، نستخدم وحدتي Arduino UNO مع شاشتين LCD 16X2 متصلتين ببعضهما البعض ونستخدم مقياسين للجهد في كل من اردوينو لتحديد قيم الإرسال (من 0 إلى 127) من السيد إلى العبد والعبد لإتقانه عن طريق تغيير مقياس فرق الجهد.
نأخذ القيمة التناظرية للإدخال في arduino pin A0 من (0 إلى 5V) باستخدام مقياس الجهد وتحويلها إلى قيمة تناظرية إلى رقمية (0 إلى 1023). ثم يتم تحويل قيم ADC هذه إلى (0 إلى 127) حيث يمكننا إرسال بيانات 7 بت فقط من خلال اتصال I2C. يتم الاتصال I2C من خلال سلكين في دبوس A4 و A5 من كلا اردوينو.
سيتم تغيير القيم في شاشة LCD الخاصة بشركة Slave Arduino عن طريق تغيير POT في الجانب الرئيسي والعكس صحيح.
برمجة I2C في اردوينو
يحتوي هذا البرنامج التعليمي على برنامجين أحدهما لـ Master Arduino والآخر لـ Slave Arduino. يتم تقديم برامج كاملة لكلا الجانبين في نهاية هذا المشروع مع فيديو توضيحي.
شرح برمجة ماستر اردوينو
1. أولاً وقبل كل شيء ، نحتاج إلى تضمين مكتبة Wire لاستخدام وظائف الاتصال I2C ومكتبة LCD لاستخدام وظائف LCD. حدد أيضًا دبابيس LCD لـ 16x2 LCD. تعرف على المزيد حول توصيل شاشة LCD مع Arduino هنا.
#تضمن
2. في الإعداد الباطل ()
- نبدأ الاتصال التسلسلي بسعر الباود 9600.
Serial.begin (9600) ؛
- بعد ذلك نبدأ اتصال I2C عند دبوس (A4 ، A5)
Wire.begin () ؛ // يبدأ اتصال I2C عند الطرف (A4 ، A5)
- بعد ذلك نقوم بتهيئة وحدة شاشة LCD في وضع 16X2 ونعرض رسالة الترحيب ويتم مسحها بعد خمس ثوانٍ.
lcd.begin (16.2) ؛ // تهيئة شاشة عرض LCD lcd.setCursor (0،0) ؛ // يعين المؤشر في السطر الأول من شاشة العرض lcd.print ("ملخص الدائرة") ؛ // يطبع CIRCUIT DIGEST في LCD.setCursor (0،1) ؛ // يعين المؤشر في السطر الثاني من شاشة العرض lcd.print ("I2C 2 ARDUINO") ؛ // يطبع I2C ARDUINO بتأخير LCD (5000) ؛ // تأخير لمدة 5 ثوانٍ lcd.clear () ؛ // يمسح شاشة LCD
3. في الحلقة الفارغة ()
- نحتاج أولاً إلى الحصول على البيانات من Slave لذلك نستخدم requestFrom () مع العنوان التابع 8 ونطلب بايت واحد
طلب الأسلاك من (8،1) ؛
تتم قراءة القيمة المستلمة باستخدام Wire.read ()
بايت MasterReceive = Wire.read () ،
- بعد ذلك ، نحتاج إلى قراءة القيمة التناظرية من اردوينو POT الرئيسي المرفق بالدبوس A0
int potvalue = analogRead (A0) ؛
نقوم بتحويل هذه القيمة من حيث البايت إلى 0 إلى 127.
بايت MasterSend = خريطة (potvalue، 0،1023،0،127) ؛
- بعد ذلك ، نحتاج إلى إرسال هذه القيم المحولة حتى نبدأ الإرسال باستخدام slave arduino بعنوان 8
Wire.beginTransmission (8) ؛ Wire.write (MasterSend) ؛ Wire.endTransmission () ؛
- بعد ذلك نعرض تلك القيم المستلمة من Arduino التابع مع تأخير قدره 500 ميكروثانية ونستقبل هذه القيم باستمرار ونعرضها.
lcd.setCursor (0،0) ؛ // يعين Currsor في السطر الأول من LCD.print (">> Master <<") ؛ // مطبوعات >> ماجستير << في LCD lcd.setCursor (0،1) ؛ // يعين المؤشر في السطر الثاني من شاشة LCD.print ("SlaveVal:") ؛ // يطبع SlaveVal: في LCD LCD.print (MasterReceive) ؛ // طباعة MasterReceive في شاشة LCD مستلمة من Slave Serial.println ("Master Received from Slave") ؛ // يطبع في Serial Monitor Serial.println (MasterReceive) ؛ تأخير (500) ؛ lcd.clear () ؛
شرح برمجة الرقيق اردوينو
1. كما هو الحال مع المعلم الرئيسي ، نحتاج أولاً إلى تضمين مكتبة Wire لاستخدام وظائف اتصال I2C ومكتبة LCD لاستخدام وظائف LCD. حدد أيضًا دبابيس LCD لـ 16x2 LCD.
#تضمن
2. في الإعداد الباطل ()
- نبدأ الاتصال التسلسلي بسعر الباود 9600.
Serial.begin (9600) ؛
- بعد ذلك نبدأ الاتصال I2C على رقم التعريف الشخصي (A4 ، A5) بعنوان تابع كـ 8. هنا من المهم تحديد عنوان الرقيق.
Wire.begin (8) ؛
بعد ذلك ، نحتاج إلى استدعاء الوظيفة عندما يتلقى Slave قيمة من السيد وعندما يطلب Master قيمة من Slave
Wire.onReceive (استقبال الحدث) ؛ Wire.onRequest (requestEvent) ؛
- بعد ذلك نقوم بتهيئة وحدة شاشة LCD في وضع 16X2 ونعرض رسالة الترحيب ويتم مسحها بعد خمس ثوانٍ.
lcd.begin (16.2) ؛ // تهيئة شاشة عرض LCD lcd.setCursor (0،0) ؛ // يعين المؤشر في السطر الأول من شاشة العرض lcd.print ("ملخص الدائرة") ؛ // يطبع CIRCUIT DIGEST في LCD.setCursor (0،1) ؛ // يعين المؤشر في السطر الثاني من شاشة العرض lcd.print ("I2C 2 ARDUINO") ؛ // يطبع I2C ARDUINO بتأخير LCD (5000) ؛ // تأخير لمدة 5 ثوانٍ lcd.clear () ؛ // يمسح شاشة LCD
3. بعد ذلك لدينا وظيفتان واحدة لحدث الطلب والأخرى لحدث الاستلام
لطلب الحدث
عند طلب Master قيمة من التابع ، سيتم تنفيذ هذه الوظيفة. تأخذ هذه الوظيفة قيمة الإدخال من Slave POT وتحولها من حيث 7 بت وترسل هذه القيمة إلى إتقانها.
طلب باطل () { int potvalue = analogRead (A0) ؛ بايت SlaveSend = خريطة (potvalue، 0،1023،0،127) ؛ Wire.write (SlaveSend) ؛ }
لتلقي الحدث
عندما يرسل Master البيانات إلى التابع بعنوان تابع (8) ، سيتم تنفيذ هذه الوظيفة. تقرأ هذه الوظيفة القيمة المستلمة من الرئيسي وتخزينها في متغير من نوع بايت .
getEvent باطل (int howMany { SlaveReceived = Wire.read ()؛ }
4. في الحلقة الفارغة ():
نعرض القيمة المستلمة من السيد باستمرار في وحدة شاشة LCD.
حلقة باطلة (باطلة) { lcd.setCursor (0،0) ؛ // يعين Currsor في السطر الأول من LCD.print (">> Slave <<") ؛ // يطبع >> الرقيق << في LCD lcd.setCursor (0،1) ؛ // يعين المؤشر في السطر الثاني من LCD.print ("MasterVal:") ؛ // يطبع MasterVal: في LCD LCD.print (SlaveReceived) ؛ // طباعة القيمة المستلمة في شاشة LCD من Master Serial.println ("Slave Received from Master:") ؛ // يطبع في Serial Monitor Serial.println (SlaveReceived) ؛ تأخير (500) ؛ lcd.clear () ؛ }
من خلال تدوير مقياس الجهد في جانب واحد ، يمكنك رؤية القيم المتغيرة على شاشة LCD على جانب آخر:
هذه هي الطريقة التي يحدث بها اتصال I2C في Arduino ، وهنا استخدمنا اثنين من Arduinos لإثبات ليس فقط إرسال البيانات ولكن أيضًا تلقي البيانات باستخدام اتصال I2C. حتى الآن يمكنك توصيل أي مستشعر I2C بـ Arduino.
يتم تقديم الترميز الكامل لـ Master و Slave Arduino أدناه مع فيديو توضيحي