# Teach Your Robot a Movement

Shows how you can teach a single-axis move by using the Record/Play tactic

Did you hear about teaching a robot a move but don't know how to do that?

Did you ever struggle around to make a polished mathematical way/time function more dirty?

Did you ever had a robot part that moved unnatural - not human like but wanted it to appear more human?

This tip shows you one of many ways to get a discreete movement profile from human interaction. It shows you how you could teach your robot moves that are from a human being.

Content

1. Overview
2. What components do you need?
3. What software do you need?
4. How do I record the data?
5. How do I play the data?

1. Overview

Basically we record a move, transform that data into executable code and execute it - play it.

In this tip we use an ultrasonic sensor to sense the distance between the sensor and my hand. This distance is what is mapped to i.e. servo angles so that the servo follows exactly the given curve.

The tip works fine for single-axis movements (like one wing of the Bøsewicht). Multi-axis movements are more sophisticated and most of the time need a pendant that is mechanical identical (like Walter or the master-slave arm). Multi-axis movements can have a profile in more than one axis - can turn in the X/Y plane and in the Y/Z plane in the same time.

2. What components do you need?

Arduino, Gobetwino, Servo, Ultrasonic Sensor

3. What software do you need?

Use this code to record the motions.

```void loop()
{
val = ultrasonic.Ranging(CM);
val = map(val, 0, 60, 0, 179);

myservo.write(val);
log(value);

delay(20);
}

void log(int value){
Serial.print("#S|LOGTEST|[");
Serial.print(val);
Serial.println("]#");
}
```

4. How do I record the data?

1. Start the Arduino.
3. Start Gobetwino
4. Record data into text file
5. Stop the recording when the move is finished
7. Smothen the data (see Appendix B)
8. Transform data from spreadsheet to C
9. Embed the C data into your robot code

5. How do I play the data?

1. Let a loop go over the lookupTable array
2. Write value from lookupTable[index] to the servo. See Appendix A for a full code sample (Nonblocking).

Using Gobetwino to debug your sensor data
"Being able to see what your robot see's in realtime is a powerful diagnostic tool when writing your software"

Gobetwino
Gobetwino is kind of a "genreric proxy" for Arduino. It's a program running on a PC, that will act on behalf of Arduino and do some of the things that Arduino can't do on its own. So it works like a go between, hence the name.

Rotate something with minimal jerk.

Appendix A: Example-Code

```/*
* Plays recorded data.
* more infos: http://letsmakerobots.com/node/34270
* created by NilsB
*/

#include <MsTimer2.h>
#include <Servo.h>

const int servoStartAngle = 100;
const int timerInMillies = 20;
const int countSinusSquareLookupTableEntries = 368;
const int sinusSquareLookupTable[] = {67, 67, 67, 69, 69, 67, 69, 69, 69, 69, 67, 67, 67, 65, 65, 65, 65, 65, 65, 65, 65, 63, 65, 65, 67, 69, 69, 65, 65, 65, 65, 65, 65, 61, 59, 59, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 56, 54, 54, 52, 52, 52, 54, 50, 50, 46, 46, 46, 44, 44, 42, 40, 40, 38, 57, 65, 57, 37, 35, 35, 33, 33, 31, 31, 31, 31, 31, 33, 33, 33, 35, 35, 35, 35, 37, 37, 40, 42, 42, 44, 46, 50, 56, 56, 54, 57, 57, 59, 65, 67, 69, 67, 73, 73, 73, 80, 82, 78, 80, 80, 82, 82, 84, 88, 92, 92, 92, 92, 90, 88, 82, 80, 76, 75, 75, 69, 69, 67, 63, 61, 59, 59, 57, 57, 52, 57, 42, 40, 38, 35, 35, 33, 37, 31, 31, 31, 31, 33, 38, 33, 33, 35, 38, 38, 42, 46, 52, 54, 57, 59, 67, 69, 69, 71, 78, 78, 80, 82, 86, 88, 90, 92, 90, 90, 90, 84, 78, 75, 69, 69, 67, 69, 54, 48, 71, 57, 38, 33, 31, 31, 31, 31, 31, 31, 29, 29, 31, 31, 33, 35, 38, 57, 42, 46, 50, 56, 57, 59, 65, 69, 69, 75, 80, 80, 84, 92, 92, 95, 97, 97, 99, 99, 103, 92, 95, 88, 95, 80, 78, 69, 69, 63, 61, 56, 90, 57, 69, 40, 57, 40, 38, 35, 33, 33, 31, 31, 33, 33, 35, 37, 35, 57, 37, 42, 38, 38, 42, 44, 50, 52, 54, 57, 57, 59, 63, 82, 67, 69, 75, 80, 80, 80, 82, 86, 90, 95, 97, 99, 97, 103, 105, 105, 111, 114, 120, 120, 116, 118, 118, 118, 118, 118, 118, 118, 116, 118, 118, 118, 118, 116, 118, 116, 118, 118, 118, 118, 118, 118, 118, 118, 118, 120, 112, 109, 107, 101, 99, 92, 88, 82, 78, 75, 69, 114, 69, 59, 57, 57, 50, 42, 40, 38, 35, 38, 31, 29, 29, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 29, 29, 31, 29, 29, 31, 29, 33, 33, 35, 37, 40, 46, 57, 59, 61, 63, 67, 69, 73};
int currentValueIndex = 0;
const int movmentIndicatorPin = 13;

void move()
{
moveServoTo(angle());

indicateMovement();
incrementOrStop();
}

void moveServoTo(int angle){
Serial.println(angle);
}

int angle(){
return sinusSquareLookupTable[currentValueIndex];
}

void indicateMovement()
{
static boolean output = HIGH;

digitalWrite(movmentIndicatorPin, output);
output = !output;
}

void incrementOrStop(){
currentValueIndex++;
if(currentValueIndex == countSinusSquareLookupTableEntries - 1){
stopMove();
}
Serial.println(currentValueIndex);
}

void stopMove(){
MsTimer2::stop();
}

void setupMovementIndicator(){
Serial.begin(9600);
pinMode(movmentIndicatorPin, OUTPUT);
}

void setupTimer2(){
MsTimer2::set(timerInMillies, move);
MsTimer2::start();
}

void setupServo(){
}

void setup(){
Serial.begin(9600);
setupMovementIndicator();
setupServo();
setupTimer2();
}

void loop(){;}
```

Appendix B: Visual comparison of raw and smoothened curve