Как закрыть/закончить 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();

//остальная часть кода

, 👍1

Обсуждение

Вы *пробовали* 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


1 ответ


Лучший ответ:

3

Есть способ сделать это, специфичный для 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