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

So here's a summary HOW-TO, for posterity:

  • add this project to your Bela projects: http://github.com/giuliomoro/OSC2OLED4Bela . If you use a different project name, replace OSC2OLED4Bela with your project name in all the steps below.
  • open the project and build it. When running, it will not emit any audio, but you should be able to send it OSC messages on bela.local:7562 from the host computer. You can run it like this for testing.
  • to see what messages and formats are supported, see the parseMessage() function in render.cpp. For instance, you can send /osc-test followed by a float, /tr followed by a float (ignored) and/or a string, /param1 followed by a float. You can edit the program to change or add support for OSC messages
  • when you have a reliable way of sending OSC messages to it from the host, create a file /lib/systemd/system/osc2oled.service with this content:
[Unit]
Description=OSC to IC2 Screen Launcher
After=network-online.target

[Service]
ExecStart=/root/Bela/projects/OSC2OLED4Bela/OSC2OLED4Bela
Type=simple
Restart=always
RestartSec=1
WorkingDirectory=/root/Bela/projects/OSC2OLED4Bela
Environment=HOME=/root
KillMode=process

[Install]
WantedBy=default.target

This can be done from the terminal or by creating a file osc2oled.service in your project (make sure the file includes only the text above and none of the automatically-generated content in the file you create) and then linking it into place by running ln -s /root/Bela/projects/OSC2OLED4Bela/osc2oled.service /lib/systemd/system/osc2oled.service in the Bela IDE console.

  • start the process in the background with systemctl start osc2oled, stop it with systemctl stop osc2oled.
  • while running in the background, you can visualise the process's output with journalctl -fu osc2oled (if executing the command from the Bela IDE console, use journalctl -n 20 -u osc2oled | cat instead)
  • once you verify it is working, you can open a different Bela project and try to send OSC to it from the Bela project instead of the host
  • once you are happy, you can enable the osc2oled process to start automatically in the background at boot with systemctl enable osc2oled. Later you can disable it with systemctl disable osc2oled
  • caveat: when running at startup, the osc2oled service will probably start after the Bela program has started, so if you send OSC to it too early when your program starts, some content may not be visualised on the screen.
    9 days later

    giuliomoro

    thanks for the overview! nice one.
    i got everything working, up to sending OSC from a Pd patch to the background program -
    but only after referencing the logs and your subsequent answer four posts up.
    is it possible, for future reference for me and my fellow nitwits, to edit your post some, and have all the relevant info in this one place?
    to clarify:

    giuliomoro [Service]
    ExecStart=/root/Bela/projects/(NAME OF PROJECT)/(NAME OF PROJECT)
    Type=simple
    Restart=always
    RestartSec=1 (<< no need for http://bela.io/ i think?)
    WorkingDirectory=/root/Bela/projects/(OSC2OLED4Bela or NEW NAME OF PROJECT)
    Environment=HOME=/root
    KillMode=process

    i realise this might all be self-explanatory to some, but it's not to everybody 🙂

    also

    giuliomoro Bela IDE console, use journacltl -n 20 -u osc2oled | cat instead)

    has a typo in journalctl, which is meh if you copy/paste.

    and last,

    giuliomoro systemctl enable osc2oled

    doesn't seem to work with the /***** osc2oled.service *****/ header (generated in the IDE > new file) still on line 1 of the service file. had to remove that, so [unit] was the first thing in there. again, probably obvious to someone who knows what they're doing, but might save some frustration for others.

    feel free to delete this post after if needed.
    and thanks for walking us through this!

    Remork is the "http://bela.io/" supposed to be in the RestartSec line?

    D'OH

    Remork still has an L too many.

    D'OH D'OH

    :face_with_rolling_eyes:

    "pedantic" == reasonable in this case. Fixed now I think (again!).

    giuliomoro can't even get the emoji to work .

    LOL 🙂

    looks super now.
    but seriously, can you pin post 84 somewhere?
    add it to the Wiki maybe? i know i'll be looking for this in the future..

    I certainly can. I'll get that together next week when I'll have an OLED screen to hand to test with and post here once it's up.

    18 days later

    giuliomoro yeah wow, im at testing stage and im not sure where im going wrong, likely something very basic in the syntax in SC but i setup a simple osc path but no results...
    ''s.boot
    ~displayOSC = NetAddr.new("192.168.7.1", 7562);
    ~displayOSC.sendMsg('bela.local:7562', "magic!"); "
    ultimately aiming to send different plot values/waveshapes

    did you change the OSC2OLED4Bela program at all? I think you are not using the correct syntax and address.
    I think in its original form it only responds to a handful of OSC addresses:

    /osc-test + float, /tr + float + string, /param1 + float.

    So the following should work (running it from Sc on the host), while OSC2OLED4Bela is running on Bela:

    ~displayOSC = NetAddr.new("192.168.7.2", 7562);
    ~displayOSC.sendMsg('/osc-test', 123.23);
    ~displayOSC.sendMsg('/tr', 123.23, 'mystr');
    ~displayOSC.sendMsg('/param1', 123.23);

      giuliomoro ok great, this is helpful thank u, ill test with this and im sure ill have some questions shortly!

      giuliomoro hi, i have two related questions that could be more SC syntax related but i thought id try here first...if i were to try and plot this line to oled
      '''
      Signal.sineFill(1000, 1.0/[1,2,3,4,5,6]).plot;
      '''
      do i use .asString to speak to OSC or .asRawOSC?
      and a similar question about printing changing values to oled,
      is printing the value of this slider related to .envirPairs?
      '''
      Window.closeAll;
      w = Window ("gui", Rect(20,20,150,30))
      .front
      .alwaysOnTop(true);
      ~sliderx = Slider(w, Rect(20,20,150,30))
      ~sliderx.action
      ({
      arg obj;
      w.view.background_(Color.black);
      obj.value.postln;
      });
      '''
      thanks, trying to get a feel for the environment

        please use backticks ( ``` ) and not ' to enclose your code

        vivian if i were to try and plot this line to oled

        The currently supported functions are the ones above and they show the few types of prints you can get currently. U assume they display some basic text only, but I don't have a working display at hand, did you try them out? To obtain anything other than that, you'll need to write some custom C++ code. The available graphics functions are here https://github.com/giuliomoro/OSC2OLED4Bela/blob/master/SSD1306_OLED.h#L151-L165

        Looking at the names there, you'd probably to use drawPixel(). I don't actually know how to handle bundles in OSC neither from the Sc side or the C side, so I'll assume for simplicity that you are sending some float values and you want to show those, but there is definitely room for improvements!

        For instance, I expect that if you add this to the body of int parseMessage(oscpkt::Message msg, void* arg):

        	oscpkt::Message::ArgReader args = msg.match("/values");
            if(args)
            {
        		const unsigned int nValues = args.nbArgRemaining();
            	float values[nValues];
            	for(unsigned int n = 0; n < nValues; ++n)
            	{
            		if(args.isFloat())
            		{
        	    		args.popFloat(values[n]);
            		} else if(args.isInt32()) {
            			int i;
            			args.popInt32(i);
            			values[n] = i;
            		} else {
            			fprintf(stderr, "Wrong type at argument %d\n", n);
            			return -1;
            		}
            	}
            	// now tenValues contains the 10 values.
                // prepare a bitmap:
                printf("received: ");
                for(unsigned int n = 0; n < 10; ++n)
                	printf("%f ", values[n]);
                printf("\n");
                clearDisplay();
                for(unsigned int x = 0; x < SSD1306_LCDWIDTH; ++x)
                {
                	// we interpret each value as the vertical displacement and
                	// we want to draw a series of horizontal lines at the specified points
                	unsigned int valIdx = x * float(nValues) / SSD1306_LCDWIDTH;
                	unsigned int y = values[valIdx] * SSD1306_LCDHEIGHT;
                	drawPixel(x, y, WHITE);
                }
                Display();
            }

        then you can send

        ~displayOSC.sendMsg('/values', 0, 0.1);

        or

        ~displayOSC.sendMsg('/values', 0, 0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9);

        to display n horizontal bars which are placed left-to-right at a relative vertical positiony, as specified by each of the float arguments (range 0 - 1). If you pass as many arguments as the number of horizontal pixels in the display ( typically 128), then each bar will be one pixel wide. There must be a better way of doing this from Sc than specifying the numbers as comma-separated values and probably using OSC bundles it would be a better idea.

        vivian do i use .asString to speak to OSC or .asRawOSC?

        no idea, sorry.

        vivian Window.closeAll;
        w = Window ("gui", Rect(20,20,150,30))
        .front
        .alwaysOnTop(true);
        ~sliderx = Slider(w, Rect(20,20,150,30))
        ~sliderx.action({
        arg obj;
        w.view.background_(Color.black);
        obj.value.postln;
        });

        I am not sure what this does, but it would seem it's trying to create a slider in a GUI? There's no easy way to have the Sc GUI mirrored on the OLED display. You'll have to send dedicated commands which are parsed by the C++ file and sent to the display.

          5 days later

          not sure what you mean with "plot a graph behind "?

            giuliomoro sorry, similar to this example where there are pixel plots behind the float pixels
            alt text

            also i cant find how i can change the thickness of the float pixels displayed

            Right, so this requires a bit more of work. The thickness of the pixel is always 1 (the drawPixel command writes one pixel at a time). Also, we transitioned to another library which is more flexible and works with more screens. Here it is: https://github.com/giuliomoro/O2O/ . You can run that example as it is and use /waveform to achieve the same that you are currently achieving with /values.
            Did you add any other code to the current version of the library?