Controlling an Arduino Smart Car with TouchDesigner

 

Controlling an Arduino Smart Car with TouchDesigner

 

TouchDesigner can be used as an interface for any Arduino setup.   Here we analyze source code provided in a STEM kit for beginners, create our own code that we can trigger from a serial connection and create a controller in TouchDesigner.

                To follow the video tutorial step by step you will need the ELEGOO UNO R3 Project Smart Robot Car Kit V 3.0 Plus, which can be found here.  I encourage you to take your own Arduino project and make your own interface using this as a rough guide. 

A more in depth video tutorial can be found here.

 

Steps for any Arduino/TouchDesigner project:

1.       Connect the arduino to touchdesigner

2.       Understand the Arduino code

3.       Write new Arduino code we can trigger from serial port

4.       Trigger Arduino code from Touchdesigner

5.       Create a remote control interface

 

Materials:

1.       TouchDesigner

2.       Elegoo Smart Car

3.       USB-A to USB-B cable

 

Sources:

https://docs.derivative.ca/index.php?title=Arduino

https://docs.derivative.ca/CHOP_Execute_DAT

https://docs.derivative.ca/index.php?title=Button_COMP

 

 

Connecting the Arduino to TouchDesigner

                This step should be taken first because it might affect how we choose to manipulate the Ardiuno code.  For simplicity, we’re going to use a wired serial connection, like you normally would connect Arduino to your pc.  We’ll tackle wireless control another day. 

 

Understanding the robot’s code and controls

 

Before we can involve TouchDesigner, we need to understand the Arduino code that makes the smart car run.  If we analyze the code, we learn how certain functions are triggered and we can manipulate the code to work in our favor.  In this case, we can trigger the Arduino code from data received over the serial port from TouchDesigner. 

For this tutorial, I chose the simplest code from Lesson 1 Make the Car Move in the smart car kit. 



Please watch the video for a walk through.                           


Write new Arduino code

                Now that we know how the smart car’s code triggers the forward, back, left and right functions, we can make our own code that listens over the serial port for commands.  None of the functions from the smart car code need to be altered.  We just need to add in the basic code found in the TD documentation that allows the Arduino to receive signal. 

Here is the source code I use in the video tutorial

/*
 * @Description: For Elegoo Smart Robot Car Kit 3.0 Plus control from TouchDesigner via wired serial connection
 * @Author:
 * @Date: 2020-12-24
 * @LastEditTime: 2021-01-03 15:30:00
*/
 
//
// Parse incoming messages consisting of two decimal values followed by a carriage return

//  Example  "f 100\n"

//  In TouchDesigner:     op('serial1').send("f 100", terminator="\n")
//
 
//     Right motor truth table
//Here are some handy tables to show the various modes of operation.
//  ENB         IN3             IN4         Description 
//  LOW   Not Applicable   Not Applicable   Motor is off
//  HIGH        LOW             LOW         Motor is stopped (brakes)
//  HIGH        LOW             HIGH        Motor is on and turning forwards
//  HIGH        HIGH            LOW         Motor is on and turning backwards
//  HIGH        HIGH            HIGH        Motor is stopped (brakes)  
 
// define IO pin
#define ENA 5
#define ENB 6
#define IN1 7
#define IN2 8
#define IN3 9
#define IN4 11
 
//set car speed
#define CAR_SPEED 100
typedef unsigned char u8;  //Change the name of unsigned char to u8
 
//Setup buffer
char buffer[16];   //maximum expected length
int len = 0;
 
/*Car Controls*/
void forward(u8 car_speed)

{

 

  analogWrite(ENA, car_speed);
  analogWrite(ENB, car_speed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}
 
 
void back(u8 car_speed)
{
 
  analogWrite(ENA, car_speed);
  analogWrite(ENB, car_speed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);

}

 

 

void left(u8 car_speed)

{

 

  analogWrite(ENA, 250);
  analogWrite(ENB, 250);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
 

  digitalWrite(IN3, LOW);

  digitalWrite(IN4, HIGH);

}
 
void right(u8 car_speed)
{
  analogWrite(ENA, 250);
  analogWrite(ENB, 250);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}
 
//Stop controlling the motor: close the motor drive enable port
void stop()

{

  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
}
 
 
 
void setup()
{
  Serial.begin(9600);
  Serial.println("Listening, Baud:9600");
 
  pinMode(IN1,OUTPUT);//before useing io pin, pin mode must be set first
  pinMode(IN3,OUTPUT);
  pinMode(IN4,OUTPUT);
  pinMode(ENA,OUTPUT);
  pinMode(ENB,OUTPUT);
}
void loop()
{
    if (Serial.available() > 0)
  pinMode(IN2,OUTPUT);
    {
        //Serial.println("Incoming bytes...");
        int incomingByte = Serial.read();
        buffer[len++] = incomingByte;
        //
        // check for overflow
        //
        if (len >= 16)
        {
            // overflow, resetting
            len = 0;
        }
        //
        // check for newline (end of message)
        //
        if (incomingByte == '\n')
        {
            // input message values into variables
            // from td:  (direction, speed)
            char direction;
            int speed;
            int n = sscanf(buffer, "%c %d", &direction, &speed);
 
            if (n == 2)
            {
                           
                switch (direction) {
                  case 'f':
                    Serial.println("Forward");
                    forward(speed);
                    break;
                  case 'b':
                    Serial.println("Back");
                    back(speed);
                    break;
                  case 'l':
                    Serial.println("Left");
                    left(speed);
                    break;
                  case 'r':
                    Serial.println("Right");
                    right(speed);
                    break;
                  default:
                    Serial.println("Stop");
                    stop();
                    break;
                }
 
            }
            else
            {
                 // parsing error, reject
                 Serial.println("PARSING ERROR, incorrect number of parameters");
            }
            len = 0; // reset buffer counter
        }
    }
}

                Test that you can trigger this code from the serial port.  You can do that by sending commands over the Arduino serial monitor or directly from TouchDesigner.  In the video, I don’t introduce TouchDesigner until I’ve tested the Arduino separately and know it works on its own.

 

Trigger Arduino code from TouchDesigner

                In this step we go back to the basics and send commands manually from TouchDesigner before building our interface buttons.  Simply connect a Serial DAT to the correct COM port and run the following line from a Text DAT:

op('serial1').send("f 100", terminator="\n")

                The above line should make the car move forward with a speed of 100.  *Make sure the car battery is turned on or nothing will happen.*

 

Create a remote control interface

                Now that we are successfully triggering the code from TouchDesigner, we can build an interface that triggers different functions.  In this case, we’ll make a forward, back, right, left and stop button.  To trigger any code we’ll need a Comp Button, Merge CHOP and CHOP executable.  The code in the CHOP executable will vary depending on the purpose of the button. 

Each button should have the corresponding code:

Forward: op('serial1').send("f 100", terminator="\n")

Back: op('serial1').send("b 100", terminator="\n")

Left: op('serial1').send("l 100", terminator="\n")

Right: op('serial1').send("r 100", terminator="\n")

Stop: op('serial1').send("s 0", terminator="\n")

Feel free to use a speed higher than 100.  Using a lower speed will make the motors whir but they won’t move. 

 


That’s all there is to it!  Please follow the video tutorial for a complete follow along.  This lesson mainly was to show how TouchDesigner can be used as an interface for any Arduino controlled device and provide general steps on how to do that. 

Have fun, don’t just exist, do something everyday that scares you. 

 

Comments

Popular posts from this blog

Using an Arduino with Touch Designer – Beginner exploration

Building an 8x8x8 LED Cube from an Ebay Kit