Write multiple bytes on I2C

How can I write multiple bytes to an I2C device? The only thing I found is to write exactly two with “write_register” (where I find the distinction between register address and value a bit arbitrary, it’s all just bytes and if the first is logically even a register address depends on the sensor).

My usecase: I want to use a Bitcraze Multi-ranger deck. It has 5 VL53L1x ToF sensors and a PCA9534 I2C IO expander connected to their resets. After powerup all the sensors have the same I2C address, but it can be changed via an I2C command. For that you use the PCA9534 to bring them out of reset one after another and change their address. Controlling the PCA9534 is fine with LUA and I can toggle the reset lines one after another. But for setting a VL53L1’s address I need to send three bytes in one go (“0x00”, “0x01”, “”). How do I do that?

At the moment, I don’t think you can send three consecutive bytes like that (though maybe two consecutive writeregister calls may be interpreted by the device that way - I kind of doubt it).

If the address is stored in non-volatile memory, you might try connecting it to another device like an Arduino or ESP board, writing the address, and then using it with your script.

Otherwise you may be stuck using an intermediate microcontroller to interpret scripted messages and send sensor values back. See here for an example:

Rationale provided by @iampete in this topic:

If you’re willing to build your own firmware, you could write a custom binding to transfer 3 bytes. Unfortunately, I don’t think that’s practical for inclusion as a PR at the moment for the reasons provided in the linked topic.

I tried that already, but as expected it does not work.

Unfortunately it is stored in volatile memory only.

That’s what I wanted to avoid since I’m literally one byte away from a solution. Though even an attiny10 (6 pin SOT23-6 package) should be able to do it, I’d still have to “split” the I2C bus with all the support circuitry, while I’d rather have the flight controller do the work.

There are write_register16 functions in AP_RangeFinder_VL53L0X and AP_RangeFinder_VL53L1X (confusingly with different signature - (uint8_t reg, uint16_t value) for the L0X, (uint16_t reg, uint16_t value) for the L1X), that would send 3 or 4 bytes respectively. How can those be (ab)used in LUA?

Check out the documentation on adding bindings. It’s reasonably straightforward once you get a handle on the binding generator syntax. You’ll have to have a build environment set up.

we can now mix manual and auto generated bindings, so it is possible to add a manual binding for a variable number of bytes.

1 Like

Then I retract my statement about not making a PR. We should probably add some functionality here.