Paso 5: Cargar el código para el Arduino
En este paso tienes que añadir el siguiente código para el Arduino. También puede descargar el sketch de Arduino desde este enlace el código. Recuerda que para enviar el código para el Arduino debe establecer el interruptor en Sparkfun escudo a la posición de DLINE como se describe en el paso 3. Antes de subir el código, correctamente debe instalar el Servidor de BitVoicer y las librerías de Pololu del conductor del motor en el IDE de Arduino (importar un .zip biblioteca).
#include <BVSP.h>#include <BVSMic.h>#include <DualMC33926MotorShield.h>// Defines the Arduino pins that will be used to control // LEDs and capture audio #define BVS_RUNNING 2 #define BVS_SRE 5 #define BVS_DATA_FWD 3 #define BVS_ACT_PERIOD 6 #define BVSM_AUDIO_INPUT 3// Defines the constants that will be passed as parameters to // the BVSP.begin function const unsigned long STATUS_REQUEST_INTERVAL = 2000; const unsigned long STATUS_REQUEST_TIMEOUT = 1000;// Defines the size of the mic buffer const int MIC_BUFFER_SIZE = 64;// Initializes a new global instance of the BVSP class BVSP bvsp = BVSP();// Initializes a new global instance of the BVSMic class BVSMic bvsm = BVSMic();// Initializes a new global instance of the // DualMC33926MotorShield class DualMC33926MotorShield ms = DualMC33926MotorShield();// Creates a buffer that will be used to read recorded samples // from the BVSMic class byte micBuffer[MIC_BUFFER_SIZE];// Creates a global variable that indicates whether the // Arduino is connected to BitVoicer Server boolean connected = false;// Defines some constants for the motor settings 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;// Declares a global variables to hold the current motor speed. // The default is SPEED_NORMAL, but there are voice // commands that change this setting. int motorSpeed = SPEED_NORMAL;// Stores the command duration in milliseconds unsigned long cmdDuration = 0;// Stores the time the command started running unsigned long cmdStartTime = 0;// Stores whether a command is running or not bool cmdRunning = false;// Stores the last MOVE_FORWARD command. This variable // is used only for the COME_BACK command. byte lastFwdCmd = 0;// Defines some constants for command names/values // Just to make the code more readable 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() { // Starts serial communication at 115200 bps Serial.begin(115200); // Sets the Arduino pin modes pinMode(BVS_RUNNING, OUTPUT); pinMode(BVS_SRE, OUTPUT); pinMode(BVS_DATA_FWD, OUTPUT); pinMode(BVS_ACT_PERIOD, OUTPUT); AllLEDsOff(); // Sets the Arduino serial port that will be used for // communication, how long it will take before a status request // times out and how often status requests should be sent to // BitVoicer Server bvsp.begin(Serial, STATUS_REQUEST_TIMEOUT, STATUS_REQUEST_INTERVAL); // Sets the function that will handle the frameReceived // event bvsp.frameReceived = BVSP_frameReceived; // Prepares the BVSMic class timer bvsm.begin(); // Prepares the motor shield class (pins and timer1) ms.init(); }void loop() { // If it is not connected to the server, opens a TCP/IP // connection, sets connected to true and resets the BVSP // class if (!connected) { Connect(Serial); connected = true; bvsp.reset(); } // Checks if the status request interval has elapsed and if it // has, sends a status request to BitVoicer Server bvsp.keepAlive(); // Checks if there is data available at the serial port buffer // and processes its content according to the specifications // of the BitVoicer Server Protocol bvsp.receive(); // Gets the respective status from the BVSP class and sets // the LEDs on or off digitalWrite(BVS_RUNNING, bvsp.isBVSRunning()); digitalWrite(BVS_DATA_FWD, bvsp.isDataFwdRunning()); // Checks if there is a SRE assigned to the Arduino if (bvsp.isSREAvailable()) { // Turns on the SRE available LED digitalWrite(BVS_SRE, HIGH); // If the BVSMic class is not recording, sets up the audio // input and starts recording if (!bvsm.isRecording) { bvsm.setAudioInput(BVSM_AUDIO_INPUT, EXTERNAL); bvsm.startRecording(); } // Checks if the BVSMic class has available samples if (bvsm.available) { // Makes sure the inbound mode is STREAM_MODE before // transmitting the stream if (bvsp.inboundMode == FRAMED_MODE) bvsp.setInboundMode(STREAM_MODE); // Reads the audio samples from the BVSMic class int bytesRead = bvsm.read(micBuffer, MIC_BUFFER_SIZE); // Sends the audio stream to BitVoicer Server bvsp.sendStream(micBuffer, bytesRead); } } else { // There is no SRE available // Turns off the SRE and ACT_PERIOD LEDs digitalWrite(BVS_SRE, LOW); digitalWrite(BVS_ACT_PERIOD, LOW); // If the BVSMic class is recording, stops it if (bvsm.isRecording) bvsm.stopRecording(); } // If the status has timed out, the connection is considered // lost if (bvsp.hasStatusTimedOut()) { // If the BVSMic is recording, stops it if (bvsm.isRecording) bvsm.stopRecording(); // Closes the TCP/IP connection Disconnect(Serial); AllLEDsOff(); connected = false; } // If a command is running, checks if its duration has // expired. If it has, stop the motors. if (cmdRunning) if (millis() - cmdStartTime >= cmdDuration) RunCommand(CMD_STOP); }// Handles the frameReceived event void BVSP_frameReceived(byte dataType, int payloadSize) { // Performs the appropriate actions based on the frame // data type. If the data type is byte, it is a command. // If the data type is int, changes the activated // period LED. switch (dataType) { case DATA_TYPE_BYTE: RunCommand(bvsp.getReceivedByte()); break; case DATA_TYPE_INT16: digitalWrite(BVS_ACT_PERIOD, bvsp.getReceivedInt16()); break; } }// Runs the command received from the server 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; } // Sets the command start time cmdStartTime = millis(); // Sets cmdRunning to true cmdRunning = true; }// Opens a TCP/IP connection with the BitVoicer Server void Connect(HardwareSerial &serialPort) { serialPort.print("$$$"); delay(500); // Use the IP address of the server and the TCP port set // in the server properties serialPort.println("open 192.168.0.11 4194"); delay(1000); serialPort.println("exit"); delay(500); }// Closes the TCP/IP connection with the BitVoicer Server void Disconnect(HardwareSerial &serialPort) { serialPort.print("$$$"); delay(500); serialPort.println("close"); delay(1000); serialPort.println("exit"); delay(500); }// Turns all LEDs off void AllLEDsOff() { digitalWrite(BVS_RUNNING, LOW); digitalWrite(BVS_SRE, LOW); digitalWrite(BVS_DATA_FWD, LOW); digitalWrite(BVS_ACT_PERIOD, LOW); }
Algunas partes de este dibujo son similares a piezas que usé en uno de mis anteriores Instructables y aborda la comunicación con el servidor BitVoicer (clasesBVSP y BVSMic ). En este Instructable, voy a pegarlo a la explicación de las nuevas piezas del bosquejo. Si desea obtener más información acerca de cómo utilizar las clases de BVSMic y la BVSP, sugiero su consulte el Instructable he mencionado más arriba.
- Declaración de constantes: al principio del bosquejo, declaro una serie de constantes que se utilizan en todo el código. El grupo de constantes con ajustes de motor define dos constantes de dirección y las velocidades de motor por defecto. La biblioteca de controlador de motor del chip acepta valores de -400 a + 400 de la velocidad del motor donde cero significa apagado. Los valores negativos indican rotación inversa o, si se han invertido los cables del motor como yo, rotación hacia adelante. El grupo de constantes con los valores del comando se refiere a los comandos que se envía desde el servidor de BitVoicer. En este dibujo he definido sólo 40 comandos básicos de tipo byte , pero los movimientos más complejos se pueden realizar la combinación de estos comandos.
- Ejecución y Control de Variables: cinco variables se definen al principio del código para el control de la ejecución de comandos (motorSpeed, cmdDuration, cmdStartTime, cmdRunning e lastFwdCmd). La variable motorSpeed mantiene la velocidad actual del motor. Esta variable se actualiza con uno de los valores predeterminados definidos por las constantes de velocidad si el Arduino recibe un comando de servidor BitVoicer para actualizar las velocidades del motor. La variable cmdDuration contiene la duración total del comando actual. Esta variable se comprueba con la variable cmdStartTime en todas las iteraciones de la función de bucle si cmdRunning es true. Si transcurrido el tiempo de ejecución de comandos, se llama a la función EjecutarComando para detener los motores. La variable lastFwdCmd contiene el último comando "ir o mover hacia adelante". Esta variable se utiliza para conocer la última distancia viajada puede ejecutar el comando "volver". Tenga en cuenta que para utilizar este comando debe primero dices el robot para dar vuelta alrededor.
- Conexión WiFi: al final del esbozo definir dos funciones para conectar y desconectar del servidor BitVoicer (conectar y desconectar). Estas funciones ponen el Microchip WiFi módulo en modo comando, abrir o cerrar una conexión TCP/IP y devolución el módulo en modo de datos. Dentro de la función de bucle , si la variable conectado no es cierto, yo llame a la función de conectar . Si la clase BVSP informa que el estado del servidor ha caducado, en otras palabras, no se ha recibido ninguna respuesta de la última petición de estado, supongo que la conexión se ha perdido y llame a la función de desconexión . Esto obligará a un nuevo intento de conexión en la siguiente iteración del bucle.
- Función EjecutarComando : llama a esta función cada vez que se recibe una orden desde el servidor de BitVoicer. Toma un valor de byte que corresponde a uno de los comandos básicos definidos por las constantes al principio del bosquejo. Cada comando básico se identifica dentro del interruptor para que el motor velocidades adecuadas se pueden definir así como la duración de comando. Al final de la función, la variable cmdRunning se establece en true y la vez devuelta por la función millis es almacenada en la variable cmdStartTime . Esto permite que el Arduino controlar la ejecución de comandos como se describe anteriormente. Los tiempos en milisegundos, para cada comando se obtuvieron como se describe en el paso anterior.