0
\$\begingroup\$

I have an Arm64 Linux board and an IST8308 3D magnetometer that I am reading via I2C with the following script:

import smbus2
i2c_bus = smbus2.SMBus(2)
i2c_magnetometer_register = 12

# initialize magnetometer
i2c_bus.write_byte_data(i2c_magnetometer_register, 32, 0) # action register
i2c_bus.write_byte_data(i2c_magnetometer_register, 50, 1) # control register 3
i2c_bus.write_byte_data(i2c_magnetometer_register, 49, 4) # control register 2
# read values
while True:
    dataxl = i2c_bus.read_byte_data(i2c_magnetometer_register, 17)
    dataxh = i2c_bus.read_byte_data(i2c_magnetometer_register, 18)
    datax = uint_to_int((dataxh << 8) + dataxl)
    datayl = i2c_bus.read_byte_data(i2c_magnetometer_register, 19)
    datayh = i2c_bus.read_byte_data(i2c_magnetometer_register, 20)
    datay = uint_to_int((datayh << 8) + datayl)
    datazl = i2c_bus.read_byte_data(i2c_magnetometer_register, 21)
    datazh = i2c_bus.read_byte_data(i2c_magnetometer_register, 22)
    dataz = uint_to_int((datazh << 8) + datazl)
    # do stuff...

According to my profiler, the read_byte_data() function is very slow compared to the declared 200Hz. I am pretty new to sensors and I am not sure if I can change some setting in the sensor in order to read faster. I referred to this code to find how to read from the sensor. I could not find the full datasheet of the IST8308 online but I found the IST8310 one.

UPDATE: according to the github code linked above, the sensor provides a status register to check for the availability of new data (DRDY - data ready). I added this check in my loop and it seems that there is always new data available. For this reason I think that the bottleneck is the Python builtin ioctl() function, that is called by read_byte_data(). However, I am not sure about it.

\$\endgroup\$
2
  • \$\begingroup\$ turned comment into answer \$\endgroup\$
    – andrsmllr
    Sep 30, 2021 at 10:07
  • \$\begingroup\$ @firion: Check here. \$\endgroup\$
    – JRE
    Sep 30, 2021 at 13:07

2 Answers 2

1
\$\begingroup\$

The root cause of the poor performance is your highly inefficient code. You perform no less than 6 byte read operations in consequtive addresses from address 17 through 22. The sensor must respond to each one of these separately, and that takes time and resources for it to process.

Be kind to your sensor. You should always strive to do as few I/O calls as possible. In your case you can do just fine with 1 inside the loop.

while True:
    buf = i2c_bus.read_i2c_block_data(i2c_magnetometer_register, 17, 6)
    # Convert to 16 bit word
    datax = uint_to_int(buf[1] << 8 + buf[0])
    .... 

Additional tips:

  • Check also the i2c baud rate settings on your board.
  • If your sensor refuses to do block reads as in the example, try reading 3 words instead of 6 bytes.
\$\endgroup\$
0
\$\begingroup\$

Where are the 200 Hz declared? Do you mean the 200 kHz of the I2C bus?
In that case your polling rate will always be slower than the 200 kHz of the I2C bus, because the bus is bidirection and there is some protocol overhead.

As a very rough estimate, you read 6 bytes in every loop iteration, so the polling rate from the sensor will be at most 200 kBits/s / (6 byte * 4 * 8 bits/byte) =~ 1000 polls per second. The additional factor of 4 is for the I2C slave and register address which are send with each read or write operation. So if # do stuff... can be neglected that is the theoretical maximum poll rate from the I2C bus (adapt I2C bus frequency if needed).

Do you use an I2C controller or is the I2C protocol bit banged by a microcontroller? Bit banging can slow down the I2C bus a lot.

\$\endgroup\$
4
  • \$\begingroup\$ 200Hz are declared in the datasheet. I must add that the datasheet specifies "200Hz ODR can be achieved with OSR≦8", but I don't know what it means. As for the estimate, shouldn't the result be ~2000 poll/s? \$\endgroup\$
    – firion
    Sep 30, 2021 at 11:00
  • \$\begingroup\$ By the way, I edited the code for clarity: the initialization happens only once. \$\endgroup\$
    – firion
    Sep 30, 2021 at 11:03
  • \$\begingroup\$ @andrsmllr: The 200Hz is the output data rate of the magnetometer. It has output data rates from 8Hz to 200Hz. I don't see where the data rate has been set, though. \$\endgroup\$
    – JRE
    Sep 30, 2021 at 12:42
  • \$\begingroup\$ I added new info that could be useful \$\endgroup\$
    – firion
    Sep 30, 2021 at 13:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.