Устройство I2C исчезает с шины после записи
В настоящее время я испытываю действительно странную проблему I2C на карте на базе Atmega32u4. Я пытаюсь использовать TLV493D, подключенный по I2C. Я знаю из этой темы, что перед использованием этого устройства мне нужно установить режим питания:
Wire.beginTransmission(HallAddressWrite); // Адрес датчика
Wire.write(configReg); // Адрес регистра конфигурации
Wire.write(powerMode); // Устанавливаем режим питания на низкий
errorCode = Wire.endTransmission(); // Остановка передачи
Но каждый раз, когда я пытаюсь записать в регистр TLV493D, устройство просто исчезает с шины I2C! Я знаю, это звучит странно, но я могу продемонстрировать это с помощью модифицированной версии сканера I2C по умолчанию
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");
Serial.println("Beginning write test...");
Wire.beginTransmission(address);
// нет записи регистра
errorCode = Wire.endTransmission();
Serial.print("Test ended with code : ");
Serial.println(errorCode);
Serial.println("SECOND Beginning write test...");
Wire.beginTransmission(address); // Адрес датчика
Wire.write(0x00); // Адрес регистра конфигурации
Wire.write(0x05); // Установите режим питания на низкий
errorCode = Wire.endTransmission();
Serial.print("Test ended with code : ");
Serial.println(errorCode);
nDevices++;
}
что дает результат:
I2C device found at address 0x5E !
Beginning write test...
Test ended with code : 0
SECOND Beginning write test...
Test ended with code : 0
И следующее сканирование ничего не находит. Как видите, я не теряю свое устройство, когда ничего не записываю. Но оно исчезает из моей шины, как только я что-то записываю (здесь это для настройки режима низкого энергопотребления, но любое значение сделает то же самое).
Дополнительная информация:
Мой код правильный. Я знаю это, потому что у меня нет проблем при использовании Arduino Uno или Arduino Mega. К сожалению, у меня нет Arduino Leonardo, чтобы проверить, связана ли моя проблема с Atmega32u4.
Моя проводка правильная. Я проверил сигнал на выводах SDA и SCL на TLV493D с помощью осциллографа, и все соответствует ожиданиям: 3,3 В и 100 кГц.
У меня также есть SRF02 на шине I2c: он работает так, как и ожидалось.
Я не думаю, что мой TLV493D поврежден. На самом деле, я думал, что это из-за этого. Поэтому я поменял его на другой, но проблема все еще здесь.
Я заметил, что при начале передачи I2C по адресу 0x00 я снова вижу свой TLV493D. Но это бесполезно, так как мне снова нужно устанавливать режим питания, и, таким образом, он снова исчезает с шины.
@erenaud, 👍1
Обсуждение2 ответа
Лучший ответ:
Подводя итог этой проблемы: Конфигурация TLV493D работает путем записи двух байтов с I2C. Вы должны начать с записи 0x00, который будет проигнорирован, поскольку первый регистр зарезервирован. Затем вы пишете второй байт, который фактически выполнит конфигурацию (второй регистр). Три младших бита включают или выключают режимы INT, FAST и LOW.
Я все еще не понимаю, почему я не могу включить режим INT на моем Atmega32u4, хотя на Uno или Mega (в режиме LOW) это, похоже, не проблема. В любом случае, у меня работают две конфигурации:
0x07 --> INT, FAST и LOW включены
0x01 --> включен только LOW
Я не думаю, что проблема в отключении INT. Если я правильно понял, это заставит устройство отправить импульс прерывания для запроса чтения микроконтроллера. Если вы управляете чтениями самостоятельно, я не думаю, что вам нужно включать INT.
Большое спасибо CodeGorilla за поддержку.
ОБНОВЛЕНИЕ:
Мне удалось получить Arduino Leonardo. Действительно, все мои наблюдения на моей карте на базе Atmega32u4 по-прежнему верны (запись второго регистра 0x05 заставляет устройство исчезнуть с шины, но не с 0x01 или 0x07). Но, опять же, он нормально работает на Uno или Mega... Действительно странно! Если кто-то может дать объяснение, я буду очень признателен.
По умолчанию регистр FAST устанавливается в 0 при включении питания. Если режим FAST равен 0, а вы устанавливаете LOW на 0, вы переходите в режим пониженного энергопотребления.
Глядя на ваш код, кажется, что вы не изменяете регистр FAST, а это значит, что я могу упростить ваш вопрос до «Почему мое устройство исчезает с шины I2C каждый раз, когда я его выключаю».
Просто взглянув на страницу 34 руководства пользователя на английском языке, я бы сказал, что вам нужно установить FAST на 1, прежде чем устанавливать LOW на 0.
Также - есть ли у вас подтягивающие резисторы на шине I2C? Без них у вас могут возникнуть проблемы. Обычно они составляют около 4,7 кОм для 5 В, но я не знаю, какими они должны быть для систем 3,3 В.
Спасибо за ответ. Я не совсем уверен, что понимаю. В какой точке кода я устанавливаю LOW на 0? У меня на шине I2C есть подтягивающие резисторы. И последнее, чего я действительно не понимаю, так это зачем мне все это делать, зная, что мой код прекрасно работает на Uno и Mega? Я имею в виду, в чем разница Atmega32u4?, @erenaud
@erenaud, это неправильный вопрос. Вы должны сделать все правильно, а затем решить все оставшиеся проблемы. Ваш atmega32u4 работает на 3,3 В? Тогда вам не нужен преобразователь уровня. Используйте подтягивающие резисторы. Следуйте техническому описанию., @Jot
@Jot Как я уже сказал, я использую подтягивающие резисторы., @erenaud
Извините, я упустил тот факт, что он "работал" на Uno и Mega. При использовании его с Uno/Mega вы используете шину I2C 5 В или 3,3 В? Согласно коду, который вы включили выше, и техническому описанию, на которое вы ссылаетесь, вы пишете в регистр записи 0 со значением 5. Регистр 0 зарезервирован и не должен записываться, или я неправильно прочитал техническое описание?, @Code Gorilla
@CodeGorilla Я использую шину 3,3 В. Действительно, я думал, что пишу в регистр 0 со значением 5, но меня ввел в заблуждение комментарий к фрагменту кода, который я нашел в ветке форума arduino, на которую я дал ссылку. На самом деле, я делаю в точности как в примере на странице 13 руководства пользователя. Первая запись (0x00) предназначена для первого зарезервированного регистра. Затем я пишу (0x05)) во второй регистр, который устанавливает FAST в 0, INT в 1 и LOW в 1., @erenaud
@CodeGorilla Я заметил кое-что интересное: при записи 0x07 во второй регистр (так что FAST, INT и LOW установлены в 1), я не теряю связь с устройством. Но, конечно, мои показания совершенно неверны, поскольку код, который я сейчас использовал, не поддерживает режим FAST., @erenaud
@erenaud - Может ли быть, что включение INT («не рекомендуется для I2C») и отключение Fast вызывают проблему? Вы пробовали значение 0x01? для второго регистра?, @Code Gorilla
@CodeGorilla Действительно, это тоже работает, и я думаю, вы абсолютно правы, INT не следует включать. Спасибо за помощь!, @erenaud
- Подключение нескольких MPU 6050 к Micro/Lenardo
- Pro micro Wire.endTransmission() не возвращает
- Отправка и получение различных типов данных через I2C в Arduino
- Как работают функции вне цикла void?
- Как отображать переменные на 0,96-дюймовом OLED-дисплее с библиотекой u8glib?
- Как отправить строку на мастер с помощью i2c
- Как выбрать альтернативные контакты I2C на ESP32?
- Что означает в I2C «NACK получен»?
Вы проверили, что напряжение питания не падает слишком низко при записи в TLV через I2C? Во время чтения спецификации я подумал, что это может показать наблюдаемое поведение, сбрасывая его каждый раз, когда вы записываете в него., @chrisl
Привет, chrisl, спасибо за ответ. Это действительно было хорошее замечание, но, к сожалению, напряжение питания остается постоянным на уровне 3,3 В., @erenaud