Re-using buffer with i2c...uctypes.bytearray_at()?
-
I'm really tight with memory in my WiPy so I'm going back through my program trying to be as efficient with memory usage as possible. A lot of what goes on in my code is reading from the i2c bus but it isn't always a fixed size. It could be from 3 bytes to 255 bytes.
I currently use
resp = i2c.readfrom(addr, readLen)
about every 50 milliseconds and the response is passed to another function for processing.I'd like to avoid the heap fragmentation that this must be causing. I thought the solution to this was to use a global buffer and uctypes.bytearray_at() but my first attempt failed dismally.
Here is an example of what I tried.
inqResp = bytearray(3)
buffer = bytearray(255) # Maximum size of a read.
i2c.readfrom_into(addr, inqResp)# Inquire as to the length of the incoming message.
readLen = inqResp[2] # Length comes in the 3rd byte.
msg=uctypes.bytearray_at(buffer, readLen)
i2c.readfrom_into(addr, msg)
return msgWhen I tried to run the above code it caused the WiPy to crash. Perhaps I'm misunderstanding the purpose of bytearray_at() but from the text in the documentation seemed promising. I'm not a very experienced Python programmer so I may be missing something obvious. I'm assuming there must be an easy way to do what I want.
-- mfallavol
-
That's what I was looking for. With just a few changes my memory situation is quite a bit better.
Thanks.
-
You can use
memoryview
for this. This allows to arbitrarily slice abytearray
.
https://docs.python.org/3/library/stdtypes.html#memoryview
something like:buffer = bytearray(255) mv_buffer = memoryview(buffer) i2c.readfrom_into(addr, inqResp) i2c.readfrom_into(addr, mv_buffer[:inqResp[2]]) return mv_buffer[:inqResp[2]]