Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Construye un robot de 2 ruedas controlado por voz con Arduino y BitVoicer Server

Componentes y suministros

Componente Descripción Cantidad
Arduino UNO 1
Shield controlador motor dual Pololu MC33926 1
Shield XBee SparkFun 1
Módulo Microchip RN171VX 1
Micrófono electret preamplificado SparkFun 1
Chasis robot 2WD 1
Regulador de voltaje LM1117 (TO-220) Texas Instruments 1
Condensador 10 µF 1
LED (genérico) 4
Resistencia 330 ohm 4
Pilas AA 4
Pila 9V (genérica) 1
Adaptador 9V a Jack barrel 1
Cables jumper (genéricos) 17
Cable de cobre normal 1
Tornillos y abrazadera plástica flexible para fijación 1

Herramientas y máquinas necesarias

Aplicaciones y servicios en línea

Sobre el proyecto

En este tutorial, voy a mostrar cómo construir un robot 2WD controlado por voz. Aunque solo controlo motores DC para mover el robot, el mismo enfoque puede usarse para controlar por voz motores paso a paso y servomotores, así que si planeas construir cualquier robot controlado por voz que realice movimientos mecánicos, este tutorial puede servir como referencia.

Construye un robot de 2 ruedas controlado por voz con Arduino y BitVoicer Server

Para construir este robot, básicamente necesitas: un chasis 2 ruedas, una placa Arduino, un shield controlador de motores DC, una licencia de BitVoicer Server, un módulo WiFi y un micrófono preamplificado. Hay una gran variedad de componentes en el mercado y puedes lograr los mismos resultados con diferentes combinaciones. En el Paso 1 doy detalles sobre algunos componentes usados, así que si necesitas cambiar alguno, busca componentes con características similares.

Los siguientes procedimientos se ejecutarán para transformar comandos de voz en movimientos del robot:

  1. Las ondas de audio serán capturadas y amplificadas por la placa Sparkfun Electret Breakout.
  2. La señal amplificada será digitalizada y almacenada en buffer en el Arduino usando su conversor analógico-digital (ADC).
  3. Las muestras de audio se transmitirán a BitVoicer Server usando el módulo WiFi Microchip.
  4. BitVoicer Server procesará el flujo de audio y reconocerá el habla que contiene.
  5. El habla reconocida se mapeará a comandos predefinidos que se enviarán al Arduino.
  6. El Arduino identificará el comando y definirá qué motores DC se usarán, durante cuánto tiempo y a qué velocidad.
  7. El controlador de motores se activará para proporcionar el voltaje y corriente necesarios para mover los motores.

Lista de materiales (precios aproximados)

PASO 1: Conociendo los componentes

En este paso doy información importante sobre los componentes del robot y cómo prepararlos para el montaje.

En primer lugar, el corazón del robot: un Arduino UNO R3. Aunque uso un Arduino UNO, puedes usar otras placas Arduino. Elegí el UNO porque es, con diferencia, la placa Arduino más popular y más gente podría reconstruir este robot. Si tienes un Arduino DUE, también puedes añadir respuestas de voz a tu robot como hice en este tutorial.

Para mover los motores DC, usé este shield Pololu. Es un controlador dual capaz de controlar motores DC de 5 a 28V y entregar hasta 3A continuos por motor. Aunque creo que es un shield muy bueno, lo que más me impresionó de los productos Pololu es su documentación clara y detallada. Además, Pololu proporciona una librería Arduino que hace muy simple controlar los motores. Solo tienes que pasar la velocidad y dirección (valores negativos o positivos) a la función setSpeeds. Si optas por otro controlador de motores DC, presta atención a los pines usados porque no pueden entrar en conflicto con otros pines usados por el robot. El shield Pololu usa: digitales 4, 7, 8, 9, 10 y 12; analógicos 0 y 1; tierra; y 5V. Lo más importante es que solo los pines 9 y 10 se usan como PWM y el temporizador usado para generar pulsos en estos pines no es el mismo temporizador (temporizador 2 en el UNO) usado por la clase BVSMic de BitSophia.

