Convert string into driving pattern for "robot".

For a school assignment we have to make a "robot" write a word of 4 characters or more.
So far we've got all the requirements and can make the "robot" drive.

I would like to hear your thoughts on how to convert a string into a driving pattern for the robot.
I could program functions for every letter of the alphabet but maybe there is something easier/better?

maybe there is something easier/better?

how do you measure/compare better?
what is the criteria?

How many functions does a typical robot have:
Forward, Backwards, turnLeft turnRIght
These can be parameterized by the speed or degrees.
e.g.
int Forward(int speed)
int turnleft(int degrees)

Furthermore a robot can have additional servo's, either numbered or named, and a number of sensors and its internal state.

To keep command short I would go for a protocol consisting of a command byte and one or more parameter bytes depending on command.

FBB = set forward followed by 2 bytes indicating the speed)
LBB = set turnleft

GS = getSpeed
GA = getAll (state dump)
SS = Set servo

etc.

First think of all the commands you want/need and if you get the idea you are complete start coding a parser something like this

char cmd = getCommand();

switch(command)
{
  case F : // forward!!
              speed = getInt();
              forward(speed);
              break;  
  case L : // left!!
              angle = getInt();
              turnLeft(angle);
              break;
  case G : // get something
              what = getByte;
              response = getParam(what);
              sendResponse(response);
              break;
  ...etc...
  default : // invalid command ==> error message               
}[/code']

For a school assignment we have to make a "robot" write a word of 4 characters or more.

This makes it sound as though you get to pick the word in advance. If so, you need not code for every letter, your sketch can simply issue a series of motor commands to write your chosen word. Much cooler to do it the way you suggest though, in which case a function for every letter would work. Alternatively you might try making it data driven and describe the strokes per letter and have your code interpret them and command the motors.

I indeed get to pick the word I'm supposed to write and I was also thinking of just programming a series of commands that can be put together in other functions which on their part write words on paper (e.g. long stroke, short stroke, big circle (capital o), small circle, half a circle (g) etc.).

We're using lego power functions motors in order to drive. These have 4 bundles of wires of which we only use the middle 2 (power and direction).

What I was really wondering about is, is there some sort of library that treats characters as objects with property values for all "strokes"?

Really I appreciate all help.

this is how I did the Tx controller for my Rover 5.

#define deadBand 20 
#define Xraw_center 534 
#define Yraw_center 471 
#define Joy_X_pin A0 
#define Joy_Y_pin A1


char button0=3, button1=4, button2=5, button3=6;
char sel=2;
int rawX;
int rawY;
int yaxis;
int xaxis;
int xspeed;
int yspeed;
char speedCom;
char steerCom;
char speedArray[7][7] ={
    {'v','v','v','v','v','v','v'},
    {'v','c','c','c','c','c','v'},
    {'v','c','x','x','x','c','v'},
    {'v','c','x','z','x','c','v'}, //
    {'v','c','x','x','x','c','v'},
    {'v','c','c','c','c','c','v'},
    {'v','v','v','v','v','v','v'},

};
char steerArray[7][7] ={
    {'7',' ',' ','8',' ',' ','9'},
    {' ','7',' ','8',' ','9',' '},
    {' ',' ','7','8','9',' ',' '},
    {'4','4','4','5','6','6','6'},
    {' ',' ','1','2','3',' ',' '},
    {' ','1',' ','2',' ','3',' '},
    {'1',' ',' ','2',' ',' ','3'},

};

void setup(void)
{
  pinMode(sel, INPUT);      //Set the Joyaxisstick "Select"button as an input
  digitalWrite(sel, HIGH);  //Enable the pull-up resistor on the select button
  
  pinMode(button0, INPUT);      //Set the Joyaxisstick button 0 as an input
  digitalWrite(button0, HIGH);  //Enable the pull-up resistor on button 0

  pinMode(button1, INPUT);      //Set the Joyaxisstick button 1 as an input
  digitalWrite(button1, HIGH);  //Enable the pull-up resistor on button 1
  
  pinMode(button2, INPUT);      //Set the Joyaxisstick button 2 as an input
  digitalWrite(button2, HIGH);  //Enable the pull-up resistor on button 2

  pinMode(button3, INPUT);      //Set the Joyaxisstick button 3 as an input
  digitalWrite(button3, HIGH);  //Enable the pull-up resistor on button 3
  
  Serial.begin(9600);           //Turn on the Serial Port at 9600 bps
  Serial3.begin(9600);          //Turn on the XBee Serial Port at 9600 bps
}

void loop(void)
{
  // Get joystick position
  rawX = analogRead(Joy_X_pin);
  rawY = analogRead(Joy_Y_pin);
  xaxis = rawX; 
  yaxis = rawY; 
  xspeed = map(rawX,0,1023,0,7);
  yspeed = map(rawY,0,1023,0,7);
  Serial.print("X,Y - ");
  Serial.print(xaxis);
  Serial.print(" , ");
  Serial.println(yaxis);
  Serial.print("speed - ");
  Serial.print(xspeed);
  Serial.print(" , ");
  Serial.println(yspeed);
  
  //speed
  if (rawX>0){
    if (rawX<1023) {speedCom = 'v';}
  }
  if (rawX>128){
    if (rawX<896) {speedCom = 'c';}
  }
  if (rawX>256){
    if (rawX<768) {speedCom = 'x';}
  }
  if (rawX>384){
    if (rawX<896) {speedCom = 'z';}
  }  
  if ((rawX<=(Xraw_center-deadBand))&&(rawX>=(Xraw_center-deadBand))) {speedCom = ' ';}
  
  if (rawY>0){
    if (rawY<1023) {speedCom = 'v';}
  }
  if (rawY>128){
    if (rawY<896) {speedCom = 'c';}
  }
  if (rawY>256){
    if (rawY<768) {speedCom = 'x';}
  }
  if (rawY>384){
    if (rawY<896) {speedCom = 'z';}
  } 
  if ((rawY<=(Yraw_center-deadBand))&&(rawY>=(Yraw_center-deadBand))) {speedCom = ' ';}
  
  //steering
  if (xaxis<(Xraw_center-deadBand))             //left of centre
  {
    if (yaxis<Yraw_center-deadBand) 
        {steerCom = '1';}
    else if ((yaxis>(Yraw_center-deadBand))&&(yaxis<(Yraw_center+deadBand))) 
        {steerCom = '4';}
    else if (yaxis>Yraw_center+deadBand) 
        {steerCom = '7';}    
  }
  else if (xaxis>=(Xraw_center-deadBand)&&(xaxis<=(Xraw_center+deadBand)))  // centre
  {
    if (yaxis<(Yraw_center-deadBand)) 
        {steerCom = '2';}
    else if ((yaxis>=(Yraw_center-deadBand))&&(yaxis<=(Yraw_center+deadBand))) 
        {steerCom = '5';}
    else if (yaxis>(Yraw_center+deadBand)) 
        {steerCom = '8';}
  }else if (xaxis>(Xraw_center+deadBand)){                //right of centre
      if (yaxis<(Yraw_center+deadBand)) {steerCom = '3';}
      else if ((yaxis<(Yraw_center-deadBand))&&(yaxis>(Yraw_center+deadBand))) 
        {steerCom = '6';}
      else if (yaxis>(Yraw_center+deadBand)) 
        {steerCom = '9';}
  }

 Serial.print("Speed - ");
 Serial.println(speedCom);
 Serial3.print(speedCom);
 delay(200);
 Serial.print(" Direction - ");
 Serial.println(steerCom);
 Serial3.print(steerCom);
 delay(200);
}

It is set up for to map a joystick to look like a numeric keypad.
the number keys control direction,
z,x,c,v control speed.
Using a keyboard you select a speed, then a direction.

On the Rover 5 Mega -

/* My Rover 5 basic receiver for use with a Sparkfun Monster Motor Shield
on A Mega
It's basically the example for the monster motor shield
 */
#define BRAKEVCC 0
#define CW   1
#define CCW  2
#define BRAKEGND 3
#define CS_THRESHOLD 100

/*  VNH2SP30 pin definitions
 xxx[0] controls '1' outputs
 xxx[1] controls '2' outputs */
int inApin[2] = {7, 4};  // INA: Clockwise input
int inBpin[2] = {8, 9}; // INB: Counter-clockwise input
int pwmpin[2] = {5, 6}; // PWM input
int cspin[2] = {2, 3}; // CS: Current sense ANALOG input
int enpin[2] = {0, 1}; // EN: Status of switches output (Analog pin)

int turnRate = 8;
int leftspeed = 80;
int rightspeed = 80;
int statpin = 13;

void setup()
{
  Serial.begin(9600);
  Serial3.begin(9600);
  pinMode(statpin, OUTPUT);

  // Initialize digital pins as outputs
  for (int i=0; i<2; i++)
  {
    pinMode(inApin[i], OUTPUT);
    pinMode(inBpin[i], OUTPUT);
    pinMode(pwmpin[i], OUTPUT);
  }
  // Initialize braked
  for (int i=0; i<2; i++)
  {
    digitalWrite(inApin[i], LOW);
    digitalWrite(inBpin[i], LOW);
  }
  
}

void loop()
{
   while (Serial3.available() < 1) {} // Wait until a character is received
  char val = Serial3.read();
  Serial.println(val); // for debugging
  
  switch(val) // Perform an action depending on the command
  {
  case '6':// pivot right
    {
      motorGo(0, CW, leftspeed);
      motorGo(1, CW, rightspeed);
    }
    break;
  case '4':// pivot left
    {
      motorGo(0, CCW, leftspeed);
      motorGo(1, CCW, rightspeed);
    }
    break;
  case '9'://fwd right
    {
      motorGo(0, CW, leftspeed - turnRate);
      motorGo(1, CW, rightspeed + turnRate);
    }
    break;
  case '1'://rev left
    {
      motorGo(0, CW, leftspeed + turnRate);
      motorGo(1, CW, rightspeed - turnRate);
    }
    break;
    
    case '3'://rev right
    {
      motorGo(0, CCW, leftspeed - turnRate);
      motorGo(1, CCW, rightspeed + turnRate);
    }
    break;
    case '7'://fwd left
    {
      motorGo(0, CCW, leftspeed + turnRate);
      motorGo(1, CCW, rightspeed - turnRate);
    }
    break;
    case '8'://fwd
    {
      motorGo(0, CW, leftspeed);
      motorGo(1, CCW, rightspeed);
    }
    break;case '2'://rev
    {
      motorGo(0, CCW, leftspeed);
      motorGo(1, CW, rightspeed);
    }
    break;
    case 'z'://min
    {
      leftspeed = 80;
      rightspeed = 80;
    }
    break;
    case 'x'://slow
    {
      leftspeed = 100;
      rightspeed = 100;
    }
    break;
    case 'c'://fast
    {
      leftspeed = 128;
      rightspeed = 128;
    }
    break;
    case 'v'://max
    {
      leftspeed = 255;
      rightspeed = 255;
    }
    break;
  default:
    {
      motorOff(0);
      motorOff(1);
      leftspeed = 0;
      rightspeed = 0;
    }
    break;
  }
}

void motorOff(int motor)
{
  // Initialize braked
  for (int i=0; i<2; i++)
  {
    digitalWrite(inApin[i], LOW);
    digitalWrite(inBpin[i], LOW);
  }
  analogWrite(pwmpin[motor], 0);
}

/* motorGo() will set a motor going in a specific direction
 the motor will continue going in that direction, at that speed
 until told to do otherwise.
 
 motor: this should be either 0 or 1, will selet which of the two
 motors to be controlled
 
 direct: Should be between 0 and 3, with the following result
 0: Brake to VCC
 1: Clockwise
 2: CounterClockwise
 3: Brake to GND
 
 pwm: should be a value between 0 and 255, higher the number, the faster
 it'll go
 */
void motorGo(uint8_t motor, uint8_t direct, uint8_t pwm)
{
  if (motor <= 1)
  {
    if (direct <=4)
    {
      // Set inA[motor]
      if (direct <=1)
        digitalWrite(inApin[motor], HIGH);
      else
        digitalWrite(inApin[motor], LOW);

      // Set inB[motor]
      if ((direct==0)||(direct==2))
        digitalWrite(inBpin[motor], HIGH);
      else
        digitalWrite(inBpin[motor], LOW);

      analogWrite(pwmpin[motor], pwm);
    }
  }
}

From here you could "vectorize" each character, you'll need to have some kind of odometer to see how far it went.
If you make up a list of unit vectors for each character you could then scale them to get different size characters.