Serial parsing code working on Uno, but not on Due. Can't figure out why....

Hello,

I’ve been working on code to control 4 servos via serial input on the Due. The first version of the code I wrote works, but there was a very significant latency in the response of the servos. The second version of the code I am working on works fine on the Uno and has gotten rid of the latency, but I get nothing happening on the Due.

I have very little programing experience, the functional parts of the code I have drawn from two sources I found online.

I am sending a string (from Max) to the arduino that reads, pre ‘atoi’, 6:1352&7:2055&8:2400&9:2800&, then post atoi, ‘append 32 12’. The number before the ‘:’ is the servo/pin ID and the number after is the position. (I am running 12bit servos, and my servo accepts a frequency of 330Hz, which is set in the Due variant.h).

Any help would be greatly appreciated! This project is very significant in my life, not just a side hobby.

Here is the problem code (which works perfectly, minus the Due specific analogWriteResolution, on Uno):

char buffer[50]; 
int bufferindex = 0; 

void setup()
{
  
  Serial.begin(115200);  
  
}



void loop()
{
 bufferindex = 0; 
 do
{
    buffer[bufferindex] = Serial.read();      // get a byte from the serial port 
  
    if (buffer[bufferindex]!=-1) bufferindex = bufferindex+1;      // -1 if no byte is present
  
  } while (buffer[bufferindex-1] != 32);    //keep collecting bytes until a space is received

  // Read each command pair 
char* command = strtok(buffer, "&");
while (command != 0)
{
    // Split the command in two values
    char* separator = strchr(command, ':');
    if (separator != 0)
    {
        // Actually split the string in 2: replace ':' with 0
        *separator = 0;
        int servoId = atoi(command);
        ++separator;
        int pos = atoi(separator);
   
  
  analogWriteResolution(12);
  analogWrite(servoId,pos);
   

   
}

// Find the next command in input string
    command = strtok(0, "&");

}

}

Here is the first version of my code, which works fine on the Due, but produces almost a second of latency:

#define INPUT_SIZE 50

void setup() {

Serial.begin(115200);
  
}

void loop() {
 
// Get next command from Serial (add 1 for final 0)
char input[INPUT_SIZE + 1];
byte size = Serial.readBytes(input, INPUT_SIZE);
// Add the final 0 to end the C string
input[size] = 0;

// Read each command pair 
char* command = strtok(input, "&");
while (command != 0)
{
    // Split the command in two values
    char* separator = strchr(command, ':');
    if (separator != 0)
    {
        // Actually split the string in 2: replace ':' with 0
        *separator = 0;
        int servoId = atoi(command);
        ++separator;
        int position = atoi(separator);
   
   analogWriteResolution(12);
   analogWrite(servoId,position);
    
    }
    // Find the next command in input string
    command = strtok(0, "&");
}

}

OK, do you know why the original version is slow? It is using the readBytes() function which will wait up to a second for the requested number of bytes. Since your command string is smaller than the buffer (good) then it will wait for a second before returning control to your program.

The modification looks sensible except for one thing: it never checks if the buffer size is exceeded. It is possible for glitches and interference on the line to cause the terminator to be missed and then it will start writing outside the buffer area, damaging other parts of your program's storage.

Also, as a minor point, if your terminator is a space, then use a space as the constant in your program. Although it's unlikely that a future version of this could run on a microcontroller with different character encoding, it's easier to write buffer[bufferindex-1] != ' ' instead of remembering the encoding.

So do you know where it is getting stuck? Is it actually getting out of the read-into-buffer stage? Add some feedback Serial.print() statements to show where it is getting up to.

Thank you so much for your detailed reply! A major life event come up for me on wednesday, so it will take me a few days to get back to work. When I do, I will try the trouble shooting suggestions you gave and get back with the results.