Hi guys, sorry if this question has been asked (I have checked everywhere it seems) but I am struggling to integrate the u8g2 library into my project. I have carried out the example with my display and it works perfectly (with the adapted function for my display). However, when making my new project, I don't know where to add this library. I have tried downloading the full library zip and the IDE won't allow me to upload/implement have more than one layer of folder.

Any help on this would be greatly appreciated!

the IDE is a bit grumpy about creating subfolders or more in general manage so many files as in this project. The best option is to do "save project as" to duplicate the original project and start working from there. There's also the option of keeping the O2O project standalone and run it alongside your audio-processing project (see here)

Thanks very much for this!

If I were to just download the O2O project and remove all files except for main.cpp and the U8G2 folder, then modify the main.cpp to remove any pd integration (as this won't be used for this project) would this cause any issue?

Is there anything within the settings file or any of the others that is necessary for the OLED integration?

Thanks again for all of your help!

    aaronBelaIssue would this cause any issue?

    it should be fine

    aaronBelaIssue Is there anything within the settings file or any of the others that is necessary for the OLED integration?

    Yes in the project settings you need to have in the Maker parameters box: CFLAGS=-I$(PROJECT_DIR)/u8g2/csrc;CPPFLAGS=-I$(PROJECT_DIR)/u8g2/csrc"

    22 days later

    ``Hi giuliomoro

    I have been working away at this and I was wondering about integrating trill into a live updating display. I want to basically entirely keep this project in c++ without the use of puredata (only sending a basic message for now but eventually without PD entirely).

    I am having trouble with the trill integration however, The value doesn't seem to be updating at all. I am just starting basic by drawing a bar dependent on the horizontal position whenever the bang is pressed in local.pd.

    Is there a way to achieve this, or an approach without PD at all? Sorry if this is a basic or understanding issue at all I have attached the relevant code snippets below.

    Any support with this would be greatly appreciated 🙂

    
    void trillLoop(void*)
    {
    	while(!Bela_stopRequested())
    	{
    		// Read locations from Trill sensor
    		touchSensor.readI2C();
    
    		gTouchSize = touchSensor.compoundTouchSize();
    		gTouchPosition[0] = touchSensor.compoundTouchHorizontalLocation();
    		gTouchPosition[1] = touchSensor.compoundTouchLocation();
    		usleep(gTaskSleepTime);
    	}
    }
    
    
    bool setup(BelaContext *context, void *userData)
    {
    	pinMode(context, 0, gInputPin, INPUT); //set input
    
    	if(touchSensor.setup(1, Trill::SQUARE) != 0) {
    		fprintf(stderr, "Unable to initialise Trill Square\n");
    		return false;
    	}
    
    	touchSensor.printDetails();
    
    	// Set and schedule auxiliary task for reading sensor data from the I2C bus
    	Bela_runAuxiliaryTask(trillLoop);
    
        return true;
    }
    
    
    
    
    
    void drawSensorInputAsBar(U8G2 &u8g2) {
        u8g2.clearBuffer();
        int displayWidth = u8g2.getDisplayWidth();
        int displayHeight = u8g2.getHeight();
        //u8g2.drawStr(0, 7, "| __ )| ____| |      / \\");
    
        int barWidth = 10; // Width of the bar to be drawn
        int barHeight = displayHeight; // The bar spans the full height of the display
    
        int barXPosition = static_cast<int>(gTouchPosition[0] * (displayWidth - barWidth));
    
        // Draw the vertical bar according to the touch position
        barXPosition = max(0, min(barXPosition, displayWidth - barWidth));
        u8g2.drawBox(barXPosition, 0, barWidth, barHeight); // Draw a vertical bar
    }
    
    ///.........
    else if (msg.match("/drawParams"))
    	{		
    		drawSensorInputAsBar(u8g2);
    	 
    	 }

      aaronBelaIssue Sorry for the formatting the insert code did not seem to recognise some areas

      The code button in the toolbar behaves differently according to what you have selected when you press it. If you have a single line, it enclose it in `single backticks` for inline code, but if you have multiple lines it uses

      ```
      triple backticks
      ```

      for
      block code

      aaronBelaIssue an approach without PD at all?

      Of course, just drawing inspiration from O2O's main.cpp file, as you seem to be doing already. If you are doing everything in a single process, then there may not be need for the OSC communication.

      aaronBelaIssue r, The value doesn't seem to be updating at all.

      The commands you are using in drawSensorInputAsBar() only update the in-memory buffer. You then need to call u8g2.sendBuffer(); to send the buffer to the display. Then, if drawSensorInputAsBar() is called at all, the display should be refreshed as expected.

      Thanks very much for this! I am a little confused with the trill integration basically no matter what i try I can't get the trill values to update, would the use of main instead of render be an issue? The trill sensor has been initialised, as has the auxiliary task. I have gotten trill to work for parameter control (in other projects) but not with the OLED display in the 'main' function outlined in the O2O or in the parseMessage section.
      If you need any code at all please let me know.

        aaronBelaIssue The trill sensor has been initialised, as has the auxiliary task

        Are you sure about that? If you have a main() function in your code, none of the Bela's setup or render will be called. As a matter of fact, do you see a print out such as

        Device Type: Square
        Address: 0x28
        Firmware version: 2

        ? That should happen when touchSensor.printDetails(); gets executed. If you don't see that printout, then setup() is not being called.

        > aaronBelaIssue If you need any code at all please let me know.

        Don't worry about that, I'll just keep guessing and stabbing in the dark as I've done so far :-O
        Please send all relevant code, i.e.: at least any file you have changed from the original O2O repo.

        Ahhh okay that must be where the issue is! I have exclusively been using render etc so far so 'main' I kinda assumed to be same foolishly. I need to look into how to fox this then.

        ill just attatch the main.cpp file its not much different honestly there is a little bit of trimming of other functions plus the new drawParams that has been added.

        const unsigned int gI2cBus = 1;
        #define DELAY_BUFFER_SIZE 44100
        int remotePort = 7563;
        unsigned int gActiveTarget = 0;
        const int gLocalPort = 7562; //port for incoming OSC messages
        
        
        Trill touchSensor;
        
        int gInputPin = 0;
        float gTouchPosition[2] = { 0.0 , 0.0 };
        float gTouchSize = 0.0;
        unsigned int gTaskSleepTime = 12000; // microseconds
        
        float positionXsensor = 0;
        float positionYsensor = 0;
        float largeNumber;
        
        
        
        
        void loop(void*)
        {
        	while(!Bela_stopRequested())
        	{
        		// Read locations from Trill sensor
        		touchSensor.readI2C();
        
        		gTouchSize = touchSensor.compoundTouchSize();
        		gTouchPosition[0] = touchSensor.compoundTouchHorizontalLocation();
        		gTouchPosition[1] = touchSensor.compoundTouchLocation();
        		usleep(gTaskSleepTime);
        	}
        }
        
        
        bool setup(BelaContext *context, void *userData)
        {
        	pinMode(context, 0, gInputPin, INPUT); //set input
        
        	if(touchSensor.setup(1, Trill::SQUARE) != 0) {
        		fprintf(stderr, "Unable to initialise Trill Square\n");
        		return false;
        	}
        
        	//touchSensor.printDetails();
        
        	// Set and schedule auxiliary task for reading sensor data from the I2C bus
        	Bela_runAuxiliaryTask(loop);
        
            return true;
        }
        
        
        
        
        
        void drawSensorInputAsBar(U8G2 &u8g2, float xVal) {
            u8g2.clearBuffer();
            int displayWidth = u8g2.getDisplayWidth();
            int displayHeight = u8g2.getHeight();
            //u8g2.drawStr(0, 7, "| __ )| ____| |      / \\");
        
            int barWidth = 20; // Width of the bar to be drawn
            int barHeight = displayHeight; // The bar spans the full height of the display
        
            int barXPosition = (xVal * displayWidth);
        
            // Draw the vertical bar according to the touch position
            barXPosition = min(barXPosition, displayWidth);
            u8g2.drawBox(barXPosition, 0, barWidth, barHeight); // Draw a vertical bar
            u8g2.sendBuffer();
        }
        
        
        
        
        
        
        // #define I2C_MUX // allow I2C multiplexing to select different target displays
        struct Display {U8G2 d; int mux;};
        std::vector<Display> gDisplays = {
        	// use `-1` as the last value to indicate that the display is not behind a mux, or a number between 0 and 7 for its muxed channel number
        	{ U8G2LinuxI2C(U8G2_R0, gI2cBus, 0x3c, u8g2_Setup_ssd1306_i2c_128x64_noname_f), -1 },
        	// add more displays / addresses here
        };
        
        
        
        /// Determines how to select which display a message is targeted to:
        typedef enum {
        	kTargetSingle, ///< Single target (one display).
        	kTargetEach, ///< The first argument to each message is an index corresponding to the target display
        	kTargetStateful, ///< Send a message to /target <float> to select which is the active display that all subsequent messages will be sent to
        } TargetMode;
        
        TargetMode gTargetMode = kTargetSingle; // can be changed with /targetMode
        OscReceiver oscReceiver;
        int gStop = 0;
        
        // Handle Ctrl-C by requesting that the audio rendering stop
        void interrupt_handler(int var)
        {
        	gStop = true;
        }
        
        int parseMessage(oscpkt::Message msg, const char* address, void*)
        {
        	oscpkt::Message::ArgReader args = msg.arg();
        	float xVal = gTouchPosition[0];
        	
        	//printf("AAA PLEASE");
        	enum {
        		kOk = 0,
        		kUnmatchedPattern,
        		kWrongArguments,
        		kInvalidMode,
        		kOutOfRange,
        	} error = kOk;
        	printf("Message from %s\n", address);
        	bool stateMessage = false;
        	
        	
        	U8G2& u8g2 = gDisplays[gActiveTarget].d;
        	u8g2.clearBuffer();
        	//int displayWidth = u8g2.getDisplayWidth();
        	int displayHeight = u8g2.getDisplayHeight();
        
        	// code below MUST use msg.match() to check patterns and args.pop... or args.is ... to check message content.
        	// this way, anything popped above (if we are in kTargetEach mode), won't be re-used below
        	if(error || stateMessage) {
        		// nothing to do here, just avoid matching any of the others
        	} else if (msg.match("/osc-test"))
        	{
        		if(!args.isOkNoMoreArgs()){
        			error = kWrongArguments;
        		}
        		else {
        			printf("received /osc-test\n");
        			u8g2.setFont(u8g2_font_ncenB08_tr);
        			u8g2.setFontRefHeightText();
        			u8g2.drawStr(0, displayHeight * 0.5, "OSC TEST SUCCESS!");
        		}
        	} else if (msg.match("/number"))
        	{
        		int number;
        		if(args.popNumber(number).isOkNoMoreArgs())
        		{
        			printf("received /number %d\n", number);
        			u8g2.setFont(u8g2_font_logisoso62_tn);
        			u8g2.drawUTF8(0, 0, std::to_string(number).c_str());
        		}
        		else
        			error = kWrongArguments;
        	} 
        	else if (msg.match("/drawParams"))
        	{
        		//print(gTouchPosition[0]);
        		touchSensor.readI2C();
        		xVal = gTouchPosition[0];
        		touchSensor.printDetails();
        
        		
        		drawSensorInputAsBar(u8g2,xVal);
        
        	
        	
        	
            	//u8g2.sendBuffer(); // Update the display with the new buffer contents
        	 
        	 }
        
        	
        	
        	else{
        		error = kUnmatchedPattern;
        	}
        	if(error)
        	{
        		std::string str;
        		switch(error){
        			case kUnmatchedPattern:
        				str = "no matching pattern available\n";
        				break;
        			case kWrongArguments:
        				str = "unexpected types and/or length\n";
        				break;
        			case kInvalidMode:
        				str = "invalid target mode\n";
        				break;
        			case kOutOfRange:
        				str = "argument(s) value(s) out of range\n";
        				break;
        			case kOk:
        				str = "";
        				break;
        		}
        		fprintf(stderr, "An error occurred with message to: %s: %s\n", msg.addressPattern().c_str(), str.c_str());
        		return 1;
        	} else
        	{
        		if(!stateMessage)
        			u8g2.sendBuffer();
        	}
        	return 0;
        }
        
        
        
        
        
        int main(int main_argc, char *main_argv[])
        {
        	if(0 == gDisplays.size())
        	{
        		fprintf(stderr, "No displays in gDisplays\n");
        		return 1;
        	}
        
        	for(unsigned int n = 0; n < gDisplays.size(); ++n)
        	{
        		//switchTarget(n);
        		U8G2& u8g2 = gDisplays[gActiveTarget].d;
                //drawSensorInputAsBar(u8g2, gTouchSize);
        		int mux = gDisplays[gActiveTarget].mux;
        		if(-1 != mux)
        		{
        			fprintf(stderr, "Display %u requires mux %d but I2C_MUX is disabled\n", n, mux);
        			return 1;
        		}
        		u8g2.initDisplay();
        		u8g2.setPowerSave(0);
        		u8g2.clearBuffer();
        		u8g2.setFont(u8g2_font_4x6_tf);
        		u8g2.setFontRefHeightText();
        		u8g2.setFontPosTop();
        		u8g2.drawStr(0, 0, " ____  _____ _        _");
        		u8g2.drawStr(0, 7, "| __ )| ____| |      / \\");
        		u8g2.drawStr(0, 14, "|  _ \\|  _| | |     / _ \\");
        		u8g2.drawStr(0, 21, "| |_) | |___| |___ / ___ \\");
        
        		u8g2.sendBuffer();
        		oscReceiver.setup(gLocalPort, parseMessage);
        
        		
        	while(!gStop)
        	{
        		u8g2.clearBuffer();
        		positionXsensor = gTouchPosition[0];
        		positionYsensor = gTouchPosition[1];
        
        		//drawSensorInputAsBar(u8g2, positionXsensor);
        		u8g2.drawBox(positionXsensor, 0, 15, 39);
        		u8g2.sendBuffer();
        		usleep(10000);
        	}
        	}
        	// Set up interrupt handler to catch Control-C and SIGTERM
        	signal(SIGINT, interrupt_handler);
        	signal(SIGTERM, interrupt_handler);
        	// OSC
        
        	return 0;
        }

        my apologies for the rough code

        Do you want to run audio processing in this process or will that be dealt by another program?

        Audio processing within this process for now at least 🙂

        I was trying to get these components working before integrating processing capabilities seemingly doesn't work quite that easily hahaha

        the thing is that when you provide your own main() function, then all the assumptions about a "Bela program" fall apart. The O2O program you started from does no audio processing and is meant to run alongside a "Bela program", for this reason it provides its own main() function.

        In your case what you should do is remove the main() function and move its content up to oscReceiver.setup(gLocalPort, parseMessage); to setup() and also provide a render() and cleanup() functions (even if temporarily empty/unused) just like any other Bela C++ program.
        If you want to update the display with readings from Trill, then the lines:

            while(!gStop)
            {
                u8g2.clearBuffer();
                positionXsensor = gTouchPosition[0];
                positionYsensor = gTouchPosition[1];
        
                //drawSensorInputAsBar(u8g2, positionXsensor);
                u8g2.drawBox(positionXsensor, 0, 15, 39);
                u8g2.sendBuffer();
                usleep(10000);
            }

        are best run in a dedicated thread (can be created with the usual AuxiliaryTask API).

        Hi Giulimoro,

        I have implemented this approach and all seems to be working with example values thank you very much!!

        However, something strange has happened to my two touch sensors (one bar one craft). Both are detected but give 0 readings no matter what now. I have tested with the two connectors provided, through a breadboard and without a breadboard, and with the OLED and without. The OLED display still works fine on the i2c bus that the sensor was using too. They return zero values on all of the trill examples also. This was not the case previously. Is there some kind of hardware reset i could try or should I just order a new sensor?

        Running i2cdetect -y -r 1 works as normal also and detects them with no issue, I have not changed any of the settings at all.

        Thanks very much for all of your help

          As the sensors are being detected, then it may be that some settings have been left on them and need power cycling. Try power cycling them: remove the VCC pin and reconnect it.

          Still no luck sadly, tried some different VCC connection points too no change

          SensorDetails gives this unsure if this is standard

          Device type: Bar (1)
          Address: 0x20
          Firmware version: 3

          aaronBelaIssue They return zero values on all of the trill examples al

          Really? Try opening Trill/general-settings with the CRAFT connected, open the Gui, set the mode to raw, do you see all zeros?

          Ahhh really sorry for some reason I misspoke. I have one Bar one square. Unsure why I said I had a craft. Completely on me.

          But yeah still zeroes coming up when testing any of the bar/Square examples

          Try the general-settings example then , but replace Trill::CRAFT with Trill::BAR or Trill::SQUARE instead, open the Gui, set the mode to raw, do you see all zeros?

          No this one works actually! Shows all bars at 0.500 with touches registering at the correct points