Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

structure and naming: i2c python interface vs arduino #7

Closed
Neon22 opened this issue Dec 29, 2013 · 10 comments
Closed

structure and naming: i2c python interface vs arduino #7

Neon22 opened this issue Dec 29, 2013 · 10 comments
Labels

Comments

@Neon22
Copy link
Contributor

Neon22 commented Dec 29, 2013

The arduino interface is documented here:

keywords in here:

It uses a different set of function names than micro python currently does.

There is a small reason (existing users) to follow their lead, or to make similar wrapped interfaces to help migrating users from Arduino.
Although we clearly do not want to slavish about this. The pythonic approach suits us better but for low lying interfaces there is the advantage of familiarity where applicable.
What do we want to do ? Here and in general ?

(We could also make an arduino module which wrapped micropython calls to look similar to existing arduino libraries ?)

Notes:
Specifically micropython (current) vs arduino i2cdevlib:
(note that i2cdevlib also wraps the Wire library which inherits from Stream)
pyb_I2C
i2c_obj_print
i2c_obj_start
i2c_obj_write
i2c_obj_read
i2c_obj_readAndStop
i2c_obj_stop

vs:
from Wire:
begin([addr])
requestFrom(address, quantity, [stop])
beginTransmission(address)
endTransmission([stop])
write(value, [stop]) (where value may be byte, str, array)
available()
read()
onReceive(handler)
onRequest(handler)

From I2Cdev
readBit
readBitW
readBits
readBitsW
readByte
readBytes
readWord
readWords
writeBit
writeBitW
writeBits
writeBitsW
writeByte
writeBytes
writeWord
writeWords

Where - for example - readWords supports timeouts
int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout)
The arduino lib uses its Wire and Fastwire libraries for also supporting one wire and twowire devices and deals with requests for reads longer than the inbuilt buffer...

Limitations in Wire include only allowing 7bit i2c addresses.

Extra info - maybe I should put this on a wikipage ?
One-wire on Arduino:

Stream lib

SPI lib

@hagenkaye
Copy link
Contributor

I guess the true value of making it 100% compatible with arduino is the huge amount of code already out there to interface to different sensors, devices, etc. The i2c interface is really a trivial interface to understand no matter what API is wrapped around it, IMHO.

I guess these questions pop into my mind when I think about it:

The arduino libraries are C++ and are we going to add C++ code to the existing code base?
Are users going to be python programmers or C++ programmers?
How exactly are modules for different sensors going to added by the user?

My guess is the goal is to add functionality at the user level in python as opposed to implementing some sort of easy method to import arduino code, which means the vast amount of arduino code really can't be used and must be ported. So there is going be some porting going on. Do we mimic or re-invent?

The motivation behind this interface was to keep the code small, leverage the built in capabilities of the stm chip, and provide enough functionality to easily test some i2c devices I have on hand with my micro python board.

I'm sure the final implementation is totally open for discussion.

@dpgeorge
Copy link
Member

I really don't want to pull in C++ code.

I don't see the need to be compatible with Arduino. Sure, it help people transition, but Python is so much different to C that you've got to change the way you think/code anyway, so learning the new function calls is not a big deal, IMHO.

I don't want to have to have people code in C to write a simple device driver. They should write drivers in Python, as much as that's possible. That's what the inline assembler is for, and the viper compiler (which still needs a bit of work to get it running device drivers!). So I don't really see the need to be compatible with Arduino C-names for functions.

I think wrapping the STM library to provide an interface to the peripherals, like I2C, is what we want to do. And then use this to make device drivers.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 29, 2013

My 2 cents:

Low-level APIs should be as efficient and as low-overhead as possible. Consistency (including in naming) is extra plus.

For higher-level, it makes sense to follow existing Python protocols (abstract APIs). For example, any hardware interface deals with transferring data. This would fit file-object protocol with its read() and write() methods. Consequently, device address should be passed to constructor. Of course, there need to be extra methods do delineate bus transactions. start() and stop() sound good.

