دليل · I²C · تصحيح الأخطاء
مستشعر I²C لا يظهر؟ إليك الحل — بالترتيب
وصّلت مستشعر BME280 (أو شاشة OLED، أو MPU6050)، رفعت السكتش، وكانت النتيجة… لا شيء. اللوحة لا ترى المستشعر. في تسع حالات من كل عشر يكون السبب واحدًا من أربعة أمور — وكلها سريعة الفحص إذا سِرت بالترتيب الصحيح. يعمل الأمر بالطريقة نفسها على ESP32 وESP8266 وArduino.
إن أردت أن تفهم الصورة الفيزيائية لما يفعله I²C فعليًا على السلك — START وACK وتمديد النبضة — فاطّلع على الشرح التفاعلي «بايت واحد — ست نواقل». هذا المقال هو نصفه العملي: الناقل صامت، فماذا بعد؟
الخطوة 1 — امسح الناقل أولًا دائمًا
لا تصحّح الأخطاء وأنت أعمى. كل جهاز I²C يستجيب على عنوان من 7 بتات، ويمكنك أن تسأل الناقل من الموجود. ارفع هذا وافتح Serial Monitor على 115200:
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin(); // ESP8266: D2/D1 · ESP32: 21/22 · Uno: A4/A5
}
void loop() {
byte found = 0;
Serial.println("Scanning I2C bus...");
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) { // 0 = الجهاز ردّ بإشارة ACK
Serial.printf(" found device at 0x%02X\n", addr);
found++;
}
}
Serial.println(found ? "done." : "No devices found — check wiring & pull-ups.");
delay(3000);
} ثلاث نتائج — ثلاثة تشخيصات:
- ظهر عنوان مستشعرك (مثل
0x76لمستشعر BME280) — التوصيل والتغذية سليمان؛ العلة في كود المشغّل أو في عنوان خاطئ داخل المكتبة. - ظهر عنوان مختلف — لديك القطعة الخطأ أو العنوان الخطأ (كثير من اللوحات تسمح بالتبديل بين عنوانين عبر وصلة لحام).
- «No devices found» — الطبقة الكهربائية معطّلة. تابِع القراءة.
تفضّل ماسحًا على صفحة ويب بدل كابل السيريال؟ مثال RisalDash I2C-Scanner يسرد كل عنوان مع تخمين لنوع الشريحة، حيًّا داخل المتصفح.
الخطوة 2 — المقاومات الرافعة (السبب الأول للناقل الصامت)
مخارج I²C مفتوحة المصرف: يستطيع الجهاز فقط أن يسحب الخط نحو الأسفل إلى الصفر. أما ما يعيده إلى الأعلى، إلى المستوى المنطقي العالي، فهو زوج من المقاومات الرافعة — واحدة على SDA وواحدة على SCL، إلى 3V3. بدونها تظل الخطوط عائمة، ولا يُقرأ شيء كمستوى عالٍ، ولا يجد الماسح أي شيء إطلاقًا.
- كثير من لوحات الـ breakout تحمل مقاومات رافعة أصلًا (غالبًا 10 kΩ أو 4.7 kΩ). مستشعر واحد على سلك قصير يعمل عادةً دون عناء.
- أضف مقاوماتك الخاصة فقط إذا لم يكن للوحة السيّد أي منها. القيم النموذجية: 4.7 kΩ عند 100 kHz، 2.2 kΩ عند 400 kHz — مقاومتان للناقل بأكمله، لا لكل جهاز.
- ركّبت وحدات كثيرة تحمل كل منها مقاومات رافعة؟ تنخفض المقاومة المتوازية أكثر من اللازم، ولا يمكن رفع الخطوط بنظافة — أزِل الزائد منها.
القيمة مقايضة: مقاومة أصغر = حواف أوضح لكن تيار أكبر؛ والحدّ في ورقة البيانات هو سعة الناقل (≤400 pF)، وهذا يقودنا إلى المطبّ التالي.
الخطوة 3 — الأسلاك الطويلة تقتل I²C
صُمِّم I²C لشرائح على لوحة واحدة — سنتيمترات لا أمتار. كل سنتيمتر إضافي من السلك يضيف سعة، فتتقوّس الحافة الصاعدة، وبعد ~400 pF لا يستطيع السيّد أن يميّز 1 من 0. العرَض: يعمل على الطاولة، ثم يبدأ بالتعثّر بمجرد مدّ المستشعر عبر الغرفة.
- اخفِض السرعة إلى 100 kHz (أو أقل):
Wire.setClock(100000); - استخدم مقاومات رافعة أقوى (2.2 kΩ) لمواجهة السعة.
- استخدم أزواجًا مجدولة أو مدرّعة، وأبقِ المسارات قصيرة، ولا تشاركها كابلًا شريطيًا مع إشارات مشوّشة.
- تحتاج أمتارًا فعلًا؟ إذًا I²C هو الناقل الخطأ — استخدم ناقلًا تفاضليًا (RS-485/CAN). راجِع لماذا يكون I²C قصير المدى.
الخطوة 4 — مستشعران، عنوان واحد
يرى الماسح جهازًا، لكن مستشعرك الثاني المطابق غير مرئي — لأنهما يتشاركان العنوان الثابت نفسه.
مستشعرا BME280 كلاهما يستجيب على 0x76 ويطمس أحدهما الآخر. الحلول:
- دبوس العنوان — تكشف معظم المستشعرات دبوس
ADDR/SDOينقلها إلى عنوان ثانٍ (مثل0x76←0x77). اربط واحدًا إلى العالي والآخر إلى المنخفض. - مضاعِف إرسال I²C — تمنحك شريحة
TCA9548Aثمانية نواقل فرعية معزولة، فتتعايش ثمانية مستشعرات متطابقة خلف عنوان واحد. - ناقل ثانٍ — تملك ESP32 وحدتَي I²C عتاديّتين؛ شغّل
Wire1.begin(sda2, scl2)على دبابيس أخرى.
لا يزال لا شيء؟ المشتبه بهم الأخيرون المعتادون
- تبديل SDA/SCL — الكلاسيكي. SDA→SDA وSCL→SCL؛ التقاطع يبدو مطابقًا لكن الناقل يظل صامتًا.
- مستويات الجهد — مستشعر بجهد 5 V على ESP32 بجهد 3.3 V (أو العكس) يحتاج مبدّل مستوى؛ لا توصّل 5 V مباشرة إلى دبوس ESP32.
- التغذية — وحدة نهِمة تُخفض خط 3V3 فتسقط من الناقل. امنحها مصدرًا ثابتًا ومكثّف فصل.
- تابع عالق يبقي SDA منخفضًا يقفل الناقل بأكمله. تعافَ منه بإرسال نبضات على SCL
حتى 9 مرات قبل
Wire.begin()، أو ببساطة أعِد تدوير التغذية.
اعمل بالقائمة من أعلى إلى أسفل — المسح، المقاومات الرافعة، طول السلك، العناوين، ثم المتخلّفون — وناقل I²C الميت يعود إلى الحياة تقريبًا دائمًا خلال دقائق معدودة.
وصّل مستشعرك الخاص وصدّر مخططًا نظيفًا — مباشرة في المتصفح، دون Fritzing.