We have upgraded the community system as part of the upgrade a password reset is required for all users before login in.

I2C and C++



  • Hey all,

    I have been toying with the I2C driver in C++, however I am running into a problem. I got the header files and .so files on the Omega2+ (some were already loaded) and finally got the make to run correctly. However, the debugger is throwing an error with a method such as i2c_readByte. I will post the actuall error message tomorrow morning (not by the Omega at the moment). It almost seems like there needs to be an I2C object declared similar to the python version. However, I can't find the constructor in any of the source files. Is there one? How would I call a method without having on object defined?

    I haven't slept well in the past few days, so I might be completely overlooking something.

    Thanks,

    N

    Edit: The error messages

    OnionBME280.cpp:(.text+0x3c): undefined reference to `i2c_readByte'
    

    Edit: The very simple test code

    #include <stdio.h>
    #include <stdlib.h>
    #include <onion-i2c.h>
    
    int main()
    {
    	int status, rdByte;
    
    	status = i2c_readByte(0, 0x76, 0x88, &rdByte);
    
    	// Print Results
    	printf("The result is: %i", status);
    
    	return 0;
    }


  • Are you compiling on the Omega2 or cross compiling? Have you used the -lonioni2c flag?
    Agains what binary file are you linking? I've found that when I try to link against the libonioni2c.so that is provided in the package, linking fails. That's why I recompiled the libraries and then linking works.

    See e.g. https://github.com/gamer-cndg/omega2-wii-classic-controller and https://github.com/gamer-cndg/omega2-libs.

    I2C definetly works with C++, because I've written https://github.com/maxgerhardt/omega2-lmic-lorawan (see SC18IS602B.cpp) and that worked.



  • @Maximilian-Gerhardt I am compiling on the Omega2. I do have the flag in the make file. I am using the binary from that was pre-compiled; though I am not sure if I installed it from the GitHub Repo or it it already existing on the Omega2 out of the box.

    My make file:

    # main compiler
    CC = g++
    
    TARGET1 := OnionBME280
    LIBS := "-loniondebug -lonioni2c"
    
    all: $(TARGET1)
    
    $(TARGET1): 
    	@echo "Compiling C program"
    	$(CC) $(CFLAGS) $(TARGET1).cpp -o $(TARGET1) $(LDFLAGS) $(LIB)
    
    clean:
    	@rm -rf $(TARGET1) $(TARGET2)
    

    I will take a stab at recompiling the dynamic library, though I am not a g++ guru (which may be very obvious from my makefile) and I may have issue compiling it.

    Thank you for the example, I will definitely take a look. I learn in odd manners and an effective way to use an existing example and toy around with it.

    I see Kit Bishop posts here and has a library on GitHub. Any benefit to using that over Onion's?

    Thank you for your input!



  • @larry-biscuits I'm only ever cross-compiling my programs for the Omega2. Your issue may well be that you either can't link against the I2C library or GCC can't find it.

    For the latter, make sure you opkg update && opkg install libonioni2c. You can give GCC a path to the folder where the libonion2c.so is using the -L flag. The path should be /usr/lib/.. or something.

    When you want to try cross-compiling, you should use a Xubuntu 17 virtual machine (Ubuntu 18 needs a small patch to work) and compile LEDE and the toolchain as instructed in https://github.com/OnionIoT/source. Takes several hours. Or use their docker container.

    After you have a working mipsel-openwrt-linux-g++ you can cross-compile https://github.com/OnionIoT/i2c-exp-driver or just use the one from my omega2-libs folder above. With that, you can cross-compile your OnionBME280.cpp and link against the libonioni2c.so.

    Or, even easier, you can try downloading the libonioni2c.so from my repo above and try to compile and link it on the Omega2. Just make sure you use -L . to reference the current directory as a library path so that it wil maybe try to use the local .so file instead of the system's installed one..



  • Definitely got it up and running, though I got some really weird data out of a BME280 Temp, Press, Humidity sensor. It appeared one of the registers was not being read correctly. I am thinking there might be an issue with the I2C library? I compiled the same code on a Pi and it worked without problem. On the Omega, the data seemed fine until the temperature rose above a certain value (a few degrees C above room temp, heat from my finger). Once it got above this value, it seemed the read on one of the registers turns negative which doesn't seem correct.

    I recorded the register data from the Python version of the BME280 code run on the Omega and compared against the C++ code on the Omega. I couldn't find anything in the code; I even stepped through all of the raw data. It appeared that the difference/error between the Python and the C++ code was in the raw data from the I2C read function.

    I am cranking on something else at the moment and I will have to find time to crack this nut. If anyone is interested, I can post the code to see if there may be something wrong with the I2C C++ library. I have not been able to find a whole of example code, etc. for the Omega's using C++. The overwhelming majority of code out there is in Python. I am chasing down the C++ path since I am trying to build a fairly complicated program for performing analysis and need the interop so I can have the ability to blast code to an ARM, or other processor architecture.

    Again, total disclosure, I could be the one messing something up. I do a lot of dumb things.

    @Maximilian-Gerhardt thanks again for your guidance. I do believe the hiccup I initially hit was due to the .so library file. Once recompiled, it seemed fine.



  • @larry-biscuits I'd be happy to look over the code. The major difference between C++ and Python is arbitrary integer length. Your suddenly negative number could arrise from you having an integer overflow, e.g. when storing something an in int8_t.

    Do you have an example of a register value which yields two different values when decoded with the C++ and the Python problem? That way the problem can be found very quickly.



  • @larry-biscuits exactly how did you get it working? I have the exact same problem and have tried all suggestions in this post and nothing has worked.



  • @Brian-Franklin What exact code are you running and what exact problem do you have?



  • @Maximilian-Gerhardt

    // This is my main.cpp

    #include <iostream>
    #include <onion-i2c.h>

    // confirmed /usr/include/onion-i2c.h exists
    // confirmed /usr/lib/liboniondebug.so exists
    // confirmed /usr/lib/libonioni2c.so exists

    int main(int argc, char* argv[])
    {

    std::cout << "\nTest I2C Start\n" ;
    
    int status, val;
    
    status = i2c_readByte(0, 38, 0, &val);
    
    std::cout << val;	
    
    std::cout << "\nTest I2C End\n\n" ;
    
    return 0;
    

    }

    during the linking

    g++ main.o -o minitesti2c -loniondebug -lonioni2c

    main.o: In function 'main':
    /sources/minitesti2c/main.cpp: undefined reference to 'i2c_readByte'
    /sources/minitesti2c/main.cpp: undefined reference to 'i2c_readByte'
    collect2: error: ld returned 1 exit status

    From the above suggestions I changed the test function to i2c_write

    i2c_write(0, 56, 0, 112);

    and the errors that come back are

    /sources/minitesti2c/main.cpp: undefined reference to 'i2c_write'
    /sources/minitesti2c/main.cpp: undefined reference to 'i2c_write'

    so then I copied the files /usr/lib/liboniondebug.so and /usr/lib/libonioni2c.so to the local directory and changed the link to

    g++ -L/sources/minitesti2c/ main.o -o minitesti2c -loniondebug -lonioni2c

    same error(s)

    so then I copied the libraries reference above from

    https://github.com/gamer-cndg/omega2-libs

    put them in the /sources/minitest2c/ directory

    same errors(s)

    I can confirm that my i2c chip is wired correctly

    i2cdetect -y 0 shows device at 0x38

    i2cset -y 0 0x38 0x70 works!

    i2cget -y 0 0x38 works. return 0x70!

    I don't know what to try next.



  • This post is deleted!


  • @Brian-Franklin said in I2C and C++:

    so then I copied the libraries reference above from
    https://github.com/gamer-cndg/omega2-libs
    put them in the /sources/minitest2c/ directory
    same errors(s)

    You should temporarily rename the .so libraries

    // confirmed /usr/lib/liboniondebug.so exists
    // confirmed /usr/lib/libonioni2c.so exists

    to something else so that the linker doesn't attempt to link against these. Then add -L . to the compiler options to add the current directory (.) to the linker search path.



  • @Maximilian-Gerhardt Thank You.

    I have been fighting against an error where it looked like the linker was not finding my the shared libonioni2c.so. Your suggestion about first renaming the current files /usr/lib/libonioni2c.so to /usr/lib/libonioni2c.so.XX and /usr/lib/liboniondebug.so to /usr/lib/liboniondebug.so.XX was a good suggestion.

    My error changed to libonioni2c.so not found. So it shows me the linker was finding the correct shared object but there was something wrong with that libonioni2c.so share object. then I copied the shared objecs from github https://github.com/gamer-cndg/omega2-libs and put them in /usr/lib and everything worked!!!

    2 weeks I have wasted.

    Now I don't know what is in those shared objects or what is different but at least I can continue building my project.

    From my 2 weeks of trying everything I have concluded that the shared object libraries provided in the standard distribution for the 2+ libonioni2c.so and/or liboniondebug.so are defective.


Log in to reply
 

Looks like your connection to Community was lost, please wait while we try to reconnect.