In my setup the Bela communicates serial data over the USB port with an ESP32 that runs an oled display and reads some encoders. It runs fine when I run the project from the IDE. But when run on boot it is not running. Any advise befor tuesday would be great since I need to deliver the instrument to someone else by then.

Hi Fedde, this does look quite odd indeed. I wonder if for some reason there is not enough time for the serial driver to recognise the device before setup() is executed.

@bela_robert just tried this with an Arduino and it seems to be working alright for him. I do not have any ESP32 at hand I am afraid so it is hard to know what could go wrong without replicating your setup.

Could you please send over the standard error stream so that I can take a look at which part of the communication is failing (I assume you are using the Bela cpp Serial library for this?)

In order to capture the standard error stream to a file just add this include at the beginning of your render.cpp file:
#include <stdio.h>
and the following 2 lines at the beginning of setup():

        freopen ("stderr_file.txt","w",stderr);
	fprintf (stderr, "Capturing stderr:\n");

you should be able to see the output of stderr from the last execution on the stderr_file.txt file that will be created on the project folder.

If you could share your code to take a look at that would also help.

Hi, tnx, the standard error stream gives nothing:
Capturing stderr:

What part of the do you need? Here is the setup:

bool setup(BelaContext context, void userData)
{
freopen ("stderr_file.txt","w",stderr);
fprintf (stderr, "Capturing stderr:\n");
// Initialiseer alle 6 trill sensoren
for (unsigned i = 0; i < 6; i++)
{
gTouchSensors.push_back(new Trill(1, Trill::SQUARE, i2cAddresses));
gTouchSensors.back()->printDetails();
gTouchSensors.back()->setNoiseThreshold(5);
}


// Start met scannen van de trill sensoren
Bela_runAuxiliaryTask(parseTrillData);

pinMode(context, 0, 1, INPUT);
pinMode(context, 0, 3, INPUT);

pinMode(context, 0, 0, OUTPUT);
pinMode(context, 0, 2, OUTPUT);
pinMode(context, 0, 7, OUTPUT);
pinMode(context, 0, 10, OUTPUT);

pinMode(context, 0, HW_PIN_MUX_IN_1, INPUT);
pinMode(context, 0, HW_PIN_MUX_IN_2, INPUT);

// midi frequentie conversie
// rt_printf("%f %f", 440.0f, mtof(ftom(440.0f)));


// pshifter.printWindow();

// Serial comms
gSerialNotWorking = gSerial.setup ("/dev/ttyUSB0", 115200);

if (gSerialNotWorking)
{
	rt_printf("! --> Serial not working!");
}

// De stortkoker naar de Universele Seriele Bus, onder enkele mensen ookwel bekend onder de noemer USB.
// Dump hierin shit in die de serialOut auxiliaryTask moet versturen
gPipe.setup("serialpipe");

AuxiliaryTask serialInTask = Bela_createAuxiliaryTask(serialIn, 80, "serial-in-thread", NULL);
Bela_scheduleAuxiliaryTask(serialInTask);

AuxiliaryTask serialOutTask = Bela_createAuxiliaryTask(serialOut, 70, "serial-out-thread", NULL);
Bela_scheduleAuxiliaryTask(serialOutTask);

/*
gPipe.setBlockingRt(false);
gPipe.setBlockingNonRt(false);
gPipe.setTimeoutMsNonRt(100);
*/

// Start met luisteren naar OSC
oscReceiver.setup(localPort, on_receive);	

// Start ook een unit om OSC op te sturen
oscSender.setup(remotePort, remoteIp);

scope.setup(5, context->audioSampleRate);



// Test om DelayLine te valideren..
if (false)
{
	float buffie[12] = {
		0, 0, 1, 0,
		0, 0, 0, 0,
		0, 0, 0, 0
	};
	
	rt_printf("\n\nDelayline test met delay = 0 samples\n");
	for (unsigned sample = 0; sample < 12; sample++)
		rt_printf("in: %f\t\tdelay: %f\n", buffie[sample], dline.process(buffie[sample]));
	
	rt_printf("\n\nDelayline test met delay = 2 samples\n");
	dline.setDelayInSamples(2);
	for (unsigned sample = 0; sample < 12; sample++)
		rt_printf("in: %f\t\tdelay: %f\n", buffie[sample], dline.process(buffie[sample]));
		
	rt_printf("\n\nDelayline test met delay = 7 samples (in een delayline van 6)\n");
	dline.setDelayInSamples(7);
	for (unsigned sample = 0; sample < 12; sample++)
		rt_printf("in: %f\t\tdelay: %f\n", buffie[sample], dline.process(buffie[sample]));
}

rt_printf("\n\nSetup afgerond\n");
// displayCommand(BelaBooted, 0, 0);
return true;

}

