Здравствуйте, уважаемые участники форума! Я относительно недавно занимаюсь написанием кода в 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() на более низком уровне. Возможно ли это как-то обойти?
Проблема заключается в следующем. На код мастера, приведённый ниже, 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() на более низком уровне. Возможно ли это как-то обойти?