• Hardware
  • is anyone successfully using i2c OLED / LCD?

Hi! I've been working with @RafaeleAndrade to get this type of OLED display (SSD1306) working for our respective Bela projects; I got the example code working for the i2c-1 ports on our Bela Original and Bela Mini, by making these alterations:

in SSD1306_OLED.c: replace I2C_DEV_2 with I2C_DEV_1

in I2C.h:
add #define I2C_DEV1_PATH "/dev/i2c-1”
add extern int init_i2c_dev1(unsigned char slave_address);

in I2C.c:
add I2C_DeviceT I2C_DEV_1;
add a duplicate of the init_i2c_dev2 function, but altered to dev1

in Main.c:
replace I2C_DEV2 with I2C_DEV1
replace ic2_dev2 with i2c_dev1
replace i2c-2 with i2c-1

I've put these files up online here: https://github.com/crosswick/SSD1306-OLED-display-driver-for-BeagleBone

So part 1 of the instruction that @giuliomoro gave above works, the example code is running outside of the Bela environment. For inside the Bela environment, I stumbled upon the error no matching function for call to 'Bela_createAuxiliaryTask', which was fixable by changing
void* oledTaskFunction(void*) to
void oledTaskFunction(void*)

Also I needed to add to render.cpp:

void render(BelaContext *context, void *userData)
{
}

void cleanup(BelaContext *context, void *userData)
{
}

After that, I get a Segmentation Fault:

Segmentation fault
bela: Makefile:524: recipe for target 'runide' failed
make: *** [runide] Error 139

So any help with that would be much appreciated; I presume we should take a good look at what this SSD1306_OLED code is doing in terms of memory allocation?

BTW, in terms of hardware: with the specific display module that we have available in our hackerspace, namely https://nl.aliexpress.com/item/32595065663.html, we had to not only change the resistors on the back side to change it from SPI to i2c mode; also the RES pin needs to be involved by adding a small RC circuit, found on the Axoloti forum here: http://community.axoloti.com/t/spi-i2c-oled-display/638/187

here you go, for now it's only the basic but altered render.cpp:

#include <Bela.h>
extern "C" {
int oled_main(void);  // declare the oled_main() function from Main.c
}
AuxiliaryTask oledTask;
void oledTaskFunction(void*)
{
    while(!gShouldStop){ // run the content of the loop until the program stops
        oled_main();
        usleep(50000); // always sleep in a busy loop to avoid hogging all the CPU
   }
}
bool setup(BelaContext* context, void* userData)
{
    Bela_createAuxiliaryTask(oledTaskFunction, 1, "oledTask", NULL);
    Bela_scheduleAuxiliaryTask(oledTask);
}
// optional: add some sound generator into render()

void render(BelaContext *context, void *userData)
{
}