Construye un robot de 2 ruedas controlado por voz con Arduino y BitVoicer Server

Para establecer comunicación con el servidor y acceder a los servicios de BitVoicer Server, uso el módulo WiFi Microchip RN171VX. Dos características principales destacan: toda la comunicación puede hacerse a través del puerto serie de manera simple; y el módulo tiene el mismo factor de forma que la mayoría de módulos XBee populares. En otras palabras, si ya tienes un shield XBee, lo más probable es que no necesites comprar el shield Sparkfun que uso en este robot.

Usar el shield XBee con el módulo WiFi Microchip hizo el montaje bastante fácil. Sin embargo, identifiqué un problema en esta combinación. Se sabe que trabajar con radio es extremadamente complejo y considerado por algunos como "magia vudú". Noté que mientras el adaptador WiFi está encendido y transmitiendo datos, ocurre una fuerte interferencia en la señal de audio medida por el ADC del Arduino. No pude identificar precisamente la fuente, pero tengo dos posibles causas: los picos de consumo de corriente del módulo (hasta 240mA) no se desacoplan correctamente y comprometen el voltaje de referencia del ADC del Arduino; o la señal emitida por la antena es captada por algunos pines expuestos justo debajo del módulo. Normalmente, los fabricantes de módulos WiFi instruyen a los diseñadores a evitar colocar nada (incluso planos de tierra) cerca de la antena precisamente para prevenir este tipo de problema.

Para correglo, soldé un regulador de 3.3V y un condensador electrolítico de 10μF al shield Sparkfun para que proporcionaran el voltaje de referencia al ADC del Arduino. La misma fuente de alimentación la usa el micrófono electret Sparkfun. Solucionó los problemas de pico de volumen que veía en el BitVoicer Server Manager. Incluso en periodos de silencio, el nivel de audio llegaba a 35 (0-100) en el Monitor del Servidor. Si ves lo mismo en tu proyecto, investiga qué ocurre con la señal de audio medida por el ADC del Arduino.

Decidí también usar el espacio de prototipado del shield Sparkfun para soldar unos LEDs que indican el estado de algunas funcionalidades de BitVoicer Server. En la imagen de abajo, de izquierda a derecha:

Construye un robot de 2 ruedas controlado por voz con Arduino y BitVoicer Server
Construye un robot de 2 ruedas controlado por voz con Arduino y BitVoicer Server

Respecto al micrófono electret preamplificado, hay muchas opciones: Sparkfun, Adafruit, RoboCore, Hackerstore y probablemente muchas más. Para usar el código de este tutorial, asegúrate de que el micrófono sea analógico, el voltaje requerido esté disponible en tu Arduino, y la amplificación sea suficiente (usualmente 100x para micrófonos electret) para el ADC del Arduino.

El chasis 2WD usado es uno de los más baratos y populares en eBay. El kit completo contiene: una plataforma acrílica, dos ruedas plástico/goma, una rueda 360º, dos motores DC con reductor (ratio 1:48), un porta-pilas 4xAA, dos discos codificadores de velocidad y un set de tornillos.

PASO 2: Montaje

¡Manos a la obra! En este paso debes montar todos los componentes en el chasis como se muestra en las fotos.

Si no quieres soldar los LEDs y el regulador en el shield XBee, puedes montarlos en una protoboard pequeña como se muestra abajo. En ese caso, elige una protoboard de tamaño reducido para fijarla en el chasis sin problemas.

Construye un robot de 2 ruedas controlado por voz con Arduino y BitVoicer Server

En las fotos se nota que hice un soporte de alambre de hierro para sostener el micrófono. También pegué una tira de fieltro alrededor de la rueda 360º. Tomé estas dos medidas para reducir el ruido generado por el robot y captado por el micrófono cuando se mueve. Incluso corté un trozo pequeño de esponja para aislar los cables del micrófono del soporte. Por supuesto no fue 100% efectivo, pero redujo un poco el ruido y mejoró la precisión del reconocimiento de voz.

PASO 3: Configuración del módulo WiFi

