Hi,

I'm developing a BELA_I2C port of an Arduino sketch for the MPU-9150.

Where do I find documantation about the I2C implementation used on the Bela ?

I need to interface several I2C adresses. Do I need to instantiate one I2c object for each I2C address ?

I following the I2C_MPR121, but in the writeRegister(uint8_t reg, uint8_t value) method, no I2C address is used, which is why I'm wondering... I'm not very into I2C yet...

Any pointers would be appreciated 😉

Best,
Hjalte

    HjalteBestedMoeller I need to interface several I2C adresses. Do I need to instantiate one I2c object for each I2C address ?

    yes, if you are inheriting from our I2c virtual class.

    HjalteBestedMoeller I following the I2C_MPR121, but in the writeRegister(uint8_t reg, uint8_t value) method, no I2C address is used, which is why I'm wondering... I'm not very into I2C yet...

    This class expects you to have one different object per address. You set the I2C address in the call to initI2C_RW(). If you look at Bela/include/I2c.h, you will see that there is a line there that sets the address for the open file descriptor:

      if (ioctl(i2C_file, I2C_SLAVE, i2C_address) < 0){

    If you were to change address for the same object, you'd have to call this line every time you change the address, in advance of calling writeRegister().

    (also note that the last argument to initI2C_RW() is there for legacy reasons and it is ignored).

    Ok, I see...

    What about the defines etc. A lot seems not to come from I2c.h

    Defines like: I2C_M_RD where are they defined ?
    And what about:
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages[2];

    What is I2C_file ?

      HjalteBestedMoeller Defines like: I2C_M_RD where are they defined ?
      And what about:
      struct i2c_rdwr_ioctl_data packets;
      struct i2c_msg messages[2];

      these are all from <linux/i2c.h>, which is included by I2c.h and lives in /usr/include/linux/i2c.h.

      HjalteBestedMoeller What is I2C_file ?

      It is the file descriptor associated with the i2c bus opened in initI2C_RW(), and to which settings have been applied with calls ioctl() (e.g.: for the address).

      giuliomoro changed the title to Documentation on I2C ? .

      Now I have a working library for the MPU-9150 running 9-DOF sensor fusion using a Madgwick scheme.

      If anyone is interested in the code, let me know 😉

      During the development of this I wrote some I2c utility functions for setting / getting registers, that I think makes development of I2c device classes much easier. Maybe it would a good idea to make some general interface functions to facilitate development and add them to I2c.h ?

        a month later

        Hey all, I'm again in the (painful) process of interfacing Bela via i2c to some devices, in this case the NeoTrellis board from Adafruit. Last time I was working with i2c on Bela there was a better-i2c branch in development that seemed very nice. With that I was even able to get the data straight into PD and bypass completely the custom render.
        I see though that it never made it to the master branch!
        giuliomoro, what would be the easiest way to adapt the latest branch to have the same functionality?
        Thanks for everything!

        ah that branch brings so many headaches to my memory! It was abandoned because it was under tested and then everything else moved further, leaving it lagging behind, so that now it would be fairly convoluted to backport those changes ... Also, many i2c devices have a complicated communication protocol that is best deal with through a dedicated C++ library, than trying to do it from Pd...

        Is there a Linux library available for your device? That would be the first thing to know.

        In the case of our new Trill sensors, I integrated into the default_libpd_render.cpp a way to interface to a C++ library from Pd. All the TRILL-related code is included by the ENABLE_TRILL. That gives you an idea of the extent of work that would be required to integrate other similar features.

        An alternative to integrating it in the render file as done above, would be through an OSC layer. I have done that for Trill, too (to support people who do not use Bela, or those who use something else than Pd or C++ on Bela), so it's another example of what it would take to turn an existing, working library into an OSC-compatible one (see here).

          giuliomoro Hey Giulio, thanks for answering!
          Unfortunately the NeoTrellis (based on the Adafruit Seesaw) do not have a linux library. Its Arduino library seems too big to be ported, at least for my skills.
          Maybe with the I2c utility functions that HjalteBestedMoeller was talking about it would be easier to start making a stripped version of it. I found the basic i2c class to lack the utilities to read and write i2c commands.
          Do you know if there is a i2c library similar to the Arduino Wire library for Bela/BeagleBone?
          Or if you know some better approaches, let me know!

            Sindel I found the basic i2c class to lack the utilities to read and write i2c commands.

            Yes, that was a design choice: while most I2c devices work the same way in terms of reading and writing, that is not part of the i2c protocol itself. However, in the better-i2c branch I had indeed added such functions.

            Sindel Unfortunately the NeoTrellis (based on the Adafruit Seesaw) do not have a linux library. Its Arduino library seems too big to be ported, at least for my skills.

            link to the library? I'd be happy to have a look.

            It would seem that this "seesaw" board only requires I2C. It is definitely adaptable, but it requires some time. There are only a handful of Wire functions in use, and all should be fairly easy to emulate:

            Adafruit_seesaw.cpp:764:  _i2cbus->begin();
            Adafruit_seesaw.cpp:787:    _i2cbus->beginTransmission((uint8_t)_i2caddr);
            Adafruit_seesaw.cpp:788:    _i2cbus->write((uint8_t)regHigh);
            Adafruit_seesaw.cpp:789:    _i2cbus->write((uint8_t)regLow);
            Adafruit_seesaw.cpp:799:    _i2cbus->endTransmission();
            Adafruit_seesaw.cpp:807:    _i2cbus->requestFrom((uint8_t)_i2caddr, read_now);
            Adafruit_seesaw.cpp:810:      buf[pos] = _i2cbus->read();
            Adafruit_seesaw.cpp:836:  _i2cbus->beginTransmission((uint8_t)_i2caddr);
            Adafruit_seesaw.cpp:837:  _i2cbus->write((uint8_t)regHigh);
            Adafruit_seesaw.cpp:838:  _i2cbus->write((uint8_t)regLow);
            Adafruit_seesaw.cpp:839:  _i2cbus->write((uint8_t *)buf, num);
            Adafruit_seesaw.cpp:855:  _i2cbus->endTransmission();
            Adafruit_seesaw.cpp:910:  _i2cbus->beginTransmission((uint8_t)_i2caddr);
            Adafruit_seesaw.cpp:911:  _i2cbus->write((uint8_t)regHigh);
            Adafruit_seesaw.cpp:912:  _i2cbus->write((uint8_t)regLow);
            Adafruit_seesaw.cpp:916:  _i2cbus->endTransmission();

            I would be surprised if no one already implemented the methods in Wire.h on Linux, e.g.: for a Raspberry Pi ...

            Thanks for the summary of the i2c functions!
            In any case I could find only one implementation of the Wire library for BeagleBone, here [https://github.com/AbhraneelBera/wiringBone/]. If you tell me that it won't conflict with the other pin setting in Bela I will give it a try!

            That seems ok. It seems to be using the i2c-1 bus although the docs say "i2c-2" . There is nothing on Bela on i2c-1, so there should be no conflicts there. The i2c-1 pins on Bela are highlighted here.

            a month later

            giuliomoro Sure, I was simply thinking about read/write utilities along what I implemented in I2cFunctions in this project:

            https://github.com/HjalteBested/BelaMPU9150

            I just thought that many people would write some very similar code, so it would be nice with a more streamlined approach.... Function for readByte, writeByte ,. readBytes, writeBytes to handle consecutive addresses.... could also have writeReg16, readReg16 etc..

            readBit, writeBit.

            2 years later

            A couple of us over here have been using the Neotrellis with Bela/PEPPER using Adafruit's Python library.
            Audio processes written in C talk to an OSC server written in Python which drives the Neotrellis. With this decoupling, the Neotrellis can be connected to the Bela or to a remote host (eg I glued a Pi Zero to it once).

            Performance is poor, we are more interested in having the Neotrellis hooked up to the Bela directly now, and we are not interested in using Python for this aspect of things anymore. So just putting this here. Poking around regarding Seesaw support in Rust or C; will review what's posted here.

            • Lia replied to this.
              10 days later

              plate-of-shrimp Hi! I'm also interested in connecting NeoTrellis directly to Bela using I2C. Did you have any success doing this? Thanks! 🙂

              Hi @Lia !

              On the C front, Adafruit's Seesaw/NeoTrellis library is on top of Arduino, so I have tried to skim off the non-Arduino bits and replace the pure I2C bits by talking to i2c-dev as exposed by the Linux kernel. I can get a plausible hardware ID from the NeoKeys but can't light up a NeoPixel yet.

              On the Rust front, cross-compilation seems to reveal a possible library-version-skew problem wrt linux-embedded-hal, which I hoped I could use to leverage stuff in embedded-hal that supports Seesaw (and hence NeoTrellis). Upshot is I can't cross compile. So I tried native compiling and things never finish, it looks like I just run out of memory. Well, there were reasons people were cross-compiling in the first place.

              (if we get any further with this we should break it out to a new topic.)