TouchDesigner to Arduino serial communication?

tl:dr How to parse multiple live-time changing variables send to Arduino?

Hello dear banana community!

Recently I worked on a project including TouchDesigner to Arduino communication.
I faced a problem with sending multiple live-changing data from CHOP to Arduino through serial.

I have two animations that runs independently for 10s after a different triggers (null1 on the screenshot). Ewentually there will be 5 independent animations triggered by different events.

Each animation is an analogWrite value of different motor connected to Arduino.

CHOP Execute sends data to serial1 on value change. Serial1 sends it to Arduino.
I’ve done the coding based on the example from TD docs (Arduino - Derivative).

Data send from TD are being parsed on Arduino side. Here is the problem - if I send constant value, they are saved in buffer and parsed correctly, but if I send changing values, they are changing positions in buffer, so the parsing is going wrong.
(On the screenshot first animation was triggered, so first message should be changing value and second should be 0).

Is there any other way I can send five independently changing values to Arduino through serial port? Or any other way to parse them?

I’m a begginer in Arduino and Python, any help appreciated!
:banana: :banana: :banana: :banana: :banana: :banana: :banana: :banana: :banana:

Arduino code (for debug purpose I print parsed values instead of sensor values I use to trigger animations):

char buffer[13];
int len = 0;

int sensorVal1 = 0;
int sensorVal2 = 0;

int motorPin1 = 5;
int motorPin2 = 6;

int sensorPin1 = A0;
int sensorPin2 = A1;


void setup() {
  // start serial port at 9600 bps:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);

  pinMode(sensorPin1, INPUT);
  pinMode(sensorPin2, INPUT);
  //establishContact();  // send a byte to establish contact until receiver responds
}

void loop() {

  sensorVal1 = analogRead(sensorPin1);
  sensorVal2 = analogRead(sensorPin2);

  //FINAL version prints sensor values!!!
  //Serial.print(sensorVal1); Serial.print(",");
  //Serial.print(sensorVal2);

  //Serial.println(); //terminate the line

  // if we get a valid byte, read analog ins:
  if (Serial.available() > 0) {
    // get incoming byte:
    int inByte = Serial.read();
    buffer[len++] = inByte;

    //resetting
    if (len >= 13) {
      len = 0;
    }

    //check for newline
    if (inByte == '\n') {

      int motorVal1, motorVal2;
      int n = sscanf(buffer, "%d %d", &motorVal1, &motorVal2);

      //write motor when two variables red
      if (n == 2) {

        analogWrite(motorPin1, motorVal1);
        analogWrite(motorPin2, motorVal2);

        //for DEBUG print parsed values
        Serial.print(motorVal1); Serial.print(",");
        Serial.print(motorVal2); Serial.print(",");
        Serial.print("over"); Serial.print(",");

      }

    }
  }

}

Hi.
To begin I would first make sure the message coming from the Arduino ends in a newline:

Serial.print(“over”); Serial.print(","); becomes:

Serial.println(“over”);

Then on the TouchDesigner side, make sure you are breaking up your messages by newlines:

Row/Callback Format: One Per Line

After this, we can tell if the received messages are what’s expected, etc.

Cheers.

Thanks for answer!
Now it looks like this:

Almost every second value is assigned to wrong variable. Please send help :’ )

Here I’ve printed inByte and buffer as well

One potential issue, your buffer may not be properly null terminated at times.
Also you don’t seem to reset the buffer after receiving the newline, but randomly based on
accumulated length:

I’d try this:

//check for newline
if (inByte == ‘\n’) {
buffer[len++] = 0; ← add this
len = 0; ← add this

Hi thanks a lot!

It still doesn’t work tho.
That’s the part of code I’ve changed:

  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();
    buffer[len++] = inByte;

    //check for newline
    if (inByte == '\n') {

      Serial.print(inByte);
      Serial.println();

      buffer[len++] = 0;
      len = 0;
      
      int n = sscanf(buffer, "%d, %d, %d, 5d, %d", &motorVal1, &motorVal2, &motorVal3, &motorVal4, &motorVal5);

      Serial.print("n=");
      Serial.print(n);
      Serial.println();
      
      if (n == 5) {

        analogWrite(motorPin1, motorVal1);
        analogWrite(motorPin2, motorVal2);
        analogWrite(motorPin3, motorVal3);
        analogWrite(motorPin4, motorVal4);
        analogWrite(motorPin5, motorVal5);

        Serial.print(motorVal1); Serial.print(",");
        Serial.print(motorVal2); Serial.print(",");
        Serial.print(motorVal3); Serial.print(",");
        Serial.print(motorVal4); Serial.print(",");
        Serial.print(motorVal5); Serial.print(",");
        Serial.println("over");
      }
    }

  }

CHOP Execute code:

def onValueChange(channel, sampleIndex, val, prev):

	motorVal1 = str(math.floor(op('null1')['chan1']))
	motorVal2 = str(math.floor(op('null1')['chan2']))
	motorVal3 = str(math.floor(op('null1')['chan3']))
	motorVal4 = str(math.floor(op('null1')['chan4']))
	motorVal5 = str(math.floor(op('null1')['chan5']))
	
	print(motorVal1 + " , " + motorVal2 + " , " + motorVal3 + " , " + motorVal4 + " , " + motorVal5)
	
	op('serial1').send(motorVal1 + " " + motorVal2 + " " + motorVal3 + " " + motorVal4 + " " + motorVal5, terminator="\n")
	
	
	return

It didn’t print motor values at all, so I assume n never equals 5.
So I’ve printed buffer and int n, it looks like this:

serial buffer n

Is your buffer still only 13 bytes?
That’s much too short for the full 5 values, commas etc.

Also:
%d, %d, %d, 5d, %d

Is that 5 a typo?

Cheers

No, I’ve changed it to 40 and I had a typo

Omg it works now, I cannot believe it was a typo
Thanks so much for help!

1 Like