Como dije en el Paso 1, el módulo WiFi Microchip RN171VX puede operarse totalmente a través del puerto serie. Esto hace extremadamente fácil configurar el módulo porque todos los comandos son cadenas simples enviadas a través del puerto serie del Arduino. Solo tienes que enviar una cadena con "$$$" para entrar en modo comando, enviar los comandos y luego enviar "exit" para volver a modo datos.

El código llamado Configuración módulo WiFi al final de este tutorial es el que usé para configurar el módulo en mi red doméstica. Tendrás que cambiar las partes marcadas como "XXXXXX" con información de tu red WiFi. Tres comandos hay que cambiar:

En mi red, el método de autenticación es WPA2-PSK. Si tu red usa otro método, también tendrás que cambiar el comando set wlan auth. Consulta la documentación del módulo WiFi (sección 4.3 Set Commands) para saber qué valor es correcto para tu red.

Hay un detalle importante sobre el shield Sparkfun y su pequeño interruptor. Para subir código al Arduino usando su interfaz USB, el interruptor debe estar en posición DLINE. Para que el Arduino envíe/reciba datos a través del módulo WiFi usando su puerto serie, el interruptor debe estar en posición UART. Esto es necesario porque el módulo WiFi y el chip USB del Arduino UNO usan el mismo puerto serie en el microcontrolador ATmega. Si el interruptor está en UART e intentas subir código, el IDE de Arduino mostrará un error.

Construye un robot de 2 ruedas controlado por voz con Arduino y BitVoicer Server

Para subir el código Configuración módulo WiFi al Arduino y permitir que configure el módulo, sigue estos pasos:

  1. Pon el interruptor en posición DLINE.
  2. Abre el IDE de Arduino, pega y sube el código.
  3. En cuanto termine la subida, tienes 5 segundos (delay al inicio del código) para cambiar el interruptor a UART antes de que se envíen los comandos al módulo WiFi. Si se pierde el primer comando, ninguno de los otros funcionará. En ese caso, simplemente reinicia el Arduino para que el boceto se ejecute de nuevo desde el principio.

Durante la configuración del módulo, que tarda unos 25 segundos, los LEDs del módulo parpadearán de forma distinta a su patrón estándar. En ese momento sabrás que el módulo WiFi se está configurando.

Después de configurado, intenta hacer ping (Símbolo del sistema → "ping [Dirección IP]" → Enter) al módulo usando la IP especificada en set ip address. Si no obtienes respuesta, algo falló en los pasos anteriores.

PASO 4: Planificando los movimientos del robot

Aunque el robot solo tiene dos motores DC, es capaz de realizar una serie de movimientos complejos. Para mantener este tutorial simple, definí solo unas tres docenas de movimientos básicos uniformes y algunos movimientos complejos formados por combinación de los básicos.

Como ves en las fotos del Paso 2, no uso sensores de rotación en las ruedas, ultrasónicos ni ningún otro sensor para medir distancia a objetos o distancia recorrida. Esto impide movimientos de alta precisión. Sin embargo, controlando solo dirección y velocidad de los motores se puede lograr un nivel de precisión suficiente para mover el robot.

Lo primero que necesitas saber para calcular el tiempo de ejecución necesario para cada movimiento es la velocidad media del robot. Para ello, coloca una cinta métrica paralela al robot y activa ambos motores simultáneamente durante uno o dos segundos, mide la distancia recorrida y deduce la velocidad. En mi configuración, obtuve 13,7 cm/s empleando el 62,5% de la velocidad máxima del motor (250/400, ver librería Arduino Pololu). Es decir, para mover el robot 1 metro (100 cm) hacia adelante, los motores debían activarse simultáneamente durante 7,299270... segundos. He elegido mantener el conteo en milisegundos, pero si quieres mayor precisión, considera subir la resolución a microsegundos. En resumen, para mover el robot 1 metro, debo activar ambos motores simultáneamente durante 7299 milisegundos. De este número, todo se convierte en regla de tres para otras distancias. Para movimientos de arco o circulares, una rueda debe moverse más rápido que la otra. Para girar el robot a los lados, solo una rueda debe activarse o ambas en direcciones opuestas (para girar sobre su propio eje). Aquí tendrás que usar trigonometría para averiguar la distancia recorrida por cada rueda y cuánto tiempo debe activarse cada motor. Un buen punto de partida para estos conceptos: CirclePath y Move two-wheeled robot.

