Maximising I2C throughput #9168
Replies: 3 comments 5 replies
-
You could try to vary the clock speed of I2C and compare the time for a transaction. Then you can tell which is fixed processing time and which data transfer time. Or you monitor the I2C bus directly. It may be that increasing the I2C clock speed is possible. |
Beta Was this translation helpful? Give feedback.
-
You can time the I2C transactions by wrapping them in code like this: t0 = time.ticks_us()
i2c...
dt = time.ticks_diff(time.ticks_us(), t0)
print(dt) That has given good results for me in the past. Also, I2C on ESP32 can be slow if you do lots of separate transactions. This was improved in 6bda80d. To take advantage of that you need to use For efficient use of memory, see |
Beta Was this translation helpful? Give feedback.
-
Thanks @robert-hh and @dpgeorge I have put together some test cases and will leave the results here as it might help others. Test 1 - base case Test 2 - Discard data (don't append to buffer) Test 3 - I2C read_from_mem Test 4 - I2C read_from_mem_into with preallocated buffer Seems like appending to list doesn't impact run time def timed_function(f, *args, **kwargs):
myname = str(f).split(' ')[1]
def new_func(*args, **kwargs):
t = time.ticks_us()
print('Function { myname } starting')
result = f(*args, **kwargs)
delta = time.ticks_diff(time.ticks_us(), t)
print('Function {} Time = {:6.3f}ms'.format(myname, delta / 1000))
return result
return new_func
@timed_function
# Base case
def waveform_read(self):
i = 0
while i < 8000:
self.i2c.writeto(ADDR, bytes([0xE5, 0x10]))
data = self.i2c.readfrom(ADDR, 12)
self.buffer.append(data)
i += 1
@timed_function
# Read data from I2C but don't append to list
def waveform_read_2(self):
i = 0
while i < 8000:
self.i2c.writeto(ADDR, bytes([0xE5, 0x10]))
data = self.i2c.readfrom(ADDR, 12)
i += 1
@timed_function
# Read data using I2C read_from_mem
def waveform_read_3(self):
i = 0
while i < 8000:
data = self.i2c.readfrom_mem(ADDR, 58640, 12, addrsize=16)
self.buffer.append(data)
i += 1
@timed_function
# Read data directly into buffer using I2C read_from_mem_into
def waveform_read_4(self):
i = 0
s = bytearray(12)
while i < 8000:
self.i2c.readfrom_mem_into(ADDR, 58640, s, addrsize=16)
self.buffer.append(s)
i += 1 |
Beta Was this translation helpful? Give feedback.
-
I have an I2C device that samples data at a rate of 8KHz, the I2C bus operates at 400KHz. The data size is 12 bytes + another 4 bytes for overhead and the initial write command, total of (16 bytes/128 bits). The theoretical max speed I could read data from the device would be 3,100 samples per second (400,000/128).
Using the following code I can read 8,000 samples in 4.9 seconds (1,600 samples per second). I'm reasonably happy with this result however I'm wondering if there are any easy gains to achieve a bit more bandwidth. Is there a bottleneck in my code where I append data to the buffer? Or maybe this is not an issue considering the clock speed of the ESP compared to the I2C bus?
Any thoughts?
Beta Was this translation helpful? Give feedback.
All reactions