and the functions that handele serial in / out

void serialIn(void* arg)
{
while(!Bela_stopRequested())
{
unsigned int maxLen = 128;
char serialBuffer[maxLen];

	// read from the serial port with a timeout of 100ms
	int ret = gSerial.read(serialBuffer, maxLen, 100);
	if (ret > 0)
	{
		// Bit mask for commands
		//		|7		|6		|5		|4		|3		|2		|1		|0		|
		//		|but 0	|								nummer	van	de	control	|
		//		|enc 1	|0-	1+	|						nummer	van	de	control	|
		
		for (unsigned i = 0; i < ret; i++)
		{
			int _command = serialBuffer[i];
			
			rt_printf("%i", _command);
			
			if (_command >> 7)
			{
				// Encoder command
				
				if ((_command >> 6) & 0x01)
				{
					// Encoder waarde omhoog
					rt_printf(" (Encoder++ %i)\n", _command & 0x3F);
					
					switch(_command & 0x3F)
					{
						case 0:
							synth.changeSource(gEditTrack, 1);
							break;
						case 1:
							synth.changeEffect(gEditTrack, 1);
							break;
						case 2:
							synth.incrementParameter(0 /* portamento */, gEditTrack, 1);
							break;
						case 3:
							if (!gateOutputParameterShift)
								synth.incrementParameter(1 /* gate width */, gEditTrack, 1);
							else
								synth.incrementParameter(2 /* gate delay */, gEditTrack, 1);
							break;
						case 4:
							data.addToBPM(0.5f);
							break;
					};
				}
				else
				{
					// Encoder waarde naar benee
					rt_printf(" (Encoder-- %i)\n", _command & 0x3F);
					
					switch(_command & 0x3F)
					{
						case 0:
							synth.changeSource(gEditTrack, -1);
							break;
						case 1:
							synth.changeEffect(gEditTrack, -1);
							break;
						case 2:
							synth.incrementParameter(0 /* portamento */, gEditTrack, -1);
							break;
						case 3:
							if (!gateOutputParameterShift)
								synth.incrementParameter(1 /* gate width */, gEditTrack, -1);
							else
								synth.incrementParameter(2 /* gate delay */, gEditTrack, -1);
							break;
						case 4:
							data.addToBPM(-0.5f);
							break;
					};
				}
			}
			else
			{
				// Button command
				rt_printf(" (Button  %i)\n", _command & 0x3F);
				
				switch(_command & 0x3F)
				{
					case 0:
						// Schakel de LDR mode van de huidige track
						synth.switchLDRMode(gEditTrack);
						break;
					case 1:
						// Gate output enable
						synth.switchOutputEnable(gEditTrack);
						break;
					case 2:
						gBPMPaused = data.toggleBPMPlayPause();
						break;
					case 3:
						// Flip de parameter shift knop
						gateOutputParameterShift = !gateOutputParameterShift;
						
						// Print welke parameter nu wordt bewerkt
						// false = gate width
						// true = gate delay
						if (!gateOutputParameterShift)
							rt_printf("editing gate width\n");
						else
							rt_printf("editing gate delay\n");
						break;
					case 4:
						// Gate invert
						synth.switchOutputInversion(gEditTrack);
						break;
				};
				
				
			}
		}
	}
	
	usleep(gSerialInTaskSleepTime);
}

}