Construye un robot de 2 ruedas controlado por voz con Arduino y BitVoicer Server

Como se ve al final del vídeo, también hago que el robot "dibuje" formas geométricas básicas (cuadrado, triángulo y círculo) en el suelo. Estos movimientos se logran combinando movimientos básicos (ej. avanzar, girar, avanzar, girar...). La combinación se hace en el Esquema de Voz de BitVoicer Server y no la verás en el boceto de Arduino del siguiente paso.

PASO 5: Subiendo el código al Arduino

En este paso debes subir el boceto llamado Código fuente del robot, al final de este tutorial, al Arduino. También puedes descargar el boceto desde el enlace de abajo. Recuerda que para enviar código al Arduino debes poner el interruptor del shield Sparkfun en posición DLINE como se describe en el Paso 3. Antes de subir, debes instalar correctamente las librerías de BitVoicer Server y del controlador de motores Pololu en el IDE de Arduino (Importar librería .zip).

Código fuente del robot: BVS_Demo3.ino

Algunas partes de este boceto son similares a partes que usé en un tutorial anterior y tratan la comunicación con BitVoicer Server (clases BVSP y BVSMic). En este tutorial me centraré en las partes nuevas. Si quieres más info sobre BVSP y BVSMic, te sugiero consultar el tutorial mencionado.

PASO 6: Configurando BitVoicer Server

En este paso debes construir el Esquema de Voz de BitVoicer Server con las frases a reconocer y los comandos que se enviarán al Arduino. Al final hay dos enlaces a archivos con todos los Objetos de Solución de BitVoicer Server usados. Si no quieres crear todos los objetos uno a uno, puedes importarlos (Importar Objetos de Solución) usando estos archivos.

Antes de empezar a construir el Esquema de Voz, debes crear un dispositivo que represente al Arduino en BitVoicer Server. Crea un dispositivo mixto y nómbralo ArduinoUnoWiFi. En la pestaña Comunicación, selecciona TCP/IP e introduce la IP asignada al módulo WiFi en el Paso 3. En la pestaña Cues, habilita Start of Activated Period y End of Activated Period. Selecciona comandos Int16 SendData para ambos y selecciona el dispositivo ArduinoUnoWiFi como destino. En el campo Data, introduce 1 para Start of Activated Period y 0 para End of Activated Period. Estos cues harán que el Arduino encienda un LED cada vez que se reconozca la palabra de activación. Cuando expire el periodo activado (definido en el Esquema de Voz), este LED se apagará.

Ahora construyamos el Esquema de Voz. Aunque el robot tiene solo 40 comandos básicos, puedes querer crear muchas combinaciones de palabras que disparen el mismo comando. Ejemplo: "mueve adelante un metro" y "avanza un metro" disparan el mismo comando. Además, puedes querer crear comandos complejos como "haz un cuadrado" que disparen una serie de comandos temporizados en secuencia. Por eso tu Esquema de Voz puede crecer mucho y tener muchos más de 40 comandos básicos. BitVoicer Server soporta frases ilimitadas, así que puedes definir tantas como necesites (el mío terminó con más de 80 frases). Dos consejos: crea un comando por defecto en las Opciones del BitVoicer Server Manager; y copia y pega comandos duplicados de una frase a otra.

Construye un robot de 2 ruedas controlado por voz con Arduino y BitVoicer Server

Los comandos de frase enviarán tipos de datos byte al Arduino. Usa las constantes definidas al inicio del boceto para saber qué valor enviar para cada comando. Los comandos complejos enviarán muchos valores en secuencia y tendrás que controlar el intervalo (delay) entre ellos para que ningún valor se envíe mientras el comando anterior está en ejecución. Usa el campo delay para establecer el intervalo entre comandos.

Archivos de Objetos de Solución:

PASO 7: Conclusión

