giuliomoro That's why I am asking whether parsing in C++ would be easier ...

I'll give this a try. thanks

so what you could do is parsing the received string from the auxiliary task and set several global variables. Then from render() you either call libpd_float() multiple times (each with a different receiver), or construct a list. Let me know if you need help.

    giuliomoro why using libpd_symbol() instead of libpd_float() gives the error: no matching function for call to 'libpd_symbol' ?

    libpd_symbol() requires a char* as the second argument:

    int libpd_symbol(const char *recv, const char *symbol)

    how are you calling it ?

    //////before setup:
    void serialReadTask(void*)
    {
    	while(!Bela_stopRequested())
    	{
    		unsigned int maxLen = 512;
    		char serialBuffer[maxLen];
    		// read from the serial port with a timeout of 100ms
    		int ret = gSerial.read(serialBuffer, maxLen, 100); 
    		if (ret > 0) {
    
    			for(unsigned int n = 0; n < ret; ++n)
    			{
    			printf("Received buffer: %c\n", serialBuffer[n]);
    			gSerialValue = serialBuffer[n]; 
    			}
    			usleep(gSerialReadSleepMs * 1000);
    	}
    }
    }
    #endif // ENABLE_Serial
    
    
    //////in render:
    #ifdef ENABLE_Serial
    	static uint64_t serialLastSent = 0;
    	if(context->audioFramesElapsed - serialLastSent > gSerialSendIntervalMs * 0.001f * context->audioSampleRate)
    	{
    		libpd_symbol(gSerialReceiverName, gSerialValue);
    		serialLastSent = context->audioFramesElapsed;
    	}
    #endif // ENABLE_Serial

    Well, if gSerialValue is still a float, then what you are doing is you are setting in turn to the value of each byte which is received from the UART. render() will only see the latest value that it has been set to and that's pretty meaningless. A different approach would be to make serialBuffer a global variable and use libpd_symbol(gSerialReceiverName, serialBuffer), however in this case you will occasionally send to Pd a corrupted string: if render() runs halfway through a UART receive, the first part of the string will be from from the new reading and the second part of the string will be from the previous reading.

    A more thread-safe approach is to use a Pipe to send the string value from serialReadTask() to render(). In the Communication/Serial example there is a Pipe to send one character at a time from the AuxiliaryTask to render(). If the width of the string is constant, you can just create a std::array<char, 84> at both ends of the pipe and pass data as follows:

    Pipe gSerialPipe;
    void serialReadTask(void*)
    {
    	while(!Bela_stopRequested())
    	{
    		unsigned int maxLen = 512;
    		char serialBuffer[maxLen];
    		// read from the serial port with a timeout of 100ms
    		int ret = gSerial.read(serialBuffer, maxLen, 100); 
    		if (ret > 0) {
    			gSerialPipe.writeNonRt(serialBuffer, ret);
    			usleep(gSerialReadSleepMs * 1000);
    		}
    	}
    }
    /// in setup()
    {
    ...
    	gSerialPipe.setup("serialpipe", 1024);
    ...
    }
    
    /// in render()
    {
    ..
    	char serialBuffer[maxLen];
    	size_t len = gSerialPipe.readRt(serialBuffer, maxLen);
    	if(len > 0) {
    		serialBuffer[len] = 0; // ensure the string is appropriately null-terminated, or the line below may crash
    		libpd_symbol(gSerialReceiverName, serialBuffer)
    	}
    ...
    }
    2 months later

    Thanks for the help @giuliomoro!

    Is there any reason why my GPS module looses coordinates values as soon as I run the software? Does this code send anything back to the module via uart4?

      Tree Does this code send anything back to the module via uart4?

      as far as I can tell that code doesn't use UART at all. In the code I wrote above we are not writing via UART either, so I don't see how the code could be responsible of malfunctioning of the GPS module as it does not write to it.

      Tree Is there any reason why my GPS module looses coordinates values as soon as I run the software?

      Not sure what that means.

      16 days later

      Apologies @giuliomoro, I referred to the wrong code. I am using this bit (which is appropriated from the Serial library example) to get serial data from UART4 pins:

      gSerial.setup("/dev/ttyS4", 9600);
      AuxiliaryTask serialCommsTask = Bela_createAuxiliaryTask(serialReadTask, 0, "serial-thread", NULL); 
      Bela_scheduleAuxiliaryTask(serialCommsTask);

      and I am parsing the incoming values, then sending via libpd_symbol to PD, as such:

      static uint64_t serialLastSent = 0;
      	if(context->audioFramesElapsed - serialLastSent > gSerialSendIntervalMs * 0.001f * context->audioSampleRate)
      	{
      		char serialBufferLat[maxLen];
      		char serialBufferLng[maxLen];
      		char serialBufferSts[maxLen];
      			size_t lenLat = gSerialPipeLat.readRt(serialBufferLat, maxLen);
      			size_t lenLng = gSerialPipeLng.readRt(serialBufferLng, maxLen);
      			size_t lenSts = gSerialPipeSts.readRt(serialBufferSts, maxLen);
      
      			if(lenLat > 0) {
      		serialBufferLat[lenLat] = 0; // ensure the string is appropriately null-terminated, or the line below may crash
      		libpd_symbol(gSerialReceiverNameLat, serialBufferLat);
      							serialLastSent = context->audioFramesElapsed;
      	}
      	
      			if(lenLng > 0) {
      		serialBufferLng[lenLng] = 0; // ensure the string is appropriately null-terminated, or the line below may crash
      		libpd_symbol(gSerialReceiverNameLng, serialBufferLng);
      							serialLastSent = context->audioFramesElapsed;
      	}
      	
      			if(lenSts > 0) {
      		serialBufferSts[lenSts] = 0; // ensure the string is appropriately null-terminated, or the line below may crash
      		libpd_symbol(gSerialReceiverNameSts, serialBufferSts);
      							serialLastSent = context->audioFramesElapsed;
      	}
      	
      	}

      The issue is that my GPS module (connected to UART4) loses coordinates as soon as I run the software. As part of my troubleshooting, I tried the GPS module on an Arduino and on Bela-mini (with the software being stopped) in both cases the data flow without any issues and coordinates are readable, when I run the software on Bela the module malfunctions (data is still incoming but I lose the coordinates). I wonder if you could advise on where I should look to tackle this problem?

        4 days later

        that code still doesn't send anything to UART4.

        Tree loses coordinates as soon as I run the software

        I am not sure how that can happen, considering that your software is not affecting the state of the GPS module (I cannot see any place where it is writing to the UART, but you have not posted the full code and not even all the relevant one. Namely: post at least the relevant global variables, the relevant initialisations and the code of the AuxiliaryTask). I would guess that if you were to print the data from within the AuxiliaryTask you'd see that the data is received appropriately.

        One issue you have is that the return values from reading the pipes are size_t, which is an unsigned type. The return value from Pipe::readRt() is: a positive integer is the number of bytes read, or a negative error value otherwise. When no new data from the Pipe is available, it will return -EAGAIN (i.e.: a negative integer). In this case the following tests (e.g.: if(lenLat > 0 )) will always return true because an unsigned value is always positive. This only becomes an issue if the Pipe is read less often than its written to, so the render() thread finds it empty sometimes.
        In the converse case, where you read from the pipe slower than the data is written into it by the AuxiliaryTask, you will also end up in trouble. As you are only reading once from each pipe, you may be reading old (and increasingly older) data from it. This is fixed by reading multiple times until the pipe is empty (returns a negative value). However, as in your case you are passing arbitrary length data and message boundaries are not preserved in the PIpe, I think if this was the issue you'd have noticed that already.
        Last, I am not sure it's convenient to have three different pipes, but I'd need to see the AuxiliaryTask code to confirm that.

        a year later

        Hi forum,

        I just opened this topic very similar to this one >>> It's about communication between a UART sensor > the good render.cpp code > and pure data with the r serial-uart4 object

        Many thanks