Протокол I2C не работает должным образом

Я пытаюсь сделать I2C - связь между платами NodeMCU и arduino Uno. Однако он не работает должным образом. Это делает связь на один раз, когда я загрузил код.

Код главного устройства(NodeMCU 1.0)

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <Wire.h>

HTTPClient client;

StaticJsonDocument <200> doc;

const char* ssid = "MY_SSID";
const char* pass = "MY_PASSWORD";

void setup() {
  Serial.begin(9600);
  Wire.begin(D1,D2); 
  WiFi.begin(ssid,pass);
  while(WiFi.status() != WL_CONNECTED) {;}
}

void loop() {

  const char* cd = getCode();
  if(cd==nullptr) {  
    Serial.println("Problem Occurred.");  
    delay(10000);
    return;
  }
  //Начинается плохой код...
  //В принципе, отправка 24 байтов данных для проводной передачи

  int n = strlen(cd); 
  int rem = n%24; //остаток
  int quo = (n-rem)/24; //частное

  while(quo!=0) {
    char sel[24];

    for(int i =0;i<24;i++) {
      sel[i] = cd[((((n-rem)/24)-quo)*24)+i];
    }

    Wire.beginTransmission(8);
    Wire.write(sel);
    Wire.endTransmission();
    quo-=1;
  }

  char sel[rem];
  
  for(int i =0;i<rem;i++) {
    sel[i] = cd[n-rem+i];
  }
  
  if(rem>0) {
     Wire.beginTransmission(8);
     Wire.write(sel);
     Wire.endTransmission(); 
  }
  //Плохой код закончен!

  //это тоже не работает.
  Wire.requestFrom(8,3);
  
  while(Wire.available()) {
    char c = Wire.read();
    Serial.print(c);
  }
 
  delay(15000);
}


//получить код с сервера.
const char* getCode() {
  client.begin("http://...");

  int res = client.GET();

  if(res<0) {
    return 0;
  }

  String root = client.getString();
  deserializeJson(doc,root);
  const char* code = doc["Liste"][0]["code"];
  return code;
}

Код ведомого устройства(Arduino Uno)

#include <Wire.h>

void setup() {
  Serial.begin(9600);
  Wire.begin(8);
  Wire.onReceive(received);
  Wire.onRequest(requested);
}

void loop() {delay(200);}

void received(int bytes) {

  while (Wire.available()) {
    char c = Wire.read();
    Serial.print(c);
  }

}

void requested() {
  Wire.write("abc");
}

Схема:

D1-ПДД

D2-SCL

GND-GND

, 👍3

Обсуждение

До какого напряжения 3,3 В или 5 В вы подтягиваете линию SCL и SDA? Является ли MCU контроллером 3,3 В? Просто подключить D1-SDA D2-SCL недостаточно. Если электрическая настройка в порядке, вы можете удалить весь код Wi-Fi и JSON из программы MCU и попробовать только I2S. Еще одна странная вещь: вы вызываете client.begin("http://..."); каждый раз, когда вы вызываете метод getCode() без client.end(). Возможно, это приведет к сбою соединения с сервером. Я не знаю, можно ли безопасно вызвать client.begin дважды, не вызывая close раньше.., @Peter Paul Kiefer


2 ответа


3

Возможно, вам придется провести некоторые дополнительные исследования. В данный момент я сам отлаживаю некоторые проблемы I2C. Рад поделиться тем, что дало мое исследование:

Руководящие идеи - что может сломаться?

  1. Физический уровень

    1. Непреднамеренно переключаемые соединения (SDA<>SCL)
    2. Неправильный выбор контактов на микроконтроллере
    3. Подтягивающие резисторы
      1. Слишком много
        • Устройства часто имеют подтягивания, установленные по умолчанию. На каждую шину требуется только один комплект. Правило параллельных резисторов применяется для расчета эффективного сопротивления.
      2. Слишком большой (слишком высокое сопротивление)
      3. Слишком маленький (слишком низкое сопротивление)
    4. Преобразование напряжения / Рассогласованные устройства
    5. Шипы или шумы на SDA, SCL или Vcc
    6. Паразитная емкость
      1. конструкция провода / трассировки
      2. автобус слишком длинный
  2. Протокольный уровень

    1. Неверные адреса шины / коллизии
    2. Нет ACK, полученного от slave (ref. Статья TI "Устранение неполадок протокола шины I2C" ниже)
      1. Сроки
      2. Отсутствующие / Неожиданные импульсы SCL
      3. Неполный 8-битный блок
      4. Недостающие байты
      5. Ложный подчиненный адрес
      6. Неудачное изменение адреса
    3. Сигнал NACK означает неоднозначность
    4. Несоответствие тактовой частоты (должно работать со скоростью самого медленного ведомого устройства на шине)
    5. Заблокированная шина (т. е. Устройство сбросилось или упало во время передачи, переведя шину в недопустимое состояние. Тайм-аута нет.)
    6. Multimastering (слишком много мастеров на шине?) - если более одного мастера должны поддерживать режим multi-master
    7. Растяжение часов (раб держит часы низко)
    8. Какая часть сообщения отсутствует? Получен ли начальный ACK от ведомого устройства?
  3. Кодовый слой

    1. Для плат с несколькими портами I2C корректно передавать нужный порт в соответствующую библиотеку.
    2. Использование прерываний, вызывающих проблемы с синхронизацией
    3. Использование блокирующих кодовых структур, вызывающих проблемы с синхронизацией

Методы испытаний

  • Пинг шины / сканирование шины (как многоскоростной сканер Arduino https://forum.arduino.cc/index.php?topic=197360)
  • Подключите дополнительные устройства к шине и посмотрите, какие комбинации работают для идентификации неисправного элемента
  • Мультиметр проверяет
    • Стабильный Vcc?
    • Точки соприкосновения?
    • (Открытый слив) сопротивление подтягиванию от SDA & SCL до Vcc
  • Тестовые устройства, такие как Bus Pirate
  • Анализ / декодирование осциллографа (ссылки ниже)
  • Выяснение того, какое устройство вызывает проблему. (См. Статью Hackaday) Поставьте разнозначные резисторы на выход всех микросхем шины. Значения низкого напряжения будут немного отличаться для каждого чипа, что позволит вам увидеть в оптическом прицеле, какой чип разговаривает в любой момент времени, и диагностировать, когда они разговаривают друг с другом.
  • установите мультиплексор I2C для разделения шины на один разъем для каждого устройства (т. Е. От шины к топологии звезды) (например, PCA9544A).

Ссылки

I2C Общие сведения

  • Для программирования Arduino Arduino Next Steps - Going Further with Скетчи Глава 7
  • Для ESP32 https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/

Советы по отладке I2C

  • Грунтовка I2C (I2C-bus.org) - хорошая ссылка на все, что обсуждается здесь https://www.i2c-bus.org/i2c-primer/
  • Общие проблемы https://www.i2c-bus.org/i2c-primer/common-problems/
  • Неясные проблемы https://www.i2c-bus.org/i2c-primer/obscure-problems/ Анализ неясных проблем https://www.i2c-bus.org/i2c-primer/analysing-obscure-problems/

Осциллографический анализ I2C

  • Как отладить I2C с помощью анализа формы волны (Texas Instruments) https://www.ti.com/lit/an/slyt770/slyt770.pdf
  • Использование осциллографа для отладки протокола I2C https://www.electronicproducts.com/using-an-oscilloscope-to-debug-the-i2c-protocol/
,

Я получу этот ответ для своих будущих проектов. Я нашел решение, но, к сожалению, не могу вспомнить, однако я думаю, что это было связано с уровнем кода., @Snefru Clone


1

Несколько моих советов:

  1. Если питание Arduino осуществляется через порт VIN, напряжение батареи должно быть СТРОГО от 7 до 12 вольт, иначе плата Arduino будет работать нестабильно. Для последовательной связи обычно требуется хорошая стабильность платы.
  2. Конденсатор (от 100 до 500 мкФ) между портами 5 В (или 3,3 В) и GND помогает обеспечить постоянное напряжение устройства I2C, что очень важно.
,