Ahora solo tienes que poner las pilas AA y conectar la pila de 9V al jack de alimentación del Arduino para que tu robot cobre vida. Después de subir el código, no olvides poner el interruptor del shield Sparkfun en posición UART. De lo contrario, el módulo WiFi no recibirá datos del puerto serie del Arduino.

Al encender el robot, los LEDs de estado tardarán un poco en encenderse. Verás el módulo WiFi iniciando comunicación y cuando se establezca la conexión TCP/IP, uno de los LEDs del módulo se quedará fijo. Tras unos instantes, tres de los cuatro LEDs de estado se encenderán también. Esto significa que un motor de reconocimiento de voz ha sido asignado al Arduino. A partir de ahora, el robot está listo para recibir comandos.

Tras algunas pruebas, quedé bastante satisfecho con el reconocimiento de voz, aunque no reconocía el 100% de los comandos siempre. En este aspecto BitVoicer Server me sorprendió gratamente. Sin embargo, no quedé tan satisfecho con la precisión de los movimientos. Para solucionarlo, habría que añadir sensores de rotación a las ruedas. El kit de chasis ya viene con discos decodificadores que se pueden acoplar al engranaje. Aplicar sensores a estos discos permitiría mover el robot basándose en la distancia real recorrida, haciendo sus movimientos más precisos. También podría añadir sensores ultrasónicos para evitar chocar con muebles. Probablemente lo haga algún día, pero por ahora lo dejo en tus manos.

¡Hasta la próxima!

Código

Configuración módulo WiFi

void setup() {
  Serial.begin(115200);
  pinMode(13, OUTPUT);
  delay(5000);
  Serial.print("$$$");
  delay(1000);
  Serial.println("set wlan auth 4");
  delay(1000);
  Serial.println("set wlan phrase XXXXXX");
  delay(1000);
  Serial.println("set wlan ssid XXXXXX");
  delay(1000);
  Serial.println("set wlan channel 0");
  delay(1000);
  Serial.println("set wlan join 1");
  delay(1000);
  Serial.println("set wlan tx 0");
  delay(1000);
  Serial.println("set ip dhcp 0");
  delay(1000);
  Serial.println("set ip address XXXXXX");
  delay(1000);
  Serial.println("set comm remote 0");
  delay(1000);
  Serial.println("set comm close 0");
  delay(1000);
  Serial.println("set comm open 0");
  delay(1000);
  Serial.println("set comm size 500");
  delay(1000);
  Serial.println("set comm time 50");
  delay(1000);
  Serial.println("set uart baud 115200");
  delay(1000);
  Serial.println("set uart flow 0");
  delay(1000);
  Serial.println("save");
  delay(1000);
  Serial.println("exit");
  delay(1000);
  digitalWrite(13, LOW);
}
void loop() { }

Código fuente del robot

#include <BVSP.h>
#include <BVSMic.h>
#include <DualMC33926MotorShield.h>

#define BVS_RUNNING 2
#define BVS_SRE 5
#define BVS_DATA_FWD 3
#define BVS_ACT_PERIOD 6
#define BVSM_AUDIO_INPUT 3

const unsigned long STATUS_REQUEST_INTERVAL = 2000;
const unsigned long STATUS_REQUEST_TIMEOUT = 1000;
const int MIC_BUFFER_SIZE = 64;

BVSP bvsp = BVSP();
BVSMic bvsm = BVSMic();
DualMC33926MotorShield ms = DualMC33926MotorShield();

byte micBuffer[MIC_BUFFER_SIZE];
boolean connected = false;

const int SPEED_STOP = 0;
const int SPEED_SLOW = 100;
const int SPEED_NORMAL = 250;
const int SPEED_FAST = 400;
const int DIRECTION_FRONT = -1;
const int DIRECTION_BACK = 1;

int motorSpeed = SPEED_NORMAL;
unsigned long cmdDuration = 0;
unsigned long cmdStartTime = 0;
bool cmdRunning = false;
byte lastFwdCmd = 0;

