each are separate transmission, so you need to begin and end the transmission. but it could be made "neater" if you were using a for loop.
for (byte deviceNb = 1; deviceNb < 6; deviceNb++) {
Wire.beginTransmission(deviceNb);
Wire.write(deviceNb); // sends whatever value is required
Wire.endTransmission();
}
using an array, say call it valueFor, to memorise what is to be sent to which display could help as well
for (byte deviceNb = 1; deviceNb < 6; deviceNb++) {
Wire.beginTransmission(deviceNb);
Wire.write(valueFor[deviceNb]); // sends whatever value is required
Wire.endTransmission();
}
using an array for the address of the target devices would be useful too
const byte deviceAddress[] = {1, 2, 3, 4, 5};
const byte deviceCount = sizeof deviceAddress / sizeof * deviceAddress;
byte valueFor[deviceCount];
// fill up valueFor through some algorithm, say here we put a random value
for (byte deviceNb = 0; deviceNb < deviceCount; deviceNb++) {
valueFor[deviceNb] = random(deviceCount) + 1;
}
// and when it's time to send the data
for (byte deviceNb = 0; deviceNb < deviceCount; deviceNb++) {
Wire.beginTransmission(deviceAddress[deviceNb] );
Wire.write(valueFor[deviceNb]); // sends whatever value is required
Wire.endTransmission();
}
And if you're often writing single bytes to addresses in different places in the code, you can extract it into a function where you pass a std::span of bytes to write and an address.
I've made several projects using nitacku's NI2C library, I had to make a little change to it though but all in all it hasn't let me down in those projects.
I'm not going to start pasting code here but i'm replying just to say "go have a look". It's a nonblocking I2C implementation.
cheers.