So, that leaves question of how to name low-level API. Unless function method signatures match some other API exactly, IMHO it will just add confusion to use the same names. For Arduino compatibility, there can be custom modules (API adapters).

@Neon22
Copy link
Contributor Author

Neon22 commented Dec 30, 2013

My emphasis may not have been obvious - apologies.
I am referring only to naming not implementation.

E.g. The arduino has a Serial class for comms on serial ports. It has several methods that do useful things. If the micro python one does the same (or similar functionality) then giving it the same name will aid understanding of users coming from that environment. I use Arduino specifically because I believe that is where a significant number of users will come from.

If the Arduino names don't make sense for us - e.g. for reasons of being global var oriented instead of class oriented - then I do not expect us to keep any similarity.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 30, 2013

Well, as I hinted, the problem comes when uPy's implementation does "similar, but not completely" functionality. Then naming it as Arduino would make confusion then good. And using completely new platform of course gives chances to cleanup/improve APIs, which thus will differ. So, IMHO, following Arduino naming exactly should not be the top aim, rather should target for consist naming/params.

But I understand what you mean by Arduino compatibility and definitely support that! Except that IMHO it can live in separate module(s), just for folks who want such compatibility and not native (supposedly cleaner/more advanced) API. And I have to say that I did that even before it was possible to run Python on MCU - e.g.: https://github.com/pfalcon/arduino-hosted - there're few such modules, and I wrote mine exactly because all other I saw did NOT follow Arduino API exactly; also note that I no longer use it since I "grew out" of Arduino ;-).

@Neon22
Copy link
Contributor Author

Neon22 commented Dec 30, 2013

OK. I concede :)
Lets just do "the right thing".

Perhaps its still useful to look at the arduino libs to see the kinds of interfaces they found useful.
E.g. in i2c - a time out, callbacks, and Word sized args.

@pfalcon I followed your link and agree with what you say about firmata - nevertheless I was considering writing a python module to communicate using this protocol. It seems like a somewhat widely used mechanism to communicate with microcontrolelrs and would allow (say) Processing or PureData users to easily add Micro python based controllers...
http://firmata.org/wiki/Download
Perhaps we should start a new thread/wiki page about that ?

@dpgeorge
Copy link
Member

As I said before, Python is so much different to C/Arduino that we can basically start from scratch with conventions/naming and try to "get it right". That said, it's impossible to "get it right", so we can try to learn from Arduino, copy/change as we see appropriate, and make sure things are consistently named and have consistent functionality.

@pfalcon
Copy link
Contributor

pfalcon commented Dec 31, 2013

firmata - nevertheless I was considering writing a python module to communicate using this protocol.