const byte CMD_STOP = 0;
const byte CMD_MOVE_FORWARD = 1;
const byte CMD_MOVE_FORWARD_1_CM = 2;
const byte CMD_MOVE_FORWARD_2_CM = 3;
const byte CMD_MOVE_FORWARD_5_CM = 4;
const byte CMD_MOVE_FORWARD_10_CM = 5;
const byte CMD_MOVE_FORWARD_25_CM = 6;
const byte CMD_MOVE_FORWARD_50_CM = 7;
const byte CMD_MOVE_FORWARD_1_M = 8;
const byte CMD_MOVE_BACKWARD = 9;
const byte CMD_MOVE_BACKWARD_1_CM = 10;
const byte CMD_MOVE_BACKWARD_2_CM = 11;
const byte CMD_MOVE_BACKWARD_5_CM = 12;
const byte CMD_MOVE_BACKWARD_10_CM = 13;
const byte CMD_MOVE_BACKWARD_25_CM = 14;
const byte CMD_MOVE_BACKWARD_50_CM = 15;
const byte CMD_MOVE_BACKWARD_1_M = 16;
const byte CMD_TURN_AROUND = 17;
const byte CMD_TURN_AROUND_RIGHT = 18;
const byte CMD_TURN_AROUND_LEFT = 19;
const byte CMD_DO_360 = 20;
const byte CMD_TURN_RIGHT = 21;
const byte CMD_TURN_RIGHT_10 = 22;
const byte CMD_TURN_RIGHT_25 = 23;
const byte CMD_TURN_RIGHT_45 = 24;
const byte CMD_TURN_LEFT = 25;
const byte CMD_TURN_LEFT_10 = 26;
const byte CMD_TURN_LEFT_25 = 27;
const byte CMD_TURN_LEFT_45 = 28;
const byte CMD_DO_CIRCLE = 29;
const byte CMD_COME_BACK = 30;
const byte CMD_MOVE_FORWARD_2_M = 31;
const byte CMD_MOVE_FORWARD_3_M = 32;
const byte CMD_MOVE_BACKWARD_2_M = 33;
const byte CMD_MOVE_BACKWARD_3_M = 34;
const byte CMD_SET_SPEED_SLOW = 35;
const byte CMD_SET_SPEED_NORMAL = 36;
const byte CMD_SET_SPEED_FAST = 37;
const byte CMD_TURN_LEFT_45_BACKWARD = 38;
const byte CMD_TURN_RIGHT_45_BACKWARD = 39;

void setup() {
  Serial.begin(115200);
  pinMode(BVS_RUNNING, OUTPUT);
  pinMode(BVS_SRE, OUTPUT);
  pinMode(BVS_DATA_FWD, OUTPUT);
  pinMode(BVS_ACT_PERIOD, OUTPUT);
  AllLEDsOff();
  bvsp.begin(Serial, STATUS_REQUEST_TIMEOUT, STATUS_REQUEST_INTERVAL);
  bvsp.frameReceived = BVSP_frameReceived;
  bvsm.begin();
  ms.init();
}

void loop() {
  if (!connected) {
    Connect(Serial);
    connected = true;
    bvsp.reset();
  }
  bvsp.keepAlive();
  bvsp.receive();
  digitalWrite(BVS_RUNNING, bvsp.isBVSRunning());
  digitalWrite(BVS_DATA_FWD, bvsp.isDataFwdRunning());
  if (bvsp.isSREAvailable()) {
    digitalWrite(BVS_SRE, HIGH);
    if (!bvsm.isRecording) {
      bvsm.setAudioInput(BVSM_AUDIO_INPUT, EXTERNAL);
      bvsm.startRecording();
    }
    if (bvsm.available) {
      if (bvsp.inboundMode == FRAMED_MODE) bvsp.setInboundMode(STREAM_MODE);
      int bytesRead = bvsm.read(micBuffer, MIC_BUFFER_SIZE);
      bvsp.sendStream(micBuffer, bytesRead);
    }
  } else {
    digitalWrite(BVS_SRE, LOW);
    digitalWrite(BVS_ACT_PERIOD, LOW);
    if (bvsm.isRecording) bvsm.stopRecording();
  }
  if (bvsp.hasStatusTimedOut()) {
    if (bvsm.isRecording) bvsm.stopRecording();
    Disconnect(Serial);
    AllLEDsOff();
    connected = false;
  }
  if (cmdRunning) if (millis() - cmdStartTime >= cmdDuration) RunCommand(CMD_STOP);
}

