Как закрыть/закончить Wire.begin()?
У меня есть камера ESP32, и я прикрепил к ней датчик освещенности i2c. Мне нужно прочитать уровень освещенности при запуске, тогда мне больше не нужно соединение i2c. Проблема в том, что плата использует 2 соединения i2c, я думаю (для камеры и тому подобного). Поэтому я использую свои собственные контакты для датчика (15 и 16). Это работает хорошо, я могу читать свет просто отлично, но затем камера выходит из строя, потому что (я считаю) Wire.begin(15,16) меняет контакты по умолчанию, и камера путается.
Поэтому я хотел бы сделать что-то вроде Wire.end (), чтобы забыть, что я начал Wire.begin(). Есть идеи, как я могу это сделать?
Вот соответствующий код:
#define I2C_SDA 16
#define I2C_SCL 15
BH1750 lightMeter (0x23);
TwoWire I2Clightmeter= TwoWire(1);
void setup()
{
I2Clightmeter.begin(I2C_SDA, I2C_SCL);
lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE,0x23,&I2Clightmeter);
delay(1000);
uint16_t lux = lightMeter.readLightLevel();
//остальная часть кода
@Radu, 👍1
Обсуждение1 ответ
Лучший ответ:
Есть способ сделать это, специфичный для ESP32. Однако это означает изменение того, как вы определяете свой объект I2C.
Система ESP32 настроена таким образом, что при уничтожении экземпляра TwoWire шина I2C освобождается. Но вы не можете сделать это так, как обычно определяете объект. Поэтому вместо этого вы должны использовать динамическое распределение для управления им:
TwoWire *I2Clightmeter;
void setup() {
I2Clightmeter = new TwoWire(1);
I2Clightmeter->begin(I2C_SDA, I2C_SCL);
lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE,0x23,I2Clightmeter);
delay(1000);
uint16_t lux = lightMeter.readLightLevel();
delete I2Clightmeter;
// rest of code
}
Другой альтернативой является сохранение объекта TwoWire в локальной области видимости, чтобы он был уничтожен, когда вы покидаете эту область видимости - возможно, с помощью специальной функции для него:
uint16_t getLux() {
TwoWire I2Clightmeter(1);
I2Clightmeter.begin(I2C_SDA, I2C_SCL);
lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE,0x23,&I2Clightmeter);
delay(1000);
return lightMeter.readLightLevel();
}
void setup() {
uint16_t lux = getLux();
// остальная часть кода
}
Спасибо, но, к сожалению, это не работает. Если я поставлю туда delete, он просто загрузится. Если я не ставлю delete, он выдает мне сообщение, как и раньше: [W][esp32-hal-i2c.c:905] i2c_isr_handler_default(): eject raw=0x2, int=0x200, @Radu
Вы пробовали второй вариант? Локализовать его?, @Majenko
Я не пробовал, но я не вижу, как это будет работать, так как, скорее всего, как только функция будет вызвана в c (в конкретном коде esp32), она установит что-то, что сохраняется там до тех пор, пока устройство не будет перезагружено или не произойдет какая-то другая волшебная вещь, чтобы сбросить его. Кстати, код камеры НЕ использует wire() в моей программе. Он используется библиотеками в бэкэнде. Единственный код i2c в моей программе-это считывание датчика освещенности., @Radu
Это стоит попробовать. Попробуй и доложи., @Majenko
Другой вариант - просто использовать другой канал i2c и, возможно, другие контакты., @Majenko
Попытка подключиться к первому каналу была одной из первых моих попыток. К сожалению, он все равно разбился., @Radu
Я попробовал версию scope, и, что неудивительно, она тоже застряла в бутлупе..., @Radu
Хм... Тогда у меня сейчас нет идей, извини. Может быть, поднять его как проблему в репо github - это действительно не должно привести к сбою., @Majenko
Спасибо за ваши усилия, я ценю это. - Спросил я по телефону. esp32.com форум, если я не получу ответа там тоже, я открою вопрос и на github., @Radu
Кстати, глядя на код, удаление объекта должно освободить i2c. К сожалению, происходит что-то еще :/ TwoWire::~TwoWire() { флеш(); if(i2c) { i2cRelease(i2c); i2c=NULL; } }, @Radu
Да, именно отсюда у меня и возникла идея уничтожить этот объект. Может быть, проблема не в I2C, а в коде камеры. Я знаю, что вы, вероятно, не очень контролируете это, так как оно в основном встроено в ядро., @Majenko
Хорошо, я решил эту проблему. Я переместил SDA на вывод 14, и теперь он работает, по какой-то причине :D Я считаю, что это все еще ошибка с esp-32 cam, но, по крайней мере, я заставил его работать., @Radu
- Как выбрать альтернативные контакты I2C на ESP32?
- I2C связь между Arduino Uno и Nodemcu32-s (ESP32)
- PN532 не обнаруживает RFID-карту при подключении к ESP32 в режиме I2C, но отлично работает с Arduino Uno
- Лучший способ отправки команд I2C между Arduino и ESP32
- Не могу отключить внутренний интерфейс I2C подтягиваний на ESP32
- DS3231 RTC не работает с ESP32
- Как установить подсветку дисплея 16x2 LCD I2C?
- Подключите arduino nano и ESP32 к I2C на GPIO7 и GPIO8?
Вы *пробовали*
Wire.end()
?, @MajenkoДа, конечно. Но такой функции нет., @Radu
Похоже, это то, что Arduino упустил из виду. Это то, что мы (опционально) реализовали в chipKIT... Хотя способ есть, но он не слишком веселый., @Majenko
Это заголовок esp32 для провода: https://github.com/espressif/arduino-esp32/blob/master/libraries/Wire/src/Wire.если есть способ, я хотел бы его знать, потому что без него я не могу пользоваться камерой :/, @Radu
Я просто попытался воспроизвести это, но так как у меня нет BH1750, я просто запустил решение № 1 из ответа ниже без каких-либо вложений, и оно _not_ сбой для меня. Так что, возможно, ошибка не в библиотеке проводов, а в библиотеке lightmeter (так как она может регистрировать некоторые прерывания). Попробуйте также динамически выделить его., @PMF
Спасибо за ваши усилия. Программа не требует физической платы или даже фактического использования библиотеки. Достаточно просто запустить I2Clightmeter.begin(I2C_SDA, I2C_SCL); чтобы при инициализации камеры произошел сбой. Тем не менее, я нашел решение: перемещение SDA на вывод 14, похоже, работает., @Radu