En este artículo se detallan las piezas hardware, software e información conveniente para montar y poner en marcha el robot Otto.

Enlaces

Componentes

OttoDIY

OttoDIY+

Montaje

Los STLs de las piezas impresas se encuentran en el repositorio GitHub dentro del directorio 3D print.

Para el montaje seguir el PDF incluido en la raíz del repositorio GitHub (en el momento de escribir este artículo era la versión 07).

Calibración

Cargar el siguiente programa para averiguar los ajustes de trim para cuadrar el robot:

//-----------------------------------------------------------------
//-- Easy calibration for Otto DIY
//-- CC BY SA (http://ottodiy.com)
//--  Javier Isabel, 02/06/2015
//-- VERY IMPORTANT only calibrate ONE TIME per board!to avoid damage EEPROM memory
//-----------------------------------------------------------------
#include <Otto.h>
#include <Servo.h>
#include <Oscillator.h>
#include <EEPROM.h>

//-- First step: Configure the pins where the servos are attached
/*
         --------------- 
        |     O   O     |
        |---------------|
YR 3==> |               | <== YL 2
         --------------- 
            ||     ||
            ||     ||
RR 5==>   -----   ------  <== RL 4
         |-----   ------|
*/

#define PIN_YL 2
#define PIN_YR 3
#define PIN_RL 4
#define PIN_RR 5

#define TRIM_YL 3
#define TRIM_YR 9
#define TRIM_RL -3
#define TRIM_RR 6

Otto Otto;

void setup() {
  Otto.init(PIN_YL, PIN_YR, PIN_RL, PIN_RR, false);
  Otto.setTrims(TRIM_YL, TRIM_YR, TRIM_RL, TRIM_RR); //change Trim "offset values" gradually until Otto is completely straight (90º)
  // Otto.saveTrimsOnEEPROM(); //use only after completely straight(90º), delete this line after for further programming
}

void loop() { //test comparing before & after function
  Otto.home();
}

Por medio de ensayo/error identificar los valores de TRIM_RR, TRIM_RL, TRIM_YR y TRIM_YL que hacen que las cuatro articulaciones queden perfectamente cuadradas. Cuando se consiga, descomentar la línea que contiene el comando Otto.saveTrimsOnEEPROM(); y ejecutar una vez más para que se almacenen los valores en la EEPROM. A partir de entonces, todos los sketches que utilicen la librería Otto y que inicialicen ese objeto por medio de la función init poniendo true en el quinto argumento, cargarán estos valores de la calibración de la EEPROM y por tanto comenzarán con el robot bien encuadrado.

En el repositorio hay sketches que no se basan en la librería Otto sino que gestionan los servos directamente. En estos casos la gestión del trim también se hará directamente, ya que desafortunadamente las posiciones de los trim en la EEPROM no coinciden con los que hace la librería Otto, para evitar tener que regrabar sus valores en la EEPROM cada vez que pasemos de un tipo a otro de sketch. Por ejemplo en el sketch Otto_smooth_criminal, que no utiliza la librería Otto, los trim se leen de la EEPROM en orden inverso. Por tanto, será mejor desactivar su lectura y escribir los valores de trim directamente en el código. Así:

#define EEPROM_TRIM false
// Activate to take callibration data from internal memory
#define TRIM_RR 6
#define TRIM_RL -3
#define TRIM_YR  9
#define TRIM_YL 3

Programación

De entre los varios sketches de ejemplo que vienen en el repositorio, el más práctico para empezar a hacer una programación personalizada de Otto es el Otto_BASIC. En los comentarios que hay al principio se describen las funciones básicas de la librería Otto:

/*SOUNDS******************
 * S_connection  S_disconnection  S_buttonPushed S_mode1 S_mode2 S_mode3 S_surprise S_OhOoh  S_OhOoh2  S_cuddly
 * S_sleeping  S_happy S_superHappy S_happy_short S_sad S_confused S_fart1 S_fart2  S_fart3
 */
/*MOVEMENTS LIST**************
 * dir=1---> FORWARD/LEFT
 * dir=-1---> BACKWARD/RIGTH
 * T : amount of movement. HIGHER VALUE SLOWER MOVEMENT usually 1000 (from 600 to 1400)
 * h: height of mov. around 20
     jump(steps=1, int T = 2000);
     walk(steps, T, dir);
     turn(steps, T, dir);
     bend (steps, T, dir); //usually steps =1, T=2000
     shakeLeg (steps, T, dir);
     updown(steps, T, HEIGHT);
     swing(steps, T, HEIGHT);
     tiptoeSwing(steps, T, HEIGHT);
     jitter(steps, T, HEIGHT); (small T)
     ascendingTurn(steps, T, HEIGHT);
     moonwalker(steps, T, HEIGHT,dir);
     crusaito(steps, T, HEIGHT,dir);
     flapping(steps, T, HEIGHT,dir);
/*GESTURES LIST***************
OttoHappy OttoSuperHappy  OttoSad   OttoSleeping  OttoFart  OttoConfused OttoLove  OttoAngry
OttoFretful OttoMagic  OttoWave  OttoVictory  OttoFail*/

En setup se hace una inicialización básica de la librería Otto y se emite un sonido por el buzzer. Luego en el loop se ha programado una sencilla función para que Otto camine hacia delante hasta que localice un obstáculo a menos de 15cm y dé unos pasos hacia atrás y gire.

//-- Function to avoid obstacles
void obstacleMode(){
      distance = Otto.getDistance();
      if(distance<15){
          Otto.sing(S_surprise);
               Otto.walk(2,1300,-1);
               Otto.turn(3,1000,-1);
             delay(50);
        }
        else{
          Otto.walk(2,1000,1);
        }
}

Es útil aprovechar la funcionalidad del sensor de distancia para disparar el comportamiento de Otto que queremos programar. En otro caso todo lo que programemos dentro de la función loop se ejecutará sin parar. Así por ejemplo, imitando la función obstacleMode, un ejemplo de loop en el que haremos que cuando pongamos la mano delante, Otto avance un par de pasos, haga el moonwalk hacia la derecha, dé un pequeño salto y se detenga ejecutando el gesto de victoria sería:

void loop() {
  distance = Otto.getDistance();
  if(distance<15){
    Otto.walk(2,1000,1);
    Otto.home();
    Otto.moonwalker(3, 1000, 25, -1);
    Otto.home();
    Otto.jump(1, 1000);
    Otto.home();
    Otto.playGesture(OttoVictory);
    Otto.home();
  } else {
    Otto.home();
  }
}