void BVSP_frameReceived(byte dataType, int payloadSize) {
  switch (dataType) {
    case DATA_TYPE_BYTE: RunCommand(bvsp.getReceivedByte()); break;
    case DATA_TYPE_INT16: digitalWrite(BVS_ACT_PERIOD, bvsp.getReceivedInt16()); break;
  }
}

void RunCommand(byte cmd) {
  switch (cmd) {
    case CMD_STOP: ms.setSpeeds(SPEED_STOP, SPEED_STOP); cmdRunning = false; return;
    case CMD_MOVE_FORWARD: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 60000; break;
    case CMD_MOVE_FORWARD_1_CM: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 23; break;
    case CMD_MOVE_FORWARD_2_CM: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 47; break;
    case CMD_MOVE_FORWARD_5_CM: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 117; break;
    case CMD_MOVE_FORWARD_10_CM: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 234; break;
    case CMD_MOVE_FORWARD_25_CM: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 468; break;
    case CMD_MOVE_FORWARD_50_CM: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 1170; break;
    case CMD_MOVE_FORWARD_1_M: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 2339; break;
    case CMD_MOVE_FORWARD_2_M: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 4678; break;
    case CMD_MOVE_FORWARD_3_M: lastFwdCmd = cmd; ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_FRONT); cmdDuration = 7018; break;
    case CMD_MOVE_BACKWARD: ms.setSpeeds(motorSpeed * DIRECTION_BACK, motorSpeed * DIRECTION_BACK); cmdDuration = 60000; break;
    case CMD_MOVE_BACKWARD_1_CM: ms.setSpeeds(motorSpeed * DIRECTION_BACK, motorSpeed * DIRECTION_BACK); cmdDuration = 23; break;
    case CMD_MOVE_BACKWARD_2_CM: ms.setSpeeds(motorSpeed * DIRECTION_BACK, motorSpeed * DIRECTION_BACK); cmdDuration = 47; break;
    case CMD_MOVE_BACKWARD_5_CM: ms.setSpeeds(motorSpeed * DIRECTION_BACK, motorSpeed * DIRECTION_BACK); cmdDuration = 117; break;
    case CMD_MOVE_BACKWARD_10_CM: ms.setSpeeds(motorSpeed * DIRECTION_BACK, motorSpeed * DIRECTION_BACK); cmdDuration = 234; break;
    case CMD_MOVE_BACKWARD_25_CM: ms.setSpeeds(motorSpeed * DIRECTION_BACK, motorSpeed * DIRECTION_BACK); cmdDuration = 468; break;
    case CMD_MOVE_BACKWARD_50_CM: ms.setSpeeds(motorSpeed * DIRECTION_BACK, motorSpeed * DIRECTION_BACK); cmdDuration = 1170; break;
    case CMD_MOVE_BACKWARD_1_M: ms.setSpeeds(motorSpeed * DIRECTION_BACK, motorSpeed * DIRECTION_BACK); cmdDuration = 2339; break;
    case CMD_MOVE_BACKWARD_2_M: ms.setSpeeds(motorSpeed * DIRECTION_BACK, motorSpeed * DIRECTION_BACK); cmdDuration = 4678; break;
    case CMD_MOVE_BACKWARD_3_M: ms.setSpeeds(motorSpeed * DIRECTION_BACK, motorSpeed * DIRECTION_BACK); cmdDuration = 7017; break;
    case CMD_TURN_AROUND: ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_BACK); cmdDuration = 540; break;
    case CMD_TURN_AROUND_RIGHT: ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_BACK); cmdDuration = 540; break;
    case CMD_TURN_AROUND_LEFT: ms.setSpeeds(motorSpeed * DIRECTION_BACK, motorSpeed * DIRECTION_FRONT); cmdDuration = 540; break;
    case CMD_DO_360: ms.setSpeeds(motorSpeed * DIRECTION_FRONT, motorSpeed * DIRECTION_BACK); cmdDuration = 1065; break;
    case CMD_TURN_RIGHT: ms.setSpeeds(motorSpeed * DIRECTION_FRONT, 0); cmdDuration = 503; break;
    case CMD_TURN_RIGHT_10: ms.setSpeeds(motorSpeed * DIRECTION_FRONT, 0); cmdDuration = 56; break;
    case CMD_TURN_RIGHT_25: ms.setSpeeds(motorSpeed * DIRECTION_FRONT, 0); cmdDuration = 140; break;
    case CMD_TURN_RIGHT_45: ms.setSpeeds(motorSpeed * DIRECTION_FRONT, 0); cmdDuration = 252; break;
    case CMD_TURN_LEFT: ms.setSpeeds(0, motorSpeed * DIRECTION_FRONT); cmdDuration = 503; break;
    case CMD_TURN_LEFT_10: ms.setSpeeds(0, motorSpeed * DIRECTION_FRONT); cmdDuration = 56; break;
    case CMD_TURN_LEFT_25: ms.setSpeeds(0, motorSpeed * DIRECTION_FRONT); cmdDuration = 140; break;
    case CMD_TURN_LEFT_45: ms.setSpeeds(0, motorSpeed * DIRECTION_FRONT); cmdDuration = 252; break;
    case CMD_DO_CIRCLE: ms.setSpeeds(SPEED_NORMAL * DIRECTION_FRONT, SPEED_NORMAL * DIRECTION_FRONT * 0.60); cmdDuration = 4587; break;
    case CMD_COME_BACK: RunCommand(lastFwdCmd); return;
    case CMD_SET_SPEED_SLOW: motorSpeed = SPEED_SLOW; return;
    case CMD_SET_SPEED_NORMAL: motorSpeed = SPEED_NORMAL; return;
    case CMD_SET_SPEED_FAST: motorSpeed = SPEED_FAST; return;
    case CMD_TURN_LEFT_45_BACKWARD: ms.setSpeeds(motorSpeed * DIRECTION_BACK, 0); cmdDuration = 252; break;
    case CMD_TURN_RIGHT_45_BACKWARD: ms.setSpeeds(0, motorSpeed * DIRECTION_BACK); cmdDuration = 252; break;
  }
  cmdStartTime = millis();
  cmdRunning = true;
}

