• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Проблема с I2C Slave для ESP32-S2

Goshan

New member
Здравствуйте, уважаемые участники форума! Я относительно недавно занимаюсь написанием кода в Arduino IDE и столкнулся с такой проблемой. Мне потребовалось написать код, способный работать как подчинённое устройство на шине I2C и симулирующий поведение датчика температуры. С использованием платы Arduino Nano мне это в итоге удалось и "эмулятор" заработал. Но дальше я предпринял попытку перенести этот код в контроллер ESP32 и он отказался работать. Использовалась плата LOLIN S2 Mini с контроллером ESP32-S2.

Проблема заключается в следующем. На код мастера, приведённый ниже, ESP32-S2 в режиме Slave не реагирует ни в обработчике OnReceive(), ни в обработчике OnRequest():

//начало передачи
Wire.beginTransmission(I2C_DEV_ADDR);
//запись в буфер командного сообщения длиной len байт для передачи
Wire.write(message, len);
//осуществляем передачу, но не освобождаем шину - повторный старт
Wire.endTransmission(false);

На следующий код ESP32-S2 реагирует в обработчике OnRequest() раньше, чем в обработчике OnReceive():

//начало передачи
Wire.beginTransmission(I2C_DEV_ADDR);
//запись в буфер командного сообщения длиной len байт для передачи
Wire.write(message, len);
//осуществляем передачу, но не освобождаем шину - повторный старт
Wire.endTransmission(false);
//запрос bytesToRequest байт от ведомого. Третий аргумент отсутствует, поэтому запрос завершится условием "stop"
Wire.requestFrom(I2C_DEV_ADDR, bytesToRequest);

А на этот код ESP32-S2 реагирует так, как мне нужно: в обработчике OnReceive() раньше, чем в обработчике OnRequest():

//начало передачи
Wire.beginTransmission(I2C_DEV_ADDR);
//запись в буфер командного сообщения длиной len байт для передачи
Wire.write(message, len);
//осуществляем передачу, и освобождаем шину
Wire.endTransmission(true);
//запрос bytesToRequest байт от ведомого. Третий аргумент отсутствует, поэтому запрос завершится условием "stop"
Wire.requestFrom(I2C_DEV_ADDR, bytesToRequest);

Получается, что для ESP32-S2 критерием для вызова метода OnReceive() является обязательное наличие условия "stop"? Это создаёт несовместимость с кодом для Arduino Nano, т.к. Arduino Nano в режиме Slave корректно реагирует на Wire.endTransmission(false) от мастера и осуществляет при этом приём сообщения в OnReceive(). Это также проблема и для моего кода, т.к. вначале я должен принять командный байт и только потом, проанализировав состав команды, ответить на запрос в OnRequest(). Изменить код мастера я не могу, т.к. воссоздаю с его помощью поведение другого устройства, которое в конечном итоге будет общаться с эмулятором, и это устройство успешно работает с "железным" датчиком. К сожалению, я не понимаю, как работают методы OnReceive() и OnRequest() на более низком уровне. Возможно ли это как-то обойти?
 
Сверху Снизу