adc.read_timed buffer problem ...

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
PinkInk
Posts: 65
Joined: Tue Mar 11, 2014 3:42 pm

adc.read_timed buffer problem ...

Post by PinkInk » Sun Jun 29, 2014 4:57 pm

adc.read() returns a value between 0 and 4095 (12bits) ... the pyb module documentation shows a bytearray being used as a buffer for values from adc.read_timed ... but a bytearray is an array of 8 bit integers.

I am reading a TMP36 and (buf[0]<<4) + (buf[1]>>4) appears to give a value in the range expected by adc.read().

But, is this a valid way to interpret the data output by adc.read_timed? and is there a smarter pythonic way of constructing a buffer for adc.read_timed that will make the output easier to interpret?

pfalcon
Posts: 1155
Joined: Fri Feb 28, 2014 2:05 pm

Re: adc.read_timed buffer problem ...

Post by pfalcon » Sun Jun 29, 2014 6:23 pm

If you want to increase chance to get good answer and make this topic useful for other people, please consider adding links to docs you quote.

Anyway, looking at the source, adc.read_timed() will happily accept array.array of element size you want (like 'H'). If you pass bytearray, the resolution will be just reduced to 8 bits.
Awesome MicroPython list
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/

PinkInk
Posts: 65
Joined: Tue Mar 11, 2014 3:42 pm

Re: adc.read_timed buffer problem ...

Post by PinkInk » Mon Jun 30, 2014 3:46 am

Hi @pfalcon, thanks - the referenced documentation is at https://micropython.org/doc/module/pyb/ADC

I've tried what you suggest (using build pybv10-2014-06-29-v1.1.1-98-g8139494.dfu from https://micropython.org/download/) but pyb.read_timed doesn't like the array object, In my naivety I presume "because a Python array doesn't have a fixed length therefore timed_read won't know when to stop filling it" or thereabouts?

Code: Select all

>>> import pyb, array
>>> adc=pyb.ADC(pyb.Pin.board.X5)
>>> buf=array.array('H')
>>> adc.read_timed(buf,10)
Traceback (most recent call last):
  File "<stdin>", line 0, in <module>
TypeError: object with buffer protocol required
If I understand https://docs.python.org/3/library/stdty ... #binaryseq correctly native Python doesn't have a base type (supporting 'buffer protocol') that is appropriate for values read from the pyboard's ADC - perhaps one should be added to the pyb module to keep it separate from the base microPython implementation?

PinkInk
Posts: 65
Joined: Tue Mar 11, 2014 3:42 pm

Re: adc.read_timed buffer problem ...

Post by PinkInk » Mon Jun 30, 2014 3:52 am

OK, reading further this https://docs.python.org/3/c-api/buffer. ... ferobjects seems to suggest that array.array should support the buffer protocol, therefore should work in this context, guess it just doesn't yet in microPython.

I'll just leave this and 'try again later', my 20 yr latent C 'skills' are absolutely not up to contributing a patch, before you suggest that I do ;)

PinkInk
Posts: 65
Joined: Tue Mar 11, 2014 3:42 pm

Re: adc.read_timed buffer problem ...

Post by PinkInk » Mon Jun 30, 2014 4:33 am

Ahhh ... prefilling an array seems to work, bingo?!

Code: Select all

>>> import pyb,array
>>> adc=pyb.ADC(pyb.Pin.board.X5)
>>> buf=array.array('H')
>>> for i in range(10): buf.append(0)
...
>>> adc.read_timed(buf,10)
20
>>> buf
array('H', [3666, 3664, 3673, 3671, 3671, 3669, 3672, 3671, 3666, 3671])
>>>
(X5 wasn't connected to anything)

pfalcon
Posts: 1155
Joined: Fri Feb 28, 2014 2:05 pm

Re: adc.read_timed buffer problem ...

Post by pfalcon » Mon Jun 30, 2014 11:25 pm

Good research work.

More concise, but much less efficient way to create an zero-filled array of needed size is

Code: Select all

array.array('H', [0] * 1000)
. Again, good for quick hacks, very inefficient on memory - it will first create a list of 1000 entries, then array from it.

I also was sure I implemented shortcut for creating empty array like

Code: Select all

array.array('H', 1000)
(compare that with bytearray), but apparently I didn't. I went figuring out why CPython doesn't offer that, and got dragged into http://forum.micropython.org/viewtopic.php?f=3&t=59 . I guess, I will implement it after all - while they deal with that PEP, let us have efficient way to create buffers ;-).
Awesome MicroPython list
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/

PinkInk
Posts: 65
Joined: Tue Mar 11, 2014 3:42 pm

Re: adc.read_timed buffer problem ...

Post by PinkInk » Tue Jul 01, 2014 9:58 am

I guess a generator is a more microPythonic (aka efficient) way of doing it? i.e.

Code: Select all

>>> def fillbuf(l):
...   for i in range(l): yield 0
...
>>> import array
>>> buf=array.array('H',fillbuf(10))
>>> buf
array('H', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
Which could theoretically be appended to the initialiser of a subclass of array.array I assume, excellent; an excuse to play with Python subclasses for the first time.

Post Reply