void Connect(HardwareSerial &serialPort) {
  serialPort.print("$$$");
  delay(500);
  serialPort.println("open 192.168.0.11 4194");
  delay(1000);
  serialPort.println("exit");
  delay(500);
}

void Disconnect(HardwareSerial &serialPort) {
  serialPort.print("$$$");
  delay(500);
  serialPort.println("close");
  delay(1000);
  serialPort.println("exit");
  delay(500);
}

void AllLEDsOff() {
  digitalWrite(BVS_RUNNING, LOW);
  digitalWrite(BVS_SRE, LOW);
  digitalWrite(BVS_DATA_FWD, LOW);
  digitalWrite(BVS_ACT_PERIOD, LOW);
}

Esquemáticos

Construye un robot de 2 ruedas controlado por voz con Arduino y BitVoicer Server

Proceso de manufactura

  1. Construya un robot Raspberry Pi controlado por Bluetooth con retroalimentación de audio
  2. Construya un robot con streaming de vídeo controlado por Internet con Arduino y Raspberry Pi
  3. Sistema de Asistencia RFID Fiable con Arduino y Python
  4. Pantalla LED Interactiva con Giroscopio, Anillo NeoPixel y Arduino
  5. Vehículo Controlado por Android con Raspberry Pi, Arduino y Motor Shield: Guía Completa
  6. Robot evasor de obstáculos con servo: Construcción con Arduino y HC-SR04
  7. Controla tu Roomba Create 2 con Arduino y Android: Guía Completa
  8. Brazo Robótico de 6 Grados de Libertad Controlado por Nunchuk con Arduino
  9. Construye un robot controlado por voz con Arduino Nano
  10. Electrodomésticos activados por voz: Control Bluetooth con Google Assistant
  11. Dominando reconocimiento y síntesis de voz en Arduino Due