Потому что он работает от батареи...
Пока на шине один slave, все еще как-то работает, но стоит добавить еще устройств - esp8266 начинает виснуть и перегружаться. Потому что, когда wire.h не корректно завершает чтение, slave вешает SDA на замлю и ждет от мастера SCL чтоб передать оставшийся кусок байта. Либа wire.h об этом ничего не знает т.к. в ней нет нормальной проверки колизий и пытается передать на этот или следующий slave новое сообщение. Но все устройства молчат тк ничего не получают из-за того, что наш slave притянул SDA к земле и ждет завершения своей команды. Либа ничего не получив начинает растягивать SCL. Когда растягивать уже некуда, главный цикл встает колом. Через ~3 секунды, после остановки loop, срабатывает WDT и модуль перегружается. А теперь представим, что наш slave - это часы реального времени с батарейкой. Esp8266 перегрузился, а часы нет и все еще ждут когда модуль закончит с ними чтение, удерживая SDA. Через ~3 секунды опять сработает WDT и модуль снова перезагрузится. Круг замкнулся. Не поможет даже передергивание питания, тк наши часики то с батарейкой.
потом в место того чтоб решить проблему, разработчик впиндюрил этот костыль:
Код:
if(sendStop) twi_write_stop();
i = 0;
while(SDA_READ() == 0 && (i++) < 10){
SCL_LOW();
twi_delay(twi_dcount);
SCL_HIGH();
twi_delay(twi_dcount);
}
return 0;
в надежде, что само рассосется, а оно не захотело. тогда он добавил еще один:
Код:
uint8_t twi_status(){
if (SCL_READ()==0) return I2C_SCL_HELD_LOW; //SCL held low by another device, no procedure available to recover
int clockCount = 20;
while (SDA_READ()==0 && clockCount>0){ //if SDA low, read the bits slaves have to sent to a max
twi_read_bit();
if (SCL_READ()==0) return I2C_SCL_HELD_LOW_AFTER_READ; //I2C bus error. SCL held low beyond slave clock stretch time
}
if (SDA_READ()==0) return I2C_SDA_HELD_LOW; //I2C bus error. SDA line held low by slave/another_master after n bits.
if(!twi_write_start()) return I2C_SDA_HELD_LOW_AFTER_INIT; //line busy. SDA again held low by another device. 2nd master?
else return I2C_OK; //all ok
}
и он коряво работает. вот ждем новый.