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 msg

    When 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 a bytearray.
    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]]
    

Log in to reply
 

Pycom on Twitter