void serialOut(void* arg)
{
while(!Bela_stopRequested())
{
SerialCommand command;

	unsigned nMessages = 0;
	unsigned messagesSent = 0;
	bool sendMessages = false;
	
	// -1 is niet versturen
	int messageValues[4][13] = {
		{
			-100, -100, -100, -100,
			-100, -100, -100, -100,
			-100, -100, -100, -100,
			-100
		},
		{
			-100, -100, -100, -100,
			-100, -100, -100, -100,
			-100, -100, -100, -100,
			-100
		},
		{
			-100, -100, -100, -100,
			-100, -100, -100, -100,
			-100, -100, -100, -100,
			-100
		},
		{
			-100, -100, -100, -100,
			-100, -100, -100, -100,
			-100, -100, -100, -100,
			-100
		}
	};
	/*
	int messageRings[13] = {
		0, 0, 0, 0,
		0, 0, 0, 0,
		0, 0, 0, 0,
		0
	};
	*/
	
	// De gegevens gaan hier de pijp uit en de meest recente van elk bericht wordt genoteerd
	// Er kunnen dus maximaal 12 berichten worden verstuurd per keer dat deze thread bezig is
	while (gPipe.readNonRt(command) > 0 && !gSerialNotWorking)
	{
		sendMessages = true;
		
		// Sla de waarde van deze message op op de index van het message type
		// Na deze iteratie blijft alleen de meest recente message dus over..
		messageValues[command.ring][command.cmd] = command.value;
		// messageRings[command.cmd] = command.ring;
		
		/*
		gSerial.write("<");
		gSerial.write(std::to_string(command.cmd).c_str());
		gSerial.write(",");
		gSerial.write(std::to_string(command.value).c_str());
		gSerial.write(",");
		gSerial.write(std::to_string(command.ring).c_str());
		gSerial.write(">");
			*/
		
		nMessages++;
	}
	
	// Zijn er ansich berichten uit de pipe gehaald?
	if (sendMessages)
	{
		// Over alle ringen itereren
		for (int r = 0; r < 4; r++)
		{
			// Over alle commands itereren
			for (int m = 0; m < 13; m++)
			{
				// Kijken of er voor dit command een message uit de pipe is gehaald
				if (!(messageValues[r][m] == -100))
				{
					gSerial.write("<");
					gSerial.write(std::to_string(m).c_str());
					gSerial.write(",");
					gSerial.write(std::to_string(messageValues[r][m]).c_str());
					gSerial.write(",");
					gSerial.write(std::to_string(r).c_str());
					gSerial.write(">");
					
					messagesSent++;
				}
			}
		}
		
		rt_printf("%i serial messages sent out of %i messages (%f%)\n", messagesSent, nMessages, (static_cast<float>(messagesSent) / static_cast<float>(nMessages)) * 100);
	}
	
	// rt_printf("serial out task while() 3\n");
	usleep(gSerialOutTaskSleepTime);
	// rt_printf("serial out task while() 4\n");
}

}

Hi Fedde, thanks for sharing. It does look good to me, you can probably get away with just one auxiliary task to handle all the serial I/O but that should not be an issue (and can be done in 2 as well).

Only thing I can still think about is that setup runs before the serial connection is established (I just realised I wrote it the wrong way around before).

I imagine that you would be getting a non-zero return from gSerial.setup() in that case. Have you been able to try delaying the program startup? Does that work at all? (I believe Giulio suggested this on a parallel thread).

I can replicate your setup and see what else I find, but that will definitely not happen before tomorrow.

I also wonder if this could be an issue with how the different devices are powered up when using them without being connected to the computer. If the ESP32 is powered from the Bela USB that might add a delay to its booting time so that it is not ready to start the serial communication when the program starts.

A 'sleep 10' to the second line of '/opt/Bela/bela_startup.sh' did make it run.