Протокол 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
@Snefru Clone, 👍3
Обсуждение2 ответа
Возможно, вам придется провести некоторые дополнительные исследования. В данный момент я сам отлаживаю некоторые проблемы I2C. Рад поделиться тем, что дало мое исследование:
Руководящие идеи - что может сломаться?
Физический уровень
- Непреднамеренно переключаемые соединения (SDA<>SCL)
- Неправильный выбор контактов на микроконтроллере
- Подтягивающие резисторы
- Слишком много
- Устройства часто имеют подтягивания, установленные по умолчанию. На каждую шину требуется только один комплект. Правило параллельных резисторов применяется для расчета эффективного сопротивления.
- Слишком большой (слишком высокое сопротивление)
- Слишком маленький (слишком низкое сопротивление)
- Слишком много
- Преобразование напряжения / Рассогласованные устройства
- Шипы или шумы на SDA, SCL или Vcc
- Паразитная емкость
- конструкция провода / трассировки
- автобус слишком длинный
Протокольный уровень
- Неверные адреса шины / коллизии
- Нет ACK, полученного от slave (ref. Статья TI "Устранение неполадок протокола шины I2C" ниже)
- Сроки
- Отсутствующие / Неожиданные импульсы SCL
- Неполный 8-битный блок
- Недостающие байты
- Ложный подчиненный адрес
- Неудачное изменение адреса
- Сигнал NACK означает неоднозначность
- Несоответствие тактовой частоты (должно работать со скоростью самого медленного ведомого устройства на шине)
- Заблокированная шина (т. е. Устройство сбросилось или упало во время передачи, переведя шину в недопустимое состояние. Тайм-аута нет.)
- Multimastering (слишком много мастеров на шине?) - если более одного мастера должны поддерживать режим multi-master
- Растяжение часов (раб держит часы низко)
- Какая часть сообщения отсутствует? Получен ли начальный ACK от ведомого устройства?
Кодовый слой
- Для плат с несколькими портами I2C корректно передавать нужный порт в соответствующую библиотеку.
- Использование прерываний, вызывающих проблемы с синхронизацией
- Использование блокирующих кодовых структур, вызывающих проблемы с синхронизацией
Методы испытаний
- Пинг шины / сканирование шины (как многоскоростной сканер 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 EDITION (Hackaday) https://hackaday.com/2016/07/19/what-could-go-wrong-i2c-edition/
- Как спроектировать и отладить пользовательскую систему I2C master-slave? (Stack Exchange) Как спроектировать и отладить пользовательскую систему I2C master-slave?
- Устранение неполадок протокола шины I2C https://www.ti.com/lit/an/scaa106/scaa106.pdf
Осциллографический анализ 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
Несколько моих советов:
- Если питание Arduino осуществляется через порт VIN, напряжение батареи должно быть СТРОГО от 7 до 12 вольт, иначе плата Arduino будет работать нестабильно. Для последовательной связи обычно требуется хорошая стабильность платы.
- Конденсатор (от 100 до 500 мкФ) между портами 5 В (или 3,3 В) и GND помогает обеспечить постоянное напряжение устройства I2C, что очень важно.
- Отправка и получение различных типов данных через I2C в Arduino
- Ведомое устройство Arduino с двумя мастерами, использующими одну и ту же шину I2C?
- I2C связь между Arduino Uno и Nodemcu32-s (ESP32)
- Соединение i2c для MCP4725 (Dac) с Esp8266 wemos d1 mini
- NodeMCU V3 и MPU6050 странные значения
- Направление по компасу не изменяется линейно
- Как работают функции вне цикла void?
- Как отображать переменные на 0,96-дюймовом OLED-дисплее с библиотекой u8glib?
До какого напряжения 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