I'm all for having as many different modules available for MicroPython as possible. My only concern is what goes into MicroPython core and what are community modules. What I'd love to see (and from communication with Damien I have a feeling he shares that idea) is really minimal core and vast and easy to get/use ecosystem of 3rd-party modules, centered around something like PyPi (well, it doesn't have to be "something like", it can be PyPi right away, we just need to be sure to not confuse CPython/JPython/IronPython people that a particular module requires MicroPython).

Of course, having that for uPy (specifically MCU ports) would take some more tools than just pip, and I guess python-flavin tool which you mention in the other ticket is the step in the right direction.

Anyway, so far we have #14 on the critical path.

@dpgeorge
Copy link
Member

dpgeorge commented Jan 2, 2014

See also #25 discussing using a different repo for additional modules. This keeps the micropython repo lean.

@Neon22
Copy link
Contributor Author

Neon22 commented Jan 5, 2014

To summarise this issue:

  • micropython intends to implement low level interfaces in C and all others built on top in python. The inline assembler and the viper compiler will take care of performance.
  • this will mean a smaller core and optional modules.
  • So using the example in the top post - there will be open,read,write,.. supplied in the main lib. All other i2c functions will be implemented in python on top of these.
  • Looking at existing embedded libs (such as Arduino libraries) is a useful way to see what functionality and problems others have found the need to supply and solve.
  • Due to the pythonic and class based nature of the environment its unlikely that many naming conventions will match existing libraries (such as the Arduino).

@Neon22 Neon22 closed this as completed Feb 5, 2014
EcmaXp added a commit to OpenPythons/micropython-opencom-legacy that referenced this issue Aug 28, 2016
drrk pushed a commit to drrk/micropython that referenced this issue Jan 22, 2017
kamtom480 pushed a commit to kamtom480/micropython that referenced this issue Jun 16, 2020
tannewt referenced this issue in tannewt/circuitpython Feb 13, 2021
dpgeorge pushed a commit that referenced this issue May 30, 2021
asan considers that memcmp(p, q, N) is permitted to access N bytes at each
of p and q, even for values of p and q that have a difference earlier.
Accessing additional values is frequently done in practice, reading 4 or
more bytes from each input at a time for efficiency, so when completing
"non_exist<TAB>" in the repl, this causes a diagnostic:

    ==16938==ERROR: AddressSanitizer: global-buffer-overflow on
    address 0x555555cd8dc8 at pc 0x7ffff726457b bp 0x7fffffffda20 sp 0x7fff
    READ of size 9 at 0x555555cd8dc8 thread T0
        #0 0x7ffff726457a  (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xb857a)
        #1 0x555555b0e82a in mp_repl_autocomplete ../../py/repl.c:301
        #2 0x555555c89585 in readline_process_char ../../lib/mp-readline/re
        #3 0x555555c8ac6e in readline ../../lib/mp-readline/readline.c:513
        #4 0x555555b8dcbd in do_repl /home/jepler/src/micropython/ports/uni
        #5 0x555555b90859 in main_ /home/jepler/src/micropython/ports/unix/
        #6 0x555555b90a3a in main /home/jepler/src/micropython/ports/unix/m
        #7 0x7ffff619a09a in __libc_start_main ../csu/libc-start.c:308
        #8 0x55555595fd69 in _start (/home/jepler/src/micropython/ports/uni

    0x555555cd8dc8 is located 0 bytes to the right of global variable
    'import_str' defined in '../../py/repl.c:285:23' (0x555555cd8dc0) of
    size 8
      'import_str' is ascii string 'import '

Signed-off-by: Jeff Epler <jepler@gmail.com>
ksekimoto pushed a commit to ksekimoto/micropython that referenced this issue Jul 16, 2021
asan considers that memcmp(p, q, N) is permitted to access N bytes at each
of p and q, even for values of p and q that have a difference earlier.
Accessing additional values is frequently done in practice, reading 4 or
more bytes from each input at a time for efficiency, so when completing
"non_exist<TAB>" in the repl, this causes a diagnostic:

    ==16938==ERROR: AddressSanitizer: global-buffer-overflow on
    address 0x555555cd8dc8 at pc 0x7ffff726457b bp 0x7fffffffda20 sp 0x7fff
    READ of size 9 at 0x555555cd8dc8 thread T0
        #0 0x7ffff726457a  (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xb857a)
        micropython#1 0x555555b0e82a in mp_repl_autocomplete ../../py/repl.c:301
        micropython#2 0x555555c89585 in readline_process_char ../../lib/mp-readline/re
        micropython#3 0x555555c8ac6e in readline ../../lib/mp-readline/readline.c:513
        micropython#4 0x555555b8dcbd in do_repl /home/jepler/src/micropython/ports/uni
        micropython#5 0x555555b90859 in main_ /home/jepler/src/micropython/ports/unix/
        micropython#6 0x555555b90a3a in main /home/jepler/src/micropython/ports/unix/m
        micropython#7 0x7ffff619a09a in __libc_start_main ../csu/libc-start.c:308
        micropython#8 0x55555595fd69 in _start (/home/jepler/src/micropython/ports/uni

    0x555555cd8dc8 is located 0 bytes to the right of global variable
    'import_str' defined in '../../py/repl.c:285:23' (0x555555cd8dc0) of
    size 8
      'import_str' is ascii string 'import '

Signed-off-by: Jeff Epler <jepler@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants