How to send sensor data to TouchDesigner using ESP32?

Hello everybody!

I was wondering about what the title says. Lately I’ve been playing with TouchDesigner and some Arduino components, like rotatory encoders, buttons, ultrasonic sensor, etc.

What I do required to be connected to the computer, because all the data is sent via serial using the USB port. This far, I’m doing OK and I’m creating nice and interesting visuals using some sensors.

The thing is that I want to get rid from all the wire thing. I have an ESP32, and I’ve done succesfully the classic LED on and off via Wifi, using HTML buttons. But as I am a beginner in both worlds (Arduino and TouchDesigner) I have no idea of how can I send information via Wifi using ESP32.

Let’s say, in example, that I want to connect a rotatory encoder and an ultrasonic sensor to the ESP32… what should I do next? the info must be sent using GET/POST? or should I send the info some kind of “wifi serial monitor”, or what?

Do anybody have any idea on this? It would be so useful.

Thank you very much!! Cheers!

You can do things like http or get/post etc, but for local area networks only, where you want a speedy and constant stream of data udp is usually the easiest.

If you get your arduino ide all setup for the esp32, load a hello world sketch to make sure it works.

Then find the esp32 udp examples, they’re a good starting place.

I usually send a simple string, comma separated values, and use some dats in touch to break that out into a friendlier format, convert to chops, etc .

Hello Lucas!

I’ve never heard of udp. Could you please tell me what’s that and why is it better than get/post?

However, I know that ESP32 works cause I’ve succesfully done the classic turning on and of a LED.

So, lets say that I am having a rotatory encoder which will send values between 0 and 50 connected to ESP32. Then I program using Arduino IDE and the ESP32 udp examples. But… How do TouchDesigner collect that data? Which operator is needed for this? As I used Serial DAT when I was sending data through serial port in order to import the information, which operator should I use for this?

Thank you very much, Lucas. As there are not many tutorials about this, your help is unvaluable to me. Cheers!

Just a few days ago I put together a prototype/test for a similar need. Here’s the arduino sketch.

// NOTE, I'm using an esp8266, you'll want to import the esp32 base library.
// the MPU9250 is a library for a 9DOF IMU I was using, you can ignore that as well since you're using dif sensors.
#include "Wire.h"
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include "MPU9250.h"

#define WIFI_SSID "MY_SSID_HERE"
#define WIFI_PASS "MY_WIFI_PASSWORD_HERE"

const char ip[]="192.168.1.184"; // IP address of computer on network running TouchDesigner
#define UDP_PORT 4210 // pick a port, any port.. make sure it's not already being used by something else.

// init some things.
WiFiUDP UDP;
MPU9250 mpu;
char packet[255];

void setup() {

  // Connecting to WiFi...
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  Serial.print("Connecting to ");
  Serial.print(WIFI_SSID);
  // Loop continuously while WiFi is not connected
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(100);
    Serial.print(".");
  }

  // begin the UDP connection.
  UDP.begin(UDP_PORT);
  
   // init serial communication for print/debug stuff.
  Serial.begin(115200);

  // begin the wire connection, for polling the MPU9250.
  Wire.begin();

  // delay a second to give everything time to finish initializing if it hasn't already.
  delay(1000);

  // init MPU9250 sensor
  mpu.setup();

  // richardson, TX has a magnetic Declination of +2° 59'.
  // to convert this to a float, left of decimal is 2, 
  // and right of decimal is 59/60 (fraction out of 60)
  // result looks like 2.9833333333333333
  // lookup different locations here: https://www.magnetic-declination.com/
  // This is info the magnetomitor needs.
  mpu.setMagneticDeclination(2.9833333333333333);

  // another long delay for mpu
  delay(1000);
  
  // calibrate the sensors.
  mpu.calibrateAccelGyro();
  mpu.calibrateMag();

  // print calibration (just for debug)
  mpu.printCalibration();

}

void loop() {

  
  static uint32_t prev_ms = millis();
  
  if ((millis() - prev_ms) > 16)
  {

    // poll the sensor
    mpu.update();

    // extract roll/pitch/yaw from sensor readings.
    float Roll = mpu.getRoll();
    float Pitch = mpu.getPitch();
    float Yaw = mpu.getYaw();

    // concatenate our data into one long string.
    // FORMAT: "Roll:123,Pitch:234,Yaw:345"
    // notice how commas separate the data into "rows" and the colons separate the data into "columns". we will use this in TouchDesigner.
    String Data = "";
    Data += "Roll:" + (String)Roll + ",";
    Data += "Pitch:" + (String)Pitch + ",";
    Data += "Yaw:" + (String)Yaw + ",";
    Data += "ElapsedTime:" + String((millis()-prev_ms)) + ",";

    // cast the string to our char array.
    Data.toCharArray( packet , Data.length() );

    // optionally, print the string to the serial port for testing.
    //Serial.println(packet);
    
    // Send the UDP packet to our ip/port address.
    UDP.beginPacket(ip, UDP_PORT);
    UDP.write(packet);
    UDP.endPacket();
    
    prev_ms = millis();
  }
}

after you have that setup, you can just drop a UDP in DAT into your Touch project, be sure to set the same port number you have in the sketch. Also, set row callback format to One Per Message.

You’ll get several rows of data streaming in if that works correctly, I just select the last row, which is the most recent message from the esp.
It will look something like this - I’m just simulating it by pasting it in a table dat.

then you can just use some easy dat logic to break that message up into usable pieces:

the rest is all typical TouchDesigner workflow stuff :slight_smile:
Hope that helps!

Ah, and for the difference between get/post and udp - I’'m sure I’m not the best person to give you the most accurate answer, but I tend to always use UDP for it’s simplicity, and how light weight it is as a protocol by default, and when certain special circumstances or needs or constraints arise, then I look into other protocols out of neccesity.

UDP is just a water hose pointed at your target computer. it doesn’t care if it’s listening or not. messages may not arrive in perfect order, maybe sometimes a message will drop or not make it.

For an application like this I think it’s pretty good though. Maybe some others will chime in about some of the other protocols

Hello Lucas!

I’ve just read your answer, and even being out of home for a couple of days, so I can’t test the code yet, just want to say one thing:

You are a HERO!!

Thank you very, very much for spending your time in such an accurate answer in order to help me. The code, the screenshots… Everything.

I will give it a try as soon as I sit in front of my computer. I’ll let you know here in this thread if all your info helped me (sure it will), so the rest of the community or whoever visiting this post can see it as well.

Thanks again, Lucas!

1 Like

Awesome best of luck! Let us know how it goes :slight_smile:

Hello there!

I’ve just tested the code and all the steps you told me and it works good! Finally, it was able to send the distance value from an ultrasonic sensor to TouchDesigner using UDP.

The only problem that I got is something that I don’t understand. It’s related to this part of the code:

// notice how commas separate the data into "rows" and the colons separate the data into "columns". we will use this in TouchDesigner.
    String Data = ""; 
    Data += (String)distance + "cm"; 

This part of the code only works when I keep the + “cm” part, if I delete it leaving just Data += (String)distance, it wont work. I tried writing (int)distance, but it won’t work anyway. Probably is just something that I am not realizing about, or maybe some kind of error difficult to explain related to my ESP32 or whatever.

Do you have any thoughts on this?

Thank you very much, the feeling when I was my data going to Touchdesigner via wifi was awesome.

Cheers, Lucas!

Sounds like you’re close!

I see that you’re formatting outgoing messages differently, which may be causing issues. My format used a comma, where you’re putting “cm”. I did not bother to include units since units never changed for me.
Also, you’re not including the variable name, ie Roll, Pitch, Yaw etc.

String Data = "";
Data += "Roll:" + (String)Roll + ",";
Data += "Pitch:" + (String)Pitch + ",";
Data += "Yaw:" + (String)Yaw + ",";

If cm is your variable name for instance, you’d want to format it something like this:

    String Data = ""; 
    Data += "cm:" + (String)distance + ",";

Which would result in a string something like this:
"cm:123.456,"

the commas and the colons are important because that’s how the patch in TD determines where a row or column of the data ends, to split the string apart.

Hi I’ve read your post, I’m trying to connect Touchdesigner to an ESP32, can you tell how you did it even if it requieres wires, i’ve been trying some tutoriales but it ain’t working

do you have a github where i can see your code? thank you very much