void cleanup(BelaContext *context, void *userData)
{
}

    crosswick

    AuxiliaryTask oledTask;
     ...
    bool setup(BelaContext* context, void* userData)
    {
        Bela_createAuxiliaryTask(oledTaskFunction, 1, "oledTask", NULL);
        Bela_scheduleAuxiliaryTask(oledTask);
    }

    The issue is that you are not assigning the return value of Bela_createAuxiliaryTask to the oledTask variable, therefore you are passing it uninitialized to Bela_scheduleAuxiliaryTask().

    The fix is this:

    bool setup(BelaContext* context, void* userData)
    {
        oledTask = Bela_createAuxiliaryTask(oledTaskFunction, 1, "oledTask", NULL);
        Bela_scheduleAuxiliaryTask(oledTask);
    }

    I see... to be honest I'm not yet very knowledgeable about such inner workings, for now I'm just trying to get your code working as you suggested it earlier in this thread.

    Adding oledTask = and cleaning/recompiling the project still gives me a Segmentation Fault:

    Running project...
    (Main)i2c-1: Bus Connected to SSD1306
    Segmentation fault
    Makefile:524: recipe for target 'runide' failed
    make: *** [runide] Error 139

      This is better. You see that now it is actually running the task (as you can tell from the fact that the line

      (Main)i2c-1: Bus Connected to SSD1306

      is printed).

      I started debugging this by copying all your code to the board and trying to run the files from your repo as a stand-alone app, and that would fail at compile time. I fixed it with this.

      Then, I managed to build a stand-alone program (non-Bela) and run it, but it would only display (Main)i2c-1: Bus Connected to SSD1306 and would not actually show anything on the display.
      Did you see the test animation on the display?

      Next thing I did was to check out the upstream code (basically, your code without your changes), which is hardcoded to use I2C-2. Once I managed to get it to build (needed the same fix as above), it ran just fine.
      I also fixed a buffer overflow that was an accident waiting to happen.

      I applied some minimal changes to be able to use i2c-1, without having to go through the whole renaming process you undertook.

      After that, the stand-alone application works fine on i2c-1 as well.

      Then I copied the files thus updated into the project, and I got to the same point you were at:

      crosswick Running project...
      (Main)i2c-1: Bus Connected to SSD1306
      Segmentation fault
      Makefile:524: recipe for target 'runide' failed
      make: *** [runide] Error 139

      (note this took me over 1 hour, and I could have saved all of that time if you had sent me the code ready to test).

      The compiler actually gives you a warning that is the key to solve the issue:

      /root/Bela/projects/ssd/render.cpp:17:1: warning: control reaches end of non-void function [-Wreturn-type]
      }
      ^
      1 warning generated.

      This means that you are supposed to return a value from setup() and you are not. If the initialization goes well, you should return true.

      So this works for me:

      bool setup(BelaContext* context, void* userData)
      {
          oledTask = Bela_createAuxiliaryTask(oledTaskFunction, 1, "oledTask", NULL);
          Bela_scheduleAuxiliaryTask(oledTask);
          return true;
      }

      For the avoidance of doubt, here is a repo containing a complete Bela project where this code is working correctly. Note that the program may take a while to stop after you hit stop, because the oled_main() function takes forever to return.

        Thanks @giuliomoro. First off, to address this:

        giuliomoro (note this took me over 1 hour, and I could have saved all of that time if you had sent me the code ready to test).

        I highly value your time and enormous help on this forum... I had doublechecked that the code worked on my Bela Mini before I uploaded it to github. I just checked again and these steps work for me:

        • download the .zip from https://github.com/crosswick/SSD1306-OLED-display-driver-for-BeagleBone
        • in the Bela interface, create a new C++ project called 'OLED_test_github'
        • use 'Upload file' to add the seven relevant .h and .c files to the project
        • with Terminal and ssh root@192.168.7.2, navigate to Bela/projects/OLED_test_github
        • run gcc *.c -o oled which returns a bunch of warnings but no errors;
        • run ./oled which makes the display connected to ic2-1 perform the test animations.

        My Bela Mini is running v0.3.6b, which I believe is the latest version.

        hmm that's interesting, I am wondering if you have a very very old Bela image (circa 2016)?

        Otherwise the second of these lines in I2C.c should break

        #include<linux/i2c.h>
        #include<linux/i2c-dev.h>

        ?

        Can you run grep v0 /etc/motd on the board? What does it return?

          giuliomoro This means that you are supposed to return a value from setup() and you are not. If the initialization goes well, you should return true.

          Great! it also works for me. I can now go on to test out these display functions from within PD; my plan is to use the customRender PD example project as a starting point.

          Thank you!

          giuliomoro Can you run grep v0 /etc/motd on the board? What does it return?

          Bela image, v0.3.6b, 23 October 2018

          giuliomoro and grep linux /root/Bela/projects/OLED_test_github/* ?

          /root/Bela/projects/OLED_test_github/I2C.c:#include<linux/i2c.h>
          /root/Bela/projects/OLED_test_github/I2C.c:#include<linux/i2c-dev.h>
          grep: /root/Bela/projects/OLED_test_github/build: Is a directory
          Binary file /root/Bela/projects/OLED_test_github/oled matches

          and what's the output of

          dpkg -l | grep i2c

          ?

          ii i2c-tools 3.1.2-3 armhf heterogeneous set of I2C tools for Linux

          I did use i2cdetect earlier to check whether the display module was connected... I don't recall exactly if I installed it or if it was already there. Maybe that makes a difference?

          right so the problem is on my board, where I have actually installed an extra package libi2c-dev, which causes the an error when including both files listed above. UOPS!

            🙂 let me know if I can be of any further assistance. I think it might be best for me to first work on the PD integration and after that write up a how-to.

              giuliomoro Giulio, thanks a lot for your assistance and attention! After the post 30 I was able to connect my bela on the OLED screen. crosswick will try to connect it on PD, and I'll try to connect on Sc now. we'll keep you update! I'm also up to write a documentation about it 🙂

              15 days later

              Good news - I've got an application running that can run independently from PD or SC, that translates incoming OSC messages into SSD1306 display commands.

              I've been heavily inspired by this conversation: https://forum.bela.io/d/497-how-do-i-get-two-programs-running-at-the-same-time

              Also I've read elsewhere on the forum that for starting up a second/background application like this, it should be possible to use a self-made run.sh script in the project directory.

              Two questions now that I'm having a challenge figuring out:
              - in run.sh, after starting up the OSC->OLED application, how do I resume the normal Run procedure for a PD or SC project?
              - is there a similar way to end/kill the application that is triggered by the Stop button in the IDE interface?

                Hey @crosswick & @giuliomoro

                Trying to get an OLED display to work based on the repo @giuliomoro posted in reply #30 (https://github.com/giuliomoro/bela-ssd1306) and I'm actually getting the following warnings and a runide error:

                Build finished
                In file SSD1306_OLED.c: [warning] passing 'const unsigned char *' to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 33, line: 2419
                In file SSD1306_OLED.c: [warning] passing 'char [3]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 22, line: 2430
                In file SSD1306_OLED.c: [warning] passing 'const unsigned char *' to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 30, line: 2442
                In file SSD1306_OLED.c: [warning] passing 'char [3]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 20, line: 2443
                In file SSD1306_OLED.c: [warning] passing 'char *' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 22, line: 2479
                In file SSD1306_OLED.c: [warning] passing 'char [4]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 26, line: 2657
                In file SSD1306_OLED.c: [warning] passing 'char [4]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 26, line: 2659
                In file SSD1306_OLED.c: [warning] passing 'char [4]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 26, line: 2661
                In file SSD1306_OLED.c: [warning] passing 'char [4]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 26, line: 2663
                In file SSD1306_OLED.c: [warning] passing 'char [2]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 24, line: 2686
                In file example_app.c: [warning] passing 'char [7]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 15, line: 261
                In file example_app.c: [warning] passing 'char [14]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 15, line: 286
                In file example_app.c: [warning] passing 'char [3]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 15, line: 293
                In file example_app.c: [warning] passing 'char [19]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 17, line: 377
                In file example_app.c: [warning] passing 'char [21]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 17, line: 379
                In file example_app.c: [warning] passing 'char [10]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign] column: 17, line: 382
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2419:33: warning: passing 'const unsigned char *' to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]    
                     return print(strPtr, strlen(strPtr));                                
                                  ^~~~~~
                /usr/include/string.h:394:35: note: passing argument to parameter '__s' here
                extern size_t strlen (const char *__s)
                                                 ^
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2430:22: warning: passing 'char [3]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]
                return print_str("\r\n");                     
                                 ^~~~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2417:38: note: passing argument to parameter 'strPtr' here
                short print_str(const unsigned char *strPtr)                                     
                                                    ^
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2442:30: warning: passing 'const unsigned char *' to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]    
                n = print(strPtr, strlen(strPtr));                             
                          ^~~~~~
                /usr/include/string.h:394:35: note: passing argument to parameter '__s' here
                extern size_t strlen (const char *__s)                                 
                                                 ^
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2443:20: warning: passing 'char [3]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]
                 n += print_str("\r\n");
                                ^~~~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2417:38: note: passing argument to parameter 'strPtr' here
                short print_str(const unsigned char *strPtr)
                                                    ^
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2479:22: warning: passing 'char *' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]
                return print_str(str);
                                 ^~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2417:38: note: passing argument to parameter 'strPtr' here
                short print_str(const unsigned char *strPtr)
                                                    ^
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2657:26: warning: passing 'char [4]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]
                return print_str("nan");
                ^~~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2417:38: note: passing argument to parameter 'strPtr' here
                short print_str(const unsigned char *strPtr)                                     
                                                    ^
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2659:26: warning: passing 'char [4]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]
                return print_str("inf");                         
                                 ^~~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2417:38: note: passing argument to parameter 'strPtr' here
                short print_str(const unsigned char *strPtr)
                                                    ^
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2661:26: warning: passing 'char [4]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]
                return print_str("ovf");  // constant determined empirically
                                 ^~~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2417:38: note: passing argument to parameter 'strPtr' here
                short print_str(const unsigned char *strPtr)
                                                    ^
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2663:26: warning: passing 'char [4]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]
                return print_str("ovf");  // constant determined empirically
                                 ^~~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2417:38: note: passing argument to parameter 'strPtr' here
                short print_str(const unsigned char *strPtr)
                                                    ^
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2686:24: warning: passing 'char [2]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]
                n += print_str(".");
                               ^~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.c:2417:38: note: passing argument to parameter 'strPtr' here
                short print_str(const unsigned char *strPtr)
                                                    ^
                10 warnings generated.
                /root/Bela/projects/bela-ssd1306/example_app.c:261:15: warning: passing 'char [7]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]    
                print_str("scroll");
                          ^~~~~~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.h:172:45: note: passing argument to parameter 'strPtr' here
                extern short print_str(const unsigned char *strPtr); 
                                                           ^
                /root/Bela/projects/bela-ssd1306/example_app.c:286:15: warning: passing 'char [14]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]    
                print_str("HELLO FELLAS!");
                          ^~~~~~~~~~~~~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.h:172:45: note: passing argument to parameter 'strPtr' here
                extern short print_str(const unsigned char *strPtr);
                                                           ^
                /root/Bela/projects/bela-ssd1306/example_app.c:293:15: warning: passing 'char [3]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]
                print_str("0x");
                          ^~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.h:172:45: note: passing argument to parameter 'strPtr' here
                extern short print_str(const unsigned char *strPtr);
                                                           ^
                /root/Bela/projects/bela-ssd1306/example_app.c:377:17: warning: passing 'char [19]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]    
                print_strln("deeplyembedded.org"); 
                            ^~~~~~~~~~~~~~~~~~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.h:174:47: note: passing argument to parameter 'strPtr' here
                extern short print_strln(const unsigned char *strPtr);
                                                             ^
                /root/Bela/projects/bela-ssd1306/example_app.c:379:17: warning: passing 'char [21]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]    
                print_strln("Author:Vinay Divakar");
                            ^~~~~~~~~~~~~~~~~~~~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.h:174:47: note: passing argument to parameter 'strPtr' here
                extern short print_strln(const unsigned char *strPtr);
                                                             ^
                /root/Bela/projects/bela-ssd1306/example_app.c:382:17: warning: passing 'char [10]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]    
                print_strln("THANK YOU");
                            ^~~~~~~~~~~
                /root/Bela/projects/bela-ssd1306/SSD1306_OLED.h:174:47: note: passing argument to parameter 'strPtr' here
                extern short print_strln(const unsigned char *strPtr);                                             
                                                             ^
                6 warnings generated.
                Running project...
                (Main)i2c-2: Bus Connected to SSD1306
                Makefile:524: recipe for target 'runide' failed
                make: *** [runide] Error 1

                I also want to just confirm the correct pin connections and I2C bus to be using when using the files in the repo linked above. It seemed at the beginning of the thread that it made most sense to connect to the I2C1 bus, but I noticed in the terminal that it says "(Main)i2c-2: Bus Connected to SSD1306" - so I'm also wondering whether I'm connecting to the wrong bus.

                My breadboard is currently set up with a Bela Mini like this:

                Ground: P2_21
                VIN: P2_23
                SCL: P2_9
                SDA: P2_11

                Is this correct? Or should I be using I2C2? i.e.:
                Ground: P2_21
                VIN: P2_23
                SCL: P1_26
                SDA: P1_28

                Per @crosswick's note concerning the RST pin - I'm using the circuit noted here:
                http://community.axoloti.com/t/spi-i2c-oled-display/638/187

                Specifically - I've got a 10k resistor connected to the 3.3V rail, a 68nf cap connected to ground - I'm running a wire at the junction point on the terminal strip where the 10k resistor meets the 68nf cap to another terminal strip where a 100k resistor is tied to ground and I have a wire from that strip connected to the RST pin.

                Is this the correct way to deal with the RST pin? I've seen other examples where RST is connected to a GPIO pin - but there doesn't appear to be an RST pin noted in the code anywhere and it isn't mentioned in this thread explicitly either.

                Just trying to get this example code running so I can move on